Compare commits

...

1029 Commits
9.4 ... 10.4.2

Author SHA1 Message Date
Mario
44a0311798 Merge branch 'master' of https://framagit.org/hubzilla/core 2025-08-08 07:51:42 +00:00
Mario
2ac06fef9a version 10.4.2 2025-08-08 07:51:12 +00:00
Mario
5b6a38aa2d changelog 2025-08-08 07:48:14 +00:00
Mario
37b9919905 bump version 2025-08-07 22:53:26 +00:00
Mario
283c018d07 implement item_custom_display hook in mod HQ 2025-08-07 22:51:40 +00:00
Mario
51c79aecac make item_normal() deal with various item types and add missing reactions modal 2025-08-07 22:36:35 +00:00
Mario
9343f00918 improve memory consumption when deleting big threads 2025-08-07 19:05:58 +00:00
Mario
962b4e5b4c fix php error
(cherry picked from commit eeef6cfd00)

Co-authored-by: Mario <mario@mariovavti.com>
2025-08-07 14:57:11 +00:00
Mario
eeef6cfd00 fix php error 2025-08-07 14:55:00 +00:00
Mario
96c7912fa6 update the contact edit header so that both, image and text are linked to the profile 2025-08-02 11:48:50 +00:00
Mario
91f1f8ed7c version 10.4.1 2025-07-31 08:46:43 +00:00
Mario
3f7ed72ece changelogà 2025-07-31 08:43:31 +00:00
Mario
3385c694aa add delay before collapsing 2025-07-31 08:22:01 +00:00
Mario
a922f5ca6c bump version 2025-07-30 19:20:35 +00:00
Mario
88977a406c imagesLoaded() should not be required in updateConvItems() anymore since we call it before updateConvItems() already (famous last words). 2025-07-30 19:19:00 +00:00
Mario
e98f019b16 fix regression in pubstream tag view, use correct prefixes in pub_tagadelic() and some whitespace fixes 2025-07-30 16:22:08 +00:00
Mario
50f5fcb16b always update photo DB entries on move - fixes issue where photos were not found by photo picker after folder rename as reported by chris 2025-07-30 06:45:25 +00:00
Mario
bf35a661bf remove trailing comma 2025-07-29 11:02:43 +00:00
Mario
ecc94cdecd fix a weird rendering issue which was triggered by load events fireing after the timeout was already in action 2025-07-29 09:28:00 +00:00
Mario
e79a70d2b1 var > const and style 2025-07-27 10:24:53 +00:00
Mario
6916a825ee move the freshly created content to the center instead of top and use smooth scrolling 2025-07-27 10:23:23 +00:00
Mario
b5a798f068 fix comment preview and scroll to the just created comment after posting it 2025-07-27 09:52:48 +00:00
Mario
e5c54fadea Merge branch 'update-derived-theme-tutorial' into 'dev'
Update derived theme tutorial

See merge request hubzilla/core!2219
2025-07-27 08:15:15 +00:00
Mario
f2217e9016 Merge branch 'fix-pubstream-tagcloud-tpl' into 'dev'
Fix pubstream tagcloud and category cloud

See merge request hubzilla/core!2218
2025-07-27 08:14:41 +00:00
Saiwal K
4d6bebb846 Fix pubstream tagcloud and category cloud 2025-07-27 08:14:41 +00:00
Harald Eilertsen
2e9b1d25e1 Replace mention of theme_init function
The theme_init function is no longer needed, and the example isn't using
it. So we replace it with a bit more description of the theme info in
the comment, and how that works.
2025-07-24 12:50:50 +02:00
Harald Eilertsen
8604ba016e Update derived theme tutorial
Adds another lesson on customising the theme using styles and overriding
templates.

Also some minor language cleanup and add some introductory text before
lesson 1.
2025-07-24 12:40:13 +02:00
Mario
cc35afa4c9 bump version 2025-07-23 12:07:45 +00:00
Mario
f01c5ad0c1 remove logging 2025-07-23 12:07:21 +00:00
Mario
7b6a8fdba1 fix issue where reply modal would not show anymore after reactions loaded 2025-07-23 12:06:48 +00:00
Mario
2c9f184a09 tagcloud fixes 2025-07-23 08:19:40 +00:00
Mario
6f158f37c9 Merge branch 'improve-derived-themes' into 'dev'
Add 'extends' attribute to theme info

See merge request hubzilla/core!2217
2025-07-23 07:54:30 +00:00
Mario
f88d2ba0c4 Merge branch 'tag-cloud-tpl-fix' into 'dev'
Add tpl for tagcloud and directory keyword cloud

See merge request hubzilla/core!2216
2025-07-23 07:53:10 +00:00
Saiwal K
170f157aae Add tpl for tagcloud and directory keyword cloud 2025-07-23 07:53:09 +00:00
Mario
82817b4532 tagadelic: look up toplevels only
(cherry picked from commit 3eeaca4aab)

Co-authored-by: Mario <mario@mariovavti.com>
2025-07-22 10:34:19 +00:00
Mario
3eeaca4aab tagadelic: look up toplevels only 2025-07-22 10:32:57 +00:00
Mario
a3dd4a4d3d revert cleanup template
(cherry picked from commit c383e6af80)

Co-authored-by: Mario <mario@mariovavti.com>
2025-07-22 10:22:38 +00:00
Mario
c383e6af80 revert cleanup template 2025-07-22 10:21:34 +00:00
Mario
517e14cc38 cleanup template
(cherry picked from commit eb3dfb2488)

Co-authored-by: Mario <mario@mariovavti.com>
2025-07-22 10:17:05 +00:00
Mario
eb3dfb2488 cleanup template 2025-07-22 10:16:09 +00:00
Mario
70e8648d91 the item_wall directive is not required here since we are looking for parent items which we own - remove it since it will make the DB engine use the wrong index in certain cases. also remove duplication of item_type directive when looking up articles
(cherry picked from commit ae8e9bc353)

Co-authored-by: Mario <mario@mariovavti.com>
2025-07-22 09:33:34 +00:00
Mario
ae8e9bc353 the item_wall directive is not required here since we are looking for parent items which we own - remove it since it will make the DB engine use the wrong index in certain cases. also remove duplication of item_type directive when looking up articles 2025-07-22 09:32:20 +00:00
Harald Eilertsen
88227b9155 Rename derived theme tutorial file 2025-07-20 20:33:56 +02:00
Harald Eilertsen
ae77ab7f20 Add derived theme tutorial to help index 2025-07-20 20:28:39 +02:00
Harald Eilertsen
308380fe52 Add 'extends' attribute to theme info
To create a derived (or child) theme, the array held in
`App::$theme_info` must contain a key `extends` that contains the name
of the parent theme as a value.

The derived theme tutorial would suggest adding the key in the
`themename_init()` function, however this does not work. The theme info
is repopulated from the theme info file after the theme init function
has run, and so the `extends` key disappears.

This patch adds `extends` as a first class attribute for themes, so that
it can be specified directly in the theme info in the top file comment
block. It also updates the derived theme tutorial to reflect this
change.
2025-07-20 20:23:25 +02:00
Mario
ee7b982358 Merge branch '10.4RC' 2025-07-15 06:40:43 +00:00
Mario
2740f36259 version 10.4 2025-07-15 06:40:19 +00:00
Mario
ff16810e76 Merge branch 'dev' into 10.4RC 2025-07-15 06:35:47 +00:00
Mario
161cfcd64d update changelog 2025-07-15 06:33:41 +00:00
Mario
d16d1fdcd5 Merge branch 'more-nb-translation-and-fixes' into 'dev'
More translations and fix for Norwegian nb

See merge request hubzilla/core!2214
2025-07-15 06:13:46 +00:00
Harald Eilertsen
06c0652b05 More translations and fix for Norwegian nb
Wiki's and profiles both used the "Create new" button, so don't add what
is being created to the translation :)
2025-07-14 22:23:58 +02:00
Mario
a2fb2e04f3 add support for did:key verificationMethod in checkEddsaSignature() 2025-07-14 14:13:34 +00:00
Mario
b376f810bf strict check and whitespace 2025-07-14 13:56:51 +00:00
Mario
0c2bcda431 some documentation 2025-07-14 13:48:59 +00:00
Mario
22cb0d3c6b use a custom function to build the psr7 request to work around mod rewrite issues with ServerRequest::fromGlobals() 2025-07-14 13:45:23 +00:00
Mario Vavti
b6b4eb4c22 composer update http message signer to version 0.2.3 2025-07-14 15:35:03 +02:00
Mario
da1e0b965b Merge branch 'dev' into 10.4RC 2025-07-13 19:43:01 +00:00
Mario
d566199423 Merge branch 'update-nb-translations' into 'dev'
Update translations for Norsk Bokmål

See merge request hubzilla/core!2213
2025-07-13 19:40:28 +00:00
Mario
35be83c5f6 Merge branch 'fix-permission-context-help' into 'dev'
Fix context help link for permissions

See merge request hubzilla/core!2212
2025-07-13 19:39:21 +00:00
Harald Eilertsen
76eed3c06c Fix context help link for permissions
The target was changed when the new docs was merged.
2025-07-13 16:09:33 +02:00
Harald Eilertsen
d994e1be48 Update translations for Norsk Bokmål 2025-07-13 16:01:06 +02:00
Mario
24316bbb03 Merge branch 'dev' into 10.4RC 2025-07-13 10:32:55 +00:00
Mario
7b5a638e00 update changelog 2025-07-13 10:32:23 +00:00
Mario
fa4c86eabf update install document 2025-07-13 10:03:46 +00:00
Mario
9cf610280c add init_sys_channel utility to create the sys channel in case of headless installation - issue #1909 2025-07-13 09:57:26 +00:00
Mario
052341d24a Merge branch 'dev' into 10.4RC 2025-07-13 09:49:29 +00:00
Mario
a55bba7aa8 fix blog mode if threaded view is disabled 2025-07-13 09:47:38 +00:00
Mario
0244d9423a RC3 2025-07-10 12:02:15 +00:00
Mario
042c98cf2d Merge branch 'dev' into 10.4RC 2025-07-10 12:00:53 +00:00
Mario
2958ea8c89 update changelog 2025-07-10 12:00:32 +00:00
Mario
81a12be654 changelog 2025-07-10 11:59:27 +00:00
Mario
9f99e401bc Merge branch 'fix-markdown-mentions' into 'dev'
Prevent mentions from mangling by markdown parser

See merge request hubzilla/core!2211
2025-07-10 11:43:10 +00:00
Mario
48ef490f50 Merge branch 'dev' into 10.4RC 2025-07-10 11:40:58 +00:00
Mario Vavti
d782229ba0 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2025-07-10 11:37:01 +02:00
Mario Vavti
52291fd371 update macgirvin/http-message-signer to version 2.2 2025-07-10 11:36:38 +02:00
Mario
e0298a4378 add logging and catch exception 2025-07-09 08:00:52 +00:00
Mario
08b7eb52c7 remove unneeded code from test 2025-07-09 08:00:27 +00:00
Mario
43ebf69d09 trim the value 2025-07-08 10:47:44 +00:00
Mario
18ae629f19 remove the check for supported protocols. we can store them all because we check later if we support one of them 2025-07-08 10:46:40 +00:00
Mario
8deedd1979 remove long deprecated crypto functions 2025-07-08 10:01:10 +00:00
Mario Vavti
525594d529 update to phpseclib3 which is now a requirement for the http signer library 2025-07-08 11:35:56 +02:00
Mario Vavti
1162615c52 missing file from http-message-signer 2025-07-07 13:17:55 +02:00
Mario Vavti
c462c928e0 composer update to phpseclib version 3 2025-07-07 13:17:14 +02:00
Mario
fcb0ef9633 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2025-07-06 21:22:53 +00:00
Mario
8a4273a2f5 for now only attempt RFC9421 verification if we have the request 2025-07-06 21:22:32 +00:00
Mario Vavti
3014ae2071 update macgirvin/http-message-signer to version 2.0 2025-07-06 22:58:09 +02:00
Mario Vavti
d396043faf composer dump-autoload 2025-07-06 22:42:55 +02:00
Mario Vavti
2054359f6c testing and fixes 2025-07-06 22:41:02 +02:00
Mario
9a3735cd37 tests for Activity::get_actor_protocols() 2025-07-06 18:32:08 +00:00
Mario
222b74ec05 extend get_actor_protocols() to also check fep-fb2a actor metadata 2025-07-06 18:06:28 +00:00
Harald Eilertsen
cb491c53f7 Prevent mentions from mangling by markdown parser
Mentioning people whose handles include valid markdown would not survive
markdown to bbcode conversion wihout being mangled. An example that
brought this to my attention was a handle similar to this:

    _someuser_@testsite.example

The underscores would be interpreted as emphasis in markdown, and
converted to:

    [i]someuser[/i]@testsite.example

This patch should fix this, and hopefully any other issue with mentions
being mangled.
2025-06-28 13:35:05 +02:00
Mario
37f0074674 Merge branch 'dev' into 10.4RC 2025-06-26 08:58:56 +00:00
Mario Vavti
e6c8c47721 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2025-06-26 10:55:31 +02:00
Mario Vavti
0a98a49eeb composer update macgirvin/http-message-signer 2025-06-26 10:54:42 +02:00
Mario
7bd4217dd8 Merge branch 'dev' into 10.4RC 2025-06-26 08:12:28 +00:00
Mario
af5733888c changelog 2025-06-26 08:11:46 +00:00
Mario
c346210735 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2025-06-26 08:08:31 +00:00
Mario
6028f0490e minor refactor to get rid of the $webpage variable (it does not cut it anymore) and use $item_type instead 2025-06-26 08:08:08 +00:00
Mario Vavti
890a5942d6 Merge branch 'dev' into 10.4RC 2025-06-25 17:43:52 +02:00
Mario Vavti
7782183ae3 changelog 2025-06-25 17:40:55 +02:00
Mario Vavti
7ecbce691d RC2 2025-06-25 17:35:58 +02:00
Mario Vavti
2aeed27b9b emiting a notice from include/auth does not work. emit it from mod login if the login failed. 2025-06-25 17:33:35 +02:00
Mario Vavti
d636e71024 remove code that would never execute and make sure the first account to register is the admin account 2025-06-25 17:26:41 +02:00
Mario
2606517c1d changelog 2025-06-24 10:09:36 +00:00
Mario
0ab94d42f4 bump dev version 2025-06-24 07:58:19 +00:00
Mario
7c32b11605 update strings 2025-06-24 07:55:21 +00:00
Mario
7b6c76abf1 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2025-06-24 07:54:33 +00:00
Mario
0e31d61868 Merge branch 'some-account-cleanup' into 'dev'
A bit of cleanup for account functions

See merge request hubzilla/core!2210
2025-06-24 07:53:43 +00:00
Harald Eilertsen
66e02c5e3a A bit of cleanup for account functions 2025-06-24 07:53:42 +00:00
Mario
122747ae76 version 10.4RC1 2025-06-24 07:28:50 +00:00
Mario
9a410f57e6 fix php warnings 2025-06-24 07:25:56 +00:00
Mario
2047e9bca7 fix php warning 2025-06-23 20:06:07 +00:00
Mario
aeb54655a0 exit if we have not found anything 2025-06-23 09:24:10 +00:00
Mario
1a3ca49eba apply downstream fix from streams: do not sign (request-target) on response 2025-06-23 09:10:57 +00:00
Mario
579cf86335 rfc9421 verify: parse more fields if applicable 2025-06-23 09:03:05 +00:00
Mario
fcf42eeae0 Revert "rfc9421 verify: parse more fields if applicable"
This reverts commit 721c0b1e5b.
2025-06-23 09:02:08 +00:00
Mario
721c0b1e5b rfc9421 verify: parse more fields if applicable 2025-06-23 08:59:27 +00:00
Mario
82b2f06bdd bump version 2025-06-22 07:36:08 +00:00
Mario
b241e14c06 import App 2025-06-21 20:56:41 +00:00
Mario Vavti
89c17bac50 start verifying RFC9421 HTTP Signatures (hopefully) 2025-06-21 16:39:59 +02:00
Mario
e6bd5ef520 css fix 2025-06-20 19:08:27 +00:00
Mario
7320149fd8 only show the pin if we display the label and fix the test 2025-06-19 08:26:31 +00:00
Mario
7766e5d420 prepend geo links withe a pushpin emoji so that they can be distinguished from regular links 2025-06-19 08:18:25 +00:00
Mario
4a813c150c make sure to set the state on the correct button 2025-06-19 08:08:16 +00:00
Mario
44600c46c6 make sure there is a comment button before attempting to add a class to it 2025-06-18 17:01:26 +00:00
Mario
b5c7fff316 re-add check for sub thread wrapper 2025-06-18 16:49:33 +00:00
Mario
ce618facc8 properly set the comment button and sub-thread-wrapper state if we are loading a conversation in partly expanded mode 2025-06-18 15:55:15 +00:00
Mario Vavti
18016ab36a remove some redundant spaces in bbcode to html conversion and fix tests 2025-06-18 11:55:47 +02:00
Mario
d788233bd7 handle naked geo URIs and add tests 2025-06-18 09:18:11 +00:00
Mario
86ebef7e08 allow geo: uri and be more specific when checking uri schemes also remove zhttp which is not used anymore and ftp which is not supported by most browsers anymore 2025-06-17 09:29:27 +00:00
Mario
37159937d7 bump version 2025-06-14 10:51:48 +00:00
Mario
4d6d3befa0 leave zoom handling to the comment button click handler 2025-06-14 10:51:18 +00:00
Mario
a21785980d Merge branch 'remove-obsolete-funcs' into 'dev'
Remove obsolete functions in account.php

See merge request hubzilla/core!2208
2025-06-14 10:29:14 +00:00
Mario
14fe08240f Merge branch 'fix-album-widgets' into 'dev'
Fix undefined variable in album widgets

See merge request hubzilla/core!2207
2025-06-14 10:28:33 +00:00
Mario
73d50d8294 Merge branch 'remove-xref-module' into 'dev'
Remove unused Xref module

See merge request hubzilla/core!2206
2025-06-14 10:27:50 +00:00
Mario
767eeee6fe invert the verb query part 2025-06-13 09:42:09 +00:00
Mario
abd864a762 css fixes 2025-06-13 09:20:30 +00:00
Mario
25dba4423b bump version 2025-06-13 08:07:53 +00:00
Mario
2046abf26f trick sql to use a better suited index 2025-06-13 08:05:05 +00:00
Mario
ad7871270c add EmojiReact to the countable comment verbs 2025-06-12 11:57:13 +00:00
Mario
66512f4e51 blog mode fixes 2025-06-12 11:51:01 +00:00
Mario
71a06af8a9 consistent naming 2025-06-12 10:47:04 +00:00
Mario
14088b4b2e do not expand all 3 thread levels even if the content is already there. This would be inconsistent behaviour. 2025-06-12 08:02:52 +00:00
Mario
ec2c4fe673 css fixes 2025-06-12 07:02:14 +00:00
Mario
49a065e50b bump version 2025-06-11 19:35:40 +00:00
Mario
391c8d7cba implement indenting of already expanded but flattened items and add dblclick info badge 2025-06-11 19:35:17 +00:00
Mario
76296e72be refactor TLL to zoom in on every expansion and better maintainable code 2025-06-11 11:34:08 +00:00
Mario
d36f806ece more autoexpand iterations fixes 2025-06-10 09:06:48 +00:00
Mario
d3d8c088f3 bump version 2025-06-10 08:46:24 +00:00
Mario
4e01e21230 fix autoexpand iterations 2025-06-10 08:46:01 +00:00
Mario
673790126b dismiss summary if it is equal to content and css fixes 2025-06-09 19:09:32 +00:00
Mario
9eecd0aa3c css fixes 2025-06-09 14:11:20 +00:00
Mario
f8fb1bc3b4 use a more prominent color 2025-06-09 09:30:31 +00:00
Mario
340f5bb791 do not count iterations where we have not found a new thread 2025-06-09 08:11:41 +00:00
Mario
5504c8650e do not call preview twice and not at all if we are in modal action 2025-06-08 21:18:53 +00:00
Mario
9405f2e2d3 bump version 2025-06-08 21:09:51 +00:00
Mario
3de0d304fd fix comment image embed after transition to modal 2025-06-08 21:09:27 +00:00
Harald Eilertsen
0e4924d7c5 Remove obsolete verify_email_addressNOP function 2025-06-08 22:46:26 +02:00
Mario
20377c1ca1 css fixes 2025-06-08 19:05:58 +00:00
Mario
8af9bbb75e slightly darker colors 2025-06-08 18:53:36 +00:00
Mario
34c3a77db4 improved thread lense 2025-06-08 17:07:14 +00:00
Mario
dbc3613af5 more cleanup 2025-06-08 15:13:45 +00:00
Mario
e1d395b6ed more cleanup and introduce the thread lense 2025-06-08 09:06:01 +00:00
Harald Eilertsen
5316ebfe7c Remove obsolete functions in account.php 2025-06-08 09:43:14 +02:00
Harald Eilertsen
13755060d7 Fix undefined variable in album widgets
The Album and Portfolio widgets would reference the undefined
$phototypes array to determine the file extensions of the image sources.

It appears that the extension is not really necessary, but for
completeness I fixed the issue so that the appropriate extension will be
used by for the image source attribute.
2025-06-07 23:09:46 +02:00
Harald Eilertsen
eeb8a124fc Remove unused Xref module
See discussion here:
https://hubzilla.org/item/c611090c-1a5e-5fa5-8836-06f393fd71ef
2025-06-07 22:14:22 +02:00
Mario
5db855abfe it is hard to keep the overview with more than 3 levels 2025-06-07 09:11:12 +00:00
Mario
ab14743146 bump version 2025-06-06 12:04:47 +00:00
Mario
409c062c4f reset indents for possible followup autoexpand 2025-06-06 12:04:32 +00:00
Mario
1b494cdd27 bump version 2025-06-06 11:11:06 +00:00
Mario
f5f853cdfe improved autoexpand 2025-06-06 11:10:36 +00:00
Mario
37aa16a6c0 bump version 2025-06-05 19:43:42 +00:00
Mario
a4ebf93cb8 cleanup, fix iteration counter and bump literations to 10 2025-06-05 19:43:19 +00:00
Mario
358e7c9512 bump version 2025-06-05 16:08:44 +00:00
Mario
11b42a371e revert to previous color generation logic 2025-06-05 16:08:22 +00:00
Mario
61da32dc3f Merge branch 'new-de-docs' into 'dev'
New de docs

See merge request hubzilla/core!2205
2025-06-05 15:50:22 +00:00
Mario
5f26e77785 Merge branch 'more-phpstan-fixes' into 'dev'
More PHPStan fixes

See merge request hubzilla/core!2204
2025-06-05 15:48:17 +00:00
Mario
1d289e619e Merge branch 'crash-in-jcxeddsa2022-sign' into 'dev'
Throw if channel keys missing in JcsEddsa2022::sign

See merge request hubzilla/core!2201
2025-06-05 15:45:47 +00:00
Harald Eilertsen
0c41265613 Throw if channel keys missing in JcsEddsa2022::sign 2025-06-05 15:45:46 +00:00
Mario
b5ad0589cb bump version 2025-06-05 15:44:25 +00:00
Mario
9e87070f86 iterate only 3 levels when autoexpanding, improve color generation to get more random colors 2025-06-05 15:44:01 +00:00
Mario
3da16a4bae bump version 2025-06-05 15:09:23 +00:00
Mario
1ad76ec83f fix other reactions buttons and bring some color to indents 2025-06-05 15:09:03 +00:00
Mario
fa67852278 better center the gt 2025-06-05 08:16:51 +00:00
Mario
d9ebd880be more better center the dash 2025-06-05 08:13:19 +00:00
Mario
9d7c5d2fe2 better center the dash 2025-06-05 08:05:46 +00:00
Mario
8c268d24df version 2025-06-05 08:03:52 +00:00
Mario
f8fb550255 threading: implement manual indent and collapse 2025-06-05 08:03:33 +00:00
Mario
c1aa5a2954 bump version 2025-06-04 19:55:42 +00:00
Mario
342f736eb7 improved autoexpand 2025-06-04 19:55:05 +00:00
Mario
0283c77961 do not prevent default too early 2025-06-04 16:38:30 +00:00
Mario
7740a7501b improved indentation and its logic 2025-06-04 16:33:05 +00:00
Mario
ed97164f01 remove unused code 2025-06-04 14:35:35 +00:00
Mario
6649eca2bf move expand to item menu to get rid of the single click lag 2025-06-04 14:34:44 +00:00
Mario
64ae1eb5e8 add ability to auto-expand a comment reply thread 2025-06-03 08:31:19 +00:00
Mario
d42a89d4b5 disable reactions in pinned widget 2025-06-02 07:55:24 +00:00
Mario
bb05f520c1 fix pinned widget 2025-06-02 07:38:11 +00:00
Mario
f8afa77369 add internal follow and ignore verbs to the list of filtered verbs and add commented out code to display/count only one reaction per author. It appears there can be multiple. We should probably look into how this can happen and if we should prevent it earlier. 2025-06-01 18:48:16 +00:00
Mario
940fd26db7 add the thr_parents if we are in channel single view mode 2025-06-01 10:44:33 +00:00
Mario
fca6ddd35b change the animation so that it will not interfere with bootstrap stuff 2025-06-01 10:14:18 +00:00
Mario
a5ded5884c no need to set animation constant 2025-06-01 04:58:06 +00:00
Mario
d0686796cd it is the fill: both option that woes with dropdown visibility - set it to none 2025-06-01 04:57:05 +00:00
Mario
3ea323bfb0 handle intro notifications via /notify/view so that it will eventually be marked seen 2025-05-31 20:16:24 +00:00
Mario
c826b307c2 fix display issue 2025-05-31 18:43:07 +00:00
Mario
00edbe4393 bump version 2025-05-31 17:07:00 +00:00
Mario
525a45f69c make sure to load the profile when in channel module 2025-05-31 16:56:30 +00:00
Mario
e35d4b6be0 only show load more if total comments > loaded comments 2025-05-30 09:55:26 +00:00
Mario
83c963378e remove more redundant sql (perms for the given IDs MUST be checked at the calling module already) and update documentation 2025-05-29 19:47:53 +00:00
Mario
7705d7a87f this is not required because we already filter by a given set of ids here 2025-05-29 19:31:23 +00:00
Mario
3060126123 bump version 2025-05-29 19:12:27 +00:00
Mario
29f14ff96b only count comments if we are in threaded mode 2025-05-29 19:10:20 +00:00
Mario
8a8219fe72 improved wording 2025-05-29 18:38:11 +00:00
Mario
0aef9b486d fix typo 2025-05-29 17:58:48 +00:00
Mario
d584e4f7d5 fix queries in certain situations returning more results than we need producing unexpected rendering results 2025-05-29 17:58:04 +00:00
Mario
71fbc3ff5c bump version 2025-05-29 14:25:20 +00:00
Mario
3613257cdc pass permission sql to item_reaction_sql() in case we are a visitor and rename the variable 2025-05-29 14:24:53 +00:00
Mario
f61fd2d337 if we are not in threaded mode default comments limit to 1000 2025-05-29 11:55:02 +00:00
Mario
bd8ffcd28d bump version 2025-05-29 10:14:20 +00:00
Mario
20148d23f1 toplevel comments pagination: initial commit 2025-05-29 10:13:32 +00:00
Mario
bdcee46138 do not check for possibly unset var 2025-05-28 12:53:53 +00:00
Mario
bc40c3f7c0 bump version 2025-05-28 09:18:49 +00:00
Mario
7e3d86bc37 more refactor and streamline for re-usability and easier maintenance 2025-05-28 09:15:18 +00:00
PepeCyB
133ac409e3 remove unneeded files 2025-05-27 22:49:16 +02:00
PepeCyB
bda32015b9 new german help-files added 2025-05-27 22:48:54 +02:00
Mario
f0229c9f42 update todo 2025-05-27 09:02:52 +00:00
Mario
7cd44e2112 minor cleanup 2025-05-27 08:31:37 +00:00
Mario
3a3ae2b204 fix a undefined var warning and move some definitions closer to where the value is set for better readability 2025-05-27 08:12:33 +00:00
Mario
4df3c8d2a1 bump version 2025-05-27 08:06:20 +00:00
Mario
8d1fea7ec3 new version of items_by_parent_ids() and item_reaction_sql() with much better performance, streamline rsvp naming convention and some preparatory work for comment lazy loading (unfinshed) 2025-05-27 08:04:36 +00:00
Mario
3535cb3b96 remove the word only. the filter icon should be clear enough. 2025-05-25 17:56:38 +00:00
Mario
48af5b354d bump version 2025-05-25 14:16:47 +00:00
Mario
19df2f596b revert to previous iteration of the parents query function until performance issues will be resolved and adapt the modules accordingly 2025-05-25 14:05:08 +00:00
Harald Eilertsen
51cd6381a6 Ignore PHPStan warning of missing .htpreconfig
The existence of the file is checked in the if-statement wrapping the
include.
2025-05-24 10:52:29 +02:00
Harald Eilertsen
311e0159c9 Fix undefined static function in Zot6Handler
The static function `reply_rekey_request` did not exist, but a function
`rekey_request` that was never called did. Changed the call to use the
latter function instead.

Note: This is completely untested code, and probably needs some
validation. But then it did not work before either.
2025-05-24 10:43:39 +02:00
Harald Eilertsen
63c3f4dc20 Fix missing return in Render\Theme::current
Also made the function halt with a status 500 and log a message if no
theme was found.
2025-05-23 22:33:52 +02:00
Harald Eilertsen
b6e65a76ea Add App::$page_layouts attribute for comanche
Zotlabs\Render\Comanche::register_page_template assigns this variable in
App (for some reason), but it is not declared. As dynamic attributes are
deprecated, and will be removed in PHP 9, this patch fixes the issue by
defining the attribute in the App class.
2025-05-23 20:53:55 +02:00
Mario
d31221e61b use else instead of checking for $ret 2025-05-23 11:54:30 +00:00
Mario
043c1610fd refactor items_by_parent_ids() to accept $thr_parents as an array and stringify it here with the escape flag instead of in the caller modules 2025-05-23 11:35:10 +00:00
Mario
84a4927866 bump version 2025-05-23 10:01:18 +00:00
Mario
2c3ec1ae81 Merge branch 'phpstan-fixes' into 'dev'
Fix a selection of ussues reported by PHPStan

See merge request hubzilla/core!2203
2025-05-23 09:58:59 +00:00
Mario
5655962370 Merge branch 'update-doxygen-config' into 'dev'
Minor doxygen config update

See merge request hubzilla/core!2202
2025-05-23 09:55:15 +00:00
Mario
cd7fab3d37 refactor query in items_by_parent_ids() to prepare for pagination. Until pagination will be implemented we will load the last 100 comments. 2025-05-23 09:51:11 +00:00
Mario
980fedadc0 dba_pdo: return results when using common table expressions (CTE) 2025-05-23 09:47:25 +00:00
Harald Eilertsen
0121e4ed12 Fix undefined variables in Module/Regate.php 2025-05-22 19:03:06 +02:00
Harald Eilertsen
ea6893e3a3 Fix undefined var in Module/Invite.php
The variables $invexpire_n and $invexpire_u was undefined, but
references multiple times in a conditional. Just removed them which
should cause no changed behaviour.
2025-05-22 19:03:06 +02:00
Harald Eilertsen
8a211aff97 Remove unused code in Module/Invite.php
The $feedbk variable was set, but never used in the Module\Invite::get()
function.
2025-05-22 19:03:06 +02:00
Harald Eilertsen
daf8531804 Fix undefined var in Module/Invite.php
Fir ref to undefined $ihave variable in the Module\Invite::get() method.
The var was defined later in the method. Also refactor to fix some other
strange logic in the same area while I was there.

- Moved the logic to cound invites currently in use by a channel to a
  private function. This should probably be moved further to a Regiter
  class once we have these things more in order.
- Changed the logic checking the configuration for how many invites a
  channel can use at the same time to just return 4 (the default)
  instead of going via 'na' and then checking if it's 'na' to then use
  the default value.
- Dropped setting the config to the default if the module is visited by
  an admin. That belongs somewhere else.
2025-05-22 19:03:06 +02:00
Harald Eilertsen
961996a051 Remove duplicate array key in Lib/ThreadItem.php
The key `parent` was set twice in ThreadItem::get_template_data(), once
cast to an intvalue, and later raw from whatever type $item['parent']
held.

Since the value not converted to an int was the one used, this is what
has been kept in this patch, so as to not change existing behaviour.
2025-05-22 19:03:06 +02:00
Harald Eilertsen
0f8500244b Fix undefined variable in Lib/Activity.php
This looks like a simple typo, using camelCase instead of snake case for
the $is_collection_operation variable.

Note:
	However, as it has been undefined, this means it's been treated as
	always false until now, so this may change some behaviour.
2025-05-22 19:03:06 +02:00
Harald Eilertsen
5dcafde617 Fix exclude pattern in phpstan config 2025-05-22 19:03:06 +02:00
Harald Eilertsen
e101e4f511 Minor doxygen config update
- Enable dark mode toggle
- Remove empty footer that broke scrolling
2025-05-22 15:27:35 +02:00
Mario
a5e171a594 Revert "implement thread limit"
This reverts commit be35f612eb.
2025-05-21 11:11:21 +00:00
Mario
be35f612eb implement thread limit 2025-05-21 10:22:37 +00:00
Mario
6d306bc0b3 more return early if we have not got the required data 2025-05-21 09:24:48 +00:00
Mario
813a5b3621 return early if we have not got the required data 2025-05-21 09:23:23 +00:00
Mario
48162fc8d6 fix php warning 2025-05-21 09:13:58 +00:00
Mario
868f9a6b92 bump version 2025-05-20 20:43:10 +00:00
Mario Vavti
e022e59d0a check if function exists - aparently that is not always the case 2025-05-20 22:38:29 +02:00
Mario Vavti
9947f1ec99 add exif to extensions to install 2025-05-20 22:24:25 +02:00
Mario Vavti
6a2748724c guess_image_type(): fix minor issue and add some tests (guessing from getimagesize() and Imagick is not tested) 2025-05-20 22:10:52 +02:00
Mario
457cb74883 Merge branch 'messages-widget-tests' into 'dev'
Add a couple of tests for Widget\Messages

See merge request hubzilla/core!2200
2025-05-20 09:17:05 +00:00
Mario
90b8e08637 since photo_cache images depend on items uese default expire days instead of cache expire days otherwise they might be removed too early (if they have not been removed yet due to cache expire policy) 2025-05-19 22:00:03 +00:00
Mario
572b4a45da fix syntax error 2025-05-19 21:53:49 +00:00
Mario
2e7f806c15 add logging on failure 2025-05-19 21:52:29 +00:00
Mario
4ed8e7b469 refactor guess_image_type() 2025-05-19 21:50:20 +00:00
Harald Eilertsen
1eb3357584 Add a couple of tests for Widget\Messages
Just a couple of basic tests around listing file tags, to make sure the
code runs without any warnings.
2025-05-19 10:24:13 +02:00
Mario
3850cd9641 remove leftover after recent changes 2025-05-19 08:18:47 +00:00
Mario
6f501b37e8 Merge branch 'new-docs' into 'dev'
Replace english docs with pepecyb's docs

See merge request hubzilla/core!2189
2025-05-18 18:42:45 +00:00
Harald Eilertsen
456a741809 Replace english docs with pepecyb's docs 2025-05-18 18:42:45 +00:00
Mario
8a0c9648fe define variable 2025-05-18 16:56:12 +00:00
Mario
4625a8927c Revert "define variable"
This reverts commit a773ca8a24.
2025-05-18 16:55:55 +00:00
Mario
a773ca8a24 define variable 2025-05-18 16:55:20 +00:00
Mario
eb00fe3575 bump version 2025-05-17 18:43:42 +00:00
Mario
1666ca7cb7 actually fix thr_parent arrows 2025-05-17 18:42:42 +00:00
Mario
89aecbbc1c version 2025-05-17 16:21:26 +00:00
Mario
7b8e47b49d revert moving thr_parent retrieval to SQL in favor of a more simple solution (fixes SQL error in postgres and strict mysql) 2025-05-17 16:19:05 +00:00
Mario
cf317aa1a1 revert moving thr_parent retrieval to SQL in favor of a more simple solution (fixes SQL error in postgres and strict mysql)Zotlabs/Lib/ThreadItem.php 2025-05-17 16:18:20 +00:00
Mario
bd1e282499 bump version 2025-05-16 21:03:59 +00:00
Mario
d8a5e8c550 pinned item fixes 2025-05-16 20:43:04 +00:00
Mario
43d0e42425 refactor cache_embeds daemon to be called with uuid (instead of item id) so that it will only be processed once (the queueworker will dismiss duplicates) and add a hook for the photocache addon 2025-05-16 20:22:27 +00:00
Mario
c31b3b6b67 add avif support for php-gd 2025-05-16 07:19:50 +00:00
Mario
18be92ba22 version 2025-05-15 18:58:01 +00:00
Mario
2b38eca986 refactor sql_extra > permission_sql 2025-05-15 18:56:30 +00:00
Mario
4ec895b891 make sure sql_extra is prepared for the c table 2025-05-15 18:40:03 +00:00
Mario
757237cbb4 Revert "make sure sql_extra is prepared for the c table"
This reverts commit 869b047fde.
2025-05-15 18:39:05 +00:00
Mario
869b047fde make sure sql_extra is prepared for the c table 2025-05-15 18:38:42 +00:00
Mario
4bf6752982 implement extra sql for mod channel and display 2025-05-15 16:57:02 +00:00
Mario
5c3f2f9469 first part of cleanups for the conv libs and move thr_parent_uuid retrieval to sql 2025-05-15 12:55:44 +00:00
Mario
6e21be2d94 remove unused var 2025-05-15 11:10:21 +00:00
Mario
3e07eb78fd fix announce source title (addr) not correct 2025-05-15 11:00:18 +00:00
Mario
dceaee691f no need to scroll to toplevels 2025-05-15 07:41:22 +00:00
Mario
7cf380e390 bump version 2025-05-15 07:24:16 +00:00
Mario
9165f766c2 fix offset calculation if element position is relative and use inset box shadow for highlighting items plus some css fixes 2025-05-15 07:23:42 +00:00
Mario
d77d56dfb0 version 2025-05-14 18:54:47 +00:00
Mario
0ae938a4bf another attempt to fix collapsing 2025-05-14 18:54:14 +00:00
Mario
8a0ef4c809 Reapply "fix collapsing"
This reverts commit a3f37e2f1e.
2025-05-14 18:09:46 +00:00
Mario
a3f37e2f1e Revert "fix collapsing"
This reverts commit 948ceb3fac.
2025-05-14 17:57:08 +00:00
Mario
271b9f66ea revert css fixes for messages widget 2025-05-14 16:10:39 +00:00
Mario
4914438479 pinned item template fixes (requires more work) and minor css fixes 2025-05-14 16:07:42 +00:00
Mario
7a01eaa90f version 2025-05-14 11:01:17 +00:00
Mario
948ceb3fac fix collapsing 2025-05-14 11:00:47 +00:00
Mario
d26a3ec22b bump version 2025-05-14 09:41:31 +00:00
Mario
c4a3c7feb7 fix autosave for comments 2025-05-14 09:40:53 +00:00
Mario
6e8481e90e fix notfication issue with update activities 2025-05-14 08:57:47 +00:00
Mario
47d988419f bump version 2025-05-14 08:21:05 +00:00
Mario
a84e6e9747 streamline show more/less handling 2025-05-14 08:19:42 +00:00
Mario
aa9210921d exclude Add/Remove from network nouveau query 2025-05-13 08:49:58 +00:00
Mario
e91f8f3aef bump version 2025-05-13 08:21:20 +00:00
Mario
9b36c39eff remove and deprecate image preload setting - we will now always preload 2025-05-13 08:20:46 +00:00
Mario
a28dd9f2cf remove redundant var 2025-05-13 08:08:27 +00:00
Mario
bf79a2cf4f bump version 2025-05-13 08:05:56 +00:00
Mario
a03ca38409 use box-shadow instead of border to prevent layout moving 2025-05-13 08:05:30 +00:00
Mario
1b246e2ba5 remove redundant item_normal() from item_activity_sql() and use protect_sprintf() on thr_parents 2025-05-13 07:12:20 +00:00
Mario
f905266e4b fix php warning 2025-05-11 19:33:40 +00:00
Mario
e511220022 Merge branch 'remove-direct-access-to-app-observer' into 'dev'
Don't access App::$observer directly in core

See merge request hubzilla/core!2197
2025-05-11 18:08:16 +00:00
Mario
5655807337 fix wrong variable name 2025-05-11 17:56:46 +00:00
Mario
0930539ab4 Merge branch 'lazy' into 'dev'
Implement lazy loading of reactions and sub threads, default to threaded conversation view, some bugfixes and adjusted nomenclature

See merge request hubzilla/core!2198
2025-05-11 17:54:58 +00:00
Mario
b674a1869e undo introduction of new argument in get_template_data(). this can be accomplished more straightforward 2025-05-11 16:01:49 +00:00
Mario
16fafdbbb0 remove redundant query for stored item 2025-05-11 13:39:37 +00:00
Mario
b5acde1420 bump version for merge 2025-05-09 20:34:04 +00:00
Mario
4fa9f30189 cleanup, add some doco an add missing counts of observer event rsvps 2025-05-09 20:24:25 +00:00
Mario
57ae3325e0 allow to switch conv mode per channel 2025-05-09 19:13:49 +00:00
Harald Eilertsen
8141ef9511 Add some API docs for the observer file 2025-05-09 15:23:01 +02:00
Harald Eilertsen
e70870ce4e Move observer helper functions to separate source
The main goal was to move the functions out of the already overcrowded
`boot.php`. While I would ideally have liked to move them properly under
a namespace under `Zotlabs\`, that would break too much existing code at
this point.

Thus leaving it in include and under the global namespace for now.
2025-05-09 15:20:38 +02:00
Harald Eilertsen
7cb8a56b6a Don't access APP:$observer directly in core
Introduce helper functions to access the various fields of the xchan
stored in `App::$observer'. This removes direct access to the attribute
from core, with the aim of allowing further refactoring later.

We can not yet make the `App::$observer` attribute private, though, as
it is also accessed directly by some addons.
2025-05-09 15:15:35 +02:00
Mario
07ca5d54c8 version 2025-05-09 09:43:02 +00:00
Mario
dfde321a3b fix statObj 2025-05-09 09:42:29 +00:00
Mario
aab53c9fc9 provide owner uid for item_normal() in items_by_thr_parent() and set history.pushState when requesting a subthread 2025-05-09 09:35:31 +00:00
Mario
9def0f280f notification fixes 2025-05-09 08:53:47 +00:00
Mario
e71c95a5a5 refactor item_normal() to allow a profile_uid and a prefix as arguments 2025-05-08 12:05:31 +00:00
Mario
1be6c11bad implement moderation of reactions 2025-05-08 11:48:58 +00:00
Mario
030fe8c656 bump version 2025-05-08 10:36:45 +00:00
Mario
8f539e3707 fix announce action label and modal not closing 2025-05-08 10:35:32 +00:00
Mario
918377a67b provide commentable state and minor cleanup 2025-05-08 10:27:57 +00:00
Mario
25e29ec544 fix wrong order of args 2025-05-08 08:39:32 +00:00
Mario
71f80aa4d2 cleanup template 2025-05-07 19:23:21 +00:00
Mario
070d839ad9 version 2025-05-07 19:03:26 +00:00
Mario
ee9b53132e wording, fix comment preview and remove logging 2025-05-07 19:02:53 +00:00
Mario
ca4bb5927e whitespace 2025-05-07 12:36:40 +00:00
Mario
6ed56f9996 sess_data has been changed to mediumtext a while ago via update 2025-05-07 12:33:17 +00:00
Mario
ac5d22d514 refactor doreply() and move reply functionality to modal 2025-05-07 12:31:47 +00:00
Mario
21279b7d4e version 2025-05-06 09:14:17 +00:00
Mario
77c310e393 mark lazy loaded items read and minor cleanup 2025-05-06 09:13:35 +00:00
Mario
c5d75f23e5 fix title and summary converted to bbcode 2025-05-06 06:57:45 +00:00
Mario
a00db63b3e imagesLoaded() can deal with strings 2025-05-06 06:45:58 +00:00
Mario
1d60d38cdc version 2025-05-06 06:41:57 +00:00
Mario
0b42197a99 allow preloading images if dom element is not yet in page 2025-05-06 06:41:26 +00:00
Mario
07da20d00c fix verb and hash for notifications 2025-05-05 07:44:39 +00:00
Mario
d413cf8a30 wrong logic 2025-05-04 20:15:30 +00:00
Mario
1da0ea86f0 more wording 2025-05-04 19:45:57 +00:00
Mario
72f36920ef more on wording 2025-05-04 19:35:14 +00:00
Mario Vavti
7a4d568bfb fix query for postgres 2025-05-04 21:27:41 +02:00
Mario Vavti
0d1c5e26a7 do not add the item-highlight class to any toplevel item 2025-05-04 21:13:36 +02:00
Mario Vavti
ff0a5a0507 mod network fixes 2025-05-04 20:46:49 +02:00
Mario
da780e4e08 this got removed by accident 2025-05-04 16:06:58 +00:00
Mario
0c783773d8 more streamline wording 2025-05-04 15:41:43 +00:00
Mario
5edeb7bd53 remove uuid from mid queries (it is not needed) and slightly alter the query to fetch the parents 2025-05-04 15:40:17 +00:00
Mario
20c8f69efa use profile_uid for mod channel 2025-05-04 13:22:18 +00:00
Mario
b694ed6229 handle blog_mode in conv template 2025-05-04 04:36:12 +00:00
Mario
b4f7daadfb improved blog_mode query 2025-05-03 20:43:26 +00:00
Mario
fb3eae96ab implement blog_mode 2025-05-03 19:04:20 +00:00
Mario
cc91446c18 unseen items: only show announce activities but not the resulting item. also fix a missing operator 2025-05-03 18:03:24 +00:00
Mario
22bda936a5 more streamline wording 2025-05-03 15:58:04 +00:00
Mario
95a2de4da2 Reapply "streamline wording"
This reverts commit ee3fc54be6.
2025-05-03 15:55:13 +00:00
Mario
ee3fc54be6 Revert "streamline wording"
This reverts commit e2c477d775.
2025-05-03 15:52:30 +00:00
Mario
e2c477d775 streamline wording 2025-05-03 15:42:26 +00:00
Mario
6ddd31bfba bump version 2025-05-03 09:42:08 +00:00
Mario
3653f769d9 fix notification button for medium screen size (right aside collapsed) 2025-05-03 09:41:41 +00:00
Mario
261f0e4120 default ordering to created 2025-05-03 09:06:15 +00:00
Mario
6fce724f69 yet another refactor to cover unseen pubstream notifications 2025-05-03 08:32:01 +00:00
Mario
dedab1ad4f this performs way better 2025-05-02 16:48:34 +00:00
Mario
cf1a404945 bump version 2025-05-02 16:24:54 +00:00
Mario
ac4af6f9ef Ãfix marking read of reactions 2025-05-02 16:02:47 +00:00
Mario
69ade6d2cb cleanup 2025-05-02 14:03:45 +00:00
Mario
6db5236bf5 provide thr_parent uuid in the item array and make use of it in various places 2025-05-02 13:58:01 +00:00
Mario
b39fb945f5 move look up of thr_parents to separate function and minor fixes 2025-05-02 13:24:58 +00:00
Mario
3fcd5a0f0f fix display issue 2025-05-02 07:52:41 +00:00
Mario
62635aa803 version 2025-05-01 10:52:32 +00:00
Mario
32717d910c add counts for rsvp activities and some visual shenenigans 2025-05-01 10:52:15 +00:00
Mario
881f540e43 some visual changes 2025-04-30 19:31:31 +00:00
Mario
e5cd6330b3 default to threaded 2025-04-30 14:42:09 +00:00
Mario
e91021f648 rename wrapper class 2025-04-30 09:06:01 +00:00
Mario
1463c1a526 refactor 2025-04-30 08:28:47 +00:00
Mario
e195897dc7 slightly change the way we deal with perms 2025-04-29 21:18:53 +00:00
Mario
b6f0fe7583 refactor with permissions 2025-04-29 09:52:30 +00:00
Mario Vavti
377fe32795 add branch to version string 2025-04-26 22:41:35 +02:00
Mario Vavti
73d444bd8a some refactoring and implement subthread fetching 2025-04-26 22:33:32 +02:00
Mario Vavti
80415f6bd3 remove unused code 2025-04-26 14:33:45 +02:00
Mario Vavti
7ab531025c streamline sql functions 2025-04-26 12:19:04 +02:00
Mario Vavti
763a4f1fbb implement observer activity visibility 2025-04-26 10:46:48 +02:00
Mario Vavti
cde558a43f also remove the parent line from the query 2025-04-25 23:47:04 +02:00
Mario Vavti
bafbbc9d5b revert adding of id - we can not use it 2025-04-25 23:22:06 +02:00
Mario Vavti
ad4eec1145 kind of fix the like response 2025-04-25 23:02:28 +02:00
Mario Vavti
0584094f05 use normal size modal 2025-04-25 22:36:27 +02:00
Mario Vavti
c614f899b7 implement requesting of reactions 2025-04-25 22:35:13 +02:00
Mario Vavti
0940be57fd should compare against item.mid 2025-04-25 16:47:15 +02:00
Mario Vavti
7e148c1e30 the c table must also include item_normal() 2025-04-25 16:16:37 +02:00
Mario
babc3df364 this should not be required anymore 2025-04-25 12:53:47 +00:00
Mario
ba9637e129 lazy load - initial commit 2025-04-25 12:46:30 +00:00
Mario Vavti
a48a72d1cd use a separator 2025-04-24 10:05:00 +02:00
Mario Vavti
1edea291a4 we have update an existing result - do not create another result set for this action 2025-04-24 09:58:37 +02:00
Mario
b7ef3fab3c dreport: do not store dismissed create activities 2025-04-24 07:09:29 +00:00
Mario
afe31160db mod item: deprecate x() and use $_POST instead of $_REQUEST 2025-04-24 06:41:43 +00:00
Mario
4849d50610 add some styling to dreport 2025-04-23 20:17:02 +00:00
Mario
d5f7b620c4 fix regex to catch codeblocks with params like class etc 2025-04-23 19:37:57 +00:00
Mario
6515443957 more deprecate x() 2025-04-23 19:09:12 +00:00
Mario
8b352e4c64 more deprecate x() 2025-04-23 18:41:26 +00:00
Mario
7c59dd9fd7 more deprecate x() 2025-04-23 18:17:23 +00:00
Mario
118a223ee1 fix term.imgurl not stored in item_store_update() 2025-04-23 09:10:58 +00:00
Mario
481113f641 set $plink to null if not provided 2025-04-22 09:30:35 +00:00
Mario
bed929c966 define variable 2025-04-21 19:33:46 +00:00
Mario
10345a5418 more php warnings 2025-04-21 19:28:44 +00:00
Mario
efc9581798 comment out localize_item() in Enotify::submit() and fix some PHP warnings 2025-04-21 19:18:37 +00:00
Mario
005b9919d0 x() to !empty() 2025-04-21 17:25:20 +00:00
Mario
86e88c6bb0 also continue if we have not got a filepath for some reasonà 2025-04-21 15:27:55 +00:00
Mario
7505f7039a define variable 2025-04-21 11:52:34 +00:00
Mario
5a52b6afea define variable 2025-04-21 11:42:24 +00:00
Mario
86f8d8ecdf fix php warnings 2025-04-21 11:39:35 +00:00
Mario
81559e9bcf fix php warnings 2025-04-21 11:30:42 +00:00
Mario
1b458c7d65 missing include 2025-04-21 10:15:51 +00:00
Mario
d2177f27f9 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2025-04-21 10:09:54 +00:00
Mario
da6db54122 some cleanup for boot.php 2025-04-21 10:09:33 +00:00
Mario Vavti
1e41c83b35 fix test 2025-04-20 21:43:32 +02:00
Mario
8bc079aa3d cleanup Web/Router 2025-04-20 19:23:54 +00:00
Mario
a5a58d73ff cleanup Lib/WebServer 2025-04-20 18:42:26 +00:00
Mario
68967e93d6 wrong class 2025-04-20 16:16:15 +00:00
Mario Vavti
88f1a7d652 whitespace 2025-04-20 18:11:12 +02:00
Mario Vavti
21c2fabae0 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2025-04-20 18:06:03 +02:00
Mario Vavti
a36afc0bb7 rawurlencode the cloud paths - issue #1903 (second part) 2025-04-20 18:04:59 +02:00
Mario Vavti
7855aaf53c set App::$query_string from from server.request_uri instead of server.query_string because the latter will mostly be urldecoded by the server already - issue #1903 (first part) 2025-04-20 18:04:03 +02:00
Mario Vavti
6535475a99 add some padding for breadcrumb 2025-04-20 17:59:40 +02:00
Mario
ddaaac1103 Merge branch 'debian_install_20250415' into 'dev'
debian install script

See merge request hubzilla/core!2196
2025-04-19 05:45:17 +00:00
Mario
295266cb10 Merge branch 'refactor-language-selector' into 'dev'
Move lang_selector function to Lang module and refactor

See merge request hubzilla/core!2195
2025-04-19 05:43:26 +00:00
Harald Eilertsen
e800d176fb Move lang_selector function to Lang module and refactor 2025-04-19 05:43:25 +00:00
Mario Vavti
cace4c6c65 strtotime() accounts with the timezone - set it to UTC for the stored timestamp 2025-04-18 22:38:45 +02:00
Mario Vavti
d7aff9a4dd fix wrong logic 2025-04-18 21:19:38 +02:00
Mario Vavti
a4a7794315 implement until= in message filter 2025-04-18 21:00:33 +02:00
Mario Vavti
c1d87fa65d more doco 2025-04-18 10:27:13 +02:00
Mario Vavti
e69763f86d add more message filter tests 2025-04-18 10:21:16 +02:00
Mario Vavti
5db5a5cfe9 fixes and more test samples 2025-04-17 14:29:27 +02:00
Mario Vavti
24f71dfcf8 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2025-04-17 11:35:24 +02:00
Mario Vavti
6d62acb446 extend MessageFilter::test_condition() to deal with && and || conditions and add tests 2025-04-17 11:35:06 +02:00
Mario
32ab6344c4 use mb_strlen() instead of strlen() 2025-04-16 18:51:59 +00:00
Mario
60b4c003af $_REQUEST > $_POST 2025-04-16 11:07:03 +00:00
Mario
4c962417ff pÃrevent storing files/folder with filenames exceeding their max name length 2025-04-16 11:03:08 +00:00
Mario
d2aad8a41a stephenhill/base58 seems not maintained anymore and throws a deprecation warning - fix here for now 2025-04-16 08:36:10 +00:00
Mario
fd0f6d4fa8 check if the uuid is mapped before using it 2025-04-16 08:15:30 +00:00
Mario
87d68b175e fix undefined variable warning 2025-04-16 08:08:02 +00:00
Mario
64652c1d6e fix variable name 2025-04-16 07:51:22 +00:00
Mario
9342a92682 deal with link type attachments 2025-04-16 07:44:40 +00:00
Mario
443c5495e9 do not translate network to stream 2025-04-16 07:44:12 +00:00
OJ Randon
80f3892ba0 check if update script for selfHOST was downloaded 2025-04-15 17:39:14 +02:00
OJ Randon
16ee954048 use wget to download composer and checksum 2025-04-15 17:36:47 +02:00
OJ Randon
4e367e1e67 Merge remote-tracking branch 'official/dev' into fix_debianinstall 2025-04-15 17:31:28 +02:00
Mario
7f7763ee0c remove redundant var declaration 2025-04-15 14:38:28 +00:00
Mario
868a8ccfd9 fix more php warnings 2025-04-15 14:37:38 +00:00
Mario
b7b1a5574f fix more php warnings 2025-04-15 14:28:42 +00:00
Mario
aa0c8973fa fix more php warnings 2025-04-15 14:25:48 +00:00
Mario
f6b91f97bf this should be info instead of notice 2025-04-15 14:21:20 +00:00
Mario
d82e7c9f6c fix php warning 2025-04-15 14:20:27 +00:00
Mario
083b2b1bbc add suport for strong bbcode tag 2025-04-15 09:10:45 +00:00
Mario
805bbd1c3e fix color bbcode markup 2025-04-15 09:03:32 +00:00
Mario
077ca1aea5 change photo.filename to type text (some platforms have very long filenames for their profile photos) 2025-04-15 08:41:10 +00:00
Mario
1217ae3b3e remove it 2025-04-15 08:05:22 +00:00
Mario
17777981ac this should not be required because it only affects likes which are already handled before (reaction) 2025-04-15 07:43:11 +00:00
Mario
ddc4bdcebe set default value and add comment 2025-04-14 16:41:39 +00:00
Mario Vavti
126c7f9d62 improved tests 2025-04-14 17:35:35 +02:00
Mario
75d1be092e default to null 2025-04-14 14:34:21 +00:00
Mario Vavti
0d51ff1906 add test for Activity::getUUID() and Avtivity::getMessageID() methods 2025-04-14 13:23:49 +02:00
Mario
679b5098da provide methods to get mid and uuid from activity object, add quirks to retrieve markdown content 2025-04-14 09:24:20 +00:00
Mario
224b32e767 remove borders from some buttons 2025-04-14 07:25:08 +00:00
Mario
1f943474cb boxy: up padding left also for the itrm tools 2025-04-13 18:49:38 +00:00
Mario
6891db1b23 boxy: minor css fix 2025-04-13 13:55:11 +00:00
Mario
a19951528d minor css fix 2025-04-13 09:16:03 +00:00
Mario
a4ea4ecc3b video poster requires a single quote 2025-04-11 20:03:01 +00:00
Mario Vavti
8c182c9d68 version 10.2.3 2025-04-11 21:30:03 +02:00
Mario
384eea79dc changelog
(cherry picked from commit 6068c0e8c2)

Co-authored-by: Mario <mario@mariovavti.com>
2025-04-11 19:28:46 +00:00
Mario
c2a09434ca Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2025-04-11 19:28:01 +00:00
Mario
6068c0e8c2 changelog 2025-04-11 19:27:28 +00:00
Mario Vavti
f8bc755c20 fix bougus merge to master 2025-04-11 21:13:40 +02:00
Mario
fd86ccb4eb Merge branch 'increase-memory-limit-for-ci' into 'dev'
CI: Up the memory limit to allow for coverage reporting

See merge request hubzilla/core!2194
2025-04-11 09:38:16 +00:00
Mario
c36d159997 Merge branch 'fix_debianinstall' into 'dev'
Fix debianinstall

See merge request hubzilla/core!2192
2025-04-11 09:37:29 +00:00
OJ Random
efd61cb43a Fix debianinstall 2025-04-11 09:37:29 +00:00
Mario Vavti
aa38e8360a version 10.2.2 2025-04-11 10:45:43 +02:00
Mario
fdf6680b29 changelog
(cherry picked from commit b79c19c66d)

Co-authored-by: Mario <mario@mariovavti.com>
2025-04-11 08:44:37 +00:00
Mario
b79c19c66d changelog 2025-04-11 08:36:28 +00:00
Mario
8999a96ef0 cleanup deprecated forum queries and possibly improved performance 2025-04-11 10:23:46 +02:00
Mario
b5d2236a58 do not return success if Libzot::fetch() did not return anything useful and remove redundant parameter $hub
(cherry picked from commit 3550609d29)

Co-authored-by: Mario <mario@mariovavti.com>
2025-04-11 07:48:28 +00:00
Mario
91e59d3c4f make sure we have an encoded activity before we go on building the packet, do not json_encode() a possibly empty item.target
(cherry picked from commit fe8ae2f88e)

Co-authored-by: Mario <mario@mariovavti.com>
2025-04-11 07:45:24 +00:00
Mario
a6ff444e19 fix some plink for forum posts and comments
(cherry picked from commit a5a2d80c50)

Co-authored-by: Mario <mario@mariovavti.com>
2025-04-11 07:42:50 +00:00
Harald Eilertsen
ee4cc51a05 CI: Up the memory limit to allow for coverage reporting 2025-04-10 21:45:22 +02:00
Mario
29d4edb285 fix an obscure delivering issue which incidentally also fixes a delivering issue that required an ugly hack to work around
(cherry picked from commit 7c79ec9626)

Co-authored-by: Mario <mario@mariovavti.com>
2025-04-10 13:04:41 +00:00
Mario
7c79ec9626 fix an obscure delivering issue which incidentally also fixes a delivering issue that required an ugly hack to work around 2025-04-10 13:03:11 +00:00
Mario
66f793cb83 more fix downstream test for an upstream bug 2025-04-09 16:07:00 +00:00
Mario
6d926f4271 fix downstream test for an upstream bug 2025-04-09 15:47:21 +00:00
Mario Vavti
6ffd3fd9d4 composer update chillerlan/php-qrcode 2025-04-09 15:54:58 +02:00
Mario Vavti
3d204c782b --no-dev! 2025-04-09 15:47:23 +02:00
Mario Vavti
20f8239b44 composer update commerceguys/intl 2025-04-09 15:41:01 +02:00
Mario Vavti
10c2bd83d3 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2025-04-09 14:22:23 +02:00
Mario Vavti
4b02bd60cb composer update libs 2025-04-09 14:19:48 +02:00
Mario
50ea3afcb0 re-add red-koala.png which has been removed by accident 2025-04-09 10:43:57 +00:00
Mario
982d7540cc wrong ticks 2025-04-09 10:29:23 +00:00
Mario
b9aec78dde rename README > README.md 2025-04-09 10:26:00 +00:00
Mario
f5b1fda6b7 reorganize emojis and allow custom site emojis 2025-04-09 10:21:01 +00:00
Mario
4dfdb2b2e1 bump item.obj and item.target to mediumtext for mysql 2025-04-05 18:48:07 +00:00
Mario
a5a2d80c50 fix some plink for forum posts and comments 2025-04-05 15:55:58 +00:00
Mario
8da7fe8dbe whitespace 2025-04-04 15:44:04 +00:00
Mario
f64c5977f8 move weblink to after embedPhotos 2025-04-04 15:42:17 +00:00
Mario
a16e024b51 cleanup 2025-04-04 15:34:55 +00:00
Mario
860de5e28e bump version 2025-04-04 15:22:46 +00:00
Mario
b38da72535 move jot related functions to jot-header and some cleanup 2025-04-04 15:22:09 +00:00
Mario
2c4f1dcf03 use the syntax which allows image descriptions 2025-04-04 15:20:57 +00:00
Mario
0a1255518f bump version 2025-04-04 10:56:01 +00:00
Mario
a822e94f9b move jot popup handling to template, port photo selector to vanilla javascript and enable it for comments if applicable 2025-04-04 10:51:51 +00:00
Mario
484971c90a use png for hubzilla emoji 2025-04-04 07:15:23 +00:00
Mario
e11035acf4 optimize svg 2025-04-03 18:17:25 +00:00
Mario
3d522b99d8 add hubzilla emoji, make sure the compared term type is an integer 2025-04-03 18:12:23 +00:00
Mario
e62c4e6088 some emoji type tags do not have an id, we will use icon.url instead in those cases 2025-04-03 17:15:22 +00:00
Mario
703ccc2a9a this is required e.g. when relaying emoji reactions otherwise the relevant data will be missing 2025-04-03 12:01:11 +00:00
Mario
b2d09134c1 more smilies() fixes 2025-04-03 11:58:13 +00:00
Mario
de3f491966 make sure object actor is an array if we are going to use it 2025-04-03 11:57:25 +00:00
Mario
322a021765 for consistency use just the name as short name 2025-04-03 10:01:09 +00:00
Mario
d191b66bb8 move custom emoji rendering to smilies() 2025-04-03 09:55:59 +00:00
Mario
5241a159d2 bump version 2025-04-02 10:53:50 +00:00
Mario
fe8ae2f88e make sure we have an encoded activity before we go on building the packet, do not json_encode() a possibly empty item.target 2025-04-02 10:53:13 +00:00
Mario
3550609d29 do not return success if Libzot::fetch() did not return anything useful and remove redundant parameter $hub 2025-04-02 10:49:38 +00:00
OJ Randon
c6df3b0b97 fix stop of mysql 2025-04-02 11:38:22 +02:00
OJ Randon
e6ca21965b check if updates work 2025-04-01 13:39:41 +02:00
OJ Randon
c44c522d7d wording and confirmation that Raspi 5 is working 2025-04-01 01:10:16 +02:00
OJ Randon
f48bf8e366 fix certbot installation 2025-04-01 00:45:59 +02:00
OJ Randon
6e1cdebbf4 use https for selfhost updater (dyn dns) 2025-04-01 00:45:10 +02:00
Mario
eb592bb741 bump version 2025-03-28 20:49:27 +00:00
Mario
db5d67a4e0 cleanup deprecated forum queries and possibly improved performance 2025-03-28 20:46:17 +00:00
Mario
6e390a06e1 remove deprecated emojiReaction 2025-03-28 20:43:08 +00:00
Mario
295d5f06dc lazy load profile images for likes and remove zid function for the profile image src attribute
(cherry picked from commit 30d552255e)

Co-authored-by: Mario <mario@mariovavti.com>
2025-03-28 13:31:47 +00:00
Mario
30d552255e lazy load profile images for likes and remove zid function for the profile image src attribute 2025-03-28 13:29:43 +00:00
Mario
0522bd5593 include unapproved connections in deliverable_abook_xchans(). here is why: if they are at a hub, where an approved connection already exists, they will already receive the message since our defaultult permission allows view_stream. If view_stream is not allowed they will be filtered later in the process. We will however exclude blocked connections (approved or unapproved) already here now. 2025-03-27 12:43:53 +00:00
Mario
a46d837267 minor cleanup 2025-03-27 10:31:07 +00:00
Mario
bee493f628 remove redundant variables and use document.body.clientWidth instead of rounded window.innerWidth 2025-03-26 11:20:11 +00:00
Mario
a4f4a082af fix another js error on small screens and use const instead of let where applicable 2025-03-25 10:38:00 +00:00
Mario
dd9ab07044 restrict access to tool to local channels 2025-03-24 09:11:26 +00:00
Mario
afd811a875 more deprercate jquery 2025-03-23 14:14:19 +00:00
Mario Vavti
122d46b79b use the new version of unparse_url() and fall through to destination if nothing before applied - otherwise remote redirects will fail (e.g. being logged in to a remote server and vewing a linked image with an attached zid at another server) 2025-03-22 18:18:55 +01:00
Mario
36448adad4 minor refactor 2025-03-21 16:58:27 +00:00
Mario
8f93d9aa75 do not check length, it will not be there if the var is null 2025-03-21 11:33:56 +00:00
Mario
76f50d7150 fix some js errors on mobile devices 2025-03-21 11:30:40 +00:00
Mario
80c9880a67 do not include our own activities in unseen forum notifications 2025-03-20 13:39:32 +00:00
Mario
d1f54507f6 Disable browser rotating image based on EXIF metadata. We remove EXIF data for thumbnails but not for the original files. If the preview image has different orientation than the original size it has a strange effect when viewing. 2025-03-20 13:12:45 +00:00
Mario
334852d733 bump version 2025-03-18 08:15:30 +00:00
Mario
362be52be0 version 10.2.1 2025-03-18 08:10:15 +00:00
Mario
20f5e654ad changelog
(cherry picked from commit 34b2bdcf2c)

Co-authored-by: Mario <mario@mariovavti.com>
2025-03-18 08:09:03 +00:00
Mario
34b2bdcf2c changelog 2025-03-18 08:08:14 +00:00
Mario
8c38ee8208 fix sse_bs query 2025-03-18 08:00:37 +00:00
Mario
2c1c12825d we require the HTTP signature to be set in the HTTP_AUTHORIZATION field somewhere down the line (probably in Web/HTTPSig). Make sure it is there.
(cherry picked from commit 5188b9cef5)

Co-authored-by: Mario <mario@mariovavti.com>
2025-03-18 07:58:14 +00:00
Mario
5188b9cef5 we require the HTTP signature to be set in the HTTP_AUTHORIZATION field somewhere down the line (probably in Web/HTTPSig). Make sure it is there. 2025-03-18 07:52:39 +00:00
Mario
8c0b7ce4de Merge branch 'help_davs' into 'dev'
access cloud files under linux using davs

See merge request hubzilla/core!2190
2025-03-17 20:02:25 +00:00
Mario
17d0d6f75d Merge branch 'dedup-head_get_icon' into 'dev'
Remove duped head_get_icon function

See merge request hubzilla/core!2191
2025-03-17 20:00:58 +00:00
Mario
bbcf7e9aa1 Merge branch '10.2RC' 2025-03-17 19:39:51 +00:00
Mario
45a2ebc662 version 10.2 2025-03-17 19:33:32 +00:00
Mario
aece22aee6 Merge branch 'dev' into 10.2RC 2025-03-17 19:32:36 +00:00
Mario
9904eba277 update changelog 2025-03-17 19:32:10 +00:00
Mario
7c0f98a513 Merge branch 'dev' into 10.2RC 2025-03-17 19:30:39 +00:00
Mario
8d25b6eae4 changelog 2025-03-17 19:23:30 +00:00
Mario
9369085835 Merge branch 'dev' into 10.2RC 2025-03-17 19:20:55 +00:00
Harald Eilertsen
059113d2a8 Remove duped head_get_icon function
This function was existing both as a static function in the App class,
and as a standalone global function. While only the standalone function
was used, this patch changes the callsite to use the static function in
the App class instead, and removed the global variant.

Note: While unlikely, this _could_ break some addons or custom themes
_if_ they call the global head_get_icon function themselves. I have not
found any addons or themes that do so.

This patch also fixes an issue where an incorrect url would be produced
if the URL set by App::head_set_icon would start with '://' for some
reason.

Also added doc comments for both App::head_set_icon and
App::head_get_icon.
2025-03-17 20:17:54 +01:00
OJ Random
f60dff788e access cloud files under linux using davs 2025-03-17 19:03:19 +01:00
Mario
9c20b4809a an attempt to fix no notifications for likes on our comments - beause it came up in the support forum. also some minor cleanup 2025-03-17 08:57:15 +00:00
Mario
00b3039b6e Merge branch 'dev' into 10.2RC 2025-03-16 11:16:31 +00:00
Mario
2695094d16 fix fullscreen view 2025-03-16 11:16:04 +00:00
Mario
bcfdb73001 Merge branch 'dev' into 10.2RC 2025-03-14 10:52:17 +00:00
Mario
1650809cd8 update changelog 2025-03-14 10:51:40 +00:00
Mario
991815469f Merge branch 'dev' into 10.2RC 2025-03-14 10:49:50 +00:00
Mario
c5fb8eafac allow to send signed requests from mod zot_probe 2025-03-12 19:15:28 +00:00
Mario
a0c98e070e Merge branch 'dev' into 10.2RC 2025-03-09 16:14:46 +00:00
Mario
7d6202be13 wrong logic 2025-03-09 16:13:47 +00:00
Mario
4ba470318c Merge branch 'dev' into 10.2RC 2025-03-09 10:09:47 +00:00
Mario
e948aaf751 changelog 2025-03-09 10:06:53 +00:00
Mario
3789017ca0 print an ugly error message and the destination if OWA failed for some reason 2025-03-09 10:03:07 +00:00
Mario
48f5acced3 remove leading @ 2025-03-09 10:00:53 +00:00
Mario
13e2d2f654 css fix
(cherry picked from commit 8d45fd36a1)

Co-authored-by: Mario <mario@mariovavti.com>
2025-03-07 09:02:29 +00:00
Mario
8d45fd36a1 css fix 2025-03-07 09:01:48 +00:00
Mario
6ed2301a94 bump version 2025-03-07 08:54:59 +00:00
Mario
a0eb701503 Merge branch 'dev' into 10.2RC 2025-03-07 08:54:06 +00:00
Mario
39f9a38b23 css fix 2025-03-07 08:51:26 +00:00
Mario
590c0ea778 add pdl file for mod rmagic 2025-03-07 08:43:17 +00:00
Mario
f36d8e4bd2 fix fatal error if variable is an empty string 2025-03-07 08:38:33 +00:00
Mario
4e3bec8a35 streamline login pages layout - fix issue #1892 2025-03-07 08:30:43 +00:00
Mario
eec918bf4a escape tags on xchan name and cleanup baseurl/site_url variables which should be the same 2025-03-06 11:42:25 +00:00
Mario
13002af4c3 version 10.2RC1 2025-03-06 10:00:21 +00:00
Mario
40c63a7f12 changelog 2025-03-06 09:57:49 +00:00
Mario
3d0621eb8c remove superfluous file 2025-03-06 09:17:55 +00:00
Mario
030c02dfdc boxy alignment 2025-03-05 17:03:31 +00:00
Mario
00c1509549 update string to match with the autotime string 2025-03-05 16:42:25 +00:00
Mario
8122c40252 bump dev version 2025-03-05 10:22:46 +00:00
Mario
787c63b7ae version 10.2RC and strings 2025-03-05 10:17:39 +00:00
Mario
ee988edc83 make sure attachment is an array
(cherry picked from commit 2b4b409c01)

Co-authored-by: Mario <mario@mariovavti.com>
2025-03-03 08:56:30 +00:00
Mario
a71f5e123a Debianinstall
(cherry picked from commit cf408c3fac)

34e867cf provide a simplified automated installation as we had years ago
266df96c a) php version for max uplaod sizes b) hubzilla is the only option
c4d340d1 fixed installation of addons
b80a8a01 added composer
f1961884 composer: do not download again but install in any case
96710d83 help: default database name and user
ecf35537 fix composer
2d2bf751 main differences to homeinstall script
dcca3cab changed disclaimer
6c65c17f removed set path to convert because it does not have to be changed
ed77bfb5 email verification
93f85913 environments
00dd3bdd Debian 12 again
10223ef7 extra headings
f528a959 wording
18565bb2 sury instead of Debian repo
bc07f0c4 Merge remote-tracking branch 'origin/dev' into dev
38743496 fixed php install and db creation
d08bb5e6 fixed variable for creating db
b1cc4f4f do not care about more then one single webserver installed
8b0ec26a Merge branch core:master into dev
88e3522d Merge branch 'debianinstall' into dev

Co-authored-by: OJ Random <ojrandom@protonmail.com>
2025-03-03 08:41:11 +00:00
Mario
7579749adc Merge branch 'debianinstall' into 'master'
Debianinstall

See merge request hubzilla/core!2179
2025-03-03 08:40:29 +00:00
OJ Random
cf408c3fac Debianinstall 2025-03-03 08:40:29 +00:00
Mario
0c97792ca7 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2025-02-28 20:29:08 +00:00
Mario
84d63b3b67 fix $owner_hash not set correctly when editing and some whitespace fixes 2025-02-28 20:28:49 +00:00
Mario Vavti
63aa50eb8d Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2025-02-26 16:37:38 +01:00
Mario Vavti
7fb13f23fe fix docu 2025-02-26 16:37:22 +01:00
Mario
65156a0e4d Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2025-02-26 15:33:05 +00:00
Mario
e3eebcd95d calculate observer.baseurl from xchan_url since xchan_connurl is only set for zot xchans 2025-02-26 15:32:36 +00:00
Mario Vavti
9eff1a08d4 refactor unparse_url() to allow to return a custom field set only and add tests 2025-02-26 16:26:40 +01:00
Mario
cfcac590c3 refine text 2025-02-26 12:57:38 +00:00
Mario
872415bffe fix an issue where some participants could not post to forums 2025-02-26 12:52:27 +00:00
Mario
a46b781664 slightly improve event object rendering 2025-02-22 14:43:25 +00:00
Mario
b77fac43c8 feedutils: fix php warnings and style 2025-02-21 09:51:59 +00:00
Mario
2b4b409c01 make sure attachment is an array 2025-02-20 11:27:46 +00:00
Mario
67aa547c48 bump version 2025-02-20 11:09:57 +00:00
Mario Vavti
e288f33776 looks like we now require vendor/symfony for production 2025-02-20 12:05:50 +01:00
Mario Vavti
a5aab4c30e Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2025-02-20 11:44:54 +01:00
Mario Vavti
cf7613b3e0 composer --no-dev 2025-02-20 11:44:00 +01:00
Mario
fa01a2b348 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2025-02-20 10:36:58 +00:00
Mario Vavti
65c8de3410 update to smarty v5 2025-02-20 11:35:33 +01:00
Mario Vavti
d9b262348f update composer libs 2025-02-20 11:29:06 +01:00
Mario
ea9d2a0acf prefer contextHistory over context 2025-02-19 09:46:52 +00:00
Mario
5d55006be8 Merge branch 'replace-epub-thumbnail-code' into 'dev'
Replace Epub thumbnail generation with our own code

See merge request hubzilla/core!2186
2025-02-14 15:06:25 +00:00
Mario
d9ced0c6bf Merge branch 'update-gitignore' into 'dev'
Exclude test results and PHPStan from git

See merge request hubzilla/core!2188
2025-02-14 14:58:26 +00:00
Mario
8d4d1b17c7 Merge branch 'cherry-pick-10e2fbb2' into 'dev'
Update Spanish strings

See merge request hubzilla/core!2187
2025-02-14 14:58:07 +00:00
Mario
453f6a08a3 Merge branch 'highlight_mark_button3' into 'dev'
Highlight_mark_button3

See merge request hubzilla/core!2185
2025-02-14 14:56:17 +00:00
Rocky
b6560e5456 Highlight_mark_button3 2025-02-14 14:56:17 +00:00
Mario
b805f48c32 revert adding of additional sort field which was added for testingg 2025-02-13 18:57:43 +00:00
Harald Eilertsen
33b78a4943 Exclude test results and PHPStan from git 2025-02-13 16:02:35 +01:00
Manuel Jiménez Friaza
48b187ccd8 Update Spanish strings
(cherry picked from commit 10e2fbb22c6369c9ef6cbc6f943ff6878206e9fb)

Co-authored-by: mjfriaza:4GF~eYj,-iAv <mjfriaza@disroot.org>
2025-02-13 14:11:13 +00:00
Mario
f680bba3e6 select navbar by id to avoid conflict with possible additional navbars 2025-02-13 10:18:12 +00:00
Harald Eilertsen
09aabc6b41 Remove dependency on PHP EpubMeta library. 2025-02-12 20:05:42 +01:00
Harald Eilertsen
0dd456c653 Replace the the code to extract epub thumbnails
The PHP Epub Meta library has a dependency that prevents deployment on
32bit architectures. We also don't need all the functionality in that
library, so this patch replaces it with our own simplified code for
fetching the cover embedded in Epub archives.

We also expand the test suite and clean up some minor issues in the
Epubthumbnail class.
2025-02-12 20:05:42 +01:00
Harald Eilertsen
97ba14cbe0 Configue gd for jpeg support in CI
For some reason the gd build did not find libjpeg, even though it was
installed in the image. We will need jpeg support for testing the
thumbnail generation, so this patch adds the required configuration.
2025-02-12 20:01:45 +01:00
Mario Vavti
ee6367a549 bump version 2025-02-11 19:15:15 +01:00
Mario Vavti
fc52d1b44f exclude uplinked items from those queries since they are unlikely to be the originals (sourced items from a channel at the same hub) 2025-02-11 19:14:11 +01:00
Mario Vavti
bfce562a46 start sending contextHistory along with context 2025-02-11 17:52:26 +01:00
Mario Vavti
8d8a7f44e1 bump version 2025-02-01 12:36:54 +01:00
Mario Vavti
6c8da6ce36 version 10.0.8 2025-02-01 12:30:15 +01:00
Mario
e19a050b92 changelog
(cherry picked from commit a13bf6a3fe)

Co-authored-by: Mario Vavti <mario@mariovavti.com>
2025-02-01 11:28:04 +00:00
Mario Vavti
a13bf6a3fe changelog 2025-02-01 12:26:49 +01:00
Mario
0edf761499 Merge branch 'owa-error-messages' into 'dev'
Add error message on missing owa auth headers

See merge request hubzilla/core!2183
2025-02-01 10:53:12 +00:00
Mario
bf76d5981f Merge branch 'testing-add-psr4-namespace' into 'dev'
Add Zotlabs\Tests namespace to autloader in dev

See merge request hubzilla/core!2182
2025-02-01 10:50:44 +00:00
Mario
33fcb43173 Merge branch 'dba_pdo-insert-and-update' into 'dev'
Add an insert and update methods to dba_pdo

See merge request hubzilla/core!2181
2025-02-01 10:49:47 +00:00
Mario
ffae47f523 Merge branch 'highlight_button' into 'dev'
add highlight/mark button

See merge request hubzilla/core!2180
2025-02-01 10:35:03 +00:00
Rocky
c07cdb30fa add highlight/mark button 2025-02-01 10:35:03 +00:00
Mario
546c4fcad2 calling fetch_post_tags() will add duplicate items here
(cherry picked from commit 0a17b83578)

Co-authored-by: Mario Vavti <mario@mariovavti.com>
2025-02-01 00:03:50 +00:00
Mario Vavti
0a17b83578 calling fetch_post_tags() will add duplicate items here 2025-02-01 01:02:06 +01:00
Mario
2782b6d724 possible sql performance improvements
(cherry picked from commit dc076a4c00)

Co-authored-by: Mario Vavti <mario@mariovavti.com>
2025-01-30 12:10:45 +00:00
Mario Vavti
dc076a4c00 possible sql performance improvements 2025-01-30 13:09:04 +01:00
Harald Eilertsen
a550c7c853 Add error message on missing owa auth headers
If the /owa endpoint received a request with a missing or invalid
Authorization header, it would return an error to the requester, but
without any message describing why it failes.

This patch adds a message to the error response, so that it will be a
bit easier to debug these issues in the future.

The owa spec includes a 'message' field in the error response, but makes
it optional. Any conforming implementations should accept a response
that includes the 'message' field.
2025-01-29 18:41:40 +01:00
Harald Eilertsen
7a3d59bff3 Add Zotlabs\Tests namespace to autloader in dev
This is technically not needed, as we load the required classes in the
bootstrap file (`tests/unit/bootstrap.php`), but it helps editors that
integrate with language servers etc to find the classes so it does not
flag errors everywhere.
2025-01-29 15:56:17 +01:00
Harald Eilertsen
82a3b71a51 Fix broken DbaPdo test on postgresql 2025-01-29 13:24:12 +01:00
Harald Eilertsen
e39b2eb7b9 Add an dba_pdo::update method
This is a convenience funcition to make it easier to update an existing
row in a database table.
2025-01-29 12:42:44 +01:00
Harald Eilertsen
9f8248cc9c Use returning clause on dba_pdo::insert where supported
By using the returning clause when inserting a new record, we get back
the inserted record right away; thus saving us an extra roundtrip to the
database.

Both PostgreSQL and MariaDB supports this clause, but MySQL don't. In
that case we fall back to manually fetching the last inserted row.
2025-01-29 12:42:44 +01:00
Harald Eilertsen
71e4326606 Fetch the server version on dba_pdo::connect.
The server version string is useful to among other things check whether
we are running on a real MySQL system, or MariaDB. Instead of fetching
it every time we need it, cache it in the dba_pdo object when we connect
to the db.
2025-01-29 12:42:44 +01:00
Harald Eilertsen
7eb6f9b11d Only skip DbaPdo returning test on actual MySQL
MySQL does not support the INSERT...RETURNING clause, while MariaDB
does. This patch ensures that the test is not skipped on MariaDB, but
only on an actual MySQL system.
2025-01-29 12:42:44 +01:00
Harald Eilertsen
4625ffa6b4 Fix return value from dba_pdo::q()
According to the documentation, this function should never return null.
Still that's what it did if a non-select query raised a PDOException.
This patch fixes this, so that it so that the function conforms to the
docs.
2025-01-29 12:42:44 +01:00
Harald Eilertsen
3e6a646603 Add an insert method to dba_pdo
A common use case is to insert a record into a database table, but also
instantiate an object from the inserted data. This requires that we know
the value of any default or calculated columns that is filled in by the
database when the row is inserter.

This patch adds a `insert` method to pda_dbo that will insert a row, and
immediately fetch the row back from the database – including the default
and calculated values not specified by the insert itself.
2025-01-29 12:42:36 +01:00
Mario
324b281813 fix php warniing in case tgt_type is not set
(cherry picked from commit 03d1f3383e)

Co-authored-by: Mario Vavti <mario@mariovavti.com>
2025-01-24 12:16:33 +00:00
Mario Vavti
03d1f3383e fix php warniing in case tgt_type is not set 2025-01-24 13:10:46 +01:00
Mario
69a23c604d return if $furl is empty for some reason
(cherry picked from commit 174469970a)

Co-authored-by: Mario Vavti <mario@mariovavti.com>
2025-01-24 11:44:34 +00:00
Mario Vavti
174469970a return if $furl is empty for some reason 2025-01-24 12:43:12 +01:00
Mario Vavti
89b254dc1c add target and tgt_type tou sourced rss items if we rewrite them to our own 2025-01-24 00:11:26 +01:00
Mario Vavti
8e51988e96 unescape_tags() on URLs before we start messing with them 2025-01-23 21:24:06 +01:00
Mario Vavti
52e279f443 fix auto save draft not set correctly and use round instead of ceil for cover height calculation 2025-01-23 19:08:58 +01:00
Mario Vavti
4efa853690 tagsinput still requires jquery 2025-01-23 13:08:13 +01:00
Mario Vavti
9b13055dfe version 10.0.7 2025-01-22 13:08:42 +01:00
Mario
06afd8a375 changelog
(cherry picked from commit 27efb887d2)

Co-authored-by: Mario Vavti <mario@mariovavti.com>
2025-01-22 11:24:32 +00:00
Mario
6f027544d6 make sure to provide uid to drop_item() where applicable and check ownership when imporing feed items
(cherry picked from commit ccd52584a4)

Co-authored-by: Mario Vavti <mario@mariovavti.com>
2025-01-22 11:22:15 +00:00
Mario Vavti
2d2c9fa519 bump version 2025-01-22 11:50:46 +01:00
Mario Vavti
27efb887d2 changelog 2025-01-22 11:48:51 +01:00
Mario Vavti
ccd52584a4 make sure to provide uid to drop_item() where applicable and check ownership when imporing feed items 2025-01-22 10:43:33 +01:00
Mario Vavti
ab0fdb13d4 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2025-01-17 12:38:22 +01:00
Mario Vavti
2bca44ed25 bump version 2025-01-17 12:38:08 +01:00
Mario Vavti
eab08d0bcb rewrite redbasic javascript without jquery 2025-01-17 12:37:21 +01:00
Mario
d3f00704bd Merge branch 'add-security-policy' into 'dev'
Proposing a security policy.

See merge request hubzilla/core!2164
2025-01-16 12:29:57 +00:00
Harald Eilertsen
1e1a7109a9 Proposing a security policy. 2025-01-16 12:29:57 +00:00
Mario
ebab5ff281 use bin2hex() instead of btoa() to create an id for the toast. btoa() will not work with nonascii chars.
(cherry picked from commit 0165f44063)

Co-authored-by: Mario Vavti <mario@mariovavti.com>
2025-01-15 12:00:01 +00:00
Mario Vavti
0165f44063 use bin2hex() instead of btoa() to create an id for the toast. btoa() will not work with nonascii chars. 2025-01-15 12:50:45 +01:00
Mario
5fb6e5d6f7 fix regression in notifications filter
(cherry picked from commit 8fc0e41beb)

Co-authored-by: Mario Vavti <mario@mariovavti.com>
2025-01-06 09:15:59 +00:00
Mario Vavti
8fc0e41beb fix regression in notifications filter 2025-01-06 10:14:54 +01:00
Mario Vavti
3ad63a6e82 bump version 2025-01-05 13:40:29 +01:00
Mario Vavti
5a84ffdcda version 10.0.6 2025-01-05 13:31:28 +01:00
Mario
ad993645be changelog
(cherry picked from commit 392cb020aa)

Co-authored-by: Mario Vavti <mario@mariovavti.com>
2025-01-05 12:30:32 +00:00
Mario Vavti
392cb020aa changelog 2025-01-05 13:29:21 +01:00
Mario
0701cde239 dismiss entries where primary location data is not complete for some reason
(cherry picked from commit 884b612ffc)

Co-authored-by: Mario Vavti <mario@mariovavti.com>
2025-01-05 11:56:51 +00:00
Mario
a136c288d5 cleanup outdated doc entries just once after the docs were imported to the db
(cherry picked from commit ae0d138d2a)

Co-authored-by: Mario Vavti <mario@mariovavti.com>
2025-01-05 11:56:09 +00:00
Mario Vavti
884b612ffc dismiss entries where primary location data is not complete for some reason 2025-01-05 12:40:56 +01:00
Mario Vavti
ae0d138d2a cleanup outdated doc entries just once after the docs were imported to the db 2025-01-05 11:00:48 +01:00
Mario
1624a2620a remove redundant arguments
(cherry picked from commit 48ef4744ac)

Co-authored-by: Mario Vavti <mario@mariovavti.com>
2025-01-04 10:20:40 +00:00
Mario Vavti
48ef4744ac remove redundant arguments 2025-01-04 11:19:03 +01:00
Mario Vavti
a17cb75baf bump version 2024-12-29 17:42:53 +01:00
Mario Vavti
f4769d0f04 version 10.0.5 2024-12-29 17:36:28 +01:00
Mario Vavti
c8e30a00e2 Merge branch 'dev' 2024-12-29 17:35:44 +01:00
Mario Vavti
169c971cb1 changelog 2024-12-29 17:35:10 +01:00
Mario Vavti
51745d3652 Merge branch 'dev' 2024-12-29 17:18:04 +01:00
Mario Vavti
3ebbb91ae9 pass uid to drop_item() to ensure we will have permission to actually drop the item 2024-12-29 17:17:22 +01:00
Mario
762d402dea Merge branch 'dev' 2024-12-26 09:00:33 +00:00
Mario
051cef79fc changelog 2024-12-26 09:00:02 +00:00
Mario
b05a440f03 version 10.0.4 2024-12-26 08:58:46 +00:00
Mario
9bb4988eda Merge branch 'dev' 2024-12-26 08:55:36 +00:00
Mario
f66f0e398b missing argument name 2024-12-26 08:54:58 +00:00
Mario
49cb73c8c7 version 10.0.3 2024-12-26 08:04:05 +00:00
Mario
2a00bd9a28 Merge branch 'dev' 2024-12-26 08:03:26 +00:00
Mario
553b3f6faa changelog and bump version 2024-12-26 08:02:29 +00:00
Mario
2980827925 fix another possible loop 2024-12-26 07:55:08 +00:00
Mario
45a78dcbc0 this should fix the infinite loop caused by a regression in Daemon/Expire 2024-12-25 20:53:32 +00:00
Mario
5813b65aed hotfix release version 10.0.2 2024-12-25 12:03:43 +00:00
Mario
f8acd1d3a5 Merge branch 'dev' 2024-12-25 12:02:32 +00:00
Mario
c9ebb23b69 hotfix for loop caused in Daemon/Expire 2024-12-25 12:00:27 +00:00
Mario
bc998eacd0 bump version 2024-12-22 17:40:41 +00:00
Mario
648979467a do not allow a new zid to override an existing remote login - otherwise a prfactored request with an added zid can log us out 2024-12-22 17:39:58 +00:00
Mario
5c0ff6f584 once more improved imagesLoaded() 2024-12-22 17:35:25 +00:00
Mario
632721da4e version 10.0.1 2024-12-22 08:51:48 +00:00
Mario
f3a702e927 Merge branch 'dev' 2024-12-22 08:51:15 +00:00
Mario
58985f2200 update changelog 2024-12-22 08:51:04 +00:00
Mario
c55662510d fetch missing commit from dev 2024-12-22 08:31:04 +00:00
Mario
f01e917fff Merge branch 'dev' 2024-12-22 08:26:26 +00:00
Mario
3940187d19 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2024-12-22 08:20:24 +00:00
Mario
1215e8a030 Revert "Drop obsolete library LightOpenID"
This reverts commit e516c1352f
2024-12-22 08:19:55 +00:00
Mario
5b6e27233a fix sql error 2024-12-22 08:15:16 +00:00
Mario
b80cba4e68 Merge branch '10.0RC' 2024-12-21 18:49:06 +00:00
Mario
f2b28f5bbb version 10.0 2024-12-21 18:46:40 +00:00
Mario
4aeb4963a4 Merge branch 'dev' into 10.0RC 2024-12-21 18:44:04 +00:00
Mario
de9b10e850 more changelog 2024-12-21 18:43:41 +00:00
Mario
36a1d98c52 changelog 2024-12-21 18:09:56 +00:00
Mario
cf66f245b4 RC2 2024-12-21 12:34:05 +00:00
Mario
b1f2f67a04 better pubs notofication fiy and also fix a javascript error and remove last bit of jquery from notifications 2024-12-21 12:07:31 +00:00
Mario
bd10c1e40a fix anomaly in pubs notification 2024-12-21 11:55:19 +00:00
Mario
e146eaa8f8 bump version 2024-12-21 10:28:07 +00:00
Mario
92e21c4f3d deduplicate the images array by src 2024-12-21 10:27:28 +00:00
Mario
55265c8a3e track processed images 2024-12-20 20:53:47 +00:00
Mario
c3cc624621 bump version 2024-12-20 19:13:21 +00:00
Mario
b466932e37 improved imagesLoaded() and formatting 2024-12-20 19:12:09 +00:00
Mario
a3248e8b3b version 2024-12-20 12:36:00 +00:00
Mario
9ec2db7c97 port scrollToItem() to vanilla js and more fixes 2024-12-20 12:35:29 +00:00
Mario
9bd94287dd improved imagesLoaded() and notifications fixes 2024-12-20 11:47:38 +00:00
Mario
faca95b21c bump version 2024-12-19 23:18:59 +00:00
Mario
79f8b06ede various fixes for the last commit 2024-12-19 23:17:56 +00:00
Mario
a2dde34b1b refactor notifications widget and updateConvItems() to not require jquery 2024-12-19 18:49:07 +00:00
Mario
fb5824417e Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2024-12-19 10:37:44 +00:00
Mario
804b4effa2 changelog 2024-12-19 10:37:19 +00:00
Mario Vavti
4c8e1de4c6 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2024-12-13 10:09:07 +01:00
Mario
d9c69b747d bump dev version 2024-12-13 09:07:55 +00:00
Mario Vavti
0e4be679e4 composer dump autoload 2024-12-13 09:59:31 +01:00
Mario
14360c4735 version 10.0RC and strings 2024-12-13 08:49:18 +00:00
Mario
2da55d3bd8 remove jquery.timeago.js in favor of a native js implementation 2024-12-12 14:18:55 +00:00
Mario Vavti
e9222d0d9a add test for item_forwardable() 2024-12-10 22:45:56 +01:00
Mario
93f72a53f5 introduce item_forwardable() and check it before we call the notifier to possibly safe some processes - test will follow, also add some other possibly blocking flags to the add item 2024-12-10 10:27:48 +00:00
Mario
93c4bd4692 pubcrawl: support for inbound add/remove activities and minor cleanup 2024-12-10 09:22:17 +00:00
Mario
486c21b519 hq: improved file filtering 2024-12-09 08:42:01 +00:00
Mario
7785487d77 fix delayed post handling in cron, always set item_delayed if we select a create date 2024-12-08 22:46:21 +00:00
Mario
9756023e39 fix expiration 2024-12-07 23:25:59 +00:00
Mario Vavti
bb0a22ee58 add test for relative_time() 2024-12-07 23:49:17 +01:00
Mario
e88ae54bef add more indicators and a new function to return relative time in the past and the future 2024-12-07 20:41:13 +00:00
Mario
d37d181d94 Libzot: remove commented code which duplicates code in Activity::decode_note() 2024-12-07 19:43:17 +00:00
Mario
d59d808883 more cleanup 2024-12-07 19:38:18 +00:00
Mario
b59fe77906 provide a comments disabled indicator and some cleanup 2024-12-07 19:34:30 +00:00
Mario
1941b4f026 only allow disable_comments on thread top 2024-12-07 18:40:56 +00:00
Mario
5c82229e34 Ãfix issue where poll updates were dismissed due to missing edited update, fix wrong array key when retaining item, update dreport push to also push the related item 2024-12-06 23:31:49 +00:00
Mario
66d502d8e1 an attempt to fix some comments on/off anomalies 2024-12-06 19:24:14 +00:00
Mario
66acfc66ce set item_type so that notifier can do the right thing 2024-12-06 11:41:01 +00:00
Mario
2e13640ab4 wrong class 2024-12-05 13:14:07 +00:00
Mario
277b4f7d10 even more fa2bi 2024-12-05 13:08:48 +00:00
Mario
edf2a6db1b we use the chat-quote icon for forums throughout the app. basically because the forum posts a quote of the original post 2024-12-05 13:02:18 +00:00
Mario
8ad000ec70 more fa2bi issues 2024-12-05 12:42:37 +00:00
Mario
563628fef8 another fa2bi issue 2024-12-05 12:33:55 +00:00
Mario
15b6353c1c filtering censored xchans in mod pubstream queries has possible performance issues. we will filter them in process_delivery() instead 2024-12-05 11:27:56 +00:00
Mario
1a86348a6c Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2024-12-02 09:23:16 +00:00
Mario
a80ab5887c also copy the item_restrict field to the add activity and check for this field in the notifier 2024-12-02 09:17:15 +00:00
Mario
475ae7ba13 Merge branch 'fix/chat-icon-fix' into 'dev'
Fixed notification icons in chat

See merge request hubzilla/core!2177
2024-12-02 09:15:32 +00:00
SK
e107298125 Fixed notification icons in chat 2024-12-02 04:32:48 +05:30
Mario
428ffa5e35 save a loop by ordering results by item_wall and more uuid only lookup 2024-11-28 15:34:16 +00:00
Mario
0bffe6e019 sql lookup by uuid should be sufficient by now, remove superfluous require_once() 2024-11-28 15:12:57 +00:00
Mario Vavti
9e2f3dc05f fix more issues reported by phpstan 2024-11-27 10:25:37 +01:00
Mario
9fa18a5557 Merge branch 'phpstan-ignore-some-warnings' into 'dev'
phpstan: Ignore warnings on missing return statement.

See merge request hubzilla/core!2175
2024-11-27 08:18:58 +00:00
Mario
9608ab27c4 Merge branch 'dev' into 'dev'
updated fork-awesome icons to bootstrap

See merge request hubzilla/core!2174
2024-11-27 08:18:09 +00:00
Mario
464b331deb Merge branch 'module-admin-accounts-enhancements' into 'dev'
Fix and refactor module Admin\Accounts part I

See merge request hubzilla/core!2173
2024-11-27 08:15:59 +00:00
Harald Eilertsen
0189d04614 Fix and refactor module Admin\Accounts part I 2024-11-27 08:15:59 +00:00
Mario
cbb3ad1620 make sure to toggle aside if a notification or message is clicked and some whitespace cleanup 2024-11-26 09:57:55 +00:00
Harald Eilertsen
c0f9d55cfb phpstan: Ignore warnings on missing return statement.
While some of these may be fixable without too much hassle, quite a few
of them will possibly require architectural restructuring. We should
revisit these, but let's silence them for now.
2024-11-25 13:11:58 +01:00
Mario
0da51e0f71 fix superfluous slash in some cases 2024-11-25 08:11:33 +00:00
SK
9014a288b0 updated fork-awesome icons to bootstrap 2024-11-22 18:49:13 +05:30
Mario
dcef9f61b5 remove logging 2024-11-22 10:28:21 +00:00
Mario
3d80db0cdc Merge branch 'add-mailer-class' into 'dev'
Add Zotlabs\Lib\Mailer class to replace z_mail function.

See merge request hubzilla/core!2172
2024-11-22 09:59:14 +00:00
Harald Eilertsen
3a2f787f96 Add Zotlabs\Lib\Mailer class to replace z_mail function. 2024-11-22 09:59:14 +00:00
Mario
f7a9b84943 mod cal: if a day is provided default to week view except the date has a ! prepended 2024-11-21 09:36:31 +00:00
Mario
46e6600169 mod cal: provide a possibility to link to a specific month or day by passing a fragment 2024-11-21 09:04:55 +00:00
Mario
243a2a9bdf Update chat.tpl to correct expand and contract icons from forkawesome to bootstrap icons.
(cherry picked from commit c626985448)

Co-authored-by: Saiwal K <sk@utsukta.org>
2024-11-19 21:08:55 +00:00
Mario
91baa52b8b Merge branch 'saiwal-master-patch-76831' into 'master'
Update chat.tpl to correct expand and contract icons from forkawesome to bootstrap icons.

See merge request hubzilla/core!2171
2024-11-19 21:08:32 +00:00
Harald Eilertsen
5338793883 Ubreak tests: update MagicTest for new behaviour of Magic module. 2024-11-19 11:10:49 +01:00
Mario Vavti
9acc73b273 some cleanup for mod magic 2024-11-18 23:15:29 +01:00
Saiwal K
c626985448 Update chat.tpl to correct expand and contract icons from forkawesome to bootstrap icons. 2024-11-17 19:59:31 +00:00
Mario Vavti
5cfb3842f1 more phpstan errors 2024-11-17 20:52:13 +01:00
Mario Vavti
25b089c1a9 fix some errors detected by phpstan 2024-11-17 16:17:05 +01:00
Mario
67a9292aaa Merge branch 'issue-1879-emails-with-plus-addressing-rejected' into 'dev'
Fix #1879: Emails with + in local part was rejected.

See merge request hubzilla/core!2170
2024-11-17 10:26:25 +00:00
Mario
81dda15669 fix undefined variables 2024-11-17 07:58:11 +00:00
Harald Eilertsen
5b7f8d986c Fix #1879: Emails with + in local part was rejected. 2024-11-16 13:45:36 +01:00
Mario
5dee600735 Merge branch 'add-dev-dependecy-phpstan' into 'dev'
Add PHPStan as a developer dependency.

See merge request hubzilla/core!2169
2024-11-14 18:45:29 +00:00
Mario
01da60b385 Merge branch 'various-phpstan-issues' into 'dev'
Several issues discovered by PHPStan

See merge request hubzilla/core!2168
2024-11-14 18:40:15 +00:00
Harald Eilertsen
951800eca6 Several issues discovered by PHPStan 2024-11-14 18:40:15 +00:00
Mario
72c47cd8db version 9.5.2 - merge containers 2024-11-14 17:14:15 +00:00
Mario
e3a8668c32 Merge branch 'dev' into containers 2024-11-14 17:09:22 +00:00
Mario
fd9977eada css fixes 2024-11-14 14:22:18 +00:00
Mario
bd3304ff94 Merge branch 'oops-fix-db-update' into 'dev'
Fix invocation of DB_Update::run.

See merge request hubzilla/core!2167
2024-11-14 13:32:48 +00:00
Mario
586cda5155 fix some conent import issues
(cherry picked from commit c9a8914b07)

Co-authored-by: Mario Vavti <mario@mariovavti.com>
2024-11-14 13:30:07 +00:00
Mario Vavti
c9a8914b07 fix some conent import issues 2024-11-14 12:47:40 +01:00
Mario
b21b9260d9 fix race condition when updating multiple choice polls 2024-11-13 14:01:14 +00:00
Mario
b5c07e4c01 this is not true anymore - check owner perms 2024-11-13 11:08:18 +00:00
Harald Eilertsen
28b5b0cab5 Add PHPStan as a developer dependency.
PHPStan is a static PHP code analyzer that's aimed at finding actual
bugs in the code. Where PHP Code Sniffer is about codeing standards,
PHPStan is about correctness of code.

The provided configuration file (`phpstan.neon.dist`) is configured to
use the _lowest_ level of checks that PHPStan will report on. See
https://phpstan.org/user-guide/rule-levels for information about the
various rule levels.

Run an analysis of the code base like this:

    % ./vendor/bin/phpstan

It will output any found issues to stdout.

You can also run it like this:

    % ./vendor/bin/phpstan --error-format=raw > phpstan.log

This will give you an output file in a format that's suitable for use
with typical editors for mapping errors to source locations.
2024-11-12 09:42:11 +01:00
Mario
39d0a3f1f6 containers: poll testing 2024-11-11 22:25:53 +00:00
Mario
513cd3b99a fix click area in dropdown add/remove reaction
(cherry picked from commit 8268ed1ba7)

Co-authored-by: Mario <mario@mariovavti.com>

(cherry picked from commit ce9d67f7b1)

Co-authored-by: Mario <mario@mariovavti.com>
2024-11-11 20:00:36 +00:00
Mario
ce9d67f7b1 fix click area in dropdown add/remove reaction
(cherry picked from commit 8268ed1ba7)

Co-authored-by: Mario <mario@mariovavti.com>
2024-11-11 20:00:25 +00:00
Mario
8268ed1ba7 fix click area in dropdown add/remove reaction 2024-11-11 19:53:20 +00:00
Harald Eilertsen
6c1d0851d7 Fix invocation of DB_Update::run.
Thought this should have been part of the change set that turned the
DB_Update routine to a static function instead of a constructor to an
object that is not used.
2024-11-11 17:05:13 +01:00
Mario
3bc0fd5db4 fix undefined var warning 2024-11-11 09:18:56 +00:00
Mario Vavti
4c3f3d1477 Merge branch 'dev' into containers 2024-11-10 23:38:30 +01:00
Mario Vavti
17411a501c containers: testing sourced items 2024-11-10 23:37:45 +01:00
Mario
d446f171c5 Revert "Module\Item: Make $item_id an object property."
This reverts commit 2c17d0b031
2024-11-10 22:36:35 +00:00
Mario Vavti
b24b409a01 Merge branch 'dev' into containers 2024-11-10 19:01:40 +01:00
Mario
3791dfab3a Merge branch 'begin-refactoring-module-item' into 'dev'
Begin refactoring Module\Item

See merge request hubzilla/core!2166
2024-11-10 18:01:06 +00:00
Mario
31a146b23a Merge branch 'oops-ref-to-nonexisting-class' into 'dev'
Remove import of non-existing class in test.

See merge request hubzilla/core!2165
2024-11-10 17:55:27 +00:00
Mario Vavti
e52714ed16 make sure to notify the drop if necessary 2024-11-10 18:53:46 +01:00
Harald Eilertsen
2c17d0b031 Module\Item: Make $item_id an object property.
This also allows us to deduplicate initialization and validation.
2024-11-10 16:43:48 +01:00
Harald Eilertsen
57e69372d3 Module\Item: Move processing of zot and as requests to functions.
These seem to be entirely independent, so moving the body of the if
statements to separate functions should be fine.
2024-11-10 16:43:48 +01:00
Mario Vavti
43acb86aab fix encoding and attribution 2024-11-10 11:49:09 +01:00
Mario Vavti
e339fbcc46 container fixes for photo and file upload 2024-11-10 11:40:56 +01:00
Mario
f05b8bd87d Do not filter deleted hublocs in xchan_query because it will result in empty profile info in conversations if the hubloc was deleted. Deleting a hublocation does not neccesarily delete its content and the author could appear again from another location.
(cherry picked from commit 4e6696b049)

Co-authored-by: Mario Vavti <mario@mariovavti.com>
2024-11-09 20:12:21 +00:00
Mario Vavti
4e6696b049 Do not filter deleted hublocs in xchan_query because it will result in empty profile info in conversations if the hubloc was deleted. Deleting a hublocation does not neccesarily delete its content and the author could appear again from another location. 2024-11-09 21:11:33 +01:00
Harald Eilertsen
fbc79e36e0 Remove import of non-existing class in test.
This one snuck in by mistake. No harm done, as the actual class was
never referenced, but it should still not be there.
2024-11-09 14:38:27 +01:00
Mario Vavti
c9d4b068c2 remove extensiv logging to syslog 2024-11-09 12:49:10 +01:00
Mario Vavti
b6dbbbc82f fix regression propagating deletes 2024-11-09 12:39:24 +01:00
Mario Vavti
954d92c354 Merge branch 'dev' into containers 2024-11-09 11:27:53 +01:00
Mario Vavti
8dbebc2b42 update border color 2024-11-09 11:27:13 +01:00
Mario
14207c68ca Merge branch 'fix-incorrect-module-imports' into 'dev'
Fix incorrect module imports.

See merge request hubzilla/core!2163
2024-11-09 10:26:23 +00:00
Mario
0ed08274f1 Merge branch 'clean-up-some-dependencies' into 'dev'
Clean up deps and upgrade EpubMeta

See merge request hubzilla/core!2162
2024-11-09 10:24:26 +00:00
Mario
2a152e0803 Merge branch 'more-deprecations-in-tests' into 'dev'
Fix some more deprecation warnings in the tests.

See merge request hubzilla/core!2161
2024-11-09 10:18:27 +00:00
Mario Vavti
a0c54c5f04 make sure to store target information when decoding and indicate contained conversations with a colored border for now 2024-11-09 10:55:10 +01:00
Harald Eilertsen
ac8c80ddbe Fix incorrect module imports.
When importing modules with use statements, they always require the
fully qualified module name. Iow, there's no need to prefix them with an
extra backslash.

Ref: https://www.php.net/manual/en/language.namespaces.importing.php
2024-11-09 08:45:45 +01:00
Mario Vavti
ebad9d56c9 port to containers item_store() continued 2024-11-08 22:24:33 +01:00
Mario Vavti
0481901b59 refactor drop_item[s]() for containers 2024-11-08 20:18:20 +01:00
Harald Eilertsen
0534fe6886 Thumbs\Epubthumb: Adapt to new version of EPub meta lib.
Also fixes a few issues and refactor the code a bit.
2024-11-08 16:48:23 +01:00
Harald Eilertsen
6e51571309 Remove epub-meta from library 2024-11-08 16:48:23 +01:00
Harald Eilertsen
fe30b54975 Update php-epub-meta and use composer for dep handling.
Note that we upgrade to the 2.x branch of the dependency, as the 3.x
branch requires PHP version 8.2 or later. There's no reason for us to
move our minimum supported version of PHP just yet.
2024-11-08 16:43:29 +01:00
Harald Eilertsen
b00ae997a5 Remove obsolete and unused symfony/options-resover and process
These actually look like they could be useful, but since unused, let's
drop them for now. They can always be re-added via composer if needed
later.
2024-11-08 16:39:26 +01:00
Harald Eilertsen
b5b7d0cda9 Remove obsolete and unused sticky-kit 2024-11-08 16:39:26 +01:00
Harald Eilertsen
300d461a1a Remove obsolete and unused tiptip library 2024-11-08 16:39:26 +01:00
Harald Eilertsen
e516c1352f Drop obsolete library LightOpenID
We're not using it anyways.
2024-11-08 16:39:26 +01:00
Mario Vavti
4b4cac63fd Merge branch 'dev' into containers 2024-11-08 11:19:42 +01:00
Harald Eilertsen
47f109451d Fix some more deprecation warnings in the tests. 2024-11-07 17:29:54 +01:00
Mario
e466c73407 fix allday not set if a rsource is provided
(cherry picked from commit 17183cc5dc)

Co-authored-by: Mario <mario@mariovavti.com>
2024-11-07 14:31:18 +00:00
Mario
17183cc5dc fix allday not set if a rsource is provided 2024-11-07 14:29:52 +00:00
Mario
e5aae2af0f fix allday variable not set when clicking an event
(cherry picked from commit 939e5d9ca5)

Co-authored-by: Mario <mario@mariovavti.com>
2024-11-06 16:17:18 +00:00
Mario
939e5d9ca5 fix allday variable not set when clicking an event 2024-11-06 16:16:23 +00:00
Mario
600209e21e bump dev version 2024-11-06 15:48:18 +00:00
Mario
173c4d242d version 9.4.4 2024-11-06 13:06:05 +00:00
Mario
76b8c36f7c changelog
(cherry picked from commit 12c88c06d8)

Co-authored-by: Mario <mario@mariovavti.com>
2024-11-06 13:05:18 +00:00
Mario
12c88c06d8 changelog 2024-11-06 13:04:03 +00:00
Mario
f35352090e Update translations for Norwegian Bokmål
(cherry picked from commit 35a05073f2)

Co-authored-by: Harald Eilertsen <haraldei@anduin.net>
2024-11-06 12:30:37 +00:00
Mario
e5db47e0d5 Module\Thing: Don't try to escape field that's not present
The `profile_assign` field is only present if the multiple profiles
feature is enabled.


(cherry picked from commit 472484dde0)

Co-authored-by: Harald Eilertsen <haraldei@anduin.net>
2024-11-06 12:30:16 +00:00
Mario
6a52e502aa Module\Thing: Don't use $_REQUEST superglobal.
Replaces all occurences with $_POST or $_GET instead.


(cherry picked from commit 5c3bdbd1e0)

Co-authored-by: Harald Eilertsen <haraldei@anduin.net>
2024-11-06 12:29:46 +00:00
Mario
6a866fe904 Move Norwegian translations from nb-no to nb
(cherry picked from commit ec02453d37)

Co-authored-by: Harald Eilertsen <haraldei@anduin.net>
2024-11-06 12:28:51 +00:00
Mario
229efddbf1 Merge branch 'fix-mariadb-support-for-test-setup' into 'dev'
tests: Update test db setup script for mariadb

See merge request hubzilla/core!2160
2024-11-06 11:50:40 +00:00
Mario
abb67a4565 Merge branch 'make-phpcs-a-bit-more-lax' into 'dev'
Make phpcs a bit more lax...

See merge request hubzilla/core!2159
2024-11-06 11:49:25 +00:00
Mario
2e324d4cef Merge branch 'move-norwegian-locale' into 'dev'
Move and update norwegian locale

See merge request hubzilla/core!2158
2024-11-06 11:48:54 +00:00
Mario
d4d1a7523d Merge branch 'fix-module-thing' into 'dev'
Fix error adding Things when multiple profiles not enabled

See merge request hubzilla/core!2157
2024-11-06 11:47:57 +00:00
Mario
d9d239bf3a only zot6 hublocs have a sitekey so only query such hublocs. This will safe alternative network hublocs from being marked deleted allthough they are intact
(cherry picked from commit 7a3f2c1ba9)

Co-authored-by: Mario <mario@mariovavti.com>
2024-11-06 11:16:46 +00:00
Mario
429d15f009 correctly hide modals and remove unneeded toString() conversion since we are not dealing with string objects here
(cherry picked from commit 9f473fc204)

Co-authored-by: Mario <mario@mariovavti.com>
2024-11-06 11:16:20 +00:00
Mario
7a3f2c1ba9 only zot6 hublocs have a sitekey so only query such hublocs. This will safe alternative network hublocs from being marked deleted allthough they are intact 2024-11-06 11:12:42 +00:00
Mario
9f473fc204 correctly hide modals and remove unneeded toString() conversion since we are not dealing with string objects here 2024-11-06 09:44:07 +00:00
Harald Eilertsen
35a05073f2 Update translations for Norwegian Bokmål 2024-11-04 10:22:13 +01:00
Harald Eilertsen
472484dde0 Module\Thing: Don't try to escape field that's not present
The `profile_assign` field is only present if the multiple profiles
feature is enabled.
2024-11-03 20:42:59 +01:00
Harald Eilertsen
5c3bdbd1e0 Module\Thing: Don't use $_REQUEST superglobal.
Replaces all occurences with $_POST or $_GET instead.
2024-11-03 20:42:59 +01:00
Harald Eilertsen
ec02453d37 Move Norwegian translations from nb-no to nb 2024-11-03 18:06:42 +01:00
Mario
2b44be58c3 explicit check for channel_address
(cherry picked from commit e20327d267)

Co-authored-by: Mario <mario@mariovavti.com>
2024-11-03 11:02:35 +00:00
Mario
c44db397ff Zotlabs\Module\Setup: Fix deprecation.
Using `self` in callables has been deprecated, so change to proper fully
qualified class name.


(cherry picked from commit 8ab3ad6531)

Co-authored-by: Harald Eilertsen <haraldei@anduin.net>
2024-11-03 11:02:04 +00:00
Mario
a385fdff37 Zotlabs\Web\HttpMeta: Declare and init properties.
The $ogproperty was not declared, which triggered a warning in PHP 8.2.

Also fixed the initialization of the properties, and removed the now
superfluous constructor.


(cherry picked from commit bf008465ad)

Co-authored-by: Harald Eilertsen <haraldei@anduin.net>
2024-11-03 11:01:50 +00:00
Mario
20aacb82c6 tests: Declare private property $output.
Uncovered by PHP 8.2 because dynamic properties are deprecated.


(cherry picked from commit a29a1c768d)

Co-authored-by: Harald Eilertsen <haraldei@anduin.net>
2024-11-03 11:01:38 +00:00
Mario
0d17d8dad9 tests: Fix typo in UnitTestCase.
Uncovered by PHP 8.2 because dynamic properties are deprecated.


(cherry picked from commit 90bc987ea7)

Co-authored-by: Harald Eilertsen <haraldei@anduin.net>
2024-11-03 11:01:21 +00:00
Mario
2ab0118c13 Fix missing CSRF checks in admin/account_edit
(cherry picked from commit 38c947590e)

342d94c3 tpl: Fix warnings in templates.
bccaeb1e tests: Update Module\TestCase to support POST requests
f627e55b tests: Update account fixtures with fixed account_level.
ee62aff4 Module\Admin\Account_edit: Add missing CSRF checks.

Co-authored-by: Harald Eilertsen <haraldei@anduin.net>
2024-11-03 10:59:41 +00:00
Mario
30419bdbf6 add ocap tokens to all media files and attachments
(cherry picked from commit 2f0a47e583)

Co-authored-by: Mario <mario@mariovavti.com>
2024-11-03 10:59:16 +00:00
Mario Vavti
21b60bf119 Merge branch 'dev' into containers 2024-11-03 11:57:45 +01:00
Mario
5db3f93be9 Merge branch 'php8.2-deprecations' into 'dev'
Fix deprecations uncovered by running tests on PHP 8.2

See merge request hubzilla/core!2156
2024-11-03 10:57:03 +00:00
Mario Vavti
d25314c75b Merge branch 'dev' into containers 2024-11-03 11:45:08 +01:00
Mario
e20327d267 explicit check for channel_address 2024-11-03 10:43:17 +00:00
Harald Eilertsen
8ab3ad6531 Zotlabs\Module\Setup: Fix deprecation.
Using `self` in callables has been deprecated, so change to proper fully
qualified class name.
2024-11-03 08:48:53 +01:00
Harald Eilertsen
bf008465ad Zotlabs\Web\HttpMeta: Declare and init properties.
The $ogproperty was not declared, which triggered a warning in PHP 8.2.

Also fixed the initialization of the properties, and removed the now
superfluous constructor.
2024-11-03 08:42:11 +01:00
Harald Eilertsen
a29a1c768d tests: Declare private property $output.
Uncovered by PHP 8.2 because dynamic properties are deprecated.
2024-11-03 08:39:21 +01:00
Harald Eilertsen
90bc987ea7 tests: Fix typo in UnitTestCase.
Uncovered by PHP 8.2 because dynamic properties are deprecated.
2024-11-03 08:32:01 +01:00
Mario
46fdce4402 Merge branch 'admin-account-edit-csrf-check' into 'dev'
Fix missing CSRF checks in admin/account_edit

See merge request hubzilla/core!2155
2024-11-02 14:42:01 +00:00
Harald Eilertsen
38c947590e Fix missing CSRF checks in admin/account_edit 2024-11-02 14:42:00 +00:00
Mario
c5faa012b5 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2024-11-02 14:35:42 +00:00
Mario
2f0a47e583 add ocap tokens to all media files and attachments 2024-11-02 14:35:04 +00:00
Mario
c958cc6f90 URL escape zid param in head.tpl
This should fix issue #1877 fully.


(cherry picked from commit 065f85bab1)

Co-authored-by: Harald Eilertsen <haraldei@anduin.net>
2024-11-01 09:03:21 +00:00
Mario
541a0f6476 Merge branch 'issue-1877-more-fixes' into 'dev'
URL escape zid param in head.tpl

See merge request hubzilla/core!2154
2024-11-01 09:02:37 +00:00
Harald Eilertsen
065f85bab1 URL escape zid param in head.tpl
This should fix issue #1877 fully.
2024-10-31 19:15:52 +01:00
Mario
38ac60e618 make sure the objects published date has the correct time format
(cherry picked from commit 160c40b580)

Co-authored-by: Mario <mario@mariovavti.com>
2024-10-31 11:12:54 +00:00
Mario
160c40b580 make sure the objects published date has the correct time format 2024-10-31 11:07:42 +00:00
Mario Vavti
005d4ad351 Merge branch 'dev' into containers 2024-10-30 12:50:08 +01:00
Mario
90a1dad02c Merge branch 'make-db-upgrade-static-method' into 'dev'
Change DB_Upgrade to a static function instead.

See merge request hubzilla/core!2151
2024-10-30 11:47:52 +00:00
Harald Eilertsen
4daba84223 Make phpcs a bit more lax...
Allow spaces for indent, and newlines before braces.
2024-10-30 12:35:08 +01:00
Harald Eilertsen
fc182f1b07 tests: Update test db setup script for mariadb
Mariadb now issues warnings when using the deprecated `mysql` binary. So
we make sure to use the proper name for the binary depending on the
actual DB engine installed.
2024-10-30 12:13:21 +01:00
Mario
23a19ecf1f escape the zid parameter - issue #1877
(cherry picked from commit 0207c02420)

Co-authored-by: Mario <mario@mariovavti.com>
2024-10-30 09:18:23 +00:00
Mario
0207c02420 escape the zid parameter - issue #1877 2024-10-30 09:12:26 +00:00
Mario Vavti
68135c28da Merge branch 'dev' into containers 2024-10-30 09:50:17 +01:00
Mario
274bfa9024 Merge branch 'add-missing-test-for-bbcode-cleanup-fix' into 'dev'
tests: Tests for BBCode cleanup fix

See merge request hubzilla/core!2152
2024-10-30 08:27:44 +00:00
Mario Vavti
4bb28a21c4 Merge branch 'dev' into containers 2024-10-27 14:05:25 +01:00
Mario
8b75f50f23 fix en tos page
(cherry picked from commit 0e50b1d10c)

Co-authored-by: Mario Vavti <mario@mariovavti.com>
2024-10-27 12:57:02 +00:00
Mario Vavti
0e50b1d10c fix en tos page 2024-10-27 13:53:31 +01:00
Harald Eilertsen
8f4c3a2f88 Merge branch 'dev' into make-db-upgrade-static-method 2024-10-23 14:56:41 +02:00
Harald Eilertsen
73006ccdf5 tests: Tests for BBCode cleanup fix
Somehow I forgot to include this in the patch that fixed the issue.
2024-10-23 14:31:21 +02:00
Mario Vavti
1006ebbf61 Merge branch 'dev' into containers 2024-10-23 14:19:45 +02:00
Mario
436b1673cf make sure we select only sys channel items and remove dupes checking (this will be checked in item_store() anyway)
(cherry picked from commit e530476e6c)

Co-authored-by: Mario <mario@mariovavti.com>
2024-10-23 12:08:03 +00:00
Mario
e530476e6c make sure we select only sys channel items and remove dupes checking (this will be checked in item_store() anyway) 2024-10-23 12:06:32 +00:00
Mario
e0a91bed7a allow to file items from the public stream 2024-10-23 12:04:15 +00:00
Mario Vavti
168ec53686 Merge branch 'dev' into containers 2024-10-19 20:50:48 +02:00
Mario
4d1be3aea5 bring filed items to mod hq 2024-10-19 18:49:47 +00:00
Mario Vavti
e8f816a981 Merge branch 'dev' into containers 2024-10-18 21:36:48 +02:00
Mario
e649ba5b13 remove attach_upgrade() after 7 years it should not be required anymore 2024-10-18 19:32:41 +00:00
Mario
92ce66e766 i guess a couple of weeks have passed by now 2024-10-18 19:20:20 +00:00
Mario
96210f5ecc fix edit button not clickable if below right aside
(cherry picked from commit 1411eafa9b)

Co-authored-by: Mario <mario@mariovavti.com>
2024-10-18 19:14:04 +00:00
Mario
1411eafa9b fix edit button not clickable if below right aside 2024-10-18 19:06:35 +00:00
Mario Vavti
20db45c815 Merge branch 'dev' into containers 2024-10-18 20:19:36 +02:00
Mario Vavti
4acdb8fb10 containers: port events 2024-10-18 20:18:55 +02:00
Mario
9e9e8efb2d fix tags rendering in the editor
(cherry picked from commit f4495fd441)

Co-authored-by: Mario <mario@mariovavti.com>
2024-10-17 09:04:25 +00:00
Mario
f4495fd441 fix tags rendering in the editor 2024-10-17 09:03:32 +00:00
Harald Eilertsen
e2ae8f0c4d Zotlabs\Lib\DB_Upgrade: Add API documentation. 2024-10-14 23:07:42 +02:00
Harald Eilertsen
074dc440cc Change DB_Upgrade to a static function instead.
No need for this to be an object, since it's never referenced or even
kept after construction. Further all the functionality was in the
constructor anyways.

Also removed some unused properties.
2024-10-14 22:52:13 +02:00
Mario
e9dc4b553b Fix regex to detect URLs in cleanup_bbcode.
This fixes the issue where the text after the URL would be included in
the link if it was immediately followed by a newline.

Example:

    https://example.com
	this is a test.

Would become:

	#^[url=https://example.com_this]https://example.com_this[/url]
	is a test


(cherry picked from commit 687cda3673)

Co-authored-by: Harald Eilertsen <haraldei@anduin.net>
2024-10-12 17:08:15 +00:00
Mario Vavti
d7fa6f6709 Merge branch 'dev' into containers 2024-10-12 19:06:35 +02:00
Mario
40a9989be2 Merge branch 'fix-cleanup-bbcode-url-regex' into 'dev'
Fix naked URLs immediately followed by a newline

See merge request hubzilla/core!2150
2024-10-12 17:05:19 +00:00
Harald Eilertsen
d1648927b5 Fix some whitespace issues in zid.php.
No functional change.
2024-10-12 18:23:30 +02:00
Harald Eilertsen
ecde4a3ded Change config used by Markdown tests to reflect actual use.
This makes the configuration used align better with how it is being used
in the mdpost addon. This also reveals some issues that are less than
ideal for Markdown posts. The relevant test cases have been adjusted to
pass with the new config, but have been commented.
2024-10-12 18:19:43 +02:00
Harald Eilertsen
687cda3673 Fix regex to detect URLs in cleanup_bbcode.
This fixes the issue where the text after the URL would be included in
the link if it was immediately followed by a newline.

Example:

    https://example.com
	this is a test.

Would become:

	#^[url=https://example.com_this]https://example.com_this[/url]
	is a test
2024-10-12 18:15:54 +02:00
Mario Vavti
47cdef390a Merge branch 'dev' into containers 2024-10-12 17:17:11 +02:00
Mario
05a5b644bf Merge branch 'remove-repo-handling-from-admin-addons' into 'dev'
Remove addon repo management from admin/addons.

See merge request hubzilla/core!2149
2024-10-12 15:15:40 +00:00
Mario
84556854e8 Merge branch 'drop-unused-html5-library' into 'dev'
Remove HTML5 parser lib deprecated in Hubzilla 5.0

See merge request hubzilla/core!2148
2024-10-12 15:10:02 +00:00
Mario
314443d41e Merge branch 'first-tests-for-module-magic' into 'dev'
tests: Add some tests for the Zotlabs\Magic module.

See merge request hubzilla/core!2147
2024-10-12 15:08:29 +00:00
Mario Vavti
c23a71c936 code consistency 2024-10-12 17:05:35 +02:00
Mario Vavti
12b33a23de containers: port start_delivery_chain() 2024-10-12 16:31:00 +02:00
Mario Vavti
a305c20e08 Merge branch 'dev' into containers 2024-10-12 16:24:58 +02:00
Mario
c70bd08c10 Fix duplicate posts from forum clones
(cherry picked from commit e2cfe245b7)

Co-authored-by: Mario Vavti <mario@mariovavti.com>
2024-10-12 13:59:12 +00:00
Mario Vavti
e2cfe245b7 Fix duplicate posts from forum clones 2024-10-12 15:58:00 +02:00
Mario Vavti
12b24e0e5e containers: port mod impel 2024-10-11 17:16:44 +02:00
Mario Vavti
d5291e9b07 containers: port core modules and attach_store_item() 2024-10-11 17:10:56 +02:00
Mario Vavti
a1818b1a29 document some special handling 2024-10-10 15:10:51 +02:00
Mario Vavti
e8eb283fd8 fix c/p typo 2024-10-10 14:18:23 +02:00
Mario Vavti
96d5370122 update item entity for hubzilla 2024-10-10 14:17:13 +02:00
Mario Vavti
2bcb6a4fed merge dev and resolve conflicts 2024-10-10 13:13:17 +02:00
Mario Vavti
aee396421a revert 2024-10-10 13:09:04 +02:00
Mario Vavti
897568a087 resolve merge conflict 2024-10-10 13:07:48 +02:00
Mario Vavti
69109a558b version 9.4.3 2024-10-10 12:16:33 +02:00
Mario
4aff6d19d6 changelog
(cherry picked from commit a5c1b669b4)

Co-authored-by: Mario Vavti <mario@mariovavti.com>
2024-10-10 10:11:31 +00:00
Mario Vavti
a5c1b669b4 changelog 2024-10-10 12:09:39 +02:00
Mario
3cb5d14037 also discard Add/Remove at the AP side
(cherry picked from commit 2aee659cbd)

Co-authored-by: Mario Vavti <mario@mariovavti.com>
2024-10-10 10:04:17 +00:00
Mario
5f685bcf63 also dismiss add/remove collection activities in fetch_conversation()
(cherry picked from commit 44232677c8)

Co-authored-by: Mario <mario@mariovavti.com>
2024-10-10 10:03:51 +00:00
Mario
cb44f7e360 dismiss add/remove collection activities until we support themÃ
(cherry picked from commit 16603ca854)

Co-authored-by: Mario <mario@mariovavti.com>
2024-10-10 10:03:32 +00:00
Mario Vavti
2aee659cbd also discard Add/Remove at the AP side 2024-10-10 12:01:46 +02:00
Harald Eilertsen
b117cf9dc7 emove another PHPGit related file. 2024-10-09 23:38:01 +02:00
Mario Vavti
c2ce1d9881 containers: send add in mod like, send remove on delete 2024-10-09 22:43:01 +02:00
Harald Eilertsen
2ed8908127 Remove now unused PHPGit from library. 2024-10-09 21:02:08 +02:00
Harald Eilertsen
6588e272db Remove addon repo management from admin/addons.
This functionality was broken anyways, and needs to be rethought. Addon
reporitories can still be managed from the terminal using the tools in
util/.
2024-10-09 21:00:12 +02:00
Harald Eilertsen
c13645f136 Remove HTML5 parser lib deprecated in Hubzilla 5.0 2024-10-09 18:47:35 +02:00
Mario Vavti
8cee16be1b enable the hooks again 2024-10-09 18:26:15 +02:00
Mario Vavti
45c0091d3d more work on porting containers from streams 2024-10-09 18:17:37 +02:00
Mario
44232677c8 also dismiss add/remove collection activities in fetch_conversation() 2024-10-09 15:41:40 +00:00
Mario
16603ca854 dismiss add/remove collection activities until we support themà 2024-10-09 07:39:13 +00:00
Mario
75184355d0 whitespace and use empty for check 2024-10-06 16:47:15 +00:00
Mario
1988d21e6c start containers 2024-10-06 15:53:39 +00:00
Harald Eilertsen
bccac55cf9 tests: Add some tests for the Zotlabs\Magic module.
Only tests the delegate functionality at the moment.

This patch also includes some minor fixes to the Magic module, triggered
by the tests with empty destination URL's.
2024-10-06 11:47:45 +02:00
Mario
19eeadfe5b port some libs from streams repo 2024-10-06 08:59:36 +00:00
Mario
8f74ee67e3 css fixes
(cherry picked from commit 2693e9e990)

Co-authored-by: Mario <mario@mariovavti.com>
2024-10-04 11:27:56 +00:00
Mario
b0a11537de remove bogus icon id
(cherry picked from commit 04741c761a)

Co-authored-by: Mario <mario@mariovavti.com>
2024-10-04 11:27:40 +00:00
Mario
2693e9e990 css fixes 2024-10-04 11:26:48 +00:00
Mario
04741c761a remove bogus icon id 2024-10-04 11:14:41 +00:00
Mario
4de9cb1142 more fa2bi fixes
(cherry picked from commit 8f890fb6fa)

Co-authored-by: Mario <mario@mariovavti.com>
2024-10-04 11:07:50 +00:00
Mario
8f890fb6fa more fa2bi fixes 2024-10-04 11:06:35 +00:00
Mario
158ddfb009 changelog
(cherry picked from commit 1afb2a4ce8)

Co-authored-by: Mario <mario@mariovavti.com>
2024-10-04 07:09:21 +00:00
Mario
2b4f344181 Version 9.4.2 2024-10-04 07:07:31 +00:00
Mario
1afb2a4ce8 changelog 2024-10-04 07:06:24 +00:00
Mario
2e5f922561 due to popular demand: indicate reacted state via icon color
(cherry picked from commit afbeb58c16)

Co-authored-by: Mario <mario@mariovavti.com>
2024-10-04 06:59:50 +00:00
Mario
a6498a0cfc Reflect change to btn-link in js template
(cherry picked from commit 8ffab25f5d)

Co-authored-by: Mario <mario@mariovavti.com>
2024-10-04 06:59:16 +00:00
Mario
8ffab25f5d Reflect change to btn-link in js template 2024-10-04 06:57:46 +00:00
Mario
1073392398 Fix modal backdrop not removed when like/unlike from the modal
(cherry picked from commit 7d41deebce)

Co-authored-by: Mario <mario@mariovavti.com>
2024-10-04 06:51:15 +00:00
Mario
7d41deebce Fix modal backdrop not removed when like/unlike from the modal 2024-10-04 06:50:06 +00:00
Mario
76064dbb33 Fix missing handle icon in mod pdledit_gui
(cherry picked from commit 7e48caae6b)

Co-authored-by: Mario <mario@mariovavti.com>
2024-10-04 06:27:37 +00:00
Mario
7e48caae6b Fix missing handle icon in mod pdledit_gui 2024-10-04 06:26:34 +00:00
Mario
afbeb58c16 due to popular demand: indicate reacted state via icon color 2024-10-03 08:18:59 +00:00
Mario
1ab4f36a1b Merge branch 'master' of https://framagit.org/hubzilla/core 2024-10-03 04:52:40 +00:00
Mario
cea9c88b9e version 9.4.1 2024-10-03 04:52:18 +00:00
Mario
babe118383 Tests: Unbreak help test.
(cherry picked from commit 5b93aa1148)

Co-authored-by: Harald Eilertsen <haraldei@anduin.net>
2024-10-02 20:27:26 +00:00
Mario
2b140e53cc changelog
(cherry picked from commit 9008760aa6)

Co-authored-by: Mario <mario@mariovavti.com>
2024-10-02 20:21:51 +00:00
Mario
9008760aa6 changelog 2024-10-02 20:20:56 +00:00
Mario
fb1514a782 Help: Drop language specifier in URL when redirecting
This finally fixes the help for languages other than english.


(cherry picked from commit 4daa03f025)

Co-authored-by: Harald Eilertsen <haraldei@anduin.net>
2024-10-02 20:09:36 +00:00
Mario
7679894684 Replace drop shadow in help toc with brighter color.
The drop shadow looked terrible in dark mode. While that could be fixed,
I think it looks better with just using the link hover color and making
the selected item bold.


(cherry picked from commit 8ae9df3bb7)

Co-authored-by: Harald Eilertsen <haraldei@anduin.net>
2024-10-02 20:08:55 +00:00
Mario
520cf1015c Move some help related styling from redbasic to module css.
(cherry picked from commit 25d9d3ba1b)

Co-authored-by: Harald Eilertsen <haraldei@anduin.net>
2024-10-02 20:08:33 +00:00
Mario
64bd8eef4b Use html details element for toc on top of help pages.
This allows us to get rid of some more unneccessary JavaScript that just
implements stuff that web browsers now do anyways.


(cherry picked from commit 26ce231951)

Co-authored-by: Harald Eilertsen <haraldei@anduin.net>
2024-10-02 20:08:04 +00:00
Mario
aa42f6a6b2 Remove link to "Contents" from the help table of contect sidebar.
Changes the element where the jQuery.toc plugin looks for headings to
only include the actual help contents, not the toc itself.


(cherry picked from commit fb9464437e)

Co-authored-by: Harald Eilertsen <haraldei@anduin.net>
2024-10-02 20:07:31 +00:00
Mario
13345d3cbe deps: Upgrade smarty/smarty to version 4.5.4
This eliminates a potential vulnerability where an template author could
inject arbitrary PHP files to be run via the 'extends' tag.

See:
  - https://github.com/smarty-php/smarty/security/advisories/GHSA-4rmg-292m-wg3w
  - 0be92bc8a6

Impact assessment:

In our case I would consider this a low severity issue as we don't
allow users to dynamically add or edit smarty templates. Templates has
to be updated via merge requests, or by installing a theme. In both
cases a malicious attacker already has easier ways to inject whatever
code they want.

Further, the extend tag is not in use in any of our core templates.


(cherry picked from commit 4dff1a1e5b)

Co-authored-by: Harald Eilertsen <haraldei@anduin.net>
2024-10-02 20:06:10 +00:00
Mario
888ee16d52 fix german about page title
(cherry picked from commit 1c45030c58)

Co-authored-by: Mario <mario@mariovavti.com>
2024-10-02 20:05:06 +00:00
Mario
0f3e01f343 markdown: Don't link URLs in code blocks.
When passing a content throught the `markdown_to_bb` function
to convert any markdown in the content, any recognized URLs in the
content would be converted to BBCode links as a post processing step
after the main conversion.

After commit a1ccacb825 this did no longer
consider content within code blocks, and would thus convert them as
to BBCode links.

Example: The following content

	[code]
	example url: https://example.com
	[/code]

Would be converted to

	[code]
	example url: [url=https://example.com]https://example.com[/url]
	[/code]

Prior to commit a1ccacb825, code blocks
would be protected, so this would not happen.

This patch removes the post processing step for converting plain URLs to
links completely from this routine. This functionality is in any case
covered in the actual BBCode parser where it belongs.

This will have some other side effects as well, such as images and links
created using Markdown, will not be converted to [zmg] or [zrl] tags
where that would be done automatically before. If you intend to use a
[zrl] or [zmg] tag, you now need to do so explicitly.


(cherry picked from commit 803cd74b48)

Co-authored-by: Harald Eilertsen <haraldei@anduin.net>
2024-10-02 20:04:30 +00:00
Mario
79220ede66 rewrite sql logic to rename photos - there are more DB queries involved now but the previous logic was throwing error in postgresql (while the result was correct anyway)
(cherry picked from commit a5f0253aef)

Co-authored-by: Mario Vavti <mario@mariovavti.com>
2024-10-02 20:03:54 +00:00
Mario
6b98b799c8 Merge branch 'tests-for-activitystreams' into 'dev'
tests: Add a basic test for ActivityStreams

See merge request hubzilla/core!2146
2024-10-02 13:13:42 +00:00
Mario
9f49d313f5 Merge branch 'markdown/dont-link-urls-in-code-blocks' into 'dev'
markdown: Don't link URLs in code blocks.

See merge request hubzilla/core!2145
2024-10-02 13:10:05 +00:00
Mario Vavti
a5f0253aef rewrite sql logic to rename photos - there are more DB queries involved now but the previous logic was throwing error in postgresql (while the result was correct anyway) 2024-10-02 14:45:10 +02:00
Harald Eilertsen
4e6f871bc4 tests: Add a basic test for ActivityStreams
This is just a basic test that parses a specific object, and tests that
all the referenced objects are fetched from the originating servers.
2024-10-02 09:51:22 +02:00
Harald Eilertsen
803cd74b48 markdown: Don't link URLs in code blocks.
When passing a content throught the `markdown_to_bb` function
to convert any markdown in the content, any recognized URLs in the
content would be converted to BBCode links as a post processing step
after the main conversion.

After commit a1ccacb825 this did no longer
consider content within code blocks, and would thus convert them as
to BBCode links.

Example: The following content

	[code]
	example url: https://example.com
	[/code]

Would be converted to

	[code]
	example url: [url=https://example.com]https://example.com[/url]
	[/code]

Prior to commit a1ccacb825, code blocks
would be protected, so this would not happen.

This patch removes the post processing step for converting plain URLs to
links completely from this routine. This functionality is in any case
covered in the actual BBCode parser where it belongs.

This will have some other side effects as well, such as images and links
created using Markdown, will not be converted to [zmg] or [zrl] tags
where that would be done automatically before. If you intend to use a
[zrl] or [zmg] tag, you now need to do so explicitly.
2024-09-30 13:54:50 +02:00
Mario
0bfdb958f5 update symfony/polyfill-php81 2024-09-30 07:13:55 +00:00
Mario
becd4c6ffd update sabre/vobject 2024-09-30 07:12:30 +00:00
Mario
3f411787c1 update spomky-labs/otphp 2024-09-30 07:11:05 +00:00
Mario
5782a674b0 update ramsey/uuid 2024-09-30 07:09:20 +00:00
Mario
fc79e47d88 update scssphp 2024-09-30 07:07:30 +00:00
Mario
1c45030c58 fix german about page title 2024-09-30 06:29:37 +00:00
Mario
18f3887050 Merge branch 'more-help-improvements' into 'dev'
Fix help for other languages than english

See merge request hubzilla/core!2144
2024-09-30 06:22:28 +00:00
Mario
2cc962e53a Merge branch 'security/update/smarty' into 'dev'
deps: Upgrade smarty/smarty to version 4.5.4

See merge request hubzilla/core!2143
2024-09-30 06:20:48 +00:00
Harald Eilertsen
5b93aa1148 Tests: Unbreak help test. 2024-09-29 14:28:17 +02:00
Harald Eilertsen
4daa03f025 Help: Drop language specifier in URL when redirecting
This finally fixes the help for languages other than english.
2024-09-29 14:09:41 +02:00
Harald Eilertsen
8ae9df3bb7 Replace drop shadow in help toc with brighter color.
The drop shadow looked terrible in dark mode. While that could be fixed,
I think it looks better with just using the link hover color and making
the selected item bold.
2024-09-29 14:00:53 +02:00
Harald Eilertsen
25d9d3ba1b Move some help related styling from redbasic to module css. 2024-09-29 14:00:53 +02:00
Harald Eilertsen
26ce231951 Use html details element for toc on top of help pages.
This allows us to get rid of some more unneccessary JavaScript that just
implements stuff that web browsers now do anyways.
2024-09-29 14:00:45 +02:00
Harald Eilertsen
fb9464437e Remove link to "Contents" from the help table of contect sidebar.
Changes the element where the jQuery.toc plugin looks for headings to
only include the actual help contents, not the toc itself.
2024-09-29 13:58:41 +02:00
Harald Eilertsen
4dff1a1e5b deps: Upgrade smarty/smarty to version 4.5.4
This eliminates a potential vulnerability where an template author could
inject arbitrary PHP files to be run via the 'extends' tag.

See:
  - https://github.com/smarty-php/smarty/security/advisories/GHSA-4rmg-292m-wg3w
  - 0be92bc8a6

Impact assessment:

In our case I would consider this a low severity issue as we don't
allow users to dynamically add or edit smarty templates. Templates has
to be updated via merge requests, or by installing a theme. In both
cases a malicious attacker already has easier ways to inject whatever
code they want.

Further, the extend tag is not in use in any of our core templates.
2024-09-28 15:07:23 +02:00
Mario
b498e50f74 adjust post app icon and remove obsolete arguments
(cherry picked from commit 5cbd42bbc4)

Co-authored-by: Mario <mario@mariovavti.com>
2024-09-27 16:51:57 +00:00
Mario
2c05638776 Merge branch 'cherry-pick-d1811ea1' into 'dev'
Update Spanish strings

See merge request hubzilla/core!2142
2024-09-27 16:39:24 +00:00
Mario
5cbd42bbc4 adjust post app icon and remove obsolete arguments 2024-09-27 16:36:25 +00:00
Manuel Jiménez Friaza
ac6720e118 Update Spanish strings
(cherry picked from commit d1811ea1f3f7249023c51104154d680f09df8572)

Co-authored-by: mjfriaza:4GF~eYj,-iAv <mjfriaza@disroot.org>
2024-09-27 15:36:32 +00:00
Mario
5281f4dd9b update changelog 2024-09-25 19:35:01 +00:00
Mario
c12ef4fbf4 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2024-09-25 09:47:21 +00:00
Mario
424b31b7f0 update changelog 2024-09-25 09:46:57 +00:00
Mario
20ee1a5b5b Merge branch 'remove-tests-from-autoload' into 'dev'
Don't autoload test cases using composer.

See merge request hubzilla/core!2141
2024-09-25 08:40:45 +00:00
Harald Eilertsen
2cd779cbe9 Don't autoload test cases using composer.
Introduces a bootstrap file that ensures that the base test case classes
are loaded and available instead.

This reduces the number of warnings when running composer install.
2024-09-24 13:54:42 +02:00
4334 changed files with 256381 additions and 222365 deletions

View File

@@ -27,23 +27,21 @@ if you look for more choices. The main differences are:
- 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)
- The script under [homeinstall](https://framagit.org/hubzilla/core/-/tree/master/.homeinstall) seems to be an older version of the scripts used for Streams, i.e. [autoinstall](https://codeberg.org/streams/streams/src/branch/dev/contrib/autoinstall) and [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)
+ computer connected to your router (a Raspberry 4 will do for very small Hubs)
Software
+ fresh installation of Debian 12 (bookworm)
+ fresh installation of Debian 12 (bookworm) or Raspberry Pi OS
+ 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.
You can of course run the script on a VPS or any distant server as long as the above software requirements are satisfied.
## How to run the script
@@ -82,6 +80,11 @@ Switch the verification off
util/config system verify_email 0
Check if updates from the repository do work
util/udall
## What the script will do for you...
+ install everything required by your hubzilla instance, basically a web server (Apache), PHP, a database (MySQL), certbot,...
@@ -101,7 +104,7 @@ 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)
- Raspberry 5 with Raspberry Pi OS, Debian 12
- for tesing purposes: under localhost inside a virtual machine, [KVM](https://wiki.debian.org/KVM)
+ DynDNS
- selfHOST.de
@@ -151,8 +154,3 @@ It is recommended to run the Raspi without graphical frontend (X-Server). Use...
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

@@ -93,9 +93,8 @@ freedns_key=
# 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
db_name=hubzilla
db_user=hubzilla
#
#
# Password for package mysql-server

View File

@@ -150,7 +150,7 @@ function install_sendmail {
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"
nocheck_install "libapache2-mod-php php php-pear php-curl php-gd php-mbstring php-xml php-zip php-intl php-bcmath"
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
@@ -160,8 +160,8 @@ 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');"
EXPECTED_CHECKSUM="`wget -qO- https://composer.github.io/installer.sig`"
wget https://getcomposer.org/installer -O composer-setup.php
ACTUAL_CHECKSUM="$(php -r "echo hash_file('sha384', 'composer-setup.php');")"
if [ "$EXPECTED_CHECKSUM" != "$ACTUAL_CHECKSUM" ]
then
@@ -171,6 +171,7 @@ function install_composer {
fi
php composer-setup.php --quiet
RESULT=$?
composer --version
rm composer-setup.php
# exit $RESULT
# We install Composer globally
@@ -181,7 +182,7 @@ function install_composer {
fi
cd $install_path
export COMPOSER_ALLOW_SUPERUSER=1;
/usr/local/bin/composer install --no-dev
/usr/local/bin/composer install --no-dev --quiet
/usr/local/bin/composer show
export COMPOSER_ALLOW_SUPERUSER=0;
}
@@ -256,12 +257,18 @@ function create_zotserver_db {
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';"
Q3="GRANT ALL PRIVILEGES ON $db_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"
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 $db_name.* to $db_user@localhost identified by '$db_pass';"
Q4="FLUSH PRIVILEGES;"
SQL="${Q1}${Q2}${Q3}${Q4}"
mysql -uroot -p$mysqlpass -e "$SQL"
fi
}
@@ -301,10 +308,19 @@ function install_run_selfhost {
# 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
if [ ! -f $selfhostdir/$selfhostscript ]
then
wget --output-document=$selfhostdir/$selfhostscript https://jonaspasche.de/selfhost-updater
if [ ! -s $selfhostdir/$selfhostscript ]
then
die "Failed to download selfHOST file for dynDNS"
fi
echo "router" > $selfhostdir/device
echo "$selfhost_user" > $selfhostdir/user
echo "$selfhost_pass" > $selfhostdir/pass
print_info "Wrote file to update dynamic IP. File: $selfhostdir/$selfhostscript"
fi
print_info "executing $selfhostdir/$selfhostscript update..."
bash $selfhostdir/$selfhostscript update
fi
}
@@ -380,7 +396,7 @@ function install_letsencrypt {
then
die "Failed to install let's encrypt: 'le_email' is empty in $configfile"
fi
nocheck_install "certbot python-certbot-apache"
nocheck_install "certbot python3-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
@@ -435,7 +451,7 @@ function configure_cron_daily {
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 "systemctl stop mysql.service # 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

16
.gitignore vendored
View File

@@ -48,9 +48,10 @@ doc/html/
.zotshrc
# external repositories for themes/addons
extend/
# files generated by phpunit
# exclude test results and cache
tests/.cache
tests/.phpunit.result.cache
tests/.phpunit*
tests/results/
## exclude IDE files
@@ -67,7 +68,6 @@ nbproject/
# PHPStorm
.idea/
## composer
# locally installed composer binary
composer.phar
@@ -87,6 +87,7 @@ vendor/bin/php-parse
vendor/bin/phpcbf
vendor/bin/phpcs
vendor/bin/phpmd
vendor/bin/phpstan*
vendor/bin/phpunit
vendor/composer/pcre/
vendor/composer/xdebug-handler/
@@ -98,18 +99,11 @@ vendor/pdepend/
vendor/phar-io/
vendor/php-mock/
vendor/phpmd/
vendor/phpstan
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

@@ -32,7 +32,8 @@ before_script:
- 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
- docker-php-ext-configure gd --with-jpeg=/usr/include/
- docker-php-ext-install gd bcmath intl pdo_mysql pdo_pgsql zip exif
# Install composer
- curl -sS https://getcomposer.org/installer | php
@@ -58,7 +59,7 @@ before_script:
- 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 --no-progress --stop-on-error --coverage-text --colors=never --log-junit tests/results/junit.xml || exit_code=$?
- vendor/bin/phpunit -d memory_limit=256M --configuration tests/phpunit.xml --no-progress --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+\%/'
@@ -83,7 +84,7 @@ before_script:
- 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 --no-progress --stop-on-error --coverage-text --colors=never --log-junit tests/results/junit.xml || exit_code=$?
- vendor/bin/phpunit -d memory_limit=256M --configuration tests/phpunit.xml --no-progress --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+\%/'

View File

@@ -48,6 +48,10 @@
<exclude name="Generic.Files.OneClassPerFile.MultipleFound"/>
<exclude name="Generic.Files.OneObjectStructurePerFile.MultipleFound"/>
<exclude name="Generic.Formatting.SpaceAfterCast.NoSpace"/>
<exclude name="Generic.Classes.OpeningBraceSameLine.BraceOnNewLine" />
<exclude name="Generic.WhiteSpace.DisallowSpaceIndent.SpacesUsed" />
<exclude name="Generic.Functions.OpeningFunctionBraceKernighanRitchie.BraceOnNewLine" />
</rule>
<!--

342
CHANGELOG
View File

@@ -1,3 +1,345 @@
Hubzilla 10.4.2 (2025-08-08)
- Implement item_custom_display hook in mod HQ
- Refactor item fetching functions to reflect item_normal() changes
- Refactor item_normal() to optionally deal with various item types
- Fix missing reactions modal in threaded_conversation.tpl
- Improve memory consumption in drop_related() to fix deleting of big threads
- Fix PHP error with the potential to stuff up the queueworker
- Update the contact edit header so that both, image and text are linked to the profile
- Articles: refactor to reflect item_normal() changes
- Cards: refactor to reflect item_normal() changes
Hubzilla 10.4.1 (2025-07-31)
- Fix regression in pubstream tag view
- Fix photos meta data not updated when renaming folder in files app
- Fix syntax error in custom emoji sample code
- Fix rendering issue when image load event triggered after timeout
- Fix comment preview not always displayed
- Fix new created comment rendering offscreen
- Update derived theme tutorial and add it to the help index
- Add 'extends' attribute to theme info
- Fix reply modal remaining hidden after reactions loaded
- Refactor tagcloud to use smarty template file
- Fix regression in tagadelic
- Fix possible performance issue with archive widget
- Fix various addons which still used the deprecated $a global
Hubzilla 10.4 (2025-07-15)
- Add support for did:key verification method to checkEddsaSignature()
- Introduce util/init_sys_channel to create the sys channel if required
- Update norwegian translations
- Add init_sys_channel utility to create the sys channel in case of headless installation or failure
- Upgrade http-message-signer to version 2.3
- Upgrade phpseclib to version 3
- Minor cleanup to the account functions and added tests
- Do not sign (request-target) on response
- Start verifying incoming RFC9421 HTTP signatures
- Convert geo URIs into clickable links
- Allow geo URIs in url bbcode tags
- Cleanup obsolete and unused functions
- Remove unused Xref module
- Make sure we have the keys before attempting to sign with JcsEddsa2022
- Implement lazy loading of toplevel comments
- Update german help files
- Add App::$page_layouts attribute for comanche
- Refactor and fix numerous issues in guess_image_type()
- Add tests for Widget\Messages
- Refactor cache_embeds daemon to be called with uuid (instead of item id) so that it will only be processed once
- Add avif support for php-gd
- Exclude Add/Remove items from network nouveau query
- Always preload images and remove pre image preload setting
- Introduce per channel conversation mode setting
- Add API docs for the observer file
- Move observer helper functions to separate source
- Introduce helper functions to access the various fields of the xchan stored in App::$observer
- Refactor item_normal() to accept an owner uid
- Implement reply modal if comment replies are enabled
- Streamline wording conversation > comment > reply
- Streamline default ordering to created date
- Default to threaded conversation mode
- Implement lazy loading of reactions
- Do not store dismissed create activities in dreport
- Refactor mod item to deprecate x() and use $_POST instead of $_REQUEST superglobal
- Improved styling for dreport module
- Start deprecation of the function x()
- Minor cleanup and refactor for Web/Router
- Minor cleanup and refactor for Lib/Webserver
- Set App::$query_string from from server.request_uri instead of server.query_string because the latter will mostly be urldecoded by the server already
- Refactor language selector
- Extend message filter to support until=2025-04-18 20:49:00 for date/time based filtering and add tests
- Extend message filter to deal with && and || conditions and add tests
- Prevent storing files/folder with filenames exceeding their max name length
- Deal with attachment of type link
- Revert translation of network to stream
- Updated debian install script
- Add suport for strong bbcode tag
- Change photo.filename to type text for new installs
- Provide methods to get mid and uuid from activity object
- Minor update for boxy schema
- Update composer libs
- Reorganize emojis and allow custom site emojis
- Change item.obj and item.target to mediumtext for mysql new installs
- Move jot related functions to jot-header and some cleanup
- Port photo selector to vanilla javascript
- Enable photo selector for comments if OCAP access is enabled
- Add :hubzilla: emoji
- Add :zot: emoji
- Include unapproved connections in deliverable_abook_xchans()
- Port showHideComments() to vanilla javascript
- Disable browser rotating image based on EXIF metadata
Bugfixes
- Fix blog mode if threaded view is disabled
- Fix markdown issue with mentions
- Fix issue where item_wall was not set for article and card item types
- Fix first created account was not necessarily the admin account
- Fix notice not emited on failed login
- Fix intro notifications not handled via /notify/view and hence not marked seen
- Fix undefined static function in Zot6Handler
- Fix missing return in Render\Theme::current
- Fix announce source title (addr) not correct
- Fix offset calculation if element position is relative
- Fix autosave for comments
- Fix notfication issue with update activities
- Fix sess_data not updated to mediumtext in mysql schema file
- Fix title and summary converted to bbcode
- Fix preloading images if dom element is not yet in page
- Fix verb and hash for notifications
- Fix notification button for medium screen size (right aside collapsed)
- Fix new result set created for updated results (dreport)
- Fix regex to catch codeblocks with params like class in smilies()
- Fix term.imgurl not stored in item_store_update()
- Fix folder names are not URL escaped in Files app (issue #1903)
- Fix stephenhill/base58 PHP warnings
- Fix color bbcode markup
- Fix video poster display issue
- Fix relayed emoji reactions
- Fix some javascript errors on mobile devices
- Fix our own activities visible in unseen forum notifications
- Fix duplicated head_get_icon()
Addons
- Wiki: fix spacing in wikilist widget
- Gallery: look for templates in theme directory first
- Articles: look for templates in theme directory first
- Wiki: look for templates in theme directory first
- Pubcrawl: remove unused force note setting
- Flashcards: major refactor and added functionality
- Superblock: refactor and new siteblock option for admins
- Cart: fix issue related to HTTP3
- Pubcrawl: avoid DB lookup if not valid AS request in mod followers and mod following
- Photocache: implement prefetch via cache_embeds daemon and minor refactor
- Articles: fix Add/Remove activities not dismissed in channel activities query
- Cards: fix Add/Remove activities not dismissed in channel activities query
- Diaspora: make sure item_thread_top is set for reshares (info for filters)
- Gallery: fix missing folder field from query
- Pubcrawl: update mod ap_probe to show a visual representation if applicable
Hubzilla 10.2.3 (2025-04-11)
- Fix bogus merge from 10.2.2 release
Hubzilla 10.2.2 (2025-04-11)
- Cleanup deprecated forum queries, improved performance
- Fix zot6 handler returning success allthough Libzot::fetch() did not return anything useful
- Fix json encoding of a possibly empty item.target
- Fix permalink for forum posts and comments
- Fix an obscure delivering issue which could produce duplicate posts
- Lazy load profile photos for reactions to reduce server load
- Pubcrawl: deal with Update(Tombstone)
- Pubcrawl: fix mentions not mapped to "to" in public toplevel posts (regression)
Hubzilla 10.2.1 (2025-03-18)
- Fix OWA in cases where Signature is in the REDIRECT_REMOTE_USER field
- Fix query in mod sse_bs
Hubzilla 10.2 (2025-03-17)
- Allow to send signed requests from the zot_probe tool
- Print an error message if OWA fails
- Remove possible leading @ before processing webfinger address
- Updated debian install script
- Calculate observer.baseurl from xchan_url instead of xchan_connurl
- Refactor unparse_url() to allow return of a custom field set only and add tests
- Slightly improve event object rendering
- Update smarty library to version 5 for PHP 8.4 compatibility
- Remove vendor/symfony from gitignore file
- Update composer libraries
- Add contextHistory field to activities and prefer it over context when consuming
- Implement highlight button in jot editor
- Add test results and PHPStan to gitignore
- Update spanish strings
- Remove EpubMeta library in favor of a custom solution
- Configue gd for jpeg support in CI
- Add error message on missing owa auth headers
- Add Zotlabs\Tests namespace to autloader in dev
- Add dba_pdo::update method
- Add dba_pdo::insert method
- Rewrite redbasic javascript to remove jquery dependency
- Add security policy SECURITY.md
Bugfixes
- Fix notifications for likes on our comments
- Fix fullscreen view
- Fix boxy scheme text alignment for comments
- Fix poll date string to match with the autotime string
- Fix owner hash not set correctly when editing a post/comment
- Fix an issue where some participants could not post to forums
- Fix navbar selector conflict with possible additional navbars when using a cover photo
- Fix target and tgt_type not set for sourced rss items if we rewrite them to our own
- Fix auto save draft not set correctly
- Fix cover height calculation
Addons
- Diaspora: revisit import_diaspora_account()
- Pubcrawl: escape quotation marks in ActivityStreams link header
- Wiki: fixed wiki_page_list.tpl to use bootstrap class for layout
- BBmath: fix orientation for inline math
- BBmath: document imagemagick permissions
- Pubcrawl: ensure we select the correct hubloc hash when extending recipients list
- Msg_footer: do not add footer on edit, also dismiss anything but a create activity
- Pubcrawl: refactor activitypub addressing
- Wiki: added space to preview panel
- Startpage: update help text and some cleanup
Hubzilla 10.0.8 (2025-02-01)
- Fix duplicating terms/iconfig in addToCollectionAndSync()
- Refactor Daemon/Importdoc for better SQL performance when looking up outdated entries
- Tweak SQL in mod sse_bs for possible performance improvements
- Fix PHP warnings
- Do not run post_local hook on add activities in pubcrawl addon
- Do not run post_local hook on add activities in diaspora addon
- Remove old rawmsg/fields before storing new rawmsg in pubcrawl addon
- Fix retractions in diaspora addon
Hubzilla 10.0.7 (2025-01-22)
- Fix ownership check in consume_feed()
- Fix toast() if notification contains non-ascii characters
- Fix regression in notifications filter
Hubzilla 10.0.6 (2025-01-05)
- Fix entries where primary location data is not complete not dismissed early
- Fix query to cleanup outdated doc entries called multiple times
- Fix query to cleanup outdated doc entries
Hubzilla 10.0.5 (2024-12-29)
- Fix another instance of drop_item() not having permission to drop items
Hubzilla 10.0.4 (2024-12-26)
- Fix missing argument name
Hubzilla 10.0.3 (2024-12-26)
- Fix regression in Daemon/Channel_purge which could cause a possible infinite loop
- Fix regression in Daemon/Expire which could cause a infinite loop
Hubzilla 10.0.2 (2024-12-25)
- Hotfix comment out Daemon/Expire
- Fix zid parameter allowed to override an existing remote login
- Slightly improved imagesLoaded()
Hubzilla 10.0.1 (2024-12-22)
- Revert removing of openid library
- Fix SQL query in Daemon/Importdoc
Hubzilla 10.0 (2024-12-21)
- Port updateConvItem() and notifications widget to vanilla javascript
- Remove jquery.timeago.js in favor of a native js implementation
- Introduce item_forwardable() a function to check if an item should be frowarded
- Always set item_delayed flag if we use a custom created date
- Add indicators to items in case they are delayed, have an expiration time or commenting is disabled
- Introduce relative_time() a new function to calculate the relative time
- Refactor mod admin/accounts
- Toggle aside if a notification or message is clicked
- Add Mailer class to replace z_mail()
- Provide a possibility to link to a specific day or month in mod cal via URL fragment e.g. #2024-12-24
- Refactor mod magic
- Introduce conversation containers a.k.a. FEP-171b
- Refactor mod item
- Refactor Thumbs\Epubthumb to adapt to new version of EPub meta lib
- Remove unused libraries
- Bring filed items to mod hq
Bugfixes
- Fix comments on/off toggle
- Fix various missing icons after transition from fork-awesome
- Fix performance issue in mod pubstream
- Fix mails with + in local part rejected
- Fix % calculation in mod import_progress
- Fix query vars not unset when constructing the server address
- Fix can_comment_on_post() logic after introduction of repeats
- Fix xchan_query() not including deleted hublocs
- Fix allday variable not set when clicking an event or a resource is provided
Addons
- Introduce conversation containers a.k.a. FEP-171b
- Cards: fix comments on/off state
- Articles: fix comments on/off state
- Pubcrawl: fix encoding of stored raw message
- Gallery fix zoom icon toggle
- Pubcrawl: fix follow to non primary hub location
- Pubcrawl: rewrite id host to local host instead of primary host
Hubzilla 9.4.4 (2024-11-06)
- Update Norwegian translations
- Fix error adding things when multiple profiles not enabled
- Port mod thing to use $_GET/$_POST instead of $_REQUEST
- Move Norwegian translations from nb-no to nb
- Fix intact alernative network hublocs being marked deleted in Libsync::sync_locations()
- Fix modals only partly removed when DOM emlement updated via ajax
- Add explicit check for channel_address in channel_url()
- Fix PHP deprecation warnings in mod setup
- Fix PHP warning in Web/HttpMeta
- Fix typo in UnitTestCase
- Fix missing CSRF token checks in mod account_edit
- Fix OCAP tokens only added to images
- Fix unescaped zid parameter
- Fix wrong date format in published date in update question activities
- Fix include for en TOS page
- Fix query in copy_of_pubitem() returning duplicate items
- Fix edit button not clickable if below right aside when viewing webpages
- Fix rendering of category tags icons in the editor
- Fix regex to detect URLs in cleanup_bbcode
- Fix duplicate posts from forum clones
- Fix follow to non primary hub location in pubcrawl addon
- Fix id host not rewritten to local host in pubcrawl addon
- Fix regression when manually fetching items in pubcrawl addon
Hubzilla 9.4.3 (2024-10-10)
- Discard Add/Remove activities (Hubzilla 10 and (streams) compatibility)
- Fix HQ channel activities icons
- Fix saved search icons
Hubzilla 9.4.2 (2024-10-04)
- Indicate reacted state via icon color (community wish)
- Fix modal backdrop not removed when reacting from the modal
- Fix missing handle icon in mod pdledit_gui
Hubzilla 9.4.1 (2024-10-02)
- Various fixes for the help module
- Update smarty library via composer
- Fix URLs replaced with bbcode in codeblocks if markdown enabled
- Fix unable to move multiple files when using postgresql DB backend
- Adjust icon for post app
- Fix check for while loop in wiki addon
Hubzilla 9.4 (2024-09-25)
- If we got an ocap token try to authenticate with it first
- Hide comment titles

View File

@@ -1,48 +0,0 @@
"air" is a branch name for revision of Account-Invite-Register at the Hubzilla project
Invite:
* Rewritten and now language template driven
* Selectable templates for the invite mails
* Invitor may add personal notes in the mailtext
+ Invite codes are bound to the recipients email address
* Invite mod never more creates accounts
* new db scheme for table register
* existing register table will be migrated to the new schema even when detected at runtime
* Bugfix: creating invite codes when admin only calls Invite w/o any further action
* account library revision also together with invite mod
* Depending on config: Users may send invitations also
* Invitations expires, controlled by the invitor
* Changed and new configs:
* * invitation_only As usual before
* * invitation_also Beside other registration policies, invitations may be used also
* * invitation_max_per_day defaults 50, may be changed in adminUI admin>site
* * invitation_max_per_user defaults 4
* Requirements:
* * Addon language has to be installed
Register:
* Register panel (form) and js interaction changed
* Unused registrations expire
* Depending on config, anonymous registrations (w/o email) are supported
* :... dont't panic, that may let grow security
* Even anonymous users have to confirm their registration
* Registrations may be enabled / disabled time driven for each day in the week (dudy)
* Unsoliced registration floods may be blocked
* Limited registrations from one single source ip
* Using one additional log file, to easy interfare with f2b
Account:
* An user account always becomes created only if all depending conditions are satisfied
* AdminUI for site configuration, accounts and registrations enhancements
* Still untouched, but accountUI needs enhanced async control in case for mass delete
with deep level of recursion cascade of the dependencies (channels etc). An open TODO
since years for instances with many much users and channels.
History:
2020.03 Hubzilla Prod version 4.6 (master branch) of hubzilla/core was the base for AIR
that was assigned Version 4.6.2 at sn/core
2021.02 Hubzilla Prod version 5.2.1 (master branch) of hubzilla/core was new base for AIR
that was assigned version 5.2.2 at sn/core (air.5)
plus adjustment of hubzilla 5.2.2 (master) to sn/core (air.5) version 5.2.9

31
SECURITY.md Normal file
View File

@@ -0,0 +1,31 @@
# Hubzilla Security Policy
The [Hubzilla] Project takes security, privacy and user control over personal data seriously. We ask that any security issues be disclosed to us in a responsible manner to allow us time to remediate the issues, and site administrators time to upgrade before information about the issue is made public.
This document outlines security procedures and policies for the Hubzilla project. It covers the following components:
* The Hubzilla core repository: https://framagit.org/hubzilla/core
* The official addon repository: https://framagit.org/hubzilla/addons
* The official themes repository: https://framagit.org/hubzilla/themes
* The official widgets repository: https://framagit.org/hubzilla/widgets
## Coordinated Disclosure Guidelines
We are committed to working with security researchers to verify, reproduce, and respond to legitimate reported vulnerabilities. You can help us by following these simple guidelines:
* Submit suspected vulnerabilities by email to `security@hubzilla.org`, or as a confidential issue in the relevant repository listed above.
* Provide clear instructions on how to reproduce the issue, and if possible, a minimal Proof of Concept (PoC) exploit.
* We will acknowledge your submission as soon as we can, and will keep you updated as it is being processed. We may ask for more information, or clarifications about the issue or the steps to reproduce it during this time.
* We will assign a CVE to the issue once it is confirmed.
* We will do our best to fix the issue as soon as we can after it has been confirmed. We request that information about the vulnerability or details about how to exploit it is not disclosed to other parties until after the fix is released and some time has passed, to allow site administrators to upgrade. We will normally make the CVE public one month after a fix has been released. (This grace period can differ based on severity, and can be negotiated.)
* Please perform all tests against a local instance of the software, and refrain from running any Denial of Service or automated testing tools against public hubs or the project managers (and their partners') infrastructure.
* If the issue belongs to a third party module that we depend on, we may help with reporting it upstream if the submitter wants us to.
## Comments on this Policy
We welcome comments and suggestions for improving this policy. You can reach us at:
* Our ticketing system: https://framagit.org/hubzilla/core/-/issues
* By sending us an email at `security@hubzilla.org`.
[Hubzilla]: https://hubzilla.org

View File

@@ -0,0 +1,776 @@
<?php
namespace Zotlabs\ActivityStreams;
use Zotlabs\Lib\BaseObject;
class ASObject extends BaseObject
{
public $id;
public $type;
public $attachment;
public $attributedTo;
public $audience;
public $content;
public $context;
public $name;
public $endTime;
public $generator;
public $icon;
public $image;
public $inReplyTo;
public $location;
public $preview;
public $published;
public $replies;
public $startTime;
public $summary;
public $tag;
public $updated;
public $url;
public $to;
public $bto;
public $cc;
public $bcc;
public $mediaType;
public $duration;
public $source;
// Extension properties
public $signature;
public $proof;
public $sensitive;
public $replyTo;
public $wall;
public $isContainedConversation;
public $expires;
public $canReply;
public $canSearch;
public $directMessage;
public $commentPolicy;
/**
* @return mixed
*/
public function getDirectMessage()
{
return $this->directMessage;
}
/**
* @param mixed $directMessage
* @return ASObject
*/
public function setDirectMessage($directMessage)
{
$this->directMessage = $directMessage;
return $this;
}
/**
* @return mixed
*/
public function getSignature()
{
return $this->signature;
}
/**
* @param mixed $signature
* @return ASObject
*/
public function setSignature($signature)
{
$this->signature = $signature;
return $this;
}
/**
* @return mixed
*/
public function getProof()
{
return $this->proof;
}
/**
* @param mixed $proof
* @return ASObject
*/
public function setProof($proof)
{
$this->proof = $proof;
return $this;
}
/**
* @return mixed
*/
public function getSensitive()
{
return $this->sensitive;
}
/**
* @param mixed $sensitive
* @return ASObject
*/
public function setSensitive($sensitive)
{
$this->sensitive = $sensitive;
return $this;
}
/**
* @return mixed
*/
public function getReplyTo()
{
return $this->replyTo;
}
/**
* @param mixed $replyTo
* @return ASObject
*/
public function setReplyTo($replyTo)
{
$this->replyTo = $replyTo;
return $this;
}
/**
* @return mixed
*/
public function getWall()
{
return $this->wall;
}
/**
* @param mixed $wall
* @return ASObject
*/
public function setWall($wall)
{
$this->wall = $wall;
return $this;
}
/**
* @return mixed
*/
public function getIsContainedConversation()
{
return $this->isContainedConversation;
}
/**
* @param mixed $isContainedConversation
* @return ASObject
*/
public function setIsContainedConversation($isContainedConversation)
{
$this->isContainedConversation = $isContainedConversation;
return $this;
}
/**
* @return mixed
*/
public function getExpires()
{
return $this->expires;
}
/**
* @param mixed $expires
* @return ASObject
*/
public function setExpires($expires)
{
$this->expires = $expires;
return $this;
}
/**
* @return mixed
*/
public function getCanReply()
{
return $this->canReply;
}
/**
* @param mixed $canReply
* @return ASObject
*/
public function setCanReply($canReply)
{
$this->canReply = $canReply;
return $this;
}
/**
* @return mixed
*/
public function getCanSearch()
{
return $this->canSearch;
}
/**
* @param mixed $canSearch
* @return ASObject
*/
public function setCanSearch($canSearch)
{
$this->canSearch = $canSearch;
return $this;
}
/**
* @return mixed
*/
public function getCommentPolicy()
{
return $this->commentPolicy;
}
/**
* @param mixed $commentPolicy
* @return ASObject
*/
public function setCommentPolicy($commentPolicy)
{
$this->commentPolicy = $commentPolicy;
return $this;
}
/**
* @return mixed
*/
public function getId()
{
return $this->id;
}
/**
* @param mixed $id
* @return ASObject
*/
public function setId($id)
{
$this->id = $id;
return $this;
}
/**
* @return mixed
*/
public function getType()
{
return $this->type;
}
/**
* @param mixed $type
* @return ASObject
*/
public function setType($type)
{
$this->type = $type;
return $this;
}
/**
* @return mixed
*/
public function getAttachment()
{
return $this->attachment;
}
/**
* @param mixed $attachment
* @return ASObject
*/
public function setAttachment($attachment)
{
$this->attachment = $attachment;
return $this;
}
/**
* @return mixed
*/
public function getAttributedTo()
{
return $this->attributedTo;
}
/**
* @param mixed $attributedTo
* @return ASObject
*/
public function setAttributedTo($attributedTo)
{
$this->attributedTo = $attributedTo;
return $this;
}
/**
* @return mixed
*/
public function getAudience()
{
return $this->audience;
}
/**
* @param mixed $audience
* @return ASObject
*/
public function setAudience($audience)
{
$this->audience = $audience;
return $this;
}
/**
* @return mixed
*/
public function getContent()
{
return $this->content;
}
/**
* @param mixed $content
* @return ASObject
*/
public function setContent($content)
{
$this->content = $content;
return $this;
}
/**
* @return mixed
*/
public function getContext()
{
return $this->context;
}
/**
* @param mixed $context
* @return ASObject
*/
public function setContext($context)
{
$this->context = $context;
return $this;
}
/**
* @return mixed
*/
public function getName()
{
return $this->name;
}
/**
* @param mixed $name
* @return ASObject
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* @return mixed
*/
public function getEndTime()
{
return $this->endTime;
}
/**
* @param mixed $endTime
* @return ASObject
*/
public function setEndTime($endTime)
{
$this->endTime = $endTime;
return $this;
}
/**
* @return mixed
*/
public function getGenerator()
{
return $this->generator;
}
/**
* @param mixed $generator
* @return ASObject
*/
public function setGenerator($generator)
{
$this->generator = $generator;
return $this;
}
/**
* @return mixed
*/
public function getIcon()
{
return $this->icon;
}
/**
* @param mixed $icon
* @return ASObject
*/
public function setIcon($icon)
{
$this->icon = $icon;
return $this;
}
/**
* @return mixed
*/
public function getImage()
{
return $this->image;
}
/**
* @param mixed $image
* @return ASObject
*/
public function setImage($image)
{
$this->image = $image;
return $this;
}
/**
* @return mixed
*/
public function getInReplyTo()
{
return $this->inReplyTo;
}
/**
* @param mixed $inReplyTo
* @return ASObject
*/
public function setInReplyTo($inReplyTo)
{
$this->inReplyTo = $inReplyTo;
return $this;
}
/**
* @return mixed
*/
public function getLocation()
{
return $this->location;
}
/**
* @param mixed $location
* @return ASObject
*/
public function setLocation($location)
{
$this->location = $location;
return $this;
}
/**
* @return mixed
*/
public function getPreview()
{
return $this->preview;
}
/**
* @param mixed $preview
* @return ASObject
*/
public function setPreview($preview)
{
$this->preview = $preview;
return $this;
}
/**
* @return mixed
*/
public function getPublished()
{
return $this->published;
}
/**
* @param mixed $published
* @return ASObject
*/
public function setPublished($published)
{
$this->published = $published;
return $this;
}
/**
* @return mixed
*/
public function getReplies()
{
return $this->replies;
}
/**
* @param mixed $replies
* @return ASObject
*/
public function setReplies($replies)
{
$this->replies = $replies;
return $this;
}
/**
* @return mixed
*/
public function getStartTime()
{
return $this->startTime;
}
/**
* @param mixed $startTime
* @return ASObject
*/
public function setStartTime($startTime)
{
$this->startTime = $startTime;
return $this;
}
/**
* @return mixed
*/
public function getSummary()
{
return $this->summary;
}
/**
* @param mixed $summary
* @return ASObject
*/
public function setSummary($summary)
{
$this->summary = $summary;
return $this;
}
/**
* @return mixed
*/
public function getTag()
{
return $this->tag;
}
/**
* @param mixed $tag
* @return ASObject
*/
public function setTag($tag)
{
$this->tag = $tag;
return $this;
}
/**
* @return mixed
*/
public function getUpdated()
{
return $this->updated;
}
/**
* @param mixed $updated
* @return ASObject
*/
public function setUpdated($updated)
{
$this->updated = $updated;
return $this;
}
/**
* @return mixed
*/
public function getUrl()
{
return $this->url;
}
/**
* @param mixed $url
* @return ASObject
*/
public function setUrl($url)
{
$this->url = $url;
return $this;
}
/**
* @return mixed
*/
public function getTo()
{
return $this->to;
}
/**
* @param mixed $to
* @return ASObject
*/
public function setTo($to)
{
$this->to = $to;
return $this;
}
/**
* @return mixed
*/
public function getBto()
{
return $this->bto;
}
/**
* @param mixed $bto
* @return ASObject
*/
public function setBto($bto)
{
$this->bto = $bto;
return $this;
}
/**
* @return mixed
*/
public function getCc()
{
return $this->cc;
}
/**
* @param mixed $cc
* @return ASObject
*/
public function setCc($cc)
{
$this->cc = $cc;
return $this;
}
/**
* @return mixed
*/
public function getBcc()
{
return $this->bcc;
}
/**
* @param mixed $bcc
* @return ASObject
*/
public function setBcc($bcc)
{
$this->bcc = $bcc;
return $this;
}
/**
* @return mixed
*/
public function getMediaType()
{
return $this->mediaType;
}
/**
* @param mixed $mediaType
* @return ASObject
*/
public function setMediaType($mediaType)
{
$this->mediaType = $mediaType;
return $this;
}
/**
* @return mixed
*/
public function getDuration()
{
return $this->duration;
}
/**
* @param mixed $duration
* @return ASObject
*/
public function setDuration($duration)
{
$this->duration = $duration;
return $this;
}
/**
* @return mixed
*/
public function getSource()
{
return $this->source;
}
/**
* @param mixed $source
* @return ASObject
*/
public function setSource($source)
{
$this->source = $source;
return $this;
}
}

View File

@@ -0,0 +1,122 @@
<?php
namespace Zotlabs\ActivityStreams;
class Activity extends ASObject
{
public $actor;
public $object;
public $target;
public $result;
public $origin;
public $instrument;
/**
* @return mixed
*/
public function getActor()
{
return $this->actor;
}
/**
* @param mixed $actor
* @return Activity
*/
public function setActor($actor)
{
$this->actor = $actor;
return $this;
}
/**
* @return mixed
*/
public function getObject()
{
return $this->object;
}
/**
* @param mixed $object
* @return Activity
*/
public function setObject($object)
{
$this->object = $object;
return $this;
}
/**
* @return mixed
*/
public function getTarget()
{
return $this->target;
}
/**
* @param mixed $target
* @return Activity
*/
public function setTarget($target)
{
$this->target = $target;
return $this;
}
/**
* @return mixed
*/
public function getResult()
{
return $this->result;
}
/**
* @param mixed $result
* @return Activity
*/
public function setResult($result)
{
$this->result = $result;
return $this;
}
/**
* @return mixed
*/
public function getOrigin()
{
return $this->origin;
}
/**
* @param mixed $origin
* @return Activity
*/
public function setOrigin($origin)
{
$this->origin = $origin;
return $this;
}
/**
* @return mixed
*/
public function getInstrument()
{
return $this->instrument;
}
/**
* @param mixed $instrument
* @return Activity
*/
public function setInstrument($instrument)
{
$this->instrument = $instrument;
return $this;
}
}

View File

@@ -0,0 +1,428 @@
<?php
namespace Zotlabs\ActivityStreams;
class Actor extends ASObject
{
public $inbox;
public $outbox;
public $followers;
public $following;
public $permissions; /* extension property */
public $endpoints;
public $publicKey;
public $preferredUsername;
public $alsoKnownAs;
// Extension properties
public $movedTo;
public $copiedTo;
public $discoverable;
public $manuallyApprovesFollowers;
public $webfinger;
public $canSearch;
public $indexable;
public $assertionMethod;
public $gateways;
public $openwebauth;
public $authredirect;
/**
* @return mixed
*/
public function getAlsoKnownAs()
{
return $this->alsoKnownAs;
}
/**
* @param mixed $alsoKnownAs
* @return Actor
*/
public function setAlsoKnownAs($alsoKnownAs)
{
$this->alsoKnownAs = $alsoKnownAs;
return $this;
}
/**
* @return mixed
*/
public function getMovedTo()
{
return $this->movedTo;
}
/**
* @return mixed
*/
public function getCopiedTo()
{
return $this->copiedTo;
}
/**
* @param mixed $copiedTo
* @return Actor
*/
public function setCopiedTo($copiedTo)
{
$this->copiedTo = $copiedTo;
return $this;
}
/**
* @param mixed $movedTo
* @return Actor
*/
public function setMovedTo($movedTo)
{
$this->movedTo = $movedTo;
return $this;
}
/**
* @return mixed
*/
public function getDiscoverable()
{
return $this->discoverable;
}
/**
* @param mixed $discoverable
* @return Actor
*/
public function setDiscoverable($discoverable)
{
$this->discoverable = $discoverable;
return $this;
}
/**
* @return mixed
*/
public function getManuallyApprovesFollowers()
{
return $this->manuallyApprovesFollowers;
}
/**
* @param mixed $manuallyApprovesFollowers
* @return Actor
*/
public function setManuallyApprovesFollowers($manuallyApprovesFollowers)
{
$this->manuallyApprovesFollowers = $manuallyApprovesFollowers;
return $this;
}
/**
* @return mixed
*/
public function getPreferredUsername()
{
return $this->preferredUsername;
}
/**
* @param mixed $preferredUsername
* @return Actor
*/
public function setPreferredUsername($preferredUsername)
{
$this->preferredUsername = $preferredUsername;
return $this;
}
/**
* @return mixed
*/
public function getId()
{
return $this->id;
}
/**
* @param mixed $id
* @return Actor
*/
public function setId($id)
{
$this->id = $id;
return $this;
}
/**
* @return mixed
*/
public function getType()
{
return $this->type;
}
/**
* @param mixed $type
* @return Actor
*/
public function setType($type)
{
$this->type = $type;
return $this;
}
/**
* @return mixed
*/
public function getInbox()
{
return $this->inbox;
}
/**
* @param mixed $inbox
* @return Actor
*/
public function setInbox($inbox)
{
$this->inbox = $inbox;
return $this;
}
/**
* @return mixed
*/
public function getOutbox()
{
return $this->outbox;
}
/**
* @param mixed $outbox
* @return Actor
*/
public function setOutbox($outbox)
{
$this->outbox = $outbox;
return $this;
}
/**
* @return mixed
*/
public function getFollowers()
{
return $this->followers;
}
/**
* @param mixed $followers
* @return Actor
*/
public function setFollowers($followers)
{
$this->followers = $followers;
return $this;
}
/**
* @return mixed
*/
public function getFollowing()
{
return $this->following;
}
/**
* @param mixed $following
* @return Actor
*/
public function setFollowing($following)
{
$this->following = $following;
return $this;
}
/**
* @return mixed
*/
public function getEndpoints()
{
return $this->endpoints;
}
/**
* @param mixed $endpoints
* @return Actor
*/
public function setEndpoints($endpoints)
{
$this->endpoints = $endpoints;
return $this;
}
/**
* @return mixed
*/
public function getPublicKey()
{
return $this->publicKey;
}
/**
* @param mixed $publicKey
* @return Actor
*/
public function setPublicKey($publicKey)
{
$this->publicKey = $publicKey;
return $this;
}
/**
* @return mixed
*/
public function getWebfinger()
{
return $this->webfinger;
}
/**
* @param mixed $webfinger
* @return Actor
*/
public function setWebfinger($webfinger)
{
$this->webfinger = $webfinger;
return $this;
}
/**
* @return mixed
*/
public function getCanSearch()
{
return $this->canSearch;
}
/**
* @param mixed $canSearch
* @return Actor
*/
public function setCanSearch($canSearch)
{
$this->canSearch = $canSearch;
return $this;
}
/**
* @return mixed
*/
public function getIndexable()
{
return $this->indexable;
}
/**
* @param mixed $indexable
* @return Actor
*/
public function setIndexable($indexable)
{
$this->indexable = $indexable;
return $this;
}
/**
* @return mixed
*/
public function getAssertionMethod()
{
return $this->assertionMethod;
}
/**
* @param mixed $assertionMethod
* @return Actor
*/
public function setAssertionMethod($assertionMethod)
{
$this->assertionMethod = $assertionMethod;
return $this;
}
/**
* @return mixed
*/
public function getGateways()
{
return $this->gateways;
}
/**
* @param mixed $gateways
* @return Actor
*/
public function setGateways($gateways)
{
$this->gateways = $gateways;
return $this;
}
/**
* @return mixed
*/
public function getPermissions()
{
return $this->permissions;
}
/**
* @param mixed $permissions
* @return Actor
*/
public function setPermissions($permissions)
{
$this->permissions = $permissions;
return $this;
}
/**
* @return mixed
*/
public function getOpenwebauth()
{
return $this->openwebauth;
}
/**
* @param mixed $openwebauth
* @return Actor
*/
public function setOpenwebauth($openwebauth)
{
$this->openwebauth = $openwebauth;
return $this;
}
/**
* @return mixed
*/
public function getAuthredirect()
{
return $this->authredirect;
}
/**
* @param mixed $authredirect
* @return Actor
*/
public function setAuthredirect($authredirect)
{
$this->authredirect = $authredirect;
return $this;
}
}

View File

@@ -0,0 +1,87 @@
<?php
namespace Zotlabs\ActivityStreams;
class AssertionMethod extends ASObject
{
public $id;
public $type;
public $controller;
public $publicKeyMultibase;
/**
* @return mixed
*/
public function getId()
{
return $this->id;
}
/**
* @param mixed $id
* @return AssertionMethod
*/
public function setId($id)
{
$this->id = $id;
return $this;
}
/**
* @return mixed
*/
public function getType()
{
return $this->type;
}
/**
* @param mixed $type
* @return AssertionMethod
*/
public function setType($type)
{
$this->type = $type;
return $this;
}
/**
* @return mixed
*/
public function getController()
{
return $this->controller;
}
/**
* @param mixed $controller
* @return AssertionMethod
*/
public function setController($controller)
{
$this->controller = $controller;
return $this;
}
/**
* @return mixed
*/
public function getPublicKeyMultibase()
{
return $this->publicKeyMultibase;
}
/**
* @param mixed $publicKeyMultibase
* @return AssertionMethod
*/
public function setPublicKeyMultibase($publicKeyMultibase)
{
$this->publicKeyMultibase = $publicKeyMultibase;
return $this;
}
}

View File

@@ -0,0 +1,124 @@
<?php
namespace Zotlabs\ActivityStreams;
class Collection extends ASObject
{
public int $totalItems;
public string $current;
public string $first;
public string $last;
public array $items;
public mixed $collectionOf;
/**
* @return int
*/
public function getTotalItems(): int
{
return $this->totalItems;
}
/**
* @param mixed $totalItems
* @return Collection
*/
public function setTotalItems(mixed $totalItems): static
{
$this->totalItems = $totalItems;
return $this;
}
/**
* @return string
*/
public function getCurrent(): string
{
return $this->current;
}
/**
* @param mixed $current
* @return Collection
*/
public function setCurrent(mixed $current): static
{
$this->current = $current;
return $this;
}
/**
* @return string
*/
public function getFirst(): string
{
return $this->first;
}
/**
* @param mixed $first
* @return Collection
*/
public function setFirst(mixed $first): static
{
$this->first = $first;
return $this;
}
/**
* @return string
*/
public function getLast(): string
{
return $this->last;
}
/**
* @param mixed $last
* @return Collection
*/
public function setLast(mixed $last): static
{
$this->last = $last;
return $this;
}
/**
* @return array
*/
public function getItems(): array
{
return $this->items;
}
/**
* @param mixed $items
* @return Collection
*/
public function setItems(mixed $items): static
{
$this->items = $items;
return $this;
}
/**
* @return mixed
*/
public function getCollectionOf(): mixed
{
return $this->collectionOf;
}
/**
* @param mixed $collectionOf
* @return Collection
*/
public function setCollectionOf(mixed $collectionOf): static
{
$this->collectionOf = $collectionOf;
return $this;
}
}

View File

@@ -0,0 +1,73 @@
<?php
namespace Zotlabs\ActivityStreams;
class CollectionPage extends Collection
{
public $partOf;
public $next;
public $prev;
// startIndex only applies for OrderedCollectionPage. See
// https://www.w3.org/ns/activitystreams#OrderedCollectionPage
// It is provided here to avoid multiple inheritance
public $startIndex;
/**
* @return mixed
*/
public function getPartOf()
{
return $this->partOf;
}
/**
* @param mixed $partOf
* @return CollectionPage
*/
public function setPartOf($partOf)
{
$this->partOf = $partOf;
return $this;
}
/**
* @return mixed
*/
public function getNext()
{
return $this->next;
}
/**
* @param mixed $next
* @return CollectionPage
*/
public function setNext($next)
{
$this->next = $next;
return $this;
}
/**
* @return mixed
*/
public function getPrev()
{
return $this->prev;
}
/**
* @param mixed $prev
* @return CollectionPage
*/
public function setPrev($prev)
{
$this->prev = $prev;
return $this;
}
}

View File

@@ -0,0 +1,104 @@
<?php
namespace Zotlabs\ActivityStreams;
class IntransitiveActivity extends ASObject
{
public $actor;
public $target;
public $result;
public $origin;
public $instrument;
/**
* @return mixed
*/
public function getActor()
{
return $this->actor;
}
/**
* @param mixed $actor
* @return IntransitiveActivity
*/
public function setActor($actor)
{
$this->actor = $actor;
return $this;
}
/**
* @return mixed
*/
public function getTarget()
{
return $this->target;
}
/**
* @param mixed $target
* @return IntransitiveActivity
*/
public function setTarget($target)
{
$this->target = $target;
return $this;
}
/**
* @return mixed
*/
public function getResult()
{
return $this->result;
}
/**
* @param mixed $result
* @return IntransitiveActivity
*/
public function setResult($result)
{
$this->result = $result;
return $this;
}
/**
* @return mixed
*/
public function getOrigin()
{
return $this->origin;
}
/**
* @param mixed $origin
* @return IntransitiveActivity
*/
public function setOrigin($origin)
{
$this->origin = $origin;
return $this;
}
/**
* @return mixed
*/
public function getInstrument()
{
return $this->instrument;
}
/**
* @param mixed $instrument
* @return IntransitiveActivity
*/
public function setInstrument($instrument)
{
$this->instrument = $instrument;
return $this;
}
}

View File

@@ -0,0 +1,183 @@
<?php
namespace Zotlabs\ActivityStreams;
use Zotlabs\Lib\BaseObject;
class Link extends BaseObject
{
public $type;
public $href;
public $rel;
public $mediaType;
public $name;
public $hreflang;
public $height;
public $width;
public $preview;
/**
* @return mixed
*/
public function getType()
{
return $this->type;
}
/**
* @param mixed $type
* @return Link
*/
public function setType($type)
{
$this->type = $type;
return $this;
}
/**
* @return mixed
*/
public function getHref()
{
return $this->href;
}
/**
* @param mixed $href
* @return Link
*/
public function setHref($href)
{
$this->href = $href;
return $this;
}
/**
* @return mixed
*/
public function getRel()
{
return $this->rel;
}
/**
* @param mixed $rel
* @return Link
*/
public function setRel($rel)
{
$this->rel = $rel;
return $this;
}
/**
* @return mixed
*/
public function getMediaType()
{
return $this->mediaType;
}
/**
* @param mixed $mediaType
* @return Link
*/
public function setMediaType($mediaType)
{
$this->mediaType = $mediaType;
return $this;
}
/**
* @return mixed
*/
public function getName()
{
return $this->name;
}
/**
* @param mixed $name
* @return Link
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* @return mixed
*/
public function getHreflang()
{
return $this->hreflang;
}
/**
* @param mixed $hreflang
* @return Link
*/
public function setHreflang($hreflang)
{
$this->hreflang = $hreflang;
return $this;
}
/**
* @return mixed
*/
public function getHeight()
{
return $this->height;
}
/**
* @param mixed $height
* @return Link
*/
public function setHeight($height)
{
$this->height = $height;
return $this;
}
/**
* @return mixed
*/
public function getWidth()
{
return $this->width;
}
/**
* @param mixed $width
* @return Link
*/
public function setWidth($width)
{
$this->width = $width;
return $this;
}
/**
* @return mixed
*/
public function getPreview()
{
return $this->preview;
}
/**
* @param mixed $preview
* @return Link
*/
public function setPreview($preview)
{
$this->preview = $preview;
return $this;
}
}

View File

@@ -0,0 +1,8 @@
<?php
namespace Zotlabs\ActivityStreams;
class OrderedCollection extends Collection
{
}

View File

@@ -0,0 +1,92 @@
<?php
namespace Zotlabs\ActivityStreams;
/**
* According to the specification, OrderedCollectionPage extends
* both OrderedCollection and CollectionPage, but PHP is still a bit awkward
* when it comes to multiple inheritance. Rather than try and do this with
* traits, we'll just include the CollectionPage elements here - as this only
* consists of three properties.
*/
class OrderedCollectionPage extends OrderedCollection
{
public $partOf;
public $next;
public $prev;
public $startIndex;
/**
* @return mixed
*/
public function getPartOf()
{
return $this->partOf;
}
/**
* @param mixed $partOf
* @return OrderedCollectionPage
*/
public function setPartOf($partOf)
{
$this->partOf = $partOf;
return $this;
}
/**
* @return mixed
*/
public function getNext()
{
return $this->next;
}
/**
* @param mixed $next
* @return OrderedCollectionPage
*/
public function setNext($next)
{
$this->next = $next;
return $this;
}
/**
* @return mixed
*/
public function getPrev()
{
return $this->prev;
}
/**
* @param mixed $prev
* @return OrderedCollectionPage
*/
public function setPrev($prev)
{
$this->prev = $prev;
return $this;
}
/**
* @return mixed
*/
public function getStartIndex()
{
return $this->startIndex;
}
/**
* @param mixed $startIndex
* @return OrderedCollectionPage
*/
public function setStartIndex($startIndex)
{
$this->startIndex = $startIndex;
return $this;
}
}

View File

@@ -0,0 +1,125 @@
<?php
namespace Zotlabs\ActivityStreams;
class Place extends ASObject
{
public $accuracy;
public $altitude;
public $latitude;
public $longitude;
public $radius;
public $units;
/**
* @return mixed
*/
public function getAccuracy()
{
return $this->accuracy;
}
/**
* @param mixed $accuracy
* @return Place
*/
public function setAccuracy($accuracy)
{
$this->accuracy = $accuracy;
return $this;
}
/**
* @return mixed
*/
public function getAltitude()
{
return $this->altitude;
}
/**
* @param mixed $altitude
* @return Place
*/
public function setAltitude($altitude)
{
$this->altitude = $altitude;
return $this;
}
/**
* @return mixed
*/
public function getLatitude()
{
return $this->latitude;
}
/**
* @param mixed $latitude
* @return Place
*/
public function setLatitude($latitude)
{
$this->latitude = $latitude;
return $this;
}
/**
* @return mixed
*/
public function getLongitude()
{
return $this->longitude;
}
/**
* @param mixed $longitude
* @return Place
*/
public function setLongitude($longitude)
{
$this->longitude = $longitude;
return $this;
}
/**
* @return mixed
*/
public function getRadius()
{
return $this->radius;
}
/**
* @param mixed $radius
* @return Place
*/
public function setRadius($radius)
{
$this->radius = $radius;
return $this;
}
/**
* @return mixed
*/
public function getUnits()
{
return $this->units;
}
/**
* @param mixed $units
* @return Place
*/
public function setUnits($units)
{
$this->units = $units;
return $this;
}
}

View File

@@ -0,0 +1,29 @@
<?php
namespace Zotlabs\ActivityStreams;
class Profile extends ASObject
{
public $describes;
/**
* @return mixed
*/
public function getDescribes()
{
return $this->describes;
}
/**
* @param mixed $describes
* @return Profile
*/
public function setDescribes($describes)
{
$this->describes = $describes;
return $this;
}
}

View File

@@ -0,0 +1,68 @@
<?php
namespace Zotlabs\ActivityStreams;
class PublicKey extends ASObject
{
public $owner;
public $signatureAlgorithm;
public $publicKeyPem;
/**
* @return mixed
*/
public function getOwner()
{
return $this->owner;
}
/**
* @param mixed $owner
* @return PublicKey
*/
public function setOwner($owner)
{
$this->owner = $owner;
return $this;
}
/**
* @return mixed
*/
public function getSignatureAlgorithm()
{
return $this->signatureAlgorithm;
}
/**
* @param mixed $signatureAlgorithm
* @return PublicKey
*/
public function setSignatureAlgorithm($signatureAlgorithm)
{
$this->signatureAlgorithm = $signatureAlgorithm;
return $this;
}
/**
* @return mixed
*/
public function getPublicKeyPem()
{
return $this->publicKeyPem;
}
/**
* @param mixed $publicKeyPem
* @return PublicKey
*/
public function setPublicKeyPem($publicKeyPem)
{
$this->publicKeyPem = $publicKeyPem;
return $this;
}
}

View File

@@ -0,0 +1,67 @@
<?php
namespace Zotlabs\ActivityStreams;
class Question extends ASObject
{
public $oneOf;
public $anyOf;
public $closed;
/**
* @return mixed
*/
public function getOneOf()
{
return $this->oneOf;
}
/**
* @param mixed $oneOf
* @return Question
*/
public function setOneOf($oneOf)
{
$this->oneOf = $oneOf;
return $this;
}
/**
* @return mixed
*/
public function getAnyOf()
{
return $this->anyOf;
}
/**
* @param mixed $anyOf
* @return Question
*/
public function setAnyOf($anyOf)
{
$this->anyOf = $anyOf;
return $this;
}
/**
* @return mixed
*/
public function getClosed()
{
return $this->closed;
}
/**
* @param mixed $closed
* @return Question
*/
public function setClosed($closed)
{
$this->closed = $closed;
return $this;
}
}

View File

@@ -0,0 +1,67 @@
<?php
namespace Zotlabs\ActivityStreams;
class Relationship extends ASObject
{
public $subject;
public $object;
public $relationship;
/**
* @return mixed
*/
public function getSubject()
{
return $this->subject;
}
/**
* @param mixed $subject
* @return Relationship
*/
public function setSubject($subject)
{
$this->subject = $subject;
return $this;
}
/**
* @return mixed
*/
public function getObject()
{
return $this->object;
}
/**
* @param mixed $object
* @return Relationship
*/
public function setObject($object)
{
$this->object = $object;
return $this;
}
/**
* @return mixed
*/
public function getRelationship()
{
return $this->relationship;
}
/**
* @param mixed $relationship
* @return Relationship
*/
public function setRelationship($relationship)
{
$this->relationship = $relationship;
return $this;
}
}

View File

@@ -0,0 +1,65 @@
<?php
namespace Zotlabs\ActivityStreams;
class Signature extends ASObject
{
public $nonce;
public $creator;
public $signatureValue;
/**
* @return mixed
*/
public function getCreator()
{
return $this->creator;
}
/**
* @param mixed $creator
* @return Signature
*/
public function setCreator($creator)
{
$this->creator = $creator;
return $this;
}
/**
* @return mixed
*/
public function getSignatureValue()
{
return $this->signatureValue;
}
/**
* @param mixed $signatureValue
* @return Signature
*/
public function setSignatureValue($signatureValue)
{
$this->signatureValue = $signatureValue;
return $this;
}
/**
* @return mixed
*/
public function getNonce()
{
return $this->nonce;
}
/**
* @param mixed $nonce
* @return Signature
*/
public function setNonce($nonce)
{
$this->nonce = $nonce;
return $this;
}
}

View File

@@ -0,0 +1,48 @@
<?php
namespace Zotlabs\ActivityStreams;
class Tombstone extends ASObject
{
public $formerType;
public $deleted;
/**
* @return mixed
*/
public function getFormerType()
{
return $this->formerType;
}
/**
* @param mixed $formerType
* @return Tombstone
*/
public function setFormerType($formerType)
{
$this->formerType = $formerType;
return $this;
}
/**
* @return mixed
*/
public function getDeleted()
{
return $this->deleted;
}
/**
* @param mixed $deleted
* @return Tombstone
*/
public function setDeleted($deleted)
{
$this->deleted = $deleted;
return $this;
}
}

View File

@@ -0,0 +1,8 @@
<?php
namespace Zotlabs\ActivityStreams;
class UnhandledElementException extends \Exception
{
}

View File

@@ -6,23 +6,28 @@ class Cache_embeds {
static public function run($argc,$argv) {
if(! $argc == 2)
if(!$argc == 2) {
return;
}
$c = q("select body from item where id = %d ",
dbesc(intval($argv[1]))
$c = q("select uid, aid, body, item_private from item where uuid = '%s'",
dbesc($argv[1])
);
if(! $c)
if(!$c) {
return;
}
$item = $c[0];
// bbcode conversion by default processes embeds that aren't already cached.
// Ignore the returned html output.
bbcode($item['body']);
// photocache addon hook to prefetch one copy of public item images for the sys channel
call_hooks('cache_prefetch_hook', $item);
return;
}
}

View File

@@ -24,7 +24,7 @@ class Channel_purge {
);
if ($r) {
foreach ($r as $rv) {
drop_item($rv['id'], false);
drop_item($rv['id'], uid: $channel_id);
}
}
} while ($r);

View File

@@ -38,7 +38,13 @@ class Content_importer {
$headers = HTTPSig::create_sig($headers,$channel['channel_prvkey'], channel_url($channel),true,'sha512');
$x = z_fetch_url($hz_server . '/api/z/1.0/item/export_page?f=&since=' . urlencode($since) . '&until=' . urlencode($until) . '&page=' . $page,false,$redirects,[ 'headers' => $headers ]);
$redirects = 0;
$x = z_fetch_url(
$hz_server . '/api/z/1.0/item/export_page?f=&since=' . urlencode($since) . '&until=' . urlencode($until) . '&page=' . $page,
false,
$redirects,
[ 'headers' => $headers ]
);
// logger('item fetch: ' . print_r($x,true));
@@ -47,9 +53,9 @@ class Content_importer {
killme();
}
$j = json_decode($x['body'],true);
$j = json_decode($x['body'], true);
if(! is_array($j['item']) || ! count($j['item'])) {
if($j && empty($j['item'])) {
PConfig::Set($channel['channel_id'], 'import', 'content_completed', 1);
return;
}

View File

@@ -69,18 +69,18 @@ class Cron {
// expire any expired items
$r = q("select id,item_wall from item where expires > '2001-01-01 00:00:00' and expires < %s
$r = q("select id, uid, item_wall from item where expires > '2001-01-01 00:00:00' and expires < %s
and item_deleted = 0 ",
db_utcnow()
);
if ($r) {
require_once('include/items.php');
foreach ($r as $rr) {
drop_item($rr['id'], false, (($rr['item_wall']) ? DROPITEM_PHASE1 : DROPITEM_NORMAL));
// pass uid of the message for permission check as we are running as a daemon process with no session.
drop_item($rr['id'], (($rr['item_wall']) ? DROPITEM_PHASE1 : DROPITEM_NORMAL), uid: intval($rr['uid']));
if ($rr['item_wall']) {
// The notifier isn't normally invoked unless item_drop is interactive.
Master::Summon(['Notifier', 'drop', $rr['id']]);
if ($interval) {
usleep($interval);
}
@@ -125,14 +125,15 @@ 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(Config::Get('system', 'cache_expire_days', 7) . ' DAY')
db_quoteinterval(Config::Get('system', 'default_expire_days', 30) . ' DAY')
);
if ($r) {
q("DELETE FROM photo WHERE photo_usage = %d AND expires < %s - INTERVAL %s",
intval(PHOTO_CACHE),
db_utcnow(),
db_quoteinterval(Config::Get('system', 'cache_expire_days', 7) . ' DAY')
db_quoteinterval(Config::Get('system', 'default_expire_days', 30) . ' DAY')
);
foreach ($r as $rr) {
$file = dbunescbin($rr['content']);
if (is_file($file)) {
@@ -147,40 +148,29 @@ class Cron {
// (time travel posts). Restrict to items that have come of age in the last
// couple of days to limit the query to something reasonable.
$r = q("select id from item where item_delayed = 1 and created <= %s and created > '%s' ",
$r = q("select * from item where item_delayed = 1 and created <= %s and created > '%s' ",
db_utcnow(),
dbesc(datetime_convert('UTC', 'UTC', 'now - 2 days'))
);
if ($r) {
foreach ($r as $rr) {
$x = q("update item set item_delayed = 0 where id = %d",
intval($rr['id'])
);
if ($x) {
$z = q("select * from item where id = %d",
intval($rr['id'])
);
if ($z) {
xchan_query($z);
$sync_item = fetch_post_tags($z);
Libsync::build_sync_packet($sync_item[0]['uid'],
[
'item' => [encode_item($sync_item[0], true)]
]
);
}
Master::Summon(array('Notifier', 'wall-new', $rr['id']));
if ($interval) {
usleep($interval);
if ($r) {
xchan_query($r);
$items = fetch_post_tags($r);
foreach ($items as $item) {
$item['item_delayed'] = 0;
$post = item_store_update($item);
if($post['success']) {
Master::Summon(['Notifier', 'wall-new', $post['item_id']]);
if (!empty($post['approval_id'])) {
Master::Summon(['Notifier', 'wall-new', $post['approval_id']]);
}
}
}
}
require_once('include/attach.php');
attach_upgrade();
if ($interval) {
usleep($interval);
}
}
}
// once daily run birthday_updates and then expire in background
// FIXME: add birthday updates, both locally and for xprof for use

View File

@@ -23,13 +23,13 @@ class Expire {
// perform final cleanup on previously delete items
$r = q("select id from item where item_deleted = 1 and item_pending_remove = 0 and changed < %s - INTERVAL %s",
$r = q("select id, uid from item where item_deleted = 1 and item_pending_remove = 0 and changed < %s - INTERVAL %s",
db_utcnow(),
db_quoteinterval('10 DAY')
);
if ($r) {
foreach ($r as $rr) {
drop_item($rr['id'], false, DROPITEM_PHASE2);
drop_item($rr['id'], DROPITEM_PHASE2, uid: $rr['uid']);
}
}

View File

@@ -38,7 +38,13 @@ class File_importer {
$headers = HTTPSig::create_sig($headers,$channel['channel_prvkey'],channel_url($channel),true,'sha512');
// TODO: implement total count
$x = z_fetch_url($hz_server . '/api/z/1.0/file/export_page?f=records=1&page=' . $page, false, $redirects, [ 'headers' => $headers ]);
$redirects = 0;
$x = z_fetch_url(
$hz_server . '/api/z/1.0/file/export_page?f=records=1&page=' . $page,
false,
$redirects,
[ 'headers' => $headers ]
);
// logger('file fetch: ' . print_r($x,true));
if(! $x['success']) {

View File

@@ -11,6 +11,21 @@ class Importdoc {
self::update_docs_dir('doc/*');
$sys = get_sys_channel();
// remove old files that weren't updated (indicates they were most likely deleted).
$i = q("select id from item where uid = %d and item_type = 5 and edited < %s - INTERVAL %s",
intval($sys['channel_id']),
db_utcnow(),
db_quoteinterval('14 DAY')
);
if ($i) {
foreach ($i as $iv) {
drop_item($iv['id'], uid: $sys['channel_id']);
}
}
return;
}
@@ -18,9 +33,13 @@ class Importdoc {
static public function update_docs_dir($s) {
$f = basename($s);
$d = dirname($s);
if ($s === 'doc/html')
if ($s === 'doc/html') {
return;
}
$files = glob("$d/$f");
if ($files) {
foreach ($files as $fi) {
if ($fi === 'doc/html') {

View File

@@ -241,11 +241,6 @@ class Notifier {
$target_item = $r[0];
if (in_array($target_item['author']['xchan_network'], ['rss', 'anon', 'token'])) {
logger('notifier: target item author is not a fetchable actor', LOGGER_DEBUG);
return;
}
if (intval($target_item['item_deleted'])) {
logger('notifier: target item ITEM_DELETED', LOGGER_DEBUG);
}
@@ -268,22 +263,9 @@ 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'])) {
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'], ['Follow', 'Ignore', ACTIVITY_FOLLOW, ACTIVITY_UNFOLLOW])) {
logger('not fowarding follow/unfollow note activity');
return;
}
if (strpos($target_item['postopts'], 'nodeliver') !== false) {
logger('notifier: target item is undeliverable', LOGGER_DEBUG);
if (!item_forwardable($target_item)) {
//hz_syslog(print_r($target_item,true));
logger('notifier: target item not forwardable', LOGGER_DEBUG);
return;
}
@@ -299,7 +281,7 @@ class Notifier {
return;
}
if ($target_item['verb'] === ACTIVITY_SHARE) {
if (in_array($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'];
}
@@ -341,7 +323,13 @@ class Notifier {
self::$encoded_item = json_decode($m, true);
}
else {
self::$encoded_item = Activity::build_packet(Activity::encode_activity($target_item), self::$channel, false);
$activity = Activity::encode_activity($target_item);
if (!$activity) {
return;
}
self::$encoded_item = Activity::build_packet($activity, self::$channel, false);
}
logger('target_item: ' . print_r($target_item, true), LOGGER_DEBUG);
@@ -358,6 +346,10 @@ class Notifier {
$relay_to_owner = (!$top_level_post && intval($target_item['item_origin']) && comment_local_origin($target_item));
if (self::$channel['channel_hash'] === $target_item['owner_xchan']) {
$relay_to_owner = 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
@@ -374,7 +366,6 @@ 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;
@@ -389,7 +380,7 @@ class Notifier {
logger('normal (downstream) distribution', LOGGER_DEBUG);
}
if ($parent_item && $parent_item['item_private'] !== $target_item['item_private']) {
if (($parent_item && $parent_item['item_private'] !== $target_item['item_private']) || (intval($target_item['item_restrict']) & 1)) {
logger('conversation privacy mismatch - downstream delivery prevented');
return;
}
@@ -589,8 +580,6 @@ class Notifier {
foreach ($dhubs as $hub) {
logger('notifier_hub: ' . $hub['hubloc_url'], LOGGER_DEBUG);
if ($hub['hubloc_network'] !== 'zot6') {
$narr = [
'channel' => self::$channel,

352
Zotlabs/Entity/Account.php Normal file
View File

@@ -0,0 +1,352 @@
<?php
namespace Zotlabs\Entity;
use Zotlabs\Lib\BaseObject;
class Account extends BaseObject
{
public $account_id;
public $account_parent;
public $account_default_channel;
public $account_salt;
public $account_password;
public $account_email;
public $account_external;
public $account_language;
public $account_created;
public $account_lastlog;
public $account_flags;
public $account_roles;
public $account_reset;
public $account_expires;
public $account_expire_notified;
public $account_service_class;
public $account_level;
public $account_password_change;
/**
* @return mixed
*/
public function getId()
{
return $this->account_id;
}
/**
* @param mixed $account_id
* @return Account
*/
public function setId($account_id)
{
$this->account_id = $account_id;
return $this;
}
/**
* @return mixed
*/
public function getParent()
{
return $this->account_parent;
}
/**
* @param mixed $account_parent
* @return Account
*/
public function setParent($account_parent)
{
$this->account_parent = $account_parent;
return $this;
}
/**
* @return mixed
*/
public function getDefaultChannel()
{
return $this->account_default_channel;
}
/**
* @param mixed $account_default_channel
* @return Account
*/
public function setDefaultChannel($account_default_channel)
{
$this->account_default_channel = $account_default_channel;
return $this;
}
/**
* @return mixed
*/
public function getSalt()
{
return $this->account_salt;
}
/**
* @param mixed $account_salt
* @return Account
*/
public function setSalt($account_salt)
{
$this->account_salt = $account_salt;
return $this;
}
/**
* @return mixed
*/
public function getPassword()
{
return $this->account_password;
}
/**
* @param mixed $account_password
* @return Account
*/
public function setPassword($account_password)
{
$this->account_password = $account_password;
return $this;
}
/**
* @return mixed
*/
public function getEmail()
{
return $this->account_email;
}
/**
* @param mixed $account_email
* @return Account
*/
public function setEmail($account_email)
{
$this->account_email = $account_email;
return $this;
}
/**
* @return mixed
*/
public function getExternal()
{
return $this->account_external;
}
/**
* @param mixed $account_external
* @return Account
*/
public function setExternal($account_external)
{
$this->account_external = $account_external;
return $this;
}
/**
* @return mixed
*/
public function getLanguage()
{
return $this->account_language;
}
/**
* @param mixed $account_language
* @return Account
*/
public function setLanguage($account_language)
{
$this->account_language = $account_language;
return $this;
}
/**
* @return mixed
*/
public function getCreated()
{
return $this->account_created;
}
/**
* @param mixed $account_created
* @return Account
*/
public function setCreated($account_created)
{
$this->account_created = $account_created;
return $this;
}
/**
* @return mixed
*/
public function getLastlog()
{
return $this->account_lastlog;
}
/**
* @param mixed $account_lastlog
* @return Account
*/
public function setLastlog($account_lastlog)
{
$this->account_lastlog = $account_lastlog;
return $this;
}
/**
* @return mixed
*/
public function getFlags()
{
return $this->account_flags;
}
/**
* @param mixed $account_flags
* @return Account
*/
public function setFlags($account_flags)
{
$this->account_flags = $account_flags;
return $this;
}
/**
* @return mixed
*/
public function getRoles()
{
return $this->account_roles;
}
/**
* @param mixed $account_roles
* @return Account
*/
public function setRoles($account_roles)
{
$this->account_roles = $account_roles;
return $this;
}
/**
* @return mixed
*/
public function getReset()
{
return $this->account_reset;
}
/**
* @param mixed $account_reset
* @return Account
*/
public function setReset($account_reset)
{
$this->account_reset = $account_reset;
return $this;
}
/**
* @return mixed
*/
public function getExpires()
{
return $this->account_expires;
}
/**
* @param mixed $account_expires
* @return Account
*/
public function setExpires($account_expires)
{
$this->account_expires = $account_expires;
return $this;
}
/**
* @return mixed
*/
public function getExpireNotified()
{
return $this->account_expire_notified;
}
/**
* @param mixed $account_expire_notified
* @return Account
*/
public function setExpireNotified($account_expire_notified)
{
$this->account_expire_notified = $account_expire_notified;
return $this;
}
/**
* @return mixed
*/
public function getServiceClass()
{
return $this->account_service_class;
}
/**
* @param mixed $account_service_class
* @return Account
*/
public function setServiceClass($account_service_class)
{
$this->account_service_class = $account_service_class;
return $this;
}
/**
* @return mixed
*/
public function getLevel()
{
return $this->account_level;
}
/**
* @param mixed $account_level
* @return Account
*/
public function setLevel($account_level)
{
$this->account_level = $account_level;
return $this;
}
/**
* @return mixed
*/
public function getPasswordChange()
{
return $this->account_password_change;
}
/**
* @param mixed $account_password_change
* @return Account
*/
public function setPasswordChange($account_password_change)
{
$this->account_password_change = $account_password_change;
return $this;
}
}

714
Zotlabs/Entity/Channel.php Normal file
View File

@@ -0,0 +1,714 @@
<?php
namespace Zotlabs\Entity;
use Zotlabs\Lib\BaseObject;
class Channel extends BaseObject
{
public $channel_id;
public $channel_account_id;
public $channel_primary;
public $channel_name;
public $channel_parent;
public $channel_address;
public $channel_guid;
public $channel_guid_sig;
public $channel_hash;
public $channel_timezone;
public $channel_location;
public $channel_theme;
public $channel_startpage;
public $channel_pubkey;
public $channel_prvkey;
public $channel_epubkey;
public $channel_eprvkey;
public $channel_notifyflags;
public $channel_pageflags;
public $channel_dirdate;
public $channel_lastpost;
public $channel_deleted;
public $channel_active;
public $channel_max_anon_mail;
public $channel_max_friend_req;
public $channel_expire_days;
public $channel_passwd_reset;
public $channel_default_group;
public $channel_allow_cid;
public $channel_allow_gid;
public $channel_deny_cid;
public $channel_deny_gid;
public $channel_removed;
public $channel_system;
public $channel_moved;
public $channel_password;
public $channel_salt;
/**
* @return mixed
*/
public function getId()
{
return $this->channel_id;
}
/**
* @param mixed $channel_id
* @return Channel
*/
public function setId($channel_id)
{
$this->channel_id = $channel_id;
return $this;
}
/**
* @return mixed
*/
public function getAccountId()
{
return $this->channel_account_id;
}
/**
* @param mixed $channel_account_id
* @return Channel
*/
public function setAccountId($channel_account_id)
{
$this->channel_account_id = $channel_account_id;
return $this;
}
/**
* @return mixed
*/
public function getPrimary()
{
return $this->channel_primary;
}
/**
* @param mixed $channel_primary
* @return Channel
*/
public function setPrimary($channel_primary)
{
$this->channel_primary = $channel_primary;
return $this;
}
/**
* @return mixed
*/
public function getName()
{
return $this->channel_name;
}
/**
* @param mixed $channel_name
* @return Channel
*/
public function setName($channel_name)
{
$this->channel_name = $channel_name;
return $this;
}
/**
* @return mixed
*/
public function getParent()
{
return $this->channel_parent;
}
/**
* @param mixed $channel_parent
* @return Channel
*/
public function setParent($channel_parent)
{
$this->channel_parent = $channel_parent;
return $this;
}
/**
* @return mixed
*/
public function getAddress()
{
return $this->channel_address;
}
/**
* @param mixed $channel_address
* @return Channel
*/
public function setAddress($channel_address)
{
$this->channel_address = $channel_address;
return $this;
}
/**
* @return mixed
*/
public function getGuid()
{
return $this->channel_guid;
}
/**
* @param mixed $channel_guid
* @return Channel
*/
public function setGuid($channel_guid)
{
$this->channel_guid = $channel_guid;
return $this;
}
/**
* @return mixed
*/
public function getGuidSig()
{
return $this->channel_guid_sig;
}
/**
* @param mixed $channel_guid_sig
* @return Channel
*/
public function setGuidSig($channel_guid_sig)
{
$this->channel_guid_sig = $channel_guid_sig;
return $this;
}
/**
* @return mixed
*/
public function getHash()
{
return $this->channel_hash;
}
/**
* @param mixed $channel_hash
* @return Channel
*/
public function setHash($channel_hash)
{
$this->channel_hash = $channel_hash;
return $this;
}
/**
* @return mixed
*/
public function getTimezone()
{
return $this->channel_timezone;
}
/**
* @param mixed $channel_timezone
* @return Channel
*/
public function setTimezone($channel_timezone)
{
$this->channel_timezone = $channel_timezone;
return $this;
}
/**
* @return mixed
*/
public function getLocation()
{
return $this->channel_location;
}
/**
* @param mixed $channel_location
* @return Channel
*/
public function setLocation($channel_location)
{
$this->channel_location = $channel_location;
return $this;
}
/**
* @return mixed
*/
public function getTheme()
{
return $this->channel_theme;
}
/**
* @param mixed $channel_theme
* @return Channel
*/
public function setTheme($channel_theme)
{
$this->channel_theme = $channel_theme;
return $this;
}
/**
* @return mixed
*/
public function getStartpage()
{
return $this->channel_startpage;
}
/**
* @param mixed $channel_startpage
* @return Channel
*/
public function setStartpage($channel_startpage)
{
$this->channel_startpage = $channel_startpage;
return $this;
}
/**
* @return mixed
*/
public function getPubkey()
{
return $this->channel_pubkey;
}
/**
* @param mixed $channel_pubkey
* @return Channel
*/
public function setPubkey($channel_pubkey)
{
$this->channel_pubkey = $channel_pubkey;
return $this;
}
/**
* @return mixed
*/
public function getPrvkey()
{
return $this->channel_prvkey;
}
/**
* @param mixed $channel_prvkey
* @return Channel
*/
public function setPrvkey($channel_prvkey)
{
$this->channel_prvkey = $channel_prvkey;
return $this;
}
/**
* @return mixed
*/
public function getEpubkey()
{
return $this->channel_epubkey;
}
/**
* @param mixed $channel_epubkey
* @return Channel
*/
public function setEpubkey($channel_epubkey)
{
$this->channel_epubkey = $channel_epubkey;
return $this;
}
/**
* @return mixed
*/
public function getEprvkey()
{
return $this->channel_eprvkey;
}
/**
* @param mixed $channel_eprvkey
* @return Channel
*/
public function setEprvkey($channel_eprvkey)
{
$this->channel_eprvkey = $channel_eprvkey;
return $this;
}
/**
* @return mixed
*/
public function getNotifyflags()
{
return $this->channel_notifyflags;
}
/**
* @param mixed $channel_notifyflags
* @return Channel
*/
public function setNotifyflags($channel_notifyflags)
{
$this->channel_notifyflags = $channel_notifyflags;
return $this;
}
/**
* @return mixed
*/
public function getPageflags()
{
return $this->channel_pageflags;
}
/**
* @param mixed $channel_pageflags
* @return Channel
*/
public function setPageflags($channel_pageflags)
{
$this->channel_pageflags = $channel_pageflags;
return $this;
}
/**
* @return mixed
*/
public function getDirdate()
{
return $this->channel_dirdate;
}
/**
* @param mixed $channel_dirdate
* @return Channel
*/
public function setDirdate($channel_dirdate)
{
$this->channel_dirdate = $channel_dirdate;
return $this;
}
/**
* @return mixed
*/
public function getLastpost()
{
return $this->channel_lastpost;
}
/**
* @param mixed $channel_lastpost
* @return Channel
*/
public function setLastpost($channel_lastpost)
{
$this->channel_lastpost = $channel_lastpost;
return $this;
}
/**
* @return mixed
*/
public function getDeleted()
{
return $this->channel_deleted;
}
/**
* @param mixed $channel_deleted
* @return Channel
*/
public function setDeleted($channel_deleted)
{
$this->channel_deleted = $channel_deleted;
return $this;
}
/**
* @return mixed
*/
public function getActive()
{
return $this->channel_active;
}
/**
* @param mixed $channel_active
* @return Channel
*/
public function setActive($channel_active)
{
$this->channel_active = $channel_active;
return $this;
}
/**
* @return mixed
*/
public function getMaxAnonMail()
{
return $this->channel_max_anon_mail;
}
/**
* @param mixed $channel_max_anon_mail
* @return Channel
*/
public function setMaxAnonMail($channel_max_anon_mail)
{
$this->channel_max_anon_mail = $channel_max_anon_mail;
return $this;
}
/**
* @return mixed
*/
public function getMaxFriendReq()
{
return $this->channel_max_friend_req;
}
/**
* @param mixed $channel_max_friend_req
* @return Channel
*/
public function setMaxFriendReq($channel_max_friend_req)
{
$this->channel_max_friend_req = $channel_max_friend_req;
return $this;
}
/**
* @return mixed
*/
public function getExpireDays()
{
return $this->channel_expire_days;
}
/**
* @param mixed $channel_expire_days
* @return Channel
*/
public function setExpireDays($channel_expire_days)
{
$this->channel_expire_days = $channel_expire_days;
return $this;
}
/**
* @return mixed
*/
public function getPasswdReset()
{
return $this->channel_passwd_reset;
}
/**
* @param mixed $channel_passwd_reset
* @return Channel
*/
public function setPasswdReset($channel_passwd_reset)
{
$this->channel_passwd_reset = $channel_passwd_reset;
return $this;
}
/**
* @return mixed
*/
public function getDefaultGroup()
{
return $this->channel_default_group;
}
/**
* @param mixed $channel_default_group
* @return Channel
*/
public function setDefaultGroup($channel_default_group)
{
$this->channel_default_group = $channel_default_group;
return $this;
}
/**
* @return mixed
*/
public function getAllowCid()
{
return $this->channel_allow_cid;
}
/**
* @param mixed $channel_allow_cid
* @return Channel
*/
public function setAllowCid($channel_allow_cid)
{
$this->channel_allow_cid = $channel_allow_cid;
return $this;
}
/**
* @return mixed
*/
public function getAllowGid()
{
return $this->channel_allow_gid;
}
/**
* @param mixed $channel_allow_gid
* @return Channel
*/
public function setAllowGid($channel_allow_gid)
{
$this->channel_allow_gid = $channel_allow_gid;
return $this;
}
/**
* @return mixed
*/
public function getDenyCid()
{
return $this->channel_deny_cid;
}
/**
* @param mixed $channel_deny_cid
* @return Channel
*/
public function setDenyCid($channel_deny_cid)
{
$this->channel_deny_cid = $channel_deny_cid;
return $this;
}
/**
* @return mixed
*/
public function getDenyGid()
{
return $this->channel_deny_gid;
}
/**
* @param mixed $channel_deny_gid
* @return Channel
*/
public function setDenyGid($channel_deny_gid)
{
$this->channel_deny_gid = $channel_deny_gid;
return $this;
}
/**
* @return mixed
*/
public function getRemoved()
{
return $this->channel_removed;
}
/**
* @param mixed $channel_removed
* @return Channel
*/
public function setRemoved($channel_removed)
{
$this->channel_removed = $channel_removed;
return $this;
}
/**
* @return mixed
*/
public function getSystem()
{
return $this->channel_system;
}
/**
* @param mixed $channel_system
* @return Channel
*/
public function setSystem($channel_system)
{
$this->channel_system = $channel_system;
return $this;
}
/**
* @return mixed
*/
public function getMoved()
{
return $this->channel_moved;
}
/**
* @param mixed $channel_moved
* @return Channel
*/
public function setMoved($channel_moved)
{
$this->channel_moved = $channel_moved;
return $this;
}
/**
* @return mixed
*/
public function getPassword()
{
return $this->channel_password;
}
/**
* @param mixed $channel_password
* @return Channel
*/
public function setPassword($channel_password)
{
$this->channel_password = $channel_password;
return $this;
}
/**
* @return mixed
*/
public function getSalt()
{
return $this->channel_salt;
}
/**
* @param mixed $channel_salt
* @return Channel
*/
public function setSalt($channel_salt)
{
$this->channel_salt = $channel_salt;
return $this;
}
}

1498
Zotlabs/Entity/Item.php Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -528,49 +528,59 @@ class ActivityStreams {
}
public function checkEddsaSignature() {
$publicKey = null;
$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 ($signer && str_starts_with($signer, 'did:key:')) {
$publicKey = str_replace('did:key:', '', $signer);
$this->signer = ['id' => $signer];
if (strpos($publicKey, '#') !== false) {
$publicKey = substr($publicKey,0, strpos($publicKey, '#'));
}
}
else {
$parseUrl = parse_url($signer);
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']];
if (isset($parseUrl['fragment'])) {
if (str_starts_with($parseUrl['fragment'], 'z6Mk')) {
$publicKey = $parseUrl['fragment'];
}
unset($parseUrl['fragment']);
}
foreach($this->signer['assertionMethod'] as $am) {
if ($url === $am['controller'] &&
$am['type'] === 'Multikey' &&
str_starts_with($am['publicKeyMultibase'], 'z6Mk')
) {
$publicKey = $am['publicKeyMultibase'];
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'];
}
}
}
}

View File

@@ -341,7 +341,7 @@ class Apps {
'Suggest Channels' => t('Suggest Channels'),
'Login' => t('Login'),
'Channel Manager' => t('Channel Manager'),
'Network' => t('Stream'),
'Network' => t('Network'),
'Settings' => t('Settings'),
'Files' => t('Files'),
'Webpages' => t('Webpages'),

View File

@@ -0,0 +1,80 @@
<?php
namespace Zotlabs\Lib;
use Zotlabs\ActivityStreams\UnhandledElementException;
class BaseObject
{
public $string;
public $ldContext;
/**
* @param $input
* @param $strict
* @throws UnhandledElementException if $strict
*/
public function __construct($input = null, $strict = false)
{
if (isset($input)) {
if (is_string($input)) {
$this->string = $input;
}
elseif(is_array($input)) {
foreach ($input as $key => $value) {
$key = ($key === '@context') ? 'ldContext' : $key;
if ($strict && !property_exists($this, $key)) {
throw new UnhandledElementException("Unhandled element: $key");
}
$this->{$key} = $value;
}
}
}
return $this;
}
public function getDataType($element, $object = null)
{
$object = $object ?? $this;
$type = gettype($object[$element]);
if ($type === 'array' && array_is_list($object[$element])) {
return 'list';
}
return $type;
}
public function toArray()
{
if ($this->string) {
return $this->string;
}
$returnValue = [];
foreach ((array) $this as $key => $value) {
if (isset($value)) {
$key = ($key === 'ldContext') ? '@context' : $key;
$returnValue[$key] = (($value instanceof BaseObject) ? $value->toArray() : $value);
}
}
return $returnValue;
}
/**
* @return mixed
*/
public function getLdContext()
{
return $this->ldContext;
}
/**
* @param mixed $ldContext
* @return BaseObject
*/
public function setLdContext($ldContext)
{
$this->ldContext = $ldContext;
return $this;
}
}

View File

@@ -181,7 +181,7 @@ class Chatroom {
}
function leave($observer_xchan, $room_id, $client) {
public static function leave($observer_xchan, $room_id, $client) {
if(! $room_id || ! $observer_xchan)
return;

View File

@@ -24,10 +24,16 @@ class Connect {
$uid = $channel['channel_id'];
if (strpos($url,'@') === false && strpos($url,'/') === false) {
// If we get just a channel name and it is not an URL turn it into a local webbie
if (!str_contains($url, '@') && strpos($url,'/') === false) {
$url = $url . '@' . App::get_hostname();
}
// Remove a possible leading @
if (str_starts_with($url, '@')) {
$url = ltrim($url, '@');
}
$result = [ 'success' => false, 'message' => '' ];
$my_perms = false;

View File

@@ -1,18 +1,35 @@
<?php
/**
* A class to handle database schema upgrades.
*
* SPDX-FileCopyrightText: 2024 Hubzilla Community
* SPDX-FileContributor: Harald Eilertsen
*
* SPDX-License-Identifier: MIT
*/
namespace Zotlabs\Lib;
use Zotlabs\Lib\Config;
/**
* Upgrade the database schema if necessary.
*
* Compares the currently active database schema version with the version
* required for this version of Hubzilla, and performs the upgrade if needed.
*
* If the difference consists of more than one revision of the schema, each of
* the intermediate upgrades are performed in turn.
*/
class DB_Upgrade {
public $config_name = '';
public $func_prefix = '';
function __construct($db_revision) {
$this->config_name = 'db_version';
$this->func_prefix = '_';
/**
* Check the installed and required schema versions and perform the upgrade
* if necessary.
*
* @param int $db_version The required DB schema version.
*/
public static function run(int $db_revision): void {
$build = Config::Get('system', 'db_version', 0);
if(! intval($build))

View File

@@ -35,7 +35,7 @@ class DReport {
}
function addto_update($status) {
$this->status = $this->status . ' ' . $status;
$this->status = $this->status . ', ' . $status;
}
@@ -89,8 +89,14 @@ class DReport {
if(array_key_exists('reject',$dr) && intval($dr['reject']))
return false;
if(! ($dr['sender']))
if (!$dr['sender']) {
return false;
}
// do not store dismissed create activities
if ($dr['status'] === 'not a collection activity') {
return false;
}
// Is the sender one of our channels?

View File

@@ -95,8 +95,8 @@ class Enotify {
if (array_key_exists('verb', $params['item'])) {
// localize_item() alters the original item so make a copy first
$i = $params['item'];
logger('calling localize');
localize_item($i);
// logger('calling localize');
// localize_item($i);
$title = $i['title'];
$body = $i['body'];
$private = (($i['item_private']) || intval($i['item_obscured']));
@@ -131,9 +131,9 @@ class Enotify {
logger('notification: mail');
$subject = sprintf( t('[$Projectname:Notify] New direct message received at %s'), $sitename);
$preamble = sprintf( t('%1$s sent you a new direct message at %2$s'), $sender['xchan_name'], $sitename);
$preamble = sprintf( t('%1$s sent you a new private message at %2$s'), $sender['xchan_name'], $sitename);
$epreamble = sprintf( t('%1$s sent you %2$s.'), '[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]', '[zrl=$itemlink]' . t('a direct message') . '[/zrl]');
$sitelink = t('Please visit %s to view and/or reply to your direct messages.');
$sitelink = t('Please visit %s to view and/or reply to your private messages.');
$tsitelink = sprintf( $sitelink, $siteurl . '/hq/' . gen_link_id($params['item']['mid']));
$hsitelink = sprintf( $sitelink, '<a href="' . $siteurl . '/hq/' . gen_link_id($params['item']['mid']) . '">' . $sitename . '</a>');
$itemlink = $siteurl . '/hq/' . gen_link_id($params['item']['mid']);
@@ -146,7 +146,7 @@ class Enotify {
$itemlink = $params['link'];
$action = (($moderated) ? t('requested to comment on') : t('commented on'));
$action = (($moderated) ? t('requested to post in') : t('posted in'));
if(array_key_exists('item',$params)) {
@@ -164,8 +164,8 @@ class Enotify {
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');
if(activity_match($params['verb'], [ACTIVITY_SHARE]))
$action = (($moderated) ? t('requested to repeat') : t('repeated'));
}
@@ -213,28 +213,36 @@ class Enotify {
//$possess_desc = str_replace('<!item_type!>',$possess_desc);
// "a post"
$dest_str = sprintf(t('%1$s %2$s [zrl=%3$s]a %4$s[/zrl]'),
$dest_str = sprintf(
t('%1$s %2$s [zrl=%3$s]a %4$s[/zrl]'),
'[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]',
$action,
$itemlink,
$item_post_type);
$item_post_type
);
// "George Bull's post"
if($p)
$dest_str = sprintf(t('%1$s %2$s [zrl=%3$s]%4$s\'s %5$s[/zrl]'),
if($p) {
$dest_str = sprintf(
t('%1$s %2$s [zrl=%3$s]%4$s\'s %5$s[/zrl]'),
'[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]',
$action,
$itemlink,
$p[0]['author']['xchan_name'],
$item_post_type);
$parent_item['author']['xchan_name'],
$item_post_type
);
}
// "your post"
if($p[0]['owner']['xchan_name'] == $p[0]['author']['xchan_name'] && intval($p[0]['item_wall']))
$dest_str = sprintf(t('%1$s %2$s [zrl=%3$s]your %4$s[/zrl]'),
if ($parent_item['owner']['xchan_hash'] === $recip['channel_hash'] && intval($parent_item['item_wall'])) {
$dest_str = sprintf(
t('%1$s %2$s [zrl=%3$s]your %4$s[/zrl]'),
'[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]',
$action,
$itemlink,
$item_post_type);
$item_post_type
);
}
// Some mail softwares relies on subject field for threading.
// So, we cannot have different subjects for notifications of the same thread.
@@ -263,7 +271,7 @@ class Enotify {
$itemlink = $params['link'];
if (array_key_exists('item',$params) && (activity_match($params['item']['verb'], ['Like', 'Dislike', ACTIVITY_LIKE, ACTIVITY_DISLIKE]))) {
if (array_key_exists('item',$params) && (activity_match($params['item']['verb'], ['Like', 'Dislike', ACTIVITY_LIKE, ACTIVITY_DISLIKE, 'Announce']))) {
if(! $always_show_in_notices || !($vnotify & VNOTIFY_LIKE) || !feature_enabled($recip['channel_id'], 'dislike')) {
logger('notification: not a visible activity. Ignoring.');
pop_lang();
@@ -308,7 +316,6 @@ class Enotify {
$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'));
@@ -320,14 +327,18 @@ class Enotify {
if(activity_match($params['item']['verb'], ['Dislike', ACTIVITY_DISLIKE]))
$verb = (($moderated) ? t('requested to dislike') : t('disliked'));
if(activity_match($params['item']['verb'], [ACTIVITY_SHARE]))
$verb = (($moderated) ? t('requested to repeat') : t('repeated'));
// "your post"
if($p[0]['owner']['xchan_name'] === $p[0]['author']['xchan_name'] && intval($p[0]['item_wall']))
if ($parent_item['author']['xchan_hash'] === $recip['channel_hash']) {
$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
);
}
else {
pop_lang();
return;
@@ -406,6 +417,7 @@ class Enotify {
}
elseif (isset($params['type']) && $params['type'] === NOTIFY_TAGSHARE) {
$itemlink = $params['link'];
$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]') ,
@@ -415,7 +427,6 @@ class Enotify {
$sitelink = t('Please visit %s to view and/or reply to the conversation.');
$tsitelink = sprintf( $sitelink, $siteurl );
$hsitelink = sprintf( $sitelink, '<a href="' . $siteurl . '">' . $sitename . '</a>');
$itemlink = $params['link'];
}
elseif (isset($params['type']) && $params['type'] === NOTIFY_INTRO) {
@@ -433,6 +444,7 @@ class Enotify {
}
elseif (isset($params['type']) && $params['type'] === NOTIFY_SUGGEST) {
$itemlink = $params['link'];
$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.'),
@@ -447,7 +459,6 @@ class Enotify {
$sitelink = t('Please visit %s to approve or reject the suggestion.');
$tsitelink = sprintf( $sitelink, $siteurl );
$hsitelink = sprintf( $sitelink, '<a href="' . $siteurl . '">' . $sitename . '</a>');
$itemlink = $params['link'];
}
elseif (isset($params['type']) && $params['type'] === NOTIFY_CONFIRM) {
@@ -500,9 +511,14 @@ class Enotify {
*/
$hash = ((in_array($params['verb'], ['Create', 'Update'])) ? $params['item']['uuid'] : $params['item']['thr_parent_uuid']);
if (!$hash) {
$hash = new_uuid();
}
$datarray = [];
$datarray['hash'] = $params['item']['uuid'] ?? new_uuid();
$datarray['hash'] = $hash;
$datarray['sender_hash'] = $sender['xchan_hash'];
$datarray['xname'] = $sender['xchan_name'];
$datarray['url'] = $sender['xchan_url'];
@@ -561,8 +577,9 @@ class Enotify {
dbesc($datarray['otype'])
);
$r = q("select id from notify where hash = '%s' and ntype = %d and uid = %d limit 1",
$r = q("select id from notify where hash = '%s' and link = '%s' and ntype = %d and uid = %d limit 1",
dbesc($datarray['hash']),
dbesc($itemlink),
intval($datarray['ntype']),
intval($recip['channel_id'])
);
@@ -595,7 +612,7 @@ class Enotify {
// send email notification if notification preferences permit
require_once('bbcode.php');
require_once('include/bbcode.php');
if ((intval($recip['channel_notifyflags']) & intval($params['type'])) || $params['type'] == NOTIFY_SYSTEM) {
logger('notification: sending notification email');
@@ -840,8 +857,8 @@ class Enotify {
}
else {
$itemem_text = (($item['item_thread_top'])
? (($item['obj_type'] === 'Question') ? t('created a new poll') : t('created a new post'))
: (($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]'))
? (($item['obj_type'] === 'Question') ? t('started a poll') : t('started a conversation'))
: (($item['obj_type'] === 'Answer') ? sprintf( t('voted on %s\'s poll'), '[bdi]' . $item['owner']['xchan_name'] . '[/bdi]') : sprintf( t('posted in %s\'s conversation'), '[bdi]' . $item['owner']['xchan_name'] . '[/bdi]'))
);
if(in_array($item['obj_type'], ['Document', 'Video', 'Audio', 'Image'])) {
@@ -853,12 +870,7 @@ class Enotify {
if($item['edited'] > $item['created']) {
$edit = true;
if($item['item_thread_top']) {
$itemem_text = sprintf( t('edited a post dated %s'), relative_date($item['created']));
}
else {
$itemem_text = sprintf( t('edited a comment dated %s'), relative_date($item['created']));
}
$itemem_text = sprintf( t('edited a message dated %s'), relative_date($item['created']));
}
@@ -878,7 +890,7 @@ class Enotify {
'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['uuid']) ? $item['uuid'] : ''),
'b64mid' => ((in_array($item['verb'] , ['Like', 'Dislike', 'Announce']) && !empty($item['thr_parent_uuid'])) ? $item['thr_parent_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)),
@@ -898,14 +910,13 @@ class Enotify {
}
static public function format_notify($tt) {
$message = trim(strip_tags(bbcode($tt['msg'])));
if(strpos($message, $tt['xname']) === 0)
$message = substr($message, strlen($tt['xname']) + 1);
$x = [
'notify_link' => (($tt['ntype'] === NOTIFY_MAIL) ? $tt['link'] : z_root() . '/notify/view/' . $tt['id']),
'notify_link' => (($tt['ntype'] === NOTIFY_INTRO) ? z_root() . '/notify/view/' . $tt['id'] : $tt['link']),
'name' => $tt['xname'],
'url' => $tt['url'],
'photo' => $tt['photo'],
@@ -917,11 +928,9 @@ class Enotify {
];
return $x;
}
static public function format_intros($rr) {
return [
'notify_link' => z_root() . '/connections#' . $rr['abook_id'],
'name' => $rr['xchan_name'],

View File

@@ -13,6 +13,7 @@ class IConfig {
static public function Get(&$item, $family, $key, $default = false) {
$is_item = false;
$iid = null;
if(is_array($item)) {
$is_item = true;
@@ -27,12 +28,13 @@ class IConfig {
elseif(intval($item))
$iid = $item;
if(! $iid)
if (!$iid)
return $default;
if(is_array($item) && array_key_exists('iconfig',$item) && is_array($item['iconfig'])) {
foreach($item['iconfig'] as $c) {
if($c['iid'] == $iid && $c['cat'] == $family && $c['k'] == $key)
if (isset($c['iid']) && $c['iid'] == $iid && isset($c['cat']) && $c['cat'] == $family && isset($c['k']) && $c['k'] == $key)
return $c['v'];
}
}

View File

@@ -7,11 +7,28 @@ use StephenHill\Base58;
class JcsEddsa2022 {
public function __construct() {
return $this;
}
/**
* Sign arbitrary data with the keys of the provided channel.
*
* @param $data The data to be signed.
* @param array $channel A channel as an array of key/value pairs.
*
* @return An array with the following fields:
* - `type`: The type of signature, always `DataIntegrityProof`.
* - `cryptosuite`: The cryptographic algorithm used, always `eddsa-jcs-2022`.
* - `created`: The UTC date and timestamp when the signature was created.
* - `verificationMethod`: The channel URL and the public key separated by a `#`.
* - `proofPurpose`: The purpose of the signature, always `assertionMethod`.
* - `proofValue`: The signature itself.
*
* @throws JcsEddsa2022SignatureException if the channel is missing, or
* don't have valid keys.
*/
public function sign($data, $channel): array {
if (!is_array($channel) || !isset($channel['channel_epubkey'], $channel['channel_eprvkey'])) {
throw new JcsEddsa2022SignException('Invalid or missing channel provided.');
}
$base58 = new Base58();
$pubkey = (new Multibase())->publicKey($channel['channel_epubkey']);
$options = [

View File

@@ -0,0 +1,15 @@
<?php
/*
* SPDX-FileCopyrightText: 2025 The Hubzilla Community
* SPDX-FileContributor: Harald Eilertsen <haraldei@anduin.net>
*
* SPDX-License-Identifier: MIT
*/
namespace Zotlabs\Lib;
use Exception;
class JcsEddsa2022SignException extends Exception
{
}

View File

@@ -2,8 +2,8 @@
namespace Zotlabs\Lib;
use phpseclib\Crypt\RSA;
use phpseclib\Math\BigInteger;
use phpseclib3\Crypt\PublicKeyLoader;
use phpseclib3\Math\BigInteger;
/**
* Keyutils
@@ -16,41 +16,42 @@ class Keyutils {
* @param string $e exponent
* @return string
*/
public static function meToPem($m, $e) {
$rsa = new RSA();
$rsa->loadKey([
public static function meToPem(string $m, string $e): string
{
$parsedKey = PublicKeyLoader::load([
'e' => new BigInteger($e, 256),
'n' => new BigInteger($m, 256)
]);
return $rsa->getPublicKey();
if (method_exists($parsedKey, 'getPublicKey')) {
$parsedKey = $parsedKey->getPublicKey();
}
return $parsedKey->toString('PKCS8');
}
/**
* @param string key
* @return string
*/
public static function rsaToPem($key) {
$rsa = new RSA();
$rsa->setPublicKey($key);
return $rsa->getPublicKey(RSA::PUBLIC_FORMAT_PKCS8);
public static function rsaToPem(string $key): string
{
$parsedKey = PublicKeyLoader::load($key);
if (method_exists($parsedKey, 'getPublicKey')) {
$parsedKey = $parsedKey->getPublicKey();
}
return $parsedKey->toString('PKCS8');
}
/**
* @param string key
* @return string
*/
public static function pemToRsa($key) {
$rsa = new RSA();
$rsa->setPublicKey($key);
return $rsa->getPublicKey(RSA::PUBLIC_FORMAT_PKCS1);
public static function pemToRsa(string $key): string
{
$parsedKey = PublicKeyLoader::load($key);
if (method_exists($parsedKey, 'getPublicKey')) {
$parsedKey = $parsedKey->getPublicKey();
}
return $parsedKey->toString('PKCS1');
}
/**
@@ -58,23 +59,28 @@ class Keyutils {
* @param string $m reference modulo
* @param string $e reference exponent
*/
public static function pemToMe($key, &$m, &$e) {
public static function pemToMe(string $key): array
{
$parsedKey = PublicKeyLoader::load($key);
if (method_exists($parsedKey, 'getPublicKey')) {
$parsedKey = $parsedKey->getPublicKey();
}
$raw = $parsedKey->toString('Raw');
$rsa = new RSA();
$rsa->loadKey($key);
$rsa->setPublicKey();
$m = $rsa->modulus->toBytes();
$e = $rsa->exponent->toBytes();
$m = $raw['n'];
$e = $raw['e'];
return [$m->toBytes(), $e->toBytes()];
}
/**
* @param string $pubkey
* @return string
*/
public static function salmonKey($pubkey) {
self::pemToMe($pubkey, $m, $e);
public static function salmonKey(string $pubkey): string
{
[$m, $e] = self::pemToMe($pubkey);
/** @noinspection PhpRedundantOptionalArgumentInspection */
return 'RSA' . '.' . base64url_encode($m, true) . '.' . base64url_encode($e, true);
}
@@ -82,11 +88,13 @@ class Keyutils {
* @param string $key
* @return string
*/
public static function convertSalmonKey($key) {
if (strstr($key, ','))
public static function convertSalmonKey(string $key): string
{
if (str_contains($key, ',')) {
$rawkey = substr($key, strpos($key, ',') + 1);
else
} else {
$rawkey = substr($key, 5);
}
$key_info = explode('.', $rawkey);
@@ -96,4 +104,4 @@ class Keyutils {
return self::meToPem($m, $e);
}
}
}

View File

@@ -885,7 +885,7 @@ class Libsync {
dbesc($t)
);
q("update hubloc set hubloc_error = 1, hubloc_deleted = 1 where hubloc_url = '%s' and hubloc_sitekey != '%s'",
q("update hubloc set hubloc_error = 1, hubloc_deleted = 1 where hubloc_url = '%s' and hubloc_sitekey != '%s' and hubloc_network = 'zot6'",
dbesc($r[0]['hubloc_url']),
dbesc($r[0]['hubloc_sitekey'])
);

View File

@@ -655,6 +655,11 @@ class Libzot {
return $ret;
}
if (empty($arr['primary_location']['address'])) {
logger('Empty primary location address: ' . print_r($arr, true), LOGGER_DEBUG);
return $ret;
}
/**
* @hooks import_xchan
* Called when processing the result of zot_finger() to store the result
@@ -1134,6 +1139,7 @@ class Libzot {
}
$message_request = false;
$is_collection_operation = false;
$has_data = array_key_exists('data', $env) && $env['data'];
@@ -1141,15 +1147,33 @@ class Libzot {
$AS = null;
if ($env['encoding'] === 'activitystreams') {
$AS = new ActivityStreams($data);
if (!$AS->is_valid()) {
logger('Activity rejected: ' . print_r($data, true));
return;
// process add/remove from collection separately, as it requires a target.
// use the data object, as it will not include actor expansion
if (in_array($AS->type, ['Add', 'Remove'])
&& is_array($AS->obj)
&& array_key_exists('object', $AS->obj)
&& array_key_exists('actor', $AS->obj)
&& !empty($AS->tgt)) {
logger('relayed collection operation', LOGGER_DEBUG);
$is_collection_operation = true;
$original_id = $AS->id;
$original_type = $AS->type;
$raw_activity = $AS->data;
$AS = new ActivityStreams($raw_activity['object'], portable_id: $env['sender']);
}
if (is_array($AS->obj)) {
$item = Activity::decode_note($AS);
if (!$item) {
logger('Could not decode activity: ' . print_r($AS, true));
return;
@@ -1158,6 +1182,12 @@ class Libzot {
else {
$item = [];
}
if (!$AS->is_valid()) {
logger('Activity rejected: ' . print_r($data, true));
return;
}
logger($AS->debug(), LOGGER_DATA);
}
@@ -1198,7 +1228,6 @@ class Libzot {
logger('public post');
// Public post. look for any site members who are or may be accepting posts from this sender
// and who are allowed to see them based on the sender's permissions
// @fixme;
@@ -1265,25 +1294,6 @@ class Libzot {
$item['item_private'] = 1;
}
if ($item['mid'] === $item['parent_mid']) {
if (is_array($AS->obj) && array_key_exists('commentPolicy', $AS->obj)) {
$p = strstr($AS->obj['commentPolicy'], 'until=');
if ($p !== false) {
$comments_closed_at = datetime_convert('UTC', 'UTC', substr($p, 6));
if ($comments_closed_at === $item['created']) {
$item['item_nocomment'] = 1;
}
else {
$item['comments_closed'] = $comments_closed_at;
$aritemr['comment_policy'] = trim(str_replace($p, '', $AS->obj['commentPolicy']));
}
}
else {
$item['comment_policy'] = $AS->obj['commentPolicy'];
}
}
}
if (!empty($AS->meta['hubloc']) || $AS->sigok) {
$item['item_verified'] = true;
}
@@ -1301,7 +1311,7 @@ class Libzot {
$relay = (($env['type'] === 'response') ? true : false);
$result = self::process_delivery($env['sender'], $AS, $item, $deliveries, $relay, false, $message_request);
$result = self::process_delivery($env['sender'], $AS, $item, $deliveries, $relay, false, $message_request, false, $is_collection_operation);
Activity::init_background_fetch($env['sender']);
}
@@ -1517,7 +1527,7 @@ class Libzot {
* @return array
*/
static function process_delivery($sender, $act, $arr, $deliveries, $relay, $public = false, $request = false, $force = false) {
static function process_delivery($sender, $act, $arr, $deliveries, $relay, $public = false, $request = false, $force = false, $is_collection_operation = false) {
$result = [];
// We've validated the sender. Now make sure that the sender is the owner or author
@@ -1532,6 +1542,7 @@ class Libzot {
$local_public = $public;
$item_result = null;
$parent = null;
$DR = new DReport(z_root(), $sender, $d, $arr['mid'], $arr['uuid']);
@@ -1545,6 +1556,14 @@ class Libzot {
$DR->set_name($channel['channel_name'] . ' <' . channel_reddress($channel) . '>');
$conversation_operation = $is_collection_operation && isset($arr['target']['attributedTo']);
if (isset($arr['tgt_type']) && str_contains($arr['tgt_type'], 'Collection') && !$relay && !$conversation_operation) {
$DR->update('not a collection activity');
$result[] = $DR->get();
continue;
}
if (($act) && ($act->obj) && (!is_array($act->obj))) {
// The initial object fetch failed using the sys channel credentials.
// Try again using the delivery channel credentials.
@@ -1578,6 +1597,8 @@ class Libzot {
*
*/
if ($sender === $channel['channel_hash'] && $arr['author_xchan'] === $channel['channel_hash'] && !str_starts_with($arr['mid'], z_root())) {
$DR->update('self delivery ignored');
$result[] = $DR->get();
@@ -1624,15 +1645,6 @@ class Libzot {
if (intval($channel['channel_system']) && (!$arr['item_private']) && (!$relay)) {
$local_public = true;
$r = q("select xchan_selfcensored from xchan where xchan_hash = '%s' limit 1",
dbesc($sender)
);
// don't import sys channel posts from selfcensored authors
if ($r && (intval($r[0]['xchan_selfcensored']))) {
$local_public = false;
continue;
}
$incl = Config::Get('system','pubstream_incl');
$excl = Config::Get('system','pubstream_excl');
@@ -1640,6 +1652,17 @@ class Libzot {
$local_public = false;
continue;
}
$r = q("select xchan_selfcensored, xchan_censored from xchan where xchan_hash = '%s'",
dbesc($sender)
);
// don't import sys channel posts from selfcensored or censored authors
if ($r && ($r[0]['xchan_selfcensored'] || $r[0]['xchan_censored'])) {
$local_public = false;
continue;
}
}
$tag_delivery = tgroup_check($channel['channel_id'], $arr);
@@ -1701,6 +1724,7 @@ class Libzot {
// If this is a poll response, convert the obj_type to our (internal-only) "Answer" type
if (in_array($arr['obj_type'], ['Note', ACTIVITY_OBJ_COMMENT]) && $arr['title'] && (!$arr['body'])) {
$arr['obj_type'] = 'Answer';
$arr['item_hidden'] = 1;
}
}
@@ -1826,11 +1850,12 @@ class Libzot {
dbesc($arr['author_xchan'])
);
// reactions such as like and dislike could have an mid with /activity/ in it.
// Reactions such as like and dislike could have an mid with /activity/ in it.
// Check for both forms in order to prevent duplicates.
$r = q("select * from item where mid in ('%s','%s') and uid = %d limit 1",
$r = q("select * from item where mid in ('%s', '%s') and uid = %d limit 1",
dbesc($arr['mid']),
dbesc(str_replace(z_root() . '/activity/', z_root() . '/item/', $arr['mid'])),
dbesc(reverse_activity_mid($arr['mid'])),
intval($channel['channel_id'])
);
@@ -1859,21 +1884,29 @@ class Libzot {
$DR->update('update ignored');
$result[] = $DR->get();
}
if ($relay && $channel['channel_hash'] === $item_result['item']['owner_xchan'] && $item_result['item']['verb'] !== 'Add' && !$is_collection_operation) {
$approval = Activity::addToCollection($channel, $act->data, $item_result['item']['parent_mid'], $item_result['item'], deliver: false);
}
}
else {
$DR->update('update ignored');
$result[] = $DR->get();
// We need this line to ensure wall-to-wall comments are relayed (by falling through to the relay bit),
// We need this line to ensure wall-to-wall comments and add/remove activities are relayed (by falling through to the relay bit),
// and at the same time not relay any other relayable posts more than once, because to do so is very wasteful.
if (!intval($r[0]['item_origin']))
continue;
}
}
else {
$arr['aid'] = $channel['channel_account_id'];
$arr['uid'] = $channel['channel_id'];
// if it's a sourced post, call the post_local hooks as if it were
// posted locally so that crosspost connectors will be triggered.
$item_source = check_item_source($arr['uid'], $arr);
@@ -1902,10 +1935,15 @@ class Libzot {
}
if (post_is_importable($arr['uid'], $arr, $abook)) {
$item_result = item_store($arr);
$item_result = item_store($arr, addAndSync: false);
if ($item_result['success']) {
$item_id = $item_result['item_id'];
if ($relay && $channel['channel_hash'] === $item_result['item']['owner_xchan'] && $item_result['item']['verb'] !== 'Add' && !$is_collection_operation) {
$approval = Activity::addToCollection($channel, $act->data, $item_result['item']['parent_mid'], $item_result['item'], deliver: false);
}
if ($item_source && in_array($item_result['item']['obj_type'], ['Event', ACTIVITY_OBJ_EVENT])) {
event_addtocal($item_id, $channel['channel_id']);
}
@@ -1948,14 +1986,18 @@ class Libzot {
if ((is_array($stored)) && ($stored['id'] != $stored['parent'])
&& ($stored['author_xchan'] === $channel['channel_hash'])) {
retain_item($stored['item']['parent']);
retain_item($stored['parent']);
}
if ($relay && $item_id && $stored['item_blocked'] !== ITEM_MODERATED) {
if ($relay && $item_id && item_forwardable($stored)) {
logger('Invoking relay');
Master::Summon(['Notifier', 'relay', intval($item_id)]);
if (!empty($approval) && $approval['item_id']) {
Master::Summon(['Notifier', 'relay', intval($approval['item_id'])]);
}
$DR->addto_update('relayed');
$result[] = $DR->get();
$result = [$DR->get()];
}
}
@@ -2006,6 +2048,7 @@ class Libzot {
foreach ($items as $activity) {
$AS = new ActivityStreams($activity);
if ($AS->is_valid() && $AS->type === 'Announce' && is_array($AS->obj)
&& array_key_exists('object', $AS->obj) && array_key_exists('actor', $AS->obj)) {
// This is a relayed/forwarded Activity (as opposed to a shared/boosted object)
@@ -2014,6 +2057,30 @@ class Libzot {
$AS = new ActivityStreams($AS->obj);
}
// process add/remove from collection separately, as it requires a target.
// use the raw object, as it will not include actor expansion
if (in_array($AS->type, ['Add', 'Remove'])
&& is_array($AS->obj)
&& array_key_exists('object', $AS->obj)
&& array_key_exists('actor', $AS->obj)
&& !empty($AS->tgt)) {
logger('relayed collection operation', LOGGER_DEBUG);
$is_collection_operation = true;
$original_id = $AS->id;
$original_type = $AS->type;
$raw_activity = $AS->data;
$AS = new ActivityStreams($raw_activity['object']);
// Store the original activity id and type for later usage
$AS->meta['original_id'] = $original_id;
$AS->meta['original_type'] = $original_type;
}
if (!$AS->is_valid()) {
logger('Fetched activity rejected: ' . print_r($activity, true));
continue;
@@ -2207,7 +2274,7 @@ class Libzot {
}
$x = item_store_update($item);
$x = item_store_update($item, addAndSync: false);
// If we're updating an event that we've saved locally, we store the item info first
// because event_addtocal will parse the body to get the 'new' event details
@@ -2323,21 +2390,20 @@ class Libzot {
);
}
} else {
if ($stored['id'] !== $stored['parent']) {
q(
"update item set commented = '%s', changed = '%s' where id = %d",
dbesc(datetime_convert()),
dbesc(datetime_convert()),
intval($stored['parent'])
);
}
}
if ($stored['id'] !== $stored['parent']) {
q("update item set commented = '%s', changed = '%s' where id = %d",
dbesc(datetime_convert()),
dbesc(datetime_convert()),
intval($stored['parent'])
);
}
}
// Use phased deletion to set the deleted flag, call both tag_deliver and the notifier to notify downstream channels
// and then clean up after ourselves with a cron job after several days to do the delete_item_lowlevel() (DROPITEM_PHASE2).
drop_item($post_id, false, DROPITEM_PHASE1);
drop_item($post_id, DROPITEM_PHASE1, uid: $uid);
tag_deliver($uid, $post_id);
}

86
Zotlabs/Lib/Mailer.php Normal file
View File

@@ -0,0 +1,86 @@
<?php
/**
* Mailer class for sending emails from Hubzilla.
*
* SPDX-FileCopyrightText: 2024 Hubzilla Community
* SPDX-FileContributor: Harald Eilertsen
*
* SPDX-License-Identifier: MIT
*/
namespace Zotlabs\Lib;
use App;
/**
* A class for sending emails.
*
* Based on the previous `z_mail` function, but adaped and made more
* robust and usable as a class.
*/
class Mailer {
public function __construct(private array $params = []) {
}
public function deliver(): bool {
if(empty($this->params['fromEmail'])) {
$this->params['fromEmail'] = Config::Get('system','from_email');
if(empty($this->params['fromEmail'])) {
$this->params['fromEmail'] = 'Administrator@' . App::get_hostname();
}
}
if(empty($this->params['fromName'])) {
$this->params['fromName'] = Config::Get('system','from_email_name');
if(empty($this->params['fromName'])) {
$this->params['fromName'] = System::get_site_name();
}
}
if(empty($this->params['replyTo'])) {
$this->params['replyTo'] = Config::Get('system','reply_address');
if(empty($this->params['replyTo'])) {
$this->params['replyTo'] = 'noreply@' . App::get_hostname();
}
}
if (!isset($this->params['additionalMailHeader'])) {
$this->params['additionalMailHeader'] = '';
}
$this->params['sent'] = false;
$this->params['result'] = false;
/**
* @hooks email_send
* * \e params @see z_mail()
*/
call_hooks('email_send', $this->params);
if($this->params['sent']) {
logger('notification: z_mail returns ' . (($this->params['result']) ? 'success' : 'failure'), LOGGER_DEBUG);
return $this->params['result'];
}
$fromName = email_header_encode(html_entity_decode($this->params['fromName'],ENT_QUOTES,'UTF-8'),'UTF-8');
$messageSubject = email_header_encode(html_entity_decode($this->params['messageSubject'],ENT_QUOTES,'UTF-8'),'UTF-8');
$messageHeader =
$this->params['additionalMailHeader'] .
"From: $fromName <{$this->params['fromEmail']}>" . PHP_EOL .
"Reply-To: $fromName <{$this->params['replyTo']}>" . PHP_EOL .
"Content-Type: text/plain; charset=UTF-8";
// send the message
$res = mail(
$this->params['toEmail'], // send to address
$messageSubject, // subject
$this->params['textVersion'],
$messageHeader // message headers
);
logger('notification: z_mail returns ' . (($res) ? 'success' : 'failure'), LOGGER_DEBUG);
return $res;
}
}

View File

@@ -8,17 +8,18 @@ class MessageFilter {
public static function evaluate($item, $incl, $excl) {
$text = prepare_text($item['body'],((isset($item['mimetype'])) ? $item['mimetype'] : 'text/bbcode'));
$text = html2plain(($item['title']) ? $item['title'] . ' ' . $text : $text);
$text = prepare_text($item['body'], ((isset($item['mimetype'])) ? $item['mimetype'] : 'text/bbcode'));
$text = html2plain((!empty($item['title'])) ? $item['title'] . ' ' . $text : $text);
$lang = null;
if ((strpos($incl, 'lang=') !== false) || (strpos($excl, 'lang=') !== false) || (strpos($incl, 'lang!=') !== false) || (strpos($excl, 'lang!=') !== false)) {
$lang = detect_language($text);
}
$tags = ((isset($item['term']) && is_array($item['term']) && count($item['term'])) ? $item['term'] : false);
$until = null;
// exclude always has priority
$exclude = (($excl) ? explode("\n", $excl) : null);
@@ -41,7 +42,13 @@ class MessageFilter {
return false;
}
}
elseif (substr($word, 0, 1) === '#' && $tags) {
elseif (str_starts_with($word, 'until=')) {
$until = strtotime(trim(substr($word, 6)));
if ($until > strtotime($item['created'] . ' UTC')) {
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;
@@ -89,7 +96,13 @@ class MessageFilter {
return true;
}
}
elseif (substr($word, 0, 1) === '#' && $tags) {
elseif (str_starts_with($word, 'until=')) {
$until = strtotime(trim(substr($word, 6)));
if ($until > strtotime($item['created'] . ' UTC')) {
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;
@@ -124,9 +137,7 @@ class MessageFilter {
/**
* @brief Test for Conditional Execution conditions. Shamelessly ripped off from Code/Render/Comanche
*
* This is extensible. The first version of variable testing supports tests of the forms:
* Evaluate a conditional expression with support for AND (&&) and OR (||) operators.
*
* - ?foo ~= baz which will check if item.foo contains the string 'baz';
* - ?foo == baz which will check if item.foo is the string 'baz';
@@ -143,103 +154,110 @@ class MessageFilter {
*
* The values 0, '', an empty array, and an unset value will all evaluate to false.
*
* @param string $s
* @param array $item
* @return bool
* @param string $s The condition string to evaluate.
* @param array $item The associative array providing variable values.
* @return bool True if the condition is met, false otherwise.
*/
public static function test_condition($s,$item) {
public static function test_condition($s, $item) {
$s = trim($s);
// Handle OR (||)
// Split on '||' not inside quotes
$or_parts = preg_split('/\s*\|\|\s*/', $s);
if (count($or_parts) > 1) {
foreach ($or_parts as $part) {
if (self::test_condition(ltrim($part, '?+'), $item)) {
return true;
}
}
return false;
}
// Handle AND (&&)
// Split on '&&' not inside quotes
$and_parts = preg_split('/\s*\&\&\s*/', $s);
if (count($and_parts) > 1) {
foreach ($and_parts as $part) {
if (!self::test_condition(ltrim($part, '?+'), $item)) {
return false;
}
}
return true;
}
// Basic checks
// Contains substring (case-insensitive)
if (preg_match('/(.*?)\s\~\=\s(.*?)$/', $s, $matches)) {
$x = ((array_key_exists(trim($matches[1]),$item)) ? $item[trim($matches[1])] : EMPTY_STR);
if (stripos($x, trim($matches[2])) !== false) {
return true;
}
return false;
$x = ((array_key_exists(trim($matches[1]), $item)) ? $item[trim($matches[1])] : EMPTY_STR);
return (stripos($x, trim($matches[2])) !== false);
}
// Equality
if (preg_match('/(.*?)\s\=\=\s(.*?)$/', $s, $matches)) {
$x = ((array_key_exists(trim($matches[1]),$item)) ? $item[trim($matches[1])] : EMPTY_STR);
if ($x == trim($matches[2])) {
return true;
}
return false;
$x = ((array_key_exists(trim($matches[1]), $item)) ? $item[trim($matches[1])] : EMPTY_STR);
return ($x == trim($matches[2]));
}
// Inequality
if (preg_match('/(.*?)\s\!\=\s(.*?)$/', $s, $matches)) {
$x = ((array_key_exists(trim($matches[1]),$item)) ? $item[trim($matches[1])] : EMPTY_STR);
if ($x != trim($matches[2])) {
return true;
}
return false;
$x = ((array_key_exists(trim($matches[1]), $item)) ? $item[trim($matches[1])] : EMPTY_STR);
return ($x != trim($matches[2]));
}
// Greater than or equal
if (preg_match('/(.*?)\s\>\=\s(.*?)$/', $s, $matches)) {
$x = ((array_key_exists(trim($matches[1]),$item)) ? $item[trim($matches[1])] : EMPTY_STR);
if ($x >= trim($matches[2])) {
return true;
}
return false;
$x = ((array_key_exists(trim($matches[1]), $item)) ? $item[trim($matches[1])] : EMPTY_STR);
return ($x >= trim($matches[2]));
}
// Less than or equal
if (preg_match('/(.*?)\s\<\=\s(.*?)$/', $s, $matches)) {
$x = ((array_key_exists(trim($matches[1]),$item)) ? $item[trim($matches[1])] : EMPTY_STR);
if ($x <= trim($matches[2])) {
return true;
}
return false;
$x = ((array_key_exists(trim($matches[1]), $item)) ? $item[trim($matches[1])] : EMPTY_STR);
return ($x <= trim($matches[2]));
}
// Greater than
if (preg_match('/(.*?)\s\>\s(.*?)$/', $s, $matches)) {
$x = ((array_key_exists(trim($matches[1]),$item)) ? $item[trim($matches[1])] : EMPTY_STR);
if ($x > trim($matches[2])) {
return true;
}
return false;
$x = ((array_key_exists(trim($matches[1]), $item)) ? $item[trim($matches[1])] : EMPTY_STR);
return ($x > trim($matches[2]));
}
if (preg_match('/(.*?)\s\>\s(.*?)$/', $s, $matches)) {
$x = ((array_key_exists(trim($matches[1]),$item)) ? $item[trim($matches[1])] : EMPTY_STR);
if ($x < trim($matches[2])) {
return true;
}
return false;
// Less than
if (preg_match('/(.*?)\s\<\s(.*?)$/', $s, $matches)) {
$x = ((array_key_exists(trim($matches[1]), $item)) ? $item[trim($matches[1])] : EMPTY_STR);
return ($x < trim($matches[2]));
}
if (preg_match('/[\$](.*?)\s\{\}\s(.*?)$/', $s, $matches)) {
$x = ((array_key_exists(trim($matches[1]),$item)) ? $item[trim($matches[1])] : EMPTY_STR);
if (is_array($x) && in_array(trim($matches[2]), $x)) {
return true;
}
return false;
// Array contains value
if (preg_match('/(.*?)\s\{\}\s(.*?)$/', $s, $matches)) {
$x = ((array_key_exists(trim($matches[1]), $item)) ? $item[trim($matches[1])] : EMPTY_STR);
return (is_array($x) && in_array(trim($matches[2]), $x));
}
// Array contains key
if (preg_match('/(.*?)\s\{\*\}\s(.*?)$/', $s, $matches)) {
$x = ((array_key_exists(trim($matches[1]),$item)) ? $item[trim($matches[1])] : EMPTY_STR);
if (is_array($x) && array_key_exists(trim($matches[2]), $x)) {
return true;
}
return false;
$x = ((array_key_exists(trim($matches[1]), $item)) ? $item[trim($matches[1])] : EMPTY_STR);
return (is_array($x) && array_key_exists(trim($matches[2]), $x));
}
// Ordering of this check (for falsiness) with relation to the following one (check for truthiness) is important.
// Falsy check
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;
$x = ((array_key_exists(trim($matches[1]), $item)) ? $item[trim($matches[1])] : EMPTY_STR);
return !$x;
}
// Truthy check (default)
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;
$x = ((array_key_exists(trim($matches[1]), $item)) ? $item[trim($matches[1])] : EMPTY_STR);
return (bool)$x;
}
// If no conditions matched, return false
return false;
}
}

View File

@@ -1,127 +0,0 @@
<?php
namespace Zotlabs\Lib;
/**
* @brief wrapper for z_fetch_url() which can be instantiated with several built-in parameters and
* these can be modified and re-used. Useful for CalDAV and other processes which need to authenticate
* and set lots of CURL options (many of which stay the same from one call to the next).
*/
class SuperCurl {
private $auth;
private $url;
private $curlopt = array();
private $headers = null;
public $filepos = 0;
public $filehandle = 0;
public $request_data = '';
private $request_method = 'GET';
private $upload = false;
private $cookies = false;
private function set_data($s) {
$this->request_data = $s;
$this->filepos = 0;
}
public function curl_read($ch,$fh,$size) {
if($this->filepos < 0) {
unset($fh);
return '';
}
$s = substr($this->request_data,$this->filepos,$size);
if(strlen($s) < $size)
$this->filepos = (-1);
else
$this->filepos = $this->filepos + $size;
return $s;
}
public function __construct($opts = array()) {
$this->set($opts);
}
private function set($opts = array()) {
if($opts) {
foreach($opts as $k => $v) {
switch($k) {
case 'http_auth':
$this->auth = $v;
break;
case 'magicauth':
// currently experimental
$this->magicauth = $v;
\Zotlabs\Daemon\Master::Summon([ 'CurlAuth', $v ]);
break;
case 'custom':
$this->request_method = $v;
break;
case 'url':
$this->url = $v;
break;
case 'data':
$this->set_data($v);
if($v) {
$this->upload = true;
}
else {
$this->upload = false;
}
break;
case 'headers':
$this->headers = $v;
break;
default:
$this->curlopts[$k] = $v;
break;
}
}
}
}
function exec() {
$opts = $this->curlopts;
$url = $this->url;
if($this->auth)
$opts['http_auth'] = $this->auth;
if($this->magicauth) {
$opts['cookiejar'] = 'store/[data]/cookie_' . $this->magicauth;
$opts['cookiefile'] = 'store/[data]/cookie_' . $this->magicauth;
$opts['cookie'] = 'PHPSESSID=' . trim(file_get_contents('store/[data]/cookien_' . $this->magicauth));
$c = channelx_by_n($this->magicauth);
if($c)
$url = zid($this->url,channel_reddress($c));
}
if($this->custom)
$opts['custom'] = $this->custom;
if($this->headers)
$opts['headers'] = $this->headers;
if($this->upload) {
$opts['upload'] = true;
$opts['infile'] = $this->filehandle;
$opts['infilesize'] = strlen($this->request_data);
$opts['readfunc'] = [ $this, 'curl_read' ] ;
}
$recurse = 0;
return z_fetch_url($this->url,true,$recurse,(($opts) ? $opts : null));
}
}

View File

@@ -21,4 +21,13 @@ class Text {
return htmlspecialchars($string, ENT_COMPAT, 'UTF-8', false);
}
public static function rawurlencode_parts(string $string): string {
if (!$string) {
return EMPTY_STR;
}
return implode('/', array_map('rawurlencode', explode('/', $string)));
}
}

View File

@@ -4,8 +4,6 @@ namespace Zotlabs\Lib;
use App;
use Zotlabs\Access\AccessList;
use Zotlabs\Lib\Apps;
use Zotlabs\Lib\Config;
require_once('include/text.php');
@@ -26,6 +24,7 @@ class ThreadItem {
private $parent = null;
private $conversation = null;
private $redirect_url = null;
private $owner_addr = '';
private $owner_url = '';
private $owner_photo = '';
private $owner_name = '';
@@ -35,14 +34,12 @@ class ThreadItem {
private $channel = null;
private $display_mode = 'normal';
private $reload = '';
private $mid_uuid_map = [];
public function __construct($data) {
$this->data = $data;
$this->toplevel = ($this->get_id() == $this->get_data_value('parent'));
$this->threaded = Config::Get('system','thread_allow');
$this->threaded = ((local_channel()) ? PConfig::Get(local_channel(), 'system', 'thread_allow', true) : Config::Get('system', 'thread_allow', true));
// Prepare the children
if(isset($data['children'])) {
@@ -65,8 +62,6 @@ class ThreadItem {
unset($this->data['children']);
}
// allow a site to configure the order and content of the reaction emoji list
if($this->toplevel) {
$x = Config::Get('system','reactions');
@@ -84,7 +79,7 @@ class ThreadItem {
* _ false on failure
*/
public function get_template_data($conv_responses, $mid_uuid_map, $thread_level=1, $conv_flags = []) {
public function get_template_data($thread_level=1, $conv_flags = []) {
$result = [];
$item = $this->get_data();
@@ -103,6 +98,8 @@ class ThreadItem {
$conv = $this->get_conversation();
$observer = $conv->get_observer();
$conv->mid_uuid_map[$item['mid']] = $item['uuid'];
$acl = new AccessList([]);
$acl->set($item);
@@ -114,7 +111,7 @@ class ThreadItem {
$locktype = intval($item['item_private']);
if ($locktype === 2) {
$lock = t('Direct message');
$lock = t('Private message');
}
// 0 = limited based on public policy
@@ -187,7 +184,7 @@ class ThreadItem {
$drop = [ 'dropping' => true, 'delete' => t('Admin Delete') ];
}
$filer = ((($conv->get_profile_owner() == local_channel()) && (! array_key_exists('real_uid',$item))) ? t("Save to Folder") : false);
$filer = (((local_channel() && $conv->get_profile_owner() === local_channel()) || (local_channel() && App::$module === 'pubstream')) ? t("Save to Folder") : false);
$profile_avatar = $item['author']['xchan_photo_s'];
$profile_link = chanlink_hash($item['author_xchan']);
@@ -209,9 +206,9 @@ class ThreadItem {
}
if (in_array($item['obj_type'], ['Event', ACTIVITY_OBJ_EVENT])) {
$response_verbs[] = 'attendyes';
$response_verbs[] = 'attendno';
$response_verbs[] = 'attendmaybe';
$response_verbs[] = 'accept';
$response_verbs[] = 'reject';
$response_verbs[] = 'tentativeaccept';
if($this->is_commentable() && $observer) {
$isevent = true;
$attend = array( t('I will attend'), t('I will not attend'), t('I might attend'));
@@ -222,56 +219,8 @@ class ThreadItem {
$response_verbs[] = 'answer';
}
if (!feature_enabled($conv->get_profile_owner(),'dislike')) {
unset($conv_responses['dislike']);
}
$responses = get_responses($conv_responses,$response_verbs,$this,$item);
$my_responses = [];
foreach($response_verbs as $v) {
$my_responses[$v] = ((isset($conv_responses[$v][$item['mid'] . '-m'])) ? 1 : 0);
}
/*
$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)) {
$like_list_part = array_slice($like_list, 0, MAX_LIKERS);
array_push($like_list_part, '<a class="dropdown-item" href="#" data-toggle="modal" data-target="#likeModal-' . $this->get_id() . '"><b>' . t('View all') . '</b></a>');
} else {
$like_list_part = '';
}
$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'] : '');
$dislike_button_label = tt('Dislike','Dislikes',$dislike_count,'noun');
if (($dislike_list) && (count($dislike_list) > MAX_LIKERS)) {
$dislike_list_part = array_slice($dislike_list, 0, MAX_LIKERS);
array_push($dislike_list_part, '<a class="dropdown-item" href="#" data-toggle="modal" data-target="#dislikeModal-' . $this->get_id() . '"><b>' . t('View all') . '</b></a>');
} 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']) : '');
*/
$response_verbs[] = 'comment';
$responses = get_responses($response_verbs, $item);
/*
* We should avoid doing this all the time, but it depends on the conversation mode
@@ -281,7 +230,13 @@ class ThreadItem {
$this->check_wall_to_wall();
$children = $this->get_children();
$children_count = count($children);
if($this->is_toplevel()) {
$conv->comments_total = $responses['comment']['count'] ?? 0;
$conv->comments_loaded = $children_count;
if((local_channel() && $conv->get_profile_owner() === local_channel()) || (local_channel() && App::$module === 'pubstream')) {
$star = [
'toggle' => t("Toggle Star Status"),
@@ -293,7 +248,6 @@ class ThreadItem {
$is_comment = true;
}
$verified = (intval($item['item_verified']) ? t('Message signature validated') : '');
$forged = ((($item['sig']) && (! intval($item['item_verified']))) ? t('Message signature incorrect') : '');
$unverified = '' ; // (($this->is_wall_to_wall() && (! intval($item['item_verified']))) ? t('Message cannot be verified') : '');
@@ -326,15 +280,11 @@ class ThreadItem {
if((in_array($item['obj_type'], ['Event', ACTIVITY_OBJ_EVENT])) && $conv->get_profile_owner() == local_channel())
$has_event = true;
$like = [];
$dislike = [];
$reply_to = [];
$reactions_allowed = false;
if($this->is_commentable() && $observer) {
$like = array( t("I like this \x28toggle\x29"), t("like"));
$dislike = array( t("I don't like this \x28toggle\x29"), t("dislike"));
$reply_to = array( t("Reply to this comment"), t("reply"), t("Reply to"));
$reply_to = array( t("Reply to this message"), t("reply"), t("Reply to"));
$reactions_allowed = true;
}
@@ -378,9 +328,8 @@ class ThreadItem {
$viewthread = z_root() . '/channel/' . $owner_address . '?f=&mid=' . urlencode(gen_link_id($item['mid']));
$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();
$list_unseen_txt = $unseen_comments ? ['label' => sprintf(t('%d unseen'), $unseen_comments), 'count' => $unseen_comments] : [];
$has_tags = (($body['tags'] || $body['categories'] || $body['mentions'] || $body['attachments'] || $body['folders']) ? true : false);
@@ -390,14 +339,7 @@ class ThreadItem {
$midb64 = $item['uuid'];
$mids = [ $item['uuid'] ];
$response_mids = [];
foreach($response_verbs as $v) {
if(isset($conv_responses[$v]['mids'][$item['mid']])) {
$response_mids = array_merge($response_mids, $conv_responses[$v]['mids'][$item['mid']]);
}
}
$mids = array_merge($mids, $response_mids);
$json_mids = json_encode($mids);
// Pinned item processing
@@ -411,11 +353,26 @@ class ThreadItem {
$contact = App::$contacts[$item['author_xchan']];
}
$blog_mode = $this->get_display_mode() === 'list';
$load_more = false;
$load_more_title = '';
$comments_total_percent = 0;
if (($conv->comments_total > $conv->comments_loaded) || ($blog_mode && $conv->comments_total > 3)) {
// provide a load more comments button
$load_more = true;
$load_more_title = sprintf(t('Load the next few of total %d comments'), $conv->comments_total);
$comments_total_percent = round(100 * 3 / $conv->comments_total);
}
$expand = '';
if ($this->threaded && !empty($item['comment_count'] && !$this->is_toplevel())) {
$expand = t('Expand Replies');
}
$tmp_item = array(
'template' => $this->get_template(),
'mode' => $mode,
'item_type' => intval($item['item_type']),
//'type' => implode("",array_slice(explode("/",$item['verb']),-1)),
'body' => $body['html'],
'tags' => $body['tags'],
'categories' => $body['categories'],
@@ -424,9 +381,9 @@ class ThreadItem {
'folders' => $body['folders'],
'text' => strip_tags($body['html']),
'id' => $this->get_id(),
'parent' => $item['parent'],
'mid' => $midb64,
'mids' => $json_mids,
'parent' => $item['parent'],
'author_id' => (($item['author']['xchan_addr']) ? $item['author']['xchan_addr'] : $item['author']['xchan_url']),
'author_is_group_actor' => (($item['author']['xchan_pubforum']) ? t('Forum') : ''),
'isevent' => $isevent,
@@ -450,16 +407,15 @@ class ThreadItem {
'sparkle' => $sparkle,
'title' => $item['title'],
'title_tosource' => get_pconfig($conv->get_profile_owner(),'system','title_tosource'),
//'ago' => relative_date($item['created']),
'app' => $item['app'],
'str_app' => sprintf( t('from %s'), $item['app']),
'isotime' => datetime_convert('UTC', date_default_timezone_get(), $item['created'], 'c'),
'localtime' => datetime_convert('UTC', date_default_timezone_get(), $item['created'], 'r'),
'editedtime' => (($item['edited'] != $item['created']) ? sprintf( t('last edited: %s'), datetime_convert('UTC', date_default_timezone_get(), $item['edited'], 'r')) : ''),
'expiretime' => (($item['expires'] > NULL_DATE) ? sprintf( t('Expires: %s'), datetime_convert('UTC', date_default_timezone_get(), $item['expires'], 'r')):''),
'localtime' => datetime_convert('UTC', date_default_timezone_get(), $item['created']),
'editedtime' => (($item['edited'] != $item['created']) ? sprintf(t('Last edited %s'), relative_time($item['edited'])) : ''),
'expiretime' => (($item['expires'] > NULL_DATE) ? sprintf(t('Expires %s'), relative_time($item['expires'])) : ''),
'lock' => $lock,
'locktype' => $locktype,
'delayed' => $item['item_delayed'],
'delayed' => (($item['item_delayed']) ? sprintf(t('Published %s'), relative_time($item['created'])) : ''),
'privacy_warning' => $privacy_warning,
'verified' => $verified,
'unverified' => $unverified,
@@ -472,6 +428,7 @@ class ThreadItem {
'vote_title' => t('Voting Options'),
'is_comment' => $is_comment,
'is_new' => $is_new,
'owner_addr' => $this->get_owner_addr(),
'owner_url' => $this->get_owner_url(),
'owner_photo' => $this->get_owner_photo(),
'owner_name' => $this->get_owner_name(),
@@ -479,17 +436,16 @@ class ThreadItem {
'event' => $body['event'],
'has_tags' => $has_tags,
'reactions' => $this->reactions,
// Item toolbar buttons
// Item toolbar buttons
'emojis' => (($this->is_toplevel() && $this->is_commentable() && $observer && feature_enabled($conv->get_profile_owner(),'emojis')) ? '1' : ''),
'like' => $like,
'dislike' => ((feature_enabled($conv->get_profile_owner(),'dislike')) ? $dislike : ''),
'reply_to' => (((! $this->is_toplevel()) && feature_enabled($conv->get_profile_owner(),'reply_to')) ? $reply_to : ''),
'reply_to' => ((feature_enabled($conv->get_profile_owner(),'reply_to')) ? $reply_to : ''),
'top_hint' => t("Go to previous comment"),
'share' => $share,
'embed' => $embed,
'rawmid' => $item['mid'],
'parent_mid' => $item['parent_mid'],
'plink' => get_plink($item),
'edpost' => $edpost, // ((feature_enabled($conv->get_profile_owner(),'edit_posts')) ? $edpost : ''),
'edpost' => $edpost,
'star' => ((feature_enabled($conv->get_profile_owner(),'star_posts') && ($item['item_type'] == ITEM_TYPE_POST)) ? $star : ''),
'tagger' => ((feature_enabled($conv->get_profile_owner(),'commtag')) ? $tagger : ''),
'filer' => ((feature_enabled($conv->get_profile_owner(),'filing') && ($item['item_type'] == ITEM_TYPE_POST)) ? $filer : ''),
@@ -500,51 +456,50 @@ class ThreadItem {
'addtocal' => (($has_event) ? t('Add to Calendar') : ''),
'drop' => $drop,
'dropdown_extras' => $dropdown_extras,
// end toolbar buttons
// 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 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 : ''),
*/
// 'my_responses' => $my_responses,
'modal_dismiss' => t('Close'),
// 'showlike' => $showlike,
// 'showdislike' => $showdislike,
'comment' => ($item['item_delayed'] ? '' : $this->get_comment_box()),
'comment_hidden' => feature_enabled($conv->get_profile_owner(),'reply_to'),
'no_comment' => (($item['item_thread_top'] && $item['item_nocomment'])? t('Comments disabled') : ''),
'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_uuid' => (($item['parent_mid'] != $item['thr_parent']) ? $mid_uuid_map[$item['thr_parent']] : ''),
'thr_parent_uuid' => (($item['parent_mid'] !== $item['thr_parent'] && isset($conv->mid_uuid_map[$item['thr_parent']])) ? $conv->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()),
'reactions_allowed' => $reactions_allowed,
'reaction_str' => [t('Add yours'), t('Remove yours')]
'reaction_str' => [t('Add yours'), t('Remove yours')],
'is_contained' => $this->is_toplevel() && str_contains($item['tgt_type'], 'Collection'),
'observer_activity' => [
'like' => intval($item['observer_like_count'] ?? 0),
'dislike' => intval($item['observer_dislike_count'] ?? 0),
'announce' => intval($item['observer_announce_count'] ?? 0),
'comment' => intval($item['observer_comment_count'] ?? 0),
'accept' => intval($item['observer_accept_count'] ?? 0),
'reject' => intval($item['observer_reject_count'] ?? 0),
'tentativeaccept' => intval($item['observer_tentativeaccept_count'] ?? 0)
],
'threaded' => $this->threaded,
'blog_mode' => $blog_mode,
'collapse_comments' => t('show less'),
'expand_comments' => $this->threaded ? t('show more') : t('show all'),
'load_more' => $load_more,
'load_more_title' => $load_more_title,
'comments_total' => $conv->comments_total,
'comments_total_percent' => $comments_total_percent,
'expand' => $expand
);
$arr = array('item' => $item, 'output' => $tmp_item);
@@ -553,33 +508,19 @@ class ThreadItem {
$result = $arr['output'];
$result['children'] = array();
$nb_children = count($children);
$visible_comments = Config::Get('system','expanded_comments');
if($visible_comments === false)
$visible_comments = 3;
$visible_comments = 3; // Config::Get('system', 'expanded_comments', 3);
// needed for scroll to comment from notification but needs more work
// as we do not want to open all comments unless there is actually an #item_xx anchor
// and the url fragment is not sent to the server.
// if(in_array(\App::$module,['display','update_display']))
// $visible_comments = 99999;
if(($this->get_display_mode() === 'normal') && ($nb_children > 0)) {
if(($this->get_display_mode() === 'normal') && ($children_count > 0)) {
foreach($children as $child) {
$result['children'][] = $child->get_template_data($conv_responses, $mid_uuid_map, $thread_level + 1,$conv_flags);
$result['children'][] = $child->get_template_data($thread_level + 1, $conv_flags);
}
// Collapse
if(($nb_children > $visible_comments) || ($thread_level > 1)) {
if($thread_level === 1 && $children_count > $visible_comments) {
$result['children'][0]['comment_firstcollapsed'] = true;
$result['children'][0]['num_comments'] = $comment_count_txt['label'];
$result['children'][0]['hide_text'] = t('show all');
if($thread_level > 1) {
$result['children'][$nb_children - 1]['comment_lastcollapsed'] = true;
}
else {
$result['children'][$nb_children - ($visible_comments + 1)]['comment_lastcollapsed'] = true;
}
$result['children'][$children_count - ($visible_comments + 1)]['comment_lastcollapsed'] = true;
}
}
@@ -832,7 +773,7 @@ class ThreadItem {
*/
private function get_comment_box() {
if(!$this->is_toplevel() && !Config::Get('system','thread_allow')) {
if(!$this->is_toplevel()) {
return '';
}
@@ -868,14 +809,15 @@ class ThreadItem {
'$submit' => t('Submit'),
'$edbold' => t('Bold'),
'$editalic' => t('Italic'),
'$edhighlighter' => t('Highlight selected text'),
'$eduline' => t('Underline'),
'$edquote' => t('Quote'),
'$edcode' => t('Code'),
'$edimg' => t('Image'),
'$edimg' => t('Embed (existing) photo from your photo albums'),
'$edatt' => t('Attach/Upload file'),
'$edurl' => t('Insert Link'),
'$edvideo' => t('Video'),
'$preview' => t('Preview'), // ((feature_enabled($conv->get_profile_owner(),'preview')) ? t('Preview') : ''),
'$preview' => t('Preview'),
'$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'),
@@ -896,12 +838,13 @@ class ThreadItem {
}
/**
* Check if we are a wall to wall item and set the relevant properties
* Check if we are a wall to wall or announce item and set the relevant properties
*/
protected function check_wall_to_wall() {
$conv = $this->get_conversation();
$this->wall_to_wall = false;
$this->owner_url = '';
$this->owner_addr = '';
$this->owner_photo = '';
$this->owner_name = '';
@@ -910,12 +853,14 @@ 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_addr = $this->data['owner']['xchan_addr'];
$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_addr = $this->data['source']['xchan_addr'];
$this->owner_photo = $this->data['source']['xchan_photo_s'];
$this->owner_name = $this->data['source']['xchan_name'];
$this->wall_to_wall = true;
@@ -930,6 +875,10 @@ class ThreadItem {
return $this->owner_url;
}
private function get_owner_addr() {
return $this->owner_addr;
}
private function get_owner_photo() {
return $this->owner_photo;
}

View File

@@ -24,6 +24,10 @@ class ThreadStream {
private $prepared_item = '';
public $reload = '';
private $cipher = 'AES-128-CCM';
public $mid_uuid_map = [];
public $comments_total = 0;
public $comments_loaded = 0;
// $prepared_item is for use by alternate conversation structures such as photos
// wherein we've already prepared a top level item which doesn't look anything like
@@ -211,16 +215,15 @@ class ThreadStream {
* _ The data requested on success
* _ false on failure
*/
public function get_template_data($conv_responses, $mid_uuid_map) {
public function get_template_data() {
$result = array();
foreach($this->threads as $item) {
if(($item->get_data_value('id') == $item->get_data_value('parent')) && $this->prepared_item) {
$item_data = $this->prepared_item;
}
else {
$item_data = $item->get_template_data($conv_responses, $mid_uuid_map);
$item_data = $item->get_template_data();
}
if(!$item_data) {
logger('Failed to get item template data ('. $item->get_id() .').', LOGGER_DEBUG, LOG_ERR);

View File

@@ -89,7 +89,7 @@ trait HelpHelperTrait {
);
return bbcode(
t("This page is not yet available in {$prefered_language_name}. See [observer.baseurl]/help/developer/developer_guide#Translations for information about how to help.")
t("This page is not yet available in {$prefered_language_name}. See [observer.baseurl]/help/developer/developers_guide#Translations for information about how to help.")
);
}
}

View File

@@ -8,25 +8,25 @@ class Achievements extends \Zotlabs\Web\Controller {
// This doesn't work, so
if (! is_developer())
return;
if(argc() > 1)
$which = argv(1);
else {
notice( t('Requested profile is not available.') . EOL );
return;
}
$profile = 0;
$profile = argv(1);
$profile = argv(1);
profile_load($which,$profile);
$r = q("select channel_id from channel where channel_address = '%s'",
dbesc($which)
);
if($r) {
$owner = intval($r[0]['channel_id']);
}
$observer = \App::get_observer();
$ob_hash = (($observer) ? $observer['xchan_hash'] : '');
$perms = get_all_perms($owner,$ob_hash);
@@ -34,60 +34,60 @@ class Achievements extends \Zotlabs\Web\Controller {
notice( t('Permission denied.') . EOL);
return;
}
$newmembertext = t('Some blurb about what to do when you\'re new here');
// By default, all badges are false
$contactbadge = false;
$profilebadge = false;
$keywordsbadge = false;
// Check number of contacts. Award a badge if over 10
// We'll figure these out on each page load instead of
// We'll figure these out on each page load instead of
// writing them to the DB because that will mean one needs
// to retain their achievements - eg, you can't add
// a bunch of channels just to get your badge, and then
// delete them all again. If these become popular or
// used in profiles or something, we may need to reconsider
// and add a table for this - because this won't scale.
$r = q("select * from abook where abook_channel = %d",
intval($owner)
);
if (count($r))
$contacts = count($r);
// We're checking for 11 to adjust for the abook record for self
if ($contacts >= 11)
$contactbadge = true;
// Check if an about field in the profile has been created.
$r = q("select * from profile where uid = %d and about <> ''",
intval($owner)
);
if ($r)
$profilebadge = 1;
// Check if keywords have been set
$r = q("select * from profile where uid = %d and keywords <> ''",
intval($owner)
);
if($r)
$keywordsbadge = 1;
return replace_macros(get_markup_template("achievements.tpl"), array(
'$newmembertext' => $newmembertext,
'$profilebadge' => $profilebadge,
'$contactbadge' => $contactbadge,
'$keywordsbadge' => $keywordsbadge,
'$channelsbadge' => $channelsbadge
'$channelsbadge' => null,
));
}
}

View File

@@ -29,11 +29,11 @@ class Acl extends \Zotlabs\Web\Controller {
// logger('mod_acl: ' . print_r($_GET,true),LOGGER_DATA);
$start = (x($_REQUEST,'start') ? $_REQUEST['start'] : 0);
$count = (x($_REQUEST,'count') ? $_REQUEST['count'] : 500);
$search = (x($_REQUEST,'search') ? $_REQUEST['search'] : '');
$type = (x($_REQUEST,'type') ? $_REQUEST['type'] : '');
$noforums = (x($_REQUEST,'n') ? $_REQUEST['n'] : false);
$start = (!empty($_REQUEST['start']) ? $_REQUEST['start'] : 0);
$count = (!empty($_REQUEST['count']) ? $_REQUEST['count'] : 500);
$search = (!empty($_REQUEST['search']) ? $_REQUEST['search'] : '');
$type = (!empty($_REQUEST['type']) ? $_REQUEST['type'] : '');
$noforums = (!empty($_REQUEST['n']) ? $_REQUEST['n'] : false);
// $type =
@@ -53,7 +53,7 @@ class Acl extends \Zotlabs\Web\Controller {
// List of channels whose connections to also suggest,
// e.g. currently viewed channel or channels mentioned in a post
$extra_channels = (x($_REQUEST,'extra_channels') ? $_REQUEST['extra_channels'] : array());
$extra_channels = (!empty($_REQUEST['extra_channels']) ? $_REQUEST['extra_channels'] : []);
// The different autocomplete libraries use different names for the search text
// parameter. Internally we'll use $search to represent the search text no matter
@@ -416,7 +416,7 @@ class Acl extends \Zotlabs\Web\Controller {
}
$dirmode = intval(Config::Get('system','directory_mode'));
$search = ((x($_REQUEST,'search')) ? htmlentities($_REQUEST['search'],ENT_COMPAT,'UTF-8',false) : '');
$search = ((!empty($_REQUEST['search'])) ? htmlentities($_REQUEST['search'], ENT_COMPAT, 'UTF-8', false) : '');
if(! $search || mb_strlen($search) < 2)
return array();
@@ -446,7 +446,7 @@ class Acl extends \Zotlabs\Web\Controller {
$token = Config::Get('system','realm_token');
$count = (x($_REQUEST,'count') ? $_REQUEST['count'] : 100);
$count = (!empty($_REQUEST['count']) ? $_REQUEST['count'] : 100);
if($url) {
$query = $url . '?f=' . (($token) ? '&t=' . urlencode($token) : '');
$query .= '&name=' . urlencode($search) . "&limit=$count" . (($address) ? '&address=' . urlencode(punify($search)) : '');

View File

@@ -23,14 +23,14 @@ class Activity extends Controller {
if (! $item_id)
http_status_exit(404, 'Not found');
$portable_id = EMPTY_STR;
$portable_id = null;
$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 ";
$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 and item.item_uplink = 0 $item_normal_extra ";
$i = null;
@@ -166,6 +166,7 @@ class Activity extends Controller {
return;
}
$portable_id = null;
$ob_authorize = false;
$item_uid = 0;
@@ -191,7 +192,7 @@ class Activity extends Controller {
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 ";
$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 and item.item_uplink = 0 $item_normal_extra ";
$sigdata = HTTPSig::verify(EMPTY_STR);
if ($sigdata['portable_id'] && $sigdata['header_valid']) {

View File

@@ -8,6 +8,11 @@ class Account_edit {
function post() {
// Validate CSRF token
//
// We terminate with a 403 Forbidden status if the check fails.
check_form_security_token_ForbiddenOnErr('admin_account_edit', 'security');
$account_id = $_REQUEST['aid'];
if(! $account_id)
@@ -18,7 +23,7 @@ class Account_edit {
if($pass1 && $pass2 && ($pass1 === $pass2)) {
$salt = random_string(32);
$password_encoded = hash('whirlpool', $salt . $pass1);
$r = q("update account set account_salt = '%s', account_password = '%s',
$r = q("update account set account_salt = '%s', account_password = '%s',
account_password_changed = '%s' where account_id = %d",
dbesc($salt),
dbesc($password_encoded),
@@ -34,7 +39,7 @@ class Account_edit {
$account_level = 5;
$account_language = trim($_REQUEST['account_language']);
$r = q("update account set account_service_class = '%s', account_level = %d, account_language = '%s'
$r = q("update account set account_service_class = '%s', account_level = %d, account_language = '%s'
where account_id = %d",
dbesc($service_class),
intval($account_level),
@@ -62,8 +67,8 @@ class Account_edit {
return '';
}
$a = replace_macros(get_markup_template('admin_account_edit.tpl'), [
'$security' => get_form_security_token('admin_account_edit'),
'$account' => $x[0],
'$title' => t('Account Edit'),
'$pass1' => [ 'pass1', t('New Password'), ' ','' ],

View File

@@ -6,133 +6,33 @@ use Zotlabs\Lib\Config;
class Accounts {
/**
* @brief Handle POST actions on accounts admin page.
*
* This function is called when on the admin user/account page the form was
* submitted to handle multiple operations at once. If one of the icons next
* to an entry are pressed the function admin_page_accounts() will handle this.
*
*/
const MYP = 'ZAR'; // ZAR2x
const VERSION = '2.0.0';
function post() {
/**
* Handle POST actions on accounts admin page.
*/
public function post() {
$pending = ( x($_POST, 'pending') ? $_POST['pending'] : array() );
$users = ( x($_POST, 'user') ? $_POST['user'] : array() );
$blocked = ( x($_POST, 'blocked') ? $_POST['blocked'] : array() );
$pending = x($_POST, 'pending') ? $_POST['pending'] : array();
check_form_security_token_redirectOnErr('/admin/accounts', 'admin_accounts');
$isajax = is_ajax();
$rc = 0;
If (!is_site_admin()) {
if ($isajax) {
killme();
exit;
}
goaway(z_root() . '/');
}
if ($isajax) {
//$debug = print_r($_SESSION[self::MYP],true);
$zarop = (x($_POST['zardo']) && preg_match('/^[ad]{1,1}$/', $_POST['zardo']) )
? $_POST['zardo'] : '';
// zarat arrives with leading underscore _n
$zarat = (x($_POST['zarat']) && preg_match('/^_{1,1}[0-9]{1,6}$/', $_POST['zarat']) )
? substr($_POST['zarat'],1) : '';
$zarse = (x($_POST['zarse']) && preg_match('/^[0-9a-f]{8,8}$/', $_POST['zarse']) )
? hex2bin($_POST['zarse']) : '';
if ($zarop && $zarat >= 0 && $zarse && $zarse == $_SESSION[self::MYP]['h'][$zarat]) {
//
if ($zarop == 'd') {
$rd = q("UPDATE register SET reg_vital = 0 WHERE reg_id = %d AND SUBSTR(reg_hash,1,4) = '%s' ",
intval($_SESSION[self::MYP]['i'][$zarat]),
dbesc($_SESSION[self::MYP]['h'][$zarat])
);
$rc = '×';
}
elseif ($zarop == 'a') {
// approval, REGISTER_DENIED by user 0x0040, REGISTER_AGREED by user 0x0020 @Regate
$rd = q("UPDATE register SET reg_flags = (reg_flags & ~ 16), "
. " reg_vital = (CASE (reg_flags & ~ 48) WHEN 0 THEN 0 ELSE 1 END) "
. " WHERE reg_vital = 1 AND reg_id = %d AND SUBSTR(reg_hash,1,4) = '%s' ",
intval($_SESSION[self::MYP]['i'][$zarat]),
dbesc($_SESSION[self::MYP]['h'][$zarat])
);
$rc = 0;
$rs = q("SELECT * from register WHERE reg_id = %d ",
intval($_SESSION[self::MYP]['i'][$zarat])
);
if ($rs && ($rs[0]['reg_flags'] & ~ 48) == 0) {
// create account
$rc = 'ok'.$rs[0]['reg_id'];
$ac = create_account_from_register($rs[0]);
if ( $ac['success'] ) {
$rc .= '✔';
$auto_create = Config::Get('system','auto_channel_create',1);
if($auto_create) {
$reonar = json_decode($rs[0]['reg_stuff'], true);
// prepare channel creation
if($reonar['chan.name'])
set_aconfig($ac['account']['account_id'], 'register', 'channel_name', $reonar['chan.name']);
if($reonar['chan.did1'])
set_aconfig($ac['account']['account_id'], 'register', 'channel_address', $reonar['chan.did1']);
$permissions_role = Config::Get('system','default_permissions_role');
if($permissions_role)
set_aconfig($ac['account']['account_id'], 'register', 'permissions_role', $permissions_role);
// create channel
$new_channel = auto_channel_create($ac['account']['account_id']);
if($new_channel['success']) {
$rc .= ' c,ok' . $new_channel['channel']['channel_id'] . '✔';
}
else {
$rc .= ' c ×';
}
}
}
} else {
$rc='oh ×';
}
}
echo json_encode(array('re' => $zarop, 'at' => '_' . $zarat, 'rc' => $rc));
}
if (is_ajax()) {
$this->handle_ajax_request();
killme();
exit;
}
// change to switch structure?
// account block/unblock button was submitted
if (x($_POST, 'page_accounts_block')) {
for ($i = 0; $i < count($users); $i++) {
// if account is blocked remove blocked bit-flag, otherwise add blocked bit-flag
$op = ($blocked[$i]) ? '& ~' : '| ';
q("UPDATE account SET account_flags = (account_flags $op%d) WHERE account_id = %d",
intval(ACCOUNT_BLOCKED),
intval($users[$i])
);
}
notice( sprintf( tt("%s account blocked/unblocked", "%s account blocked/unblocked", count($users)), count($users)) );
$this->block_unblock_accounts();
}
// account delete button was submitted
if (x($_POST, 'page_accounts_delete')) {
foreach ($users as $uid){
account_remove($uid, true, false);
}
notice( sprintf( tt("%s account deleted", "%s accounts deleted", count($users)), count($users)) );
$this->delete_accounts();
}
// registration approved button was submitted
if (x($_POST, 'page_accounts_approve')) {
@@ -351,5 +251,143 @@ class Accounts {
return $o;
}
private function handle_ajax_request(): void {
//$debug = print_r($_SESSION[self::MYP],true);
$zarop = (x($_POST['zardo']) && preg_match('/^[ad]{1,1}$/', $_POST['zardo']) )
? $_POST['zardo'] : '';
// zarat arrives with leading underscore _n
$zarat = (x($_POST['zarat']) && preg_match('/^_{1,1}[0-9]{1,6}$/', $_POST['zarat']) )
? substr($_POST['zarat'],1) : '';
$zarse = (x($_POST['zarse']) && preg_match('/^[0-9a-f]{8,8}$/', $_POST['zarse']) )
? hex2bin($_POST['zarse']) : '';
if ($zarop && $zarat >= 0 && $zarse && $zarse == $_SESSION[self::MYP]['h'][$zarat]) {
//
if ($zarop == 'd') {
$rd = q("UPDATE register SET reg_vital = 0 WHERE reg_id = %d AND SUBSTR(reg_hash,1,4) = '%s' ",
intval($_SESSION[self::MYP]['i'][$zarat]),
dbesc($_SESSION[self::MYP]['h'][$zarat])
);
$rc = '×';
}
elseif ($zarop == 'a') {
// approval, REGISTER_DENIED by user 0x0040, REGISTER_AGREED by user 0x0020 @Regate
$rd = q("UPDATE register SET reg_flags = (reg_flags & ~ 16), "
. " reg_vital = (CASE (reg_flags & ~ 48) WHEN 0 THEN 0 ELSE 1 END) "
. " WHERE reg_vital = 1 AND reg_id = %d AND SUBSTR(reg_hash,1,4) = '%s' ",
intval($_SESSION[self::MYP]['i'][$zarat]),
dbesc($_SESSION[self::MYP]['h'][$zarat])
);
$rc = 0;
$rs = q("SELECT * from register WHERE reg_id = %d ",
intval($_SESSION[self::MYP]['i'][$zarat])
);
if ($rs && ($rs[0]['reg_flags'] & ~ 48) == 0) {
// create account
$rc = 'ok'.$rs[0]['reg_id'];
$ac = create_account_from_register($rs[0]);
if ( $ac['success'] ) {
$rc .= '✔';
$auto_create = Config::Get('system','auto_channel_create',1);
if($auto_create) {
$reonar = json_decode($rs[0]['reg_stuff'], true);
// prepare channel creation
if($reonar['chan.name'])
set_aconfig($ac['account']['account_id'], 'register', 'channel_name', $reonar['chan.name']);
if($reonar['chan.did1'])
set_aconfig($ac['account']['account_id'], 'register', 'channel_address', $reonar['chan.did1']);
$permissions_role = Config::Get('system','default_permissions_role');
if($permissions_role)
set_aconfig($ac['account']['account_id'], 'register', 'permissions_role', $permissions_role);
// create channel
$new_channel = auto_channel_create($ac['account']['account_id']);
if($new_channel['success']) {
$rc .= ' c,ok' . $new_channel['channel']['channel_id'] . '✔';
}
else {
$rc .= ' c ×';
}
}
}
} else {
$rc='oh ×';
}
}
echo json_encode(array('re' => $zarop, 'at' => '_' . $zarat, 'rc' => $rc));
}
}
/**
* Block or unblock accounts given by the `user` and `blocked` POST params.
*
* The post params `user` and `blocked` must be present and arrays of equal
* lengths. The `user` array should contain account id's or the accounts to
* process, and the `blocked` array holds a corresponding boolean value to
* indicate that the account at the same offset in the `user` array is or is
* not blocked.
*
* An account that is _not_ blocked will be blocked, and accounts that _are_
* blocked will be unblocked.
*
* @SuppressWarnings(PHPMD.ShortVariable)
*/
private function block_unblock_accounts(): void {
if (!isset($_POST['user']) || !isset($_POST['blocked'])) {
return;
}
$users = $_POST['user'];
$blocked = $_POST['blocked'];
if (!is_array($users) || !is_array($blocked)) {
return;
}
foreach($users as $i => $id) {
// if account is blocked remove blocked bit-flag, otherwise add blocked bit-flag
$op = $blocked[$i] ? '& ~' : '| ';
q("UPDATE account SET account_flags = (account_flags $op%d) WHERE account_id = %d",
intval(ACCOUNT_BLOCKED),
intval($id)
);
}
$count = count($users);
$fmt = tt("%s account blocked/unblocked", "%s account blocked/unblocked", $count);
notice(sprintf($fmt, $count));
}
/**
* Delete multiple accounts given by the `user` POST param.
*/
private function delete_accounts(): void {
if (!isset($_POST['user'])) {
return;
}
$users = $_POST['user'];
if (!is_array($users)) {
return;
}
foreach ($users as $uid){
account_remove($uid, true, false);
}
$count = count($users);
$fmt = tt("%s account deleted", "%s accounts deleted", $count);
notice(sprintf($fmt, $count));
}
}

View File

@@ -3,9 +3,8 @@
namespace Zotlabs\Module\Admin;
use App;
use \Zotlabs\Lib\Config;
use \Zotlabs\Storage\GitRepo;
use \Michelf\MarkdownExtra;
use Zotlabs\Lib\Config;
use Michelf\MarkdownExtra;
class Addons {
@@ -24,227 +23,6 @@ class Addons {
goaway(z_root() . '/admin/addons/' . argv(2) );
}
elseif(argc() > 2) {
switch(argv(2)) {
case 'updaterepo':
if (array_key_exists('repoName', $_REQUEST)) {
$repoName = $_REQUEST['repoName'];
}
else {
json_return_and_die(array('message' => 'No repo name provided.', 'success' => false));
}
$extendDir = 'store/[data]/git/sys/extend';
$addonDir = $extendDir . '/addon';
if (!file_exists($extendDir)) {
if (!mkdir($extendDir, 0770, true)) {
logger('Error creating extend folder: ' . $extendDir);
json_return_and_die(array('message' => 'Error creating extend folder: ' . $extendDir, 'success' => false));
}
else {
if (!symlink(realpath('extend/addon'), $addonDir)) {
logger('Error creating symlink to addon folder: ' . $addonDir);
json_return_and_die(array('message' => 'Error creating symlink to addon folder: ' . $addonDir, 'success' => false));
}
}
}
$repoDir = 'store/[data]/git/sys/extend/addon/' . $repoName;
if (!is_dir($repoDir)) {
logger('Repo directory does not exist: ' . $repoDir);
json_return_and_die(array('message' => 'Invalid addon repo.', 'success' => false));
}
if (!is_writable($repoDir)) {
logger('Repo directory not writable to web server: ' . $repoDir);
json_return_and_die(array('message' => 'Repo directory not writable to web server.', 'success' => false));
}
$git = new GitRepo('sys', null, false, $repoName, $repoDir);
try {
if ($git->pull()) {
$files = array_diff(scandir($repoDir), array('.', '..'));
foreach ($files as $file) {
if (is_dir($repoDir . '/' . $file) && $file !== '.git') {
$source = '../extend/addon/' . $repoName . '/' . $file;
$target = realpath('addon/') . '/' . $file;
unlink($target);
if (!symlink($source, $target)) {
logger('Error linking addons to /addon');
json_return_and_die(array('message' => 'Error linking addons to /addon', 'success' => false));
}
}
}
json_return_and_die(array('message' => 'Repo updated.', 'success' => true));
} else {
json_return_and_die(array('message' => 'Error updating addon repo.', 'success' => false));
}
} catch (\PHPGit\Exception\GitException $e) {
json_return_and_die(array('message' => 'Error updating addon repo.', 'success' => false));
}
break;
case 'removerepo':
if (array_key_exists('repoName', $_REQUEST)) {
$repoName = $_REQUEST['repoName'];
} else {
json_return_and_die(array('message' => 'No repo name provided.', 'success' => false));
}
$extendDir = 'store/[data]/git/sys/extend';
$addonDir = $extendDir . '/addon';
if (!file_exists($extendDir)) {
if (!mkdir($extendDir, 0770, true)) {
logger('Error creating extend folder: ' . $extendDir);
json_return_and_die(array('message' => 'Error creating extend folder: ' . $extendDir, 'success' => false));
} else {
if (!symlink(realpath('extend/addon'), $addonDir)) {
logger('Error creating symlink to addon folder: ' . $addonDir);
json_return_and_die(array('message' => 'Error creating symlink to addon folder: ' . $addonDir, 'success' => false));
}
}
}
$repoDir = 'store/[data]/git/sys/extend/addon/' . $repoName;
if (!is_dir($repoDir)) {
logger('Repo directory does not exist: ' . $repoDir);
json_return_and_die(array('message' => 'Invalid addon repo.', 'success' => false));
}
if (!is_writable($repoDir)) {
logger('Repo directory not writable to web server: ' . $repoDir);
json_return_and_die(array('message' => 'Repo directory not writable to web server.', 'success' => false));
}
/// @TODO remove directory and unlink /addon/files
if (rrmdir($repoDir)) {
json_return_and_die(array('message' => 'Repo deleted.', 'success' => true));
} else {
json_return_and_die(array('message' => 'Error deleting addon repo.', 'success' => false));
}
break;
case 'installrepo':
if (array_key_exists('repoURL', $_REQUEST)) {
require_once('library/PHPGit.autoload.php'); // Load PHPGit dependencies
$repoURL = $_REQUEST['repoURL'];
$extendDir = 'store/[data]/git/sys/extend';
$addonDir = $extendDir . '/addon';
if (!file_exists($extendDir)) {
if (!mkdir($extendDir, 0770, true)) {
logger('Error creating extend folder: ' . $extendDir);
json_return_and_die(array('message' => 'Error creating extend folder: ' . $extendDir, 'success' => false));
} else {
if (!symlink(realpath('extend/addon'), $addonDir)) {
logger('Error creating symlink to addon folder: ' . $addonDir);
json_return_and_die(array('message' => 'Error creating symlink to addon folder: ' . $addonDir, 'success' => false));
}
}
}
if (!is_writable($extendDir)) {
logger('Directory not writable to web server: ' . $extendDir);
json_return_and_die(array('message' => 'Directory not writable to web server.', 'success' => false));
}
$repoName = null;
if (array_key_exists('repoName', $_REQUEST) && $_REQUEST['repoName'] !== '') {
$repoName = $_REQUEST['repoName'];
} else {
$repoName = GitRepo::getRepoNameFromURL($repoURL);
}
if (!$repoName) {
logger('Invalid git repo');
json_return_and_die(array('message' => 'Invalid git repo', 'success' => false));
}
$repoDir = $addonDir . '/' . $repoName;
$tempRepoBaseDir = 'store/[data]/git/sys/temp/';
$tempAddonDir = $tempRepoBaseDir . $repoName;
if (!is_writable($addonDir) || !is_writable($tempAddonDir)) {
logger('Temp repo directory or /extend/addon not writable to web server: ' . $tempAddonDir);
json_return_and_die(array('message' => 'Temp repo directory not writable to web server.', 'success' => false));
}
rename($tempAddonDir, $repoDir);
if (!is_writable(realpath('addon/'))) {
logger('/addon directory not writable to web server: ' . $tempAddonDir);
json_return_and_die(array('message' => '/addon directory not writable to web server.', 'success' => false));
}
$files = array_diff(scandir($repoDir), array('.', '..'));
foreach ($files as $file) {
if (is_dir($repoDir . '/' . $file) && $file !== '.git') {
$source = '../extend/addon/' . $repoName . '/' . $file;
$target = realpath('addon/') . '/' . $file;
unlink($target);
if (!symlink($source, $target)) {
logger('Error linking addons to /addon');
json_return_and_die(array('message' => 'Error linking addons to /addon', 'success' => false));
}
}
}
$git = new GitRepo('sys', $repoURL, false, $repoName, $repoDir);
$repo = $git->probeRepo();
json_return_and_die(array('repo' => $repo, 'message' => '', 'success' => true));
}
break;
case 'addrepo':
if (array_key_exists('repoURL', $_REQUEST)) {
require_once('library/PHPGit.autoload.php'); // Load PHPGit dependencies
$repoURL = $_REQUEST['repoURL'];
$extendDir = 'store/[data]/git/sys/extend';
$addonDir = $extendDir . '/addon';
$tempAddonDir = realpath('store/[data]') . '/git/sys/temp';
if (!file_exists($extendDir)) {
if (!mkdir($extendDir, 0770, true)) {
logger('Error creating extend folder: ' . $extendDir);
json_return_and_die(array('message' => 'Error creating extend folder: ' . $extendDir, 'success' => false));
} else {
if (!symlink(realpath('extend/addon'), $addonDir)) {
logger('Error creating symlink to addon folder: ' . $addonDir);
json_return_and_die(array('message' => 'Error creating symlink to addon folder: ' . $addonDir, 'success' => false));
}
}
}
if (!is_dir($tempAddonDir)) {
if (!mkdir($tempAddonDir, 0770, true)) {
logger('Error creating temp plugin repo folder: ' . $tempAddonDir);
json_return_and_die(array('message' => 'Error creating temp plugin repo folder: ' . $tempAddonDir, 'success' => false));
}
}
$repoName = null;
if (array_key_exists('repoName', $_REQUEST) && $_REQUEST['repoName'] !== '') {
$repoName = $_REQUEST['repoName'];
} else {
$repoName = GitRepo::getRepoNameFromURL($repoURL);
}
if (!$repoName) {
logger('Invalid git repo');
json_return_and_die(array('message' => 'Invalid git repo: ' . $repoName, 'success' => false));
}
$repoDir = $tempAddonDir . '/' . $repoName;
if (!is_writable($tempAddonDir)) {
logger('Temporary directory for new addon repo is not writable to web server: ' . $tempAddonDir);
json_return_and_die(array('message' => 'Temporary directory for new addon repo is not writable to web server.', 'success' => false));
}
// clone the repo if new automatically
$git = new GitRepo('sys', $repoURL, true, $repoName, $repoDir);
$remotes = $git->git->remote();
$fetchURL = $remotes['origin']['fetch'];
if ($fetchURL !== $git->url) {
if (rrmdir($repoDir)) {
$git = new GitRepo('sys', $repoURL, true, $repoName, $repoDir);
} else {
json_return_and_die(array('message' => 'Error deleting existing addon repo.', 'success' => false));
}
}
$repo = $git->probeRepo();
$repo['readme'] = $repo['manifest'] = null;
foreach ($git->git->tree('master') as $object) {
if ($object['type'] == 'blob' && (strtolower($object['file']) === 'readme.md' || strtolower($object['file']) === 'readme')) {
$repo['readme'] = MarkdownExtra::defaultTransform($git->git->cat->blob($object['hash']));
} else if ($object['type'] == 'blob' && strtolower($object['file']) === 'manifest.json') {
$repo['manifest'] = $git->git->cat->blob($object['hash']);
}
}
json_return_and_die(array('repo' => $repo, 'message' => '', 'success' => true));
} else {
json_return_and_die(array('message' => 'No repo URL provided', 'success' => false));
}
break;
default:
break;
}
}
}
/**
@@ -408,37 +186,6 @@ class Addons {
usort($plugins,'self::plugin_sort');
$allowManageRepos = false;
if(is_writable('extend/addon') && is_writable('store/[data]')) {
$allowManageRepos = true;
}
$admin_plugins_add_repo_form= replace_macros(
get_markup_template('admin_plugins_addrepo.tpl'), array(
'$post' => 'admin/addons/addrepo',
'$desc' => t('Enter the public git repository URL of the addon repo.'),
'$repoURL' => array('repoURL', t('Addon repo git URL'), '', ''),
'$repoName' => array('repoName', t('Custom repo name'), '', '', t('(optional)')),
'$submit' => t('Download Addon Repo')
)
);
$newRepoModalID = random_string(3);
$newRepoModal = replace_macros(
get_markup_template('generic_modal.tpl'), array(
'$id' => $newRepoModalID,
'$title' => t('Install new repo'),
'$ok' => t('Install'),
'$cancel' => t('Cancel')
)
);
$reponames = $this->listAddonRepos();
$addonrepos = [];
foreach($reponames as $repo) {
$addonrepos[] = array('name' => $repo, 'description' => '');
/// @TODO Parse repo info to provide more information about repos
}
$t = get_markup_template('admin_plugins.tpl');
return replace_macros($t, array(
'$title' => t('Administration'),
@@ -449,37 +196,9 @@ class Addons {
'$plugins' => $plugins,
'$disabled' => t('Disabled - version incompatibility'),
'$form_security_token' => get_form_security_token('admin_addons'),
'$allowManageRepos' => $allowManageRepos,
'$managerepos' => t('Manage Repos'),
'$installedtitle' => t('Installed Addon Repositories'),
'$addnewrepotitle' => t('Install a New Addon Repository'),
'$expandform' => false,
'$form' => $admin_plugins_add_repo_form,
'$newRepoModal' => $newRepoModal,
'$newRepoModalID' => $newRepoModalID,
'$addonrepos' => $addonrepos,
'$repoUpdateButton' => t('Update'),
'$repoBranchButton' => t('Switch branch'),
'$repoRemoveButton' => t('Remove')
));
}
function listAddonRepos() {
$addonrepos = [];
$addonDir = 'extend/addon/';
if(is_dir($addonDir)) {
if ($handle = opendir($addonDir)) {
while (false !== ($entry = readdir($handle))) {
if ($entry != "." && $entry != "..") {
$addonrepos[] = $entry;
}
}
closedir($handle);
}
}
return $addonrepos;
}
static public function plugin_sort($a,$b) {
return(strcmp(strtolower($a[2]['name']),strtolower($b[2]['name'])));
}

View File

@@ -59,14 +59,13 @@ class Features {
}
$tpl = get_markup_template("admin_settings_features.tpl");
$o .= replace_macros($tpl, array(
return replace_macros($tpl, array(
'$form_security_token' => get_form_security_token("admin_manage_features"),
'$title' => t('Manage Additional Features'),
'$features' => $arr,
'$submit' => t('Submit'),
));
return $o;
}
}

View File

@@ -6,6 +6,8 @@ use Zotlabs\Lib\Config;
class Site {
private string $eol;
private string $joo;
/**
* @brief POST handler for Admin Site Page.
@@ -208,7 +210,6 @@ class Site {
//Config::Set('system','force_queue_threshold', $force_queue);
Config::Set('system','no_community_page', $no_community_page);
Config::Set('system','no_utf', $no_utf);
Config::Set('system','sse_enabled', $sse_enabled);

View File

@@ -2,7 +2,7 @@
namespace Zotlabs\Module\Admin;
use \Michelf\MarkdownExtra;
use Michelf\MarkdownExtra;
use Zotlabs\Lib\Config;
/**

View File

@@ -108,6 +108,9 @@ class Api extends \Zotlabs\Web\Controller {
echo api_call();
killme();
// not reached
return;
}
function oauth_get_client($request){

View File

@@ -2,7 +2,7 @@
namespace Zotlabs\Module;
use \Zotlabs\Lib as Zlib;
use Zotlabs\Lib as Zlib;
class Apporder extends \Zotlabs\Web\Controller {
@@ -25,7 +25,7 @@ class Apporder extends \Zotlabs\Web\Controller {
$syslist[] = Zlib\Apps::app_encode($li);
}
}
Zlib\Apps::translate_system_apps($syslist);
usort($syslist,'Zotlabs\\Lib\\Apps::app_name_compare');

View File

@@ -1,8 +1,8 @@
<?php
namespace Zotlabs\Module;
use \Zotlabs\Lib\Config;
use \Zotlabs\Lib as Zlib;
use Zotlabs\Lib\Config;
use Zotlabs\Lib as Zlib;
class Apps extends \Zotlabs\Web\Controller {

View File

@@ -133,6 +133,11 @@ class Attach_edit extends Controller {
}
$x = attach_move($channel_id, $resource, $newfolder, (($single) ? $newfilename : ''));
if (!$x['success']) {
notice($x['message'] . EOL);
goaway($return_path);
}
$actions_done .= 'move,';
}

View File

@@ -9,7 +9,7 @@ class Authorize extends \Zotlabs\Web\Controller {
function get() {
if (! local_channel()) {
return login();
}
}
else {
$name = $_REQUEST['client_name'];
@@ -25,7 +25,7 @@ class Authorize extends \Zotlabs\Web\Controller {
$link = (($app['url']) ? '<a style="float: none;" href="' . $app['url'] . '">' . $app['name'] . '</a> ' : $app['name']);
$o .= replace_macros(get_markup_template('oauth_authorize.tpl'), [
return replace_macros(get_markup_template('oauth_authorize.tpl'), [
'$title' => t('Authorize'),
'$authorize' => sprintf( t('Do you authorize the app %s to access your channel data?'), $link ),
'$app' => $app,
@@ -35,7 +35,6 @@ class Authorize extends \Zotlabs\Web\Controller {
'$redirect_uri' => (x($_REQUEST, 'redirect_uri') ? $_REQUEST['redirect_uri'] : ''),
'$state' => (x($_REQUEST, 'state') ? $_REQUEST['state'] : ''),
]);
return $o;
}
}
@@ -50,7 +49,7 @@ class Authorize extends \Zotlabs\Web\Controller {
// TODO: The automatic client registration protocol below should adhere more
// closely to "OAuth 2.0 Dynamic Client Registration Protocol" defined
// at https://tools.ietf.org/html/rfc7591
// If no client_id was provided, generate a new one.
if (x($_POST, 'client_id')) {
$client_id = $_POST['client_id'];
@@ -67,7 +66,7 @@ class Authorize extends \Zotlabs\Web\Controller {
$request = \OAuth2\Request::createFromGlobals();
$response = new \OAuth2\Response();
// Note, "sub" field must match type and content. $user_id is used to populate - make sure it's a string.
// Note, "sub" field must match type and content. $user_id is used to populate - make sure it's a string.
$channel = channelx_by_n(local_channel());
$user_id = $channel['channel_id'];

View File

@@ -7,7 +7,7 @@ class Authtest extends \Zotlabs\Web\Controller {
$auth_success = false;
$o .= '<h3>Magic-Auth Diagnostic</h3>';
$o = '<h3>Magic-Auth Diagnostic</h3>';
if(! local_channel()) {
notice( t('Permission denied.') . EOL);
@@ -27,7 +27,7 @@ class Authtest extends \Zotlabs\Web\Controller {
$_REQUEST['test'] = 1;
$mod = new Magic();
$x = $mod->init($a);
$x = $mod->init();
$o .= 'Local Setup returns: ' . print_r($x,true);

View File

@@ -5,30 +5,30 @@ namespace Zotlabs\Module;
class Changeaddr extends \Zotlabs\Web\Controller {
function post() {
if(! local_channel())
return;
if($_SESSION['delegate'])
return;
if((! x($_POST,'qxz_password')) || (! strlen(trim($_POST['qxz_password']))))
return;
if((! x($_POST,'verify')) || (! strlen(trim($_POST['verify']))))
return;
if($_POST['verify'] !== $_SESSION['remove_account_verify'])
return;
$account = \App::get_account();
$channel = \App::get_channel();
$x = account_verify_password($account['account_email'],$_POST['qxz_password']);
if(! ($x && $x['account']))
return;
if($account['account_password_changed'] > NULL_DATE) {
$d1 = datetime_convert('UTC','UTC','now - 48 hours');
if($account['account_password_changed'] > $d1) {
@@ -36,7 +36,7 @@ class Changeaddr extends \Zotlabs\Web\Controller {
return;
}
}
$new_address = trim($_POST['newname']);
if($new_address === $channel['channel_address'])
@@ -55,23 +55,23 @@ class Changeaddr extends \Zotlabs\Web\Controller {
channel_change_address($channel,$new_address);
goaway(z_root() . '/changeaddr');
}
function get() {
if(! local_channel())
goaway(z_root());
$channel = \App::get_channel();
$hash = random_string();
$_SESSION['remove_account_verify'] = $hash;
$tpl = get_markup_template('channel_rename.tpl');
$o .= replace_macros($tpl, array(
return replace_macros($tpl, array(
'$basedir' => z_root(),
'$hash' => $hash,
'$title' => t('Change channel nickname/address'),
@@ -80,9 +80,5 @@ class Changeaddr extends \Zotlabs\Web\Controller {
'$newname' => array('newname', t('New channel address'),$channel['channel_address'], ''),
'$submit' => t('Rename Channel')
));
return $o;
}
}

View File

@@ -85,7 +85,7 @@ class Channel extends Controller {
$headers = [
'Content-Type' => 'application/x-zot+json',
'Digest' => HTTPSig::generate_digest_header($data),
'(request-target)' => strtolower($_SERVER['REQUEST_METHOD']) . ' ' . $_SERVER['REQUEST_URI']
'Date' => datetime_convert('UTC','UTC', 'now', 'D, d M Y H:i:s \\G\\M\\T')
];
$h = HTTPSig::create_sig($headers, $channel['channel_prvkey'], channel_url($channel));
@@ -266,7 +266,7 @@ class Channel extends Controller {
'default_location' => (($is_owner) ? App::$profile['channel_location'] : ''),
'nickname' => App::$profile['channel_address'],
'lockstate' => (((strlen(App::$profile['channel_allow_cid'])) || (strlen(App::$profile['channel_allow_gid'])) || (strlen(App::$profile['channel_deny_cid'])) || (strlen(App::$profile['channel_deny_gid']))) ? 'lock' : 'unlock'),
'acl' => (($is_owner) ? populate_acl($channel_acl, true, PermissionDescription::fromGlobalPermission('view_stream'), get_post_aclDialogDescription(), 'acl_dialog_post') : ''),
'acl' => (($is_owner) ? populate_acl($channel_acl, true, PermissionDescription::fromGlobalPermission('view_stream'), get_post_aclDialogDescription(), 'member/permissions') : ''),
'permissions' => $channel_acl,
'showacl' => (($is_owner) ? 'yes' : ''),
'bang' => '',
@@ -298,12 +298,15 @@ class Channel extends Controller {
$item_normal = item_normal();
$item_normal_update = item_normal_update();
$sql_extra = item_permissions_sql(App::$profile['profile_uid']);
$sql_extra = '';
$permission_sql = item_permissions_sql(App::$profile['profile_uid']);
if (feature_enabled(App::$profile['profile_uid'], 'channel_list_mode') && (!$mid))
$page_mode = 'client';
$blog_mode = feature_enabled(App::$profile['profile_uid'], 'channel_list_mode') && !$mid;
if ($blog_mode) {
$page_mode = 'list';
else
$page_mode = 'client';
}
$abook_uids = " and abook.abook_channel = " . intval(App::$profile['profile_uid']) . " ";
@@ -334,8 +337,8 @@ class Channel extends Controller {
if (($update) && (!$load)) {
if ($mid) {
$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",
$r = q("SELECT *, parent AS item_id from item where $identifier = '%s' and uid = %d $item_normal_update
AND item_wall = 1 $simple_update $permission_sql $sql_extra limit 1",
dbesc($mid),
intval(App::$profile['profile_uid'])
);
@@ -346,6 +349,7 @@ class Channel extends Controller {
WHERE uid = %d $item_normal_update
AND item_wall = 1 $simple_update
AND (abook.abook_blocked = 0 or abook.abook_flags is null)
$permission_sql
$sql_extra
ORDER BY created DESC",
intval(App::$profile['profile_uid'])
@@ -382,8 +386,8 @@ class Channel extends Controller {
if ($noscript_content || $load) {
if ($mid) {
$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",
$r = q("SELECT *, parent AS item_id from item where $identifier = '%s' and uid = %d $item_normal
AND item_wall = 1 $permission_sql $sql_extra limit 1",
dbesc($mid),
intval(App::$profile['profile_uid'])
);
@@ -392,13 +396,18 @@ class Channel extends Controller {
}
}
else {
$r = q("SELECT DISTINCT item.parent AS item_id, $ordering FROM item
left join abook on ( item.author_xchan = abook.abook_xchan $abook_uids )
WHERE true and item.uid = %d $item_normal
$r = q("SELECT parent AS item_id, $ordering FROM item
LEFT JOIN abook ON (item.author_xchan = abook.abook_xchan $abook_uids)
WHERE item.uid = %d
AND item.id = item.parent
AND (abook.abook_blocked = 0 or abook.abook_flags is null)
AND item.item_wall = 1 AND item.item_thread_top = 1
$sql_extra $sql_extra2
ORDER BY $ordering DESC, item_id $pager_sql ",
AND item.item_wall = 1
$item_normal
$permission_sql
$sql_extra
$sql_extra2
ORDER BY $ordering DESC, item_id
$pager_sql",
intval(App::$profile['profile_uid'])
);
}
@@ -408,19 +417,15 @@ class Channel extends Controller {
}
}
if ($r) {
$parents_str = ids_to_querystr($r, 'item_id');
$thr_parents = null;
if ($mid) {
$thr_parents = get_recursive_thr_parents($r[0]);
}
$r = q("SELECT item.*, item.id AS item_id
FROM item
WHERE item.uid = %d $item_normal
AND item.parent IN ( %s )
$sql_extra ",
intval(App::$profile['profile_uid']),
dbesc($parents_str)
);
$items = items_by_parent_ids($r, $thr_parents, $permission_sql, $blog_mode);
xchan_query($r);
$items = fetch_post_tags($r, true);
xchan_query($items);
$items = fetch_post_tags($items, true);
$items = conv_sort($items, $ordering);
if ($load && $mid && (!count($items))) {
@@ -434,11 +439,8 @@ class Channel extends Controller {
$items = [];
}
$mode = (($search) ? 'search' : 'channel');
if ((!$update) && (!$load)) {
// This is ugly, but we can't pass the profile_uid through the session to the ajax updater,

View File

@@ -179,26 +179,14 @@ class Channel_calendar extends Controller {
if ($post_tags)
$datarray['term'] = $post_tags;
$item_id = event_store_item($datarray, $event);
$post = event_store_item($datarray, $event);
if ($item_id) {
$r = q("select * from item where id = %d",
intval($item_id)
);
if ($r) {
xchan_query($r);
$sync_item = fetch_post_tags($r);
$z = q("select * from event where event_hash = '%s' and uid = %d limit 1",
dbesc($r[0]['resource_id']),
intval($channel['channel_id'])
);
if ($z) {
Libsync::build_sync_packet($channel['channel_id'], array('event_item' => array(encode_item($sync_item[0], true)), 'event' => $z));
}
}
if (!empty($post['item_id'])) {
Master::Summon(['Notifier', 'event', $post['item_id']]);
}
if (!empty($post['approval_id'])) {
Master::Summon(['Notifier', 'event', $post['approval_id']]);
}
Master::Summon(array('Notifier', 'event', $item_id));
killme();
@@ -470,13 +458,14 @@ class Channel_calendar extends Controller {
}
else {
// complex deletion that needs to propagate and be performed in phases
drop_item($i[0]['id'], true, DROPITEM_PHASE1);
drop_item($i[0]['id'], DROPITEM_PHASE1);
$complex = true;
}
$ii = q("select * from item where id = %d",
intval($i[0]['id'])
);
if ($ii) {
xchan_query($ii);
$sync_item = fetch_post_tags($ii);
@@ -485,6 +474,9 @@ class Channel_calendar extends Controller {
if ($complex) {
tag_deliver($i[0]['uid'], $i[0]['id']);
if (intval($i[0]['item_wall'])) {
Master::Summon(['Notifier', 'drop', $i[0]['id']]);
}
}
}
}

View File

@@ -4,7 +4,7 @@ namespace Zotlabs\Module;
require_once('include/security.php');
use \Zotlabs\Lib as Zlib;
use Zotlabs\Lib as Zlib;
class Chatsvc extends \Zotlabs\Web\Controller {

View File

@@ -7,11 +7,12 @@ namespace Zotlabs\Module;
* Module for accessing the DAV storage area.
*/
use App;
use Sabre\DAV as SDAV;
use \Zotlabs\Web\Controller;
use \Zotlabs\Storage\BasicAuth;
use \Zotlabs\Storage\Directory;
use \Zotlabs\Storage\Browser;
use Zotlabs\Web\Controller;
use Zotlabs\Storage\BasicAuth;
use Zotlabs\Storage\Directory;
use Zotlabs\Storage\Browser;
// composer autoloader for SabreDAV
@@ -32,6 +33,15 @@ class Cloud extends Controller {
*/
function init() {
// TODO: why is this required?
// if we arrived at this path with any query parameters in the url, build a clean url without
// them and redirect.
$parsed = parse_url(App::$query_string);
if (!empty($parsed['query'])) {
goaway(z_root() . '/' . $parsed['path']);
}
if (! is_dir('store'))
os_mkdir('store', STORAGE_DEFAULT_PERMISSIONS, false);
@@ -44,15 +54,13 @@ class Cloud extends Controller {
if ($which)
profile_load( $which, $profile);
$auth = new BasicAuth();
$ob_hash = get_observer_hash();
if ($ob_hash) {
if (local_channel()) {
$channel = \App::get_channel();
$channel = App::get_channel();
$auth->setCurrentUser($channel['channel_address']);
$auth->channel_account_id = $channel['channel_account_id'];
$auth->channel_id = $channel['channel_id'];
@@ -63,19 +71,12 @@ class Cloud extends Controller {
$auth->observer = $ob_hash;
}
// if we arrived at this path with any query parameters in the url, build a clean url without
// them and redirect.
if(! array_key_exists('cloud_sort',$_SESSION)) {
$_SESSION['cloud_sort'] = 'name';
}
$_SESSION['cloud_sort'] = ((isset($_REQUEST['sort']) && $_REQUEST['sort']) ? trim(notags($_REQUEST['sort'])) : $_SESSION['cloud_sort']);
$x = clean_query_string();
if($x !== \App::$query_string)
goaway(z_root() . '/' . $x);
$rootDirectory = new Directory('/', [], $auth);
// A SabreDAV server-object
@@ -116,16 +117,16 @@ class Cloud extends Controller {
function DAVException($err) {
if($err instanceof \Sabre\DAV\Exception\NotFound) {
\App::$page['content'] = '<h2>404 Not found</h2>';
App::$page['content'] = '<h2>404 Not found</h2>';
}
elseif($err instanceof \Sabre\DAV\Exception\Forbidden) {
\App::$page['content'] = '<h2>403 Forbidden</h2>';
App::$page['content'] = '<h2>403 Forbidden</h2>';
}
elseif($err instanceof \Sabre\DAV\Exception\NotImplemented) {
goaway(z_root() . '/' . \App::$query_string);
goaway(z_root() . '/' . App::$query_string);
}
else {
\App::$page['content'] = '<h2>Unknown error</h2>';
App::$page['content'] = '<h2>Unknown error</h2>';
}
construct_page();

View File

@@ -16,7 +16,7 @@ class Conversation extends Controller {
public function init() {
if (ActivityStreams::is_as_request()) {
if (ActivityStreams::is_as_request() || Libzot::is_zot_request()) {
$item_id = argv(1);
if (!$item_id) {
@@ -30,14 +30,13 @@ class Conversation extends Controller {
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 ";
$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 and item.item_uplink = 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),
$r = q("select parent_mid from item where uuid = '%s' $item_normal order by item_wall desc limit 1",
dbesc($item_id)
);
@@ -77,16 +76,16 @@ class Conversation extends Controller {
}
}
}
elseif (Config::get('system', 'require_authenticated_fetch', false)) {
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) {
$sql_extra = item_permissions_sql(0);
$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'])
);

View File

@@ -371,7 +371,7 @@ class Cover_photo extends \Zotlabs\Web\Controller {
$tpl = get_markup_template('cover_photo.tpl');
$o .= replace_macros($tpl,array(
$output = replace_macros($tpl,array(
'$user' => \App::$channel['channel_address'],
'$info' => t('Your cover photo may be visible to anybody on the internet'),
'$existing' => get_cover_photo(local_channel(),'array',PHOTO_RES_COVER_850),
@@ -397,15 +397,15 @@ class Cover_photo extends \Zotlabs\Web\Controller {
));
call_hooks('cover_photo_content_end', $o);
call_hooks('cover_photo_content_end', $output);
return $o;
return $output;
}
else {
$filename = \App::$data['imagecrop'] . '-3';
$resolution = 3;
$tpl = get_markup_template("cropcover.tpl");
$o .= replace_macros($tpl,array(
return replace_macros($tpl,array(
'$filename' => $filename,
'$profile' => intval($_REQUEST['profile']),
'$resource' => \App::$data['imagecrop'] . '-3',
@@ -415,7 +415,6 @@ class Cover_photo extends \Zotlabs\Web\Controller {
'$form_security_token' => get_form_security_token("cover_photo"),
'$done' => t('Done Editing')
));
return $o;
}
}

View File

@@ -9,6 +9,7 @@
namespace Zotlabs\Module;
use Sabre\DAV as SDAV;
use Zotlabs\Lib\Libzot;
use Zotlabs\Storage;
use Zotlabs\Web\HTTPSig;

View File

@@ -81,7 +81,7 @@ class Display extends Controller {
'default_location' => $channel['channel_location'],
'nickname' => $channel['channel_address'],
'lockstate' => (($channel['channel_allow_cid'] || $channel['channel_allow_gid'] || $channel['channel_deny_cid'] || $channel['channel_deny_gid']) ? 'lock' : 'unlock'),
'acl' => populate_acl($channel_acl,true, \Zotlabs\Lib\PermissionDescription::fromGlobalPermission('view_stream'), get_post_aclDialogDescription(), 'acl_dialog_post'),
'acl' => populate_acl($channel_acl,true, \Zotlabs\Lib\PermissionDescription::fromGlobalPermission('view_stream'), get_post_aclDialogDescription(), 'member/permissions'),
'permissions' => $channel_acl,
'bang' => '',
'visitor' => true,
@@ -212,7 +212,7 @@ class Display extends Controller {
$observer_hash = get_observer_hash();
$item_normal = item_normal();
$item_normal_update = item_normal_update();
$sql_extra = '';
$permission_sql = '';
$r = [];
if($noscript_content || $load) {
@@ -231,7 +231,7 @@ class Display extends Controller {
}
if(!$r) {
$sql_extra = item_permissions_sql(0, $observer_hash);
$permission_sql = item_permissions_sql(0, $observer_hash);
$r = q("SELECT item.id AS item_id FROM item
WHERE ((mid = '%s'
@@ -239,7 +239,7 @@ class Display extends Controller {
AND item.deny_gid = '' AND item_private = 0 )
AND uid IN ( " . stream_perms_api_uids(($observer_hash) ? (PERMS_NETWORK|PERMS_PUBLIC) : PERMS_PUBLIC) . " ))
OR uid = %d ))) OR
(mid = '%s' $sql_extra ))
(mid = '%s' $permission_sql ))
$item_normal
limit 1",
dbesc($target_item['parent_mid']),
@@ -269,7 +269,7 @@ class Display extends Controller {
}
if(!$r) {
$sql_extra = item_permissions_sql(0, $observer_hash);
$permission_sql = item_permissions_sql(0, $observer_hash);
$r = q("SELECT item.id as item_id from item
WHERE ((parent_mid = '%s'
@@ -277,7 +277,7 @@ class Display extends Controller {
AND item.deny_gid = '' AND item_private = 0 )
and uid in ( " . stream_perms_api_uids(($observer_hash) ? (PERMS_NETWORK|PERMS_PUBLIC) : PERMS_PUBLIC) . " ))
OR uid = %d ))) OR
(parent_mid = '%s' $sql_extra ))
(parent_mid = '%s' $permission_sql ))
$item_normal
limit 1",
dbesc($target_item['parent_mid']),
@@ -288,17 +288,12 @@ class Display extends Controller {
}
if($r) {
$parents_str = ids_to_querystr($r,'item_id');
if($parents_str) {
$items = q("SELECT item.*, item.id AS item_id
FROM item
WHERE parent in ( %s ) $sql_extra $item_normal ",
dbesc($parents_str)
);
xchan_query($items);
$items = fetch_post_tags($items,true);
$items = conv_sort($items,'created');
}
$thr_parents = get_recursive_thr_parents($target_item);
$items = items_by_parent_ids($r, $thr_parents, $permission_sql);
xchan_query($items);
$items = fetch_post_tags($items,true);
$items = conv_sort($items,'created');
}
else {
$items = array();
@@ -344,7 +339,12 @@ class Display extends Controller {
'$profile_page' => xmlify(z_root() . '/display/' . gen_link_id($target_item['mid'])),
));
$x = [ 'xml' => $atom, 'channel' => $channel, 'observer_hash' => $observer_hash, 'params' => $params ];
$x = [
'xml' => $atom,
'channel' => $channel,
'observer_hash' => $observer_hash,
'params' => [],
];
call_hooks('atom_feed_top',$x);
$atom = $x['xml'];

View File

@@ -19,7 +19,7 @@ class Dreport extends \Zotlabs\Web\Controller {
$table = 'push';
if($mid) {
$i = q("select id from item where mid = '%s' and uid = %d and ( author_xchan = '%s' or ( owner_xchan = '%s' and item_wall = 1 )) ",
$i = q("select * from item where mid = '%s' and uid = %d and ( author_xchan = '%s' or ( owner_xchan = '%s' and item_wall = 1 )) ",
dbesc($mid),
intval($channel['channel_id']),
dbesc($channel['channel_hash']),
@@ -27,6 +27,12 @@ class Dreport extends \Zotlabs\Web\Controller {
);
if($i) {
\Zotlabs\Daemon\Master::Summon([ 'Notifier', 'edit_post', $i[0]['id'] ]);
$relatedItem = find_related($i[0]);
if (isset($relatedItem['id'])) {
\Zotlabs\Daemon\Master::Summon([ 'Notifier', 'edit_post', $relatedItem['id'] ]);
}
}
}
sleep(3);

View File

@@ -86,6 +86,7 @@ class Editpost extends \Zotlabs\Web\Controller {
'bbco_autocomplete'=> 'bbcode',
'return_path' => 'hq',
'button' => t('Submit'),
'disable_comments' => (($itm[0]['item_thread_top']) ? false : true),
'hide_voting' => true,
'hide_future' => true,
'hide_location' => true,

View File

@@ -43,7 +43,7 @@ class Embedphotos extends \Zotlabs\Web\Controller {
$arr = explode('/', $href);
$resource_id = array_pop($arr);
$x = self::photolink($resource_id);
if($x)
if($x)
json_return_and_die(array('status' => true, 'photolink' => $x, 'resource_id' => $resource_id));
json_return_and_die(array('errormsg' => 'Error retrieving resource ' . $resource_id, 'status' => false));
}
@@ -55,7 +55,7 @@ class Embedphotos extends \Zotlabs\Web\Controller {
$output = EMPTY_STR;
if($channel) {
$resolution = ((feature_enabled($channel['channel_id'],'large_photos')) ? 1 : 2);
$r = q("select mimetype, height, width from photo where resource_id = '%s' and $resolution = %d and uid = %d limit 1",
$r = q("select mimetype, filename from photo where resource_id = '%s' and $resolution = %d and uid = %d limit 1",
dbesc($resource),
intval($resolution),
intval($channel['channel_id'])
@@ -63,6 +63,8 @@ class Embedphotos extends \Zotlabs\Web\Controller {
if(! $r)
return $output;
$filename = $r[0]['filename'];
if($r[0]['mimetype'] === 'image/jpeg')
$ext = '.jpg';
elseif($r[0]['mimetype'] === 'image/png')
@@ -75,7 +77,7 @@ class Embedphotos extends \Zotlabs\Web\Controller {
$ext = EMPTY_STR;
$output = '[zrl=' . z_root() . '/photos/' . $channel['channel_address'] . '/image/' . $resource . ']' .
'[zmg=' . $r[0]['width'] . 'x' . $r[0]['height'] . ']' . z_root() . '/photo/' . $resource . '-' . $resolution . $ext . '[/zmg][/zrl]';
'[zmg=' . z_root() . '/photo/' . $resource . '-' . $resolution . $ext . ']' . $filename . '[/zmg][/zrl]' . "\r\n";
return $output;
}

View File

@@ -6,6 +6,8 @@ namespace Zotlabs\Module;
* @author Fabio Comuni <fabrixxm@kirgroup.com>
*/
use function Zotlabs\Render\template_escape;
require_once('include/photo/photo_driver.php');
/**

View File

@@ -11,39 +11,42 @@ require_once('include/photos.php');
class File_upload extends \Zotlabs\Web\Controller {
function post() {
logger('file upload: ' . print_r($_REQUEST,true));
logger('file upload: ' . print_r($_POST,true));
logger('file upload: ' . print_r($_FILES,true));
$channel = (($_REQUEST['channick']) ? channelx_by_nick($_REQUEST['channick']) : null);
$channel = (($_POST['channick']) ? channelx_by_nick($_POST['channick']) : null);
if(! $channel) {
if (!$channel) {
logger('channel not found');
killme();
is_ajax() ? killme() : goaway(z_root() . '/' . $_POST['return_url']);
}
$_REQUEST['source'] = 'file_upload';
$_POST['source'] = 'file_upload';
if($channel['channel_id'] != local_channel()) {
$_REQUEST['contact_allow'] = expand_acl($channel['channel_allow_cid']);
$_REQUEST['group_allow'] = expand_acl($channel['channel_allow_gid']);
$_REQUEST['contact_deny'] = expand_acl($channel['channel_deny_cid']);
$_REQUEST['group_deny'] = expand_acl($channel['channel_deny_gid']);
$_POST['contact_allow'] = expand_acl($channel['channel_allow_cid']);
$_POST['group_allow'] = expand_acl($channel['channel_allow_gid']);
$_POST['contact_deny'] = expand_acl($channel['channel_deny_cid']);
$_POST['group_deny'] = expand_acl($channel['channel_deny_gid']);
}
$_REQUEST['allow_cid'] = ((isset($_REQUEST['contact_allow'])) ? perms2str($_REQUEST['contact_allow']) : '');
$_REQUEST['allow_gid'] = ((isset($_REQUEST['group_allow'])) ? perms2str($_REQUEST['group_allow']) : '');
$_REQUEST['deny_cid'] = ((isset($_REQUEST['contact_deny'])) ? perms2str($_REQUEST['contact_deny']) : '');
$_REQUEST['deny_gid'] = ((isset($_REQUEST['group_deny'])) ? perms2str($_REQUEST['group_deny']) : '');
$_POST['allow_cid'] = ((isset($_POST['contact_allow'])) ? perms2str($_POST['contact_allow']) : '');
$_POST['allow_gid'] = ((isset($_POST['group_allow'])) ? perms2str($_POST['group_allow']) : '');
$_POST['deny_cid'] = ((isset($_POST['contact_deny'])) ? perms2str($_POST['contact_deny']) : '');
$_POST['deny_gid'] = ((isset($_POST['group_deny'])) ? perms2str($_POST['group_deny']) : '');
if(isset($_REQUEST['filename']) && strlen($_REQUEST['filename'])) {
$r = attach_mkdir($channel, get_observer_hash(), $_REQUEST);
if($r['success']) {
$hash = $r['data']['hash'];
$sync = attach_export_data($channel,$hash);
if($sync) {
Libsync::build_sync_packet($channel['channel_id'],array('file' => array($sync)));
}
goaway(z_root() . '/' . $_REQUEST['return_url']);
if(isset($_POST['filename']) && strlen($_POST['filename'])) {
$r = attach_mkdir($channel, get_observer_hash(), $_POST);
if (!$r['success']) {
notice($r['message'] . EOL);
is_ajax() ? killme() : goaway(z_root() . '/' . $_POST['return_url']);
}
$hash = $r['data']['hash'];
$sync = attach_export_data($channel,$hash);
if ($sync) {
Libsync::build_sync_packet($channel['channel_id'], ['file' => [$sync]]);
}
}
else {
@@ -90,19 +93,19 @@ class File_upload extends \Zotlabs\Web\Controller {
}
}
$r = attach_store($channel, get_observer_hash(), '', $_REQUEST);
if($r['success']) {
$sync = attach_export_data($channel,$r['data']['hash']);
if($sync)
Libsync::build_sync_packet($channel['channel_id'],array('file' => array($sync)));
$r = attach_store($channel, get_observer_hash(), '', $_POST);
if (!$r['success']) {
notice($r['message'] . EOL);
is_ajax() ? killme() : goaway(z_root() . '/' . $_POST['return_url']);
}
$sync = attach_export_data($channel,$r['data']['hash']);
if ($sync) {
Libsync::build_sync_packet($channel['channel_id'], ['file' => [$sync]]);
}
}
if(is_ajax())
killme();
goaway(z_root() . '/' . $_REQUEST['return_url']);
is_ajax() ? killme() : goaway(z_root() . '/' . $_POST['return_url']);
}

View File

@@ -1,43 +1,54 @@
<?php
namespace Zotlabs\Module;
require_once('include/security.php');
require_once('include/bbcode.php');
require_once('include/items.php');
use App;
class Filer extends \Zotlabs\Web\Controller {
function get() {
if(! local_channel()) {
if(!local_channel()) {
killme();
}
$term = unxmlify(trim($_GET['term']));
$item_id = ((\App::$argc > 1) ? intval(\App::$argv[1]) : 0);
$term = unxmlify(trim($_GET['term'] ?? ''));
$item_id = ((App::$argc > 1) ? intval(App::$argv[1]) : 0);
logger('filer: tag ' . $term . ' item ' . $item_id);
if($item_id && strlen($term)){
$sys = get_sys_channel();
$r = q("SELECT * FROM item WHERE (uid = %d OR uid = %d) AND id = %d
and item_type in (0,6,7) and item_deleted = 0 and item_unpublished = 0
and item_delayed = 0 and item_pending_remove = 0 and item_blocked = 0 LIMIT 1",
intval(local_channel()),
intval($sys['channel_id']),
intval($item_id)
);
if ($r && $r[0]['uid'] === $sys['channel_id']) {
$r = [copy_of_pubitem(App::get_channel(), $r[0]['mid'])];
}
if(!$r) {
killme();
}
$item_id = $r[0]['id'];
// file item
store_item_tag(local_channel(),$item_id,TERM_OBJ_POST,TERM_FILE,$term,'');
// protect the entire conversation from periodic expiration
$r = q("select parent from item where id = %d and uid = %d limit 1",
intval($item_id),
q("update item set item_retained = 1, changed = '%s' where id = %d and uid = %d",
dbesc(datetime_convert()),
intval($r[0]['parent']),
intval(local_channel())
);
if($r) {
$x = q("update item set item_retained = 1, changed = '%s' where id = %d and uid = %d",
dbesc(datetime_convert()),
intval($r[0]['parent']),
intval(local_channel())
);
}
}
}
else {
$filetags = array();
$r = q("select distinct(term) from term where uid = %d and ttype = %d order by term asc",
@@ -55,10 +66,10 @@ class Filer extends \Zotlabs\Web\Controller {
'$title' => t('Save to Folder'),
'$cancel' => t('Cancel')
));
echo $o;
}
killme();
}
}

View File

@@ -2,7 +2,7 @@
namespace Zotlabs\Module;
use Zorlabs\Lib\Config;
use Zotlabs\Lib\Config;
class Go extends \Zotlabs\Web\Controller {
@@ -19,7 +19,7 @@ class Go extends \Zotlabs\Web\Controller {
function get() {
if(! local_channel()) {
notify( t('This page is available only to site members') . EOL);
notice( t('This page is available only to site members') . EOL);
}
$channel = \App::get_channel();

View File

@@ -30,7 +30,7 @@ class Help extends \Zotlabs\Web\Controller {
$this->determine_help_language();
if (empty($_REQUEST['search']) && argc() === 1) {
goaway("/help/{$this->lang['language']}/about/about");
goaway("/help/about");
killme();
}
}
@@ -85,7 +85,7 @@ class Help extends \Zotlabs\Web\Controller {
}
if(argc() > 2 && argv(argc()-2) === 'assets') {
if(argc() > 2 && argv(argc()-2) === 'pic') {
$path = '';
for($x = 1; $x < argc(); $x ++) {
if(strlen($path))
@@ -155,7 +155,7 @@ class Help extends \Zotlabs\Web\Controller {
}
if (empty($args)) {
goaway("/help/{$this->lang['language']}/about/about");
goaway("/help/about/about");
}
// Keep the first remaining arg as the heading slug

View File

@@ -24,9 +24,13 @@ class Home extends Controller {
$key = Config::Get('system', 'prvkey');
$ret = json_encode(Libzot::site_info());
$headers = ['Content-Type' => 'application/x-zot+json', 'Digest' => HTTPSig::generate_digest_header($ret)];
$headers['(request-target)'] = strtolower($_SERVER['REQUEST_METHOD']) . ' ' . $_SERVER['REQUEST_URI'];
$h = HTTPSig::create_sig($headers, $key, z_root());
$headers = [
'Content-Type' => 'application/x-zot+json',
'Digest' => HTTPSig::generate_digest_header($ret),
'Date' => datetime_convert('UTC','UTC', 'now', 'D, d M Y H:i:s \\G\\M\\T')
];
$h = HTTPSig::create_sig($headers, $key, z_root());
HTTPSig::set_headers($h);
echo $ret;
@@ -68,9 +72,9 @@ class Home extends Controller {
$o = '';
if (x($_SESSION, 'theme'))
if (isset($_SESSION['theme']))
unset($_SESSION['theme']);
if (x($_SESSION, 'mobile_theme'))
if (isset($_SESSION['mobile_theme']))
unset($_SESSION['mobile_theme']);
$splash = ((argc() > 1 && argv(1) === 'splash') ? true : false);
@@ -100,14 +104,25 @@ class Home extends Controller {
goaway($frontpage);
}
$o .= '<div class="generic-content-wrapper">';
$sitename = Config::Get('system', 'sitename');
if ($sitename)
$o .= '<h1 class="home-welcome">' . sprintf(t('Welcome to %s'), $sitename) . '</h1>';
if ($sitename) {
$o .= '<div class="section-title-wrapper">';
$o .= '<h2 class="">' . sprintf(t('Welcome to %s'), $sitename) . '</h2>';
$o .= '</div>';
}
$o .= '<div class="section-content-wrapper">';
$loginbox = Config::Get('system', 'login_on_homepage');
if (intval($loginbox) || $loginbox === false)
$o .= login(true);
$o .= '</div>';
$o .= '</div>';
return $o;
}

View File

@@ -3,6 +3,7 @@ namespace Zotlabs\Module;
use App;
use Zotlabs\Widget\Messages;
use Zotlabs\Lib\Config;
class Hq extends \Zotlabs\Web\Controller {
@@ -50,14 +51,18 @@ class Hq extends \Zotlabs\Web\Controller {
// select the target item with a bias to our own item
$sql_order = ((local_channel() > $sys['channel_id']) ? 'DESC' : 'ASC');
$r = q("select id, uid, mid, parent_mid, thr_parent, verb, item_type, item_deleted, item_blocked from item where uid in (%d, %d) and $identifier = '%s' order by uid $sql_order limit 2",
$r = q("select id, uid, mid, parent, parent_mid, thr_parent, verb, item_type, item_deleted, item_blocked from item where uid in (%d, %d) and $identifier = '%s' order by uid $sql_order limit 2",
intval(local_channel()),
intval($sys['channel_id']),
dbesc($item_hash)
);
if($r) {
$target_item = $r[0];
call_hooks('item_custom_display', $target_item);
if (intval($target_item['uid']) === intval($sys['channel_id'])) {
$sys_item = true;
}
@@ -86,7 +91,7 @@ class Hq extends \Zotlabs\Web\Controller {
'default_location' => $channel['channel_location'],
'nickname' => $channel['channel_address'],
'lockstate' => (($channel['channel_allow_cid'] || $channel['channel_allow_gid'] || $channel['channel_deny_cid'] || $channel['channel_deny_gid']) ? 'lock' : 'unlock'),
'acl' => populate_acl($channel_acl,true, \Zotlabs\Lib\PermissionDescription::fromGlobalPermission('view_stream'), get_post_aclDialogDescription(), 'acl_dialog_post'),
'acl' => populate_acl($channel_acl,true, \Zotlabs\Lib\PermissionDescription::fromGlobalPermission('view_stream'), get_post_aclDialogDescription(), 'member/permissions'),
'permissions' => $channel_acl,
'bang' => '',
'visitor' => true,
@@ -129,7 +134,7 @@ class Hq extends \Zotlabs\Web\Controller {
'$nouveau' => '0',
'$wall' => '0',
'$page' => '1',
'$list' => ((x($_REQUEST,'list')) ? intval($_REQUEST['list']) : 0),
'$list' => ((!empty($_REQUEST['list'])) ? intval($_REQUEST['list']) : 0),
'$search' => '',
'$xchan' => '',
'$order' => '',
@@ -145,7 +150,6 @@ class Hq extends \Zotlabs\Web\Controller {
}
if($load && $target_item) {
if (!$sys_item) {
$r = q("SELECT item.id AS item_id FROM item
WHERE uid = %d
@@ -199,11 +203,8 @@ class Hq extends \Zotlabs\Web\Controller {
}
if($r) {
$items = q("SELECT item.*, item.id AS item_id
FROM item
WHERE parent = '%s' $item_normal $sql_extra",
dbesc($r[0]['item_id'])
);
$thr_parents = get_recursive_thr_parents($target_item);
$items = items_by_parent_ids($r, $thr_parents);
xchan_query($items,true,(($sys_item) ? local_channel() : 0));
$items = fetch_post_tags($items,true);
@@ -230,6 +231,7 @@ class Hq extends \Zotlabs\Web\Controller {
$options['offset'] = $_REQUEST['offset'] ?? 0;
$options['type'] = $_REQUEST['type'] ?? '';
$options['author'] = ((isset($_REQUEST['author'])) ? urldecode($_REQUEST['author']) : '');
$options['file'] = ((isset($_REQUEST['file'])) ? urldecode($_REQUEST['file']) : '');
$ret = Messages::get_messages_page($options);

View File

@@ -6,8 +6,8 @@ namespace Zotlabs\Module;
*
* Controller for responding to x-zot: protocol requests
* x-zot:_jkfRG85nJ-714zn-LW_VbTFW8jSjGAhAydOcJzHxqHkvEHWG2E0RbA_pbch-h4R63RG1YJZifaNzgccoLa3MQ/453c1678-1a79-4af7-ab65-6b012f6cab77
*
*/
*
*/
use Zotlabs\Lib\Activity;
use Zotlabs\Lib\ActivityStreams;
@@ -104,7 +104,7 @@ class Id extends Controller {
$headers['Content-Type'] = 'application/x-zot+json' ;
$ret = json_encode($x, JSON_UNESCAPED_SLASHES);
$headers['Digest'] = HTTPSig::generate_digest_header($ret);
$headers['(request-target)'] = strtolower($_SERVER['REQUEST_METHOD']) . ' ' . $_SERVER['REQUEST_URI'];
$headers['Date'] = datetime_convert('UTC','UTC', 'now', 'D, d M Y H:i:s \\G\\M\\T');
$h = HTTPSig::create_sig($headers,$chan['channel_prvkey'],channel_url($chan));
HTTPSig::set_headers($h);
echo $ret;

View File

@@ -164,7 +164,7 @@ class Impel extends \Zotlabs\Web\Controller {
$arr['id'] = $i[0]['id'];
// don't update if it has the same timestamp as the original
if($arr['edited'] > $i[0]['edited'])
$x = item_store_update($arr,$execflag);
$x = item_store_update($arr, $execflag , deliver: false, addAndSync: false);
}
else {
if(($i) && (intval($i[0]['item_deleted']))) {
@@ -175,7 +175,7 @@ class Impel extends \Zotlabs\Web\Controller {
);
}
else
$x = item_store($arr,$execflag);
$x = item_store($arr, $execflag, deliver: false, addAndSync: false);
}
if($x && $x['success']) {

View File

@@ -534,6 +534,7 @@ class Import extends Controller {
if ($api_path) {
$parsed = parse_url($api_path);
unset($parsed['path']);
unset($parsed['query']);
// store the import host so we can manually kick off item/file sync later in case anything did not work out
set_pconfig($channel['channel_id'], 'import', 'host', $parsed['host']);
@@ -551,7 +552,7 @@ class Import extends Controller {
$until = datetime_convert(date_default_timezone_get(), date_default_timezone_get(), 'now + 1 day');
//$poll_interval = Config::Get('system', 'poll_interval', 3);
$page = 0;
$page = 0;
Master::Summon(['Content_importer', sprintf('%d', $page), $since, $until, $channel['channel_address'], urlencode($hz_server)]);
Master::Summon(['File_importer', sprintf('%d', $page), $channel['channel_address'], urlencode($hz_server)]);

View File

@@ -29,14 +29,14 @@ class Import_progress extends \Zotlabs\Web\Controller {
$c = PConfig::Get(local_channel(), 'import', 'content_progress');
if ($c) {
$total_cpages = floor(intval($c['items_total']) / intval($c['items_page']));
$total_cpages = round(intval($c['items_total']) / intval($c['items_page']));
if(!$total_cpages) {
$total_cpages = 1; // because of floor
$total_cpages = 1; // because of round
}
$cpage = $c['last_page'] + 1; // because page count start at 0
$cprogress = intval(floor((intval($cpage) * 100) / $total_cpages));
$cprogress = intval(round((intval($cpage) * 100) / $total_cpages));
$ccompleted_str = t('Item sync completed!');
if(argv(1) === 'resume_itemsync' && $cprogress < 100) {
@@ -50,6 +50,7 @@ class Import_progress extends \Zotlabs\Web\Controller {
if ($alive) {
$parsed = parse_url($alive);
unset($parsed['path']);
unset($parsed['query']);
$hz_server = unparse_url($parsed);
$since = datetime_convert(date_default_timezone_get(), date_default_timezone_get(), '0001-01-01 00:00');
@@ -79,14 +80,14 @@ class Import_progress extends \Zotlabs\Web\Controller {
$f = PConfig::Get(local_channel(), 'import', 'files_progress');
if ($f) {
$total_fpages = floor(intval($f['files_total']) / intval($f['files_page']));
$total_fpages = round(intval($f['files_total']) / intval($f['files_page']));
if(!$total_fpages) {
$total_fpages = 1;
}
$fpage = $f['last_page'] + 1;
$fprogress = intval(floor((intval($fpage) * 100) / $total_fpages));
$fprogress = intval(round((intval($fpage) * 100) / $total_fpages));
$fcompleted_str = t('File sync completed!');
if(argv(1) === 'resume_filesync' && $fprogress < 100) {
@@ -120,6 +121,7 @@ class Import_progress extends \Zotlabs\Web\Controller {
}
$fcompleted_str = t('File sync completed but no files were found!');
}
$fprogress_str = ((intval($fprogress)) ? $fprogress . '%' : $fprogress);
@@ -127,13 +129,15 @@ class Import_progress extends \Zotlabs\Web\Controller {
if(is_ajax()) {
$ret = [
'cprogress' => $cprogress,
'fprogress' => $fprogress
'ccompleted_str' => $ccompleted_str,
'fprogress' => $fprogress,
'fcompleted_str' => $fcompleted_str
];
json_return_and_die($ret);
}
$o = replace_macros(get_markup_template("import_progress.tpl"), [
return replace_macros(get_markup_template('import_progress.tpl'), [
'$chtitle_str' => t('Channel clone status'),
'$ctitle_str' => t('Item sync status'),
'$ftitle_str' => t('File sync status'),
@@ -147,8 +151,6 @@ class Import_progress extends \Zotlabs\Web\Controller {
'$resume_str' => t('Resume'),
'$resume_helper_str' => t('Only resume if sync stalled!')
]);
return $o;
}
}

View File

@@ -310,9 +310,9 @@ class Invite extends Controller {
function get() {
// zai1
$channel_id = local_channel();
if(! local_channel()) {
if ($channel_id === false || $channel_id < 1) {
notice( 'ZAI0101E,' . t('Permission denied.') . EOL);
return;
}
@@ -330,15 +330,15 @@ class Invite extends Controller {
return $o;
}
// invitation_by_user may still not configured, the default 'na' will tell this
// if configured, 0 disables invitations by users, other numbers are how many invites a user may propagate
$invuser = Config::Get('system','invitation_by_user', 'na');
$ihave = $this->count_invites_by_user($channel_id);
// if the mortal user drives the invitation
If (! is_site_admin()) {
// when not configured, 4 is the default
$invuser = ($invuser === 'na') ? 4 : $invuser;
if (is_site_admin()) {
// Admins have unlimited invites
$invuser = '∞';
} else {
// invitation_by_user may still not configured, the default 'na' will tell this
// if configured, 0 disables invitations by users, other numbers are how many invites a user may propagate
$invuser = Config::Get('system','invitation_by_user', 4);
// a config value 0 disables invitation by users
if (!$invuser) {
@@ -350,12 +350,6 @@ class Invite extends Controller {
notice( 'ZAI0105W,' . t('You have no more invitations available') . EOL);
return '';
}
} else {
// general deity admin invite limit infinite (theoretical)
if ($invuser === 'na') Config::Set('system','invitation_by_user', 4);
// for display only
$invuser = '∞';
}
// xchan record of the page observer
@@ -394,17 +388,6 @@ class Invite extends Controller {
}
}
if ($wehave > $invmaxau) {
if (! is_site_admin()) {
$feedbk .= 'ZAI0200E,' . t('All users invitation limit exceeded.') . $eol;
}
}
// let see how many invites currently used by the user
$r = q("SELECT count(reg_id) AS n FROM register WHERE reg_vital = 1 AND reg_byc = %d",
intval(local_channel()));
$ihave = $r ? $r[0]['n'] : 0;
$tpl = get_markup_template('invite.tpl');
$inv_rabots = array(
@@ -420,11 +403,11 @@ class Invite extends Controller {
'field' => array(
'name' => 'expire',
'title' => t('duration up from now'),
'value' => ($invexpire_n ? $invexpire_n : 2),
'value' => 2,
'min' => '1',
'max' => '99',
'size' => '2',
'default' => ($invexpire_u ? $invexpire_u : 'd')
'default' => 'd',
),
'rabot' => $inv_rabots
)
@@ -583,5 +566,18 @@ class Invite extends Controller {
}
return false;
}
/**
* Find how many invites the given channel is currently using.
*
* @param int $channel_id The id of the channel
*
* @return int Number of invites this channel is currently using.
*/
private function count_invites_by_user(int $channel): int {
$r = q("SELECT count(reg_id) AS n FROM register WHERE reg_vital = 1 AND reg_byc = %d", $channel);
return $r ? $r[0]['n'] : 0;
}
}

File diff suppressed because it is too large Load Diff

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