Compare commits

...

589 Commits
5.0.2 ... 5.4.2

Author SHA1 Message Date
Mario
0ebb1f685f version 5.4.2 2021-03-15 08:55:46 +00:00
Mario
805a25eb62 more changelog
(cherry picked from commit 268464ccde)
2021-03-15 08:54:16 +00:00
Mario
4ca12afc9d changelog
(cherry picked from commit cb74de7472)
2021-03-15 08:54:05 +00:00
Mario
6cfa2572a8 do not parse bbcode in summary - issue #1532 2021-03-15 08:50:53 +00:00
Mario
04ec986bf7 cleanup
(cherry picked from commit 0fbd0ca416)
2021-03-15 08:50:29 +00:00
Max Kostikov
ee453c4acc Fix plurals variable 2021-03-15 08:50:13 +00:00
Mario
4d3524ba9d mod subthread issue continued
(cherry picked from commit b6d30f6734)
2021-03-15 08:49:53 +00:00
Mario
29beea28c2 fix mod subthread for zot6
(cherry picked from commit 22d769ecae)
2021-03-15 08:48:40 +00:00
Mario
e2a289d614 truncate too long text
(cherry picked from commit 1582b8bc96)
2021-03-15 09:43:18 +01:00
Mario
59d3483a06 save the rewritten llink
(cherry picked from commit db0e1c9f31)
2021-03-15 09:43:08 +01:00
Mario
a99161abdf if rewriting the mid also rewrite the llink
(cherry picked from commit 260c518562)
2021-03-15 09:42:56 +01:00
Mario
79d48dc92b fix mod display query
(cherry picked from commit b51049227f)
2021-03-15 09:42:41 +01:00
Mario Vavti
82192d1ead a possible fix for issue #1529
(cherry picked from commit 7ee495624e)
2021-03-09 21:40:43 +01:00
Mario
64bbbc8053 Version 5.4.1 2021-03-09 19:07:33 +00:00
Mario Vavti
4d3d868d19 changelog
(cherry picked from commit 45cc2d7bd8)
2021-03-09 19:58:40 +01:00
Max Kostikov
011342ac1b Fix undefined page end on non dynamic pages
(cherry picked from commit 182dec3e57)
2021-03-09 12:14:38 +01:00
Max Kostikov
5577383a48 Fix Spanish plural expression
(cherry picked from commit f952d65cfd)
2021-03-09 12:13:22 +01:00
Mario
dc336010db type submit should not be type button
(cherry picked from commit b09cbb72fb)
2021-03-09 12:12:53 +01:00
Mario
88fbeaddb0 fix unexpected trigger of buttons when pressing enter in input field issue #1528
(cherry picked from commit d57f4a9527)
2021-03-09 12:12:20 +01:00
Mario
7612d8246e fix summary not saved in browser autosave draft
(cherry picked from commit 8d26961639)
2021-03-09 12:11:39 +01:00
Mario
53bb16e799 fix summary not reset on cancel
(cherry picked from commit 0932d2a0a6)
2021-03-09 12:11:09 +01:00
Mario
ed04104250 fix profile not found if not logged in
(cherry picked from commit ed981ec8e8)
2021-03-09 12:10:27 +01:00
mjfriaza
97e483d684 Update Spanish 2021-03-08 10:26:38 +00:00
Mario
951e9c8c4f Merge branch '5.4RC' 2021-03-08 09:31:23 +00:00
Mario
89415e1731 release 5.4 2021-03-08 09:26:50 +00:00
Mario
f9ab020d1d Merge branch '5.4RC' of https://framagit.org/hubzilla/core into 5.4RC 2021-03-08 09:23:11 +00:00
Mario
1828ef6b68 changelog 2021-03-08 09:21:22 +00:00
Mario
4903d7b1e9 update sbom
(cherry picked from commit c67fdd9480)
2021-03-06 18:56:53 +01:00
Mario
c67fdd9480 update sbom 2021-03-06 17:55:24 +00:00
Mario
9b5979c83a fix varable name and more changelog
(cherry picked from commit 7460b1eecb)
2021-03-06 09:51:45 +01:00
Mario
7460b1eecb fix varable name and more changelog 2021-03-06 08:50:36 +00:00
Mario
7d03ff2043 sse_bs: if Enotify::format() returns an empty array do not add it to notifications (the item has probably been blocked)
(cherry picked from commit 1da494a2a5)
2021-03-05 09:26:30 +01:00
Mario
1da494a2a5 sse_bs: if Enotify::format() returns an empty array do not add it to notifications (the item has probably been blocked) 2021-03-05 08:15:41 +00:00
Mario
00ccafc90d more changelog
(cherry picked from commit e0c619519f)
2021-03-04 12:21:27 +01:00
Mario
b767e7ddec even more changelog
(cherry picked from commit 31da1362de)
2021-03-04 12:20:56 +01:00
Mario
31da1362de even more changelog 2021-03-04 11:19:23 +00:00
Mario
e0c619519f more changelog 2021-03-04 10:13:48 +00:00
Mario
f1f1e56f87 revert revert isset()
(cherry picked from commit 33e4b6db72)
2021-03-04 10:53:29 +01:00
Mario
33e4b6db72 revert revert isset() 2021-03-04 09:52:54 +00:00
Mario
1eae7b92d1 revert isset() 2021-03-04 09:50:03 +00:00
Mario
5b7a10401f version 5.4RC2 2021-03-04 09:48:19 +00:00
Mario
1b8c5b9727 changelog
(cherry picked from commit 548936c6ca)
2021-03-04 10:46:56 +01:00
Mario
548936c6ca changelog 2021-03-04 09:45:51 +00:00
Max Kostikov
7beb500fb4 Check if custom CSP is set 2021-03-04 08:36:20 +00:00
Mario
9c110e7b9b revert isset 2021-03-04 08:20:16 +00:00
Mario
129f8107d3 merge conflict 2021-03-04 08:17:07 +00:00
Mario
cb01996039 Merge branch 'dev' into 'dev'
Fix frame-src CSP error on video embedding

See merge request hubzilla/core!1918
2021-03-04 08:05:27 +00:00
Max Kostikov
33b738d00b Fix frame-src CSP error on video embedding 2021-03-04 08:05:26 +00:00
Mario
c2dc3e8dec set the default collection acl if indicated so by the role permissions but always set the created friends group as channel_default_group when creating a new channel
(cherry picked from commit 9389abdb75)
2021-03-03 14:12:42 +01:00
Mario
7d1599f9b0 group_add(): return hash if success
(cherry picked from commit f8f15f526f)
2021-03-03 14:11:54 +01:00
Mario
3d264f5a55 php8: fix warnings during install procedure
(cherry picked from commit 48bae9d421)
2021-03-03 14:11:29 +01:00
Mario
9389abdb75 set the default collection acl if indicated so by the role permissions but always set the created friends group as channel_default_group when creating a new channel 2021-03-03 14:09:17 +01:00
Mario
f8f15f526f group_add(): return hash if success 2021-03-03 13:44:38 +01:00
Mario
48bae9d421 php8: fix warnings during install procedure 2021-03-03 13:39:41 +01:00
Mario
55b4eb7b22 version 5.4RC1 2021-02-26 10:15:56 +00:00
Mario
fbb1d6aa41 Merge branch 'dev' into 'dev'
Do not overwrite HTTP schema for Youtube on embedding

See merge request hubzilla/core!1917
2021-02-26 09:03:58 +00:00
Max Kostikov
5440a65607 Do not overwrite HTTP schema for Youtube on embedding 2021-02-25 16:35:19 +00:00
Mario
36c9f9abff Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2021-02-25 15:43:13 +00:00
Mario
8295ccdda7 a possible fix for #1518 2021-02-25 15:43:01 +00:00
Mario
65892ba555 Merge branch 'dev' into 'dev'
small adjustment

See merge request hubzilla/core!1915
2021-02-25 15:10:41 +00:00
Zot
78938df133 small adjustment 2021-02-25 15:10:41 +00:00
Mario
ac6dec91f1 Merge branch 'dev' into 'dev'
Enable multimedia in podcasts

See merge request hubzilla/core!1916
2021-02-25 15:09:31 +00:00
Mario
373612a046 do not poll feeds if feed_contacts are not allowed 2021-02-25 15:05:49 +00:00
Mario
c1afa306c9 fix logic 2021-02-25 14:15:13 +00:00
Mario
65a20a780d bump version 2021-02-25 12:56:57 +00:00
Mario
b29e121113 replace sticky_kit with a simpler homwgrown solution (still a bit raw) and slightly change the way we load new content so that people with a long aside column do not have to scroll all the way to the bottom for loading the next page 2021-02-25 12:55:19 +00:00
Michal Klodner
f45ebfa223 - Enable enclosures in Atom/RSS (podcasts)
- Remove checking of audio/video URLs for pattern at the end
2021-02-24 21:03:05 +00:00
Mario
a033c439f3 zap compat export fixes 2021-02-24 10:19:15 +00:00
Mario
66e4bc327f Merge branch 'dev' into 'dev'
export compatibility from hubzilla to zap

See merge request hubzilla/core!1910
2021-02-24 08:35:30 +00:00
Zot
df362e4f81 export compatibility from hubzilla to zap 2021-02-24 08:35:29 +00:00
Max Kostikov
82ee980172 Merge branch 'dev' into 'dev'
Update Russian translation

See merge request hubzilla/core!1912
2021-02-23 12:33:17 +00:00
Max Kostikov
463a8d338e Update hmessages.po 2021-02-23 12:29:02 +00:00
Max Kostikov
d074bb65da Update Russian hstrings.php 2021-02-23 12:26:20 +00:00
Max Kostikov
b7c411470b Update Russian hmessages.po 2021-02-23 12:24:59 +00:00
Max Kostikov
e09e6c5524 Missprint 2021-02-23 12:22:19 +00:00
Mario
fa73c8d15e bump dev version to 5.5 2021-02-23 10:57:37 +00:00
Mario
6060ca127b composer dump-autoload 2021-02-23 10:54:27 +00:00
Mario
ca4e0351cf update strings 2021-02-23 10:52:38 +00:00
Mario
f3be2ecc9d version 5.4RC 2021-02-23 10:48:47 +00:00
Mario
135305d975 Merge branch 'dev' into 'dev'
Rename photo storage type system variable

See merge request hubzilla/core!1911
2021-02-23 10:02:16 +00:00
Max Kostikov
34aa8ba3cc Rename photo storage type system variable 2021-02-23 10:02:15 +00:00
Mario
28fe91dfa7 Merge branch 'dev' of https://codeberg.org/hubzilla/hubzilla into dev 2021-02-23 09:53:12 +00:00
mjfriaza
883b519714 Update Spanish version 2021-02-23 09:52:24 +00:00
hubzilla
9dae590c64 Merge pull request 'Update Spanish version' (#4) from mjfriaza/hubzilla:dev into dev
Reviewed-on: https://codeberg.org/hubzilla/hubzilla/pulls/4
2021-02-23 10:49:21 +01:00
Mario
d4159e8333 streamline iconf names and make sure to save the correct data 2021-02-22 10:32:05 +00:00
Max Kostikov
90d04082a1 Fix missprint 2021-02-21 14:13:46 +01:00
Max Kostikov
a84c7271f2 Formatting 2021-02-20 14:49:31 +01:00
Max Kostikov
f46ddf2273 Bump DB version 2021-02-20 14:47:50 +01:00
Max Kostikov
b401869d30 Rename photo storage type system variable 2021-02-20 14:47:14 +01:00
Max Kostikov
cc55716879 Merge branch 'dev' into 'dev'
Dev sync

See merge request kostikov/core!1
2021-02-20 13:39:54 +00:00
Mario
ddad4f604b provide raw base64 encoded crypto 2021-02-19 17:37:53 +00:00
Mario
dc553ab309 summary edit actions 2021-02-19 10:24:20 +00:00
Mario
a2d170385b deprecate summary tag in favour of a separate input field 2021-02-19 10:11:24 +00:00
Mario
a275726988 update site once a day 2021-02-19 09:26:39 +00:00
Mario
863d4d83a1 fix recursive shares 2021-02-19 07:41:29 +00:00
Mario
d50381c9c6 fix summary regex after recent bbcode chane 2021-02-18 20:36:56 +00:00
Mario
c9bbe1a735 adjust error reporting for php8 to not report warnings - they are too many 2021-02-18 20:04:34 +00:00
Mario
18b9d1efd8 this setting is probably not required anymoreà 2021-02-18 20:00:20 +00:00
Mario
85f1845d15 fix usage of null coalescing operator 2021-02-18 19:46:26 +00:00
Mario
c34fc416a2 php8 warnings 2021-02-18 19:32:45 +00:00
Mario
7794ee5a88 php8 warnings 2021-02-18 13:32:02 +00:00
Mario
65068479b9 php8 warnings 2021-02-18 13:29:15 +00:00
mjfriaza
655ae9d1cd Merge branch 'dev' into dev 2021-02-18 13:28:05 +01:00
mjfriaza
76163fc37b Update Spanish version 2021-02-18 13:22:57 +01:00
Mario
92f3c5ae21 backward compatibility with recent crypto changes 2021-02-18 09:36:22 +00:00
Mario
c3ec5d4d6a do not try to fetch legacy zot zotfeed - they will not return anything useful 2021-02-17 20:16:20 +00:00
Mario
0aeb4d6fb5 php8: fix mod mail if there are no messages 2021-02-17 19:41:27 +00:00
Mario
edd4ac791f remove logging 2021-02-17 18:15:09 +00:00
Mario
27577824de fix php8 issue in include/oembed and unencapsulate for zot_refresh() 2021-02-17 18:14:29 +00:00
Mario Vavti
281b2261af reduce loglevel until the most glaring php8 issues will be resolved 2021-02-16 14:35:01 +01:00
Mario
3eaf0b7f23 php8 another fix 2021-02-16 12:56:34 +00:00
Mario
76ad2c0fa4 php8 fix 2021-02-16 12:41:27 +00:00
Mario
efaadf54d3 make sure we do not try to update columns which do not exist 2021-02-16 09:21:55 +00:00
Mario
6f71c6d950 fix detection of multiline codeblocks after recent change to bbcode() 2021-02-15 19:18:49 +00:00
Mario
ad0b0364b8 missing files 2021-02-15 18:42:21 +00:00
Mario
e8c2e17bc9 compser update twbs/bootstrap 2021-02-15 18:41:44 +00:00
Mario
6fae291cc8 missing file 2021-02-15 18:40:00 +00:00
Mario
1e48be7ab7 compser update symfony/polyfill-ctype 2021-02-15 18:39:11 +00:00
Mario
0cd4c34101 compser update sabre/dav /vobject 2021-02-15 18:35:40 +00:00
Mario
02401ea9fd composer update ramsey/collection 2021-02-15 18:29:24 +00:00
Mario
18c8f1b903 composer update brick/math 2021-02-15 18:27:20 +00:00
Mario
4171a0136a revert debug code 2021-02-15 18:25:04 +00:00
Mario
ba29a6ce4d composer update smarty 2021-02-15 18:23:26 +00:00
Mario
d72a096fa5 fix preview generating duplicate IDs 2021-02-15 10:15:57 +00:00
Mario
ed99392001 move substitution of new lines with <br> to the end of bbcode(). This will fix issue #1512. 2021-02-15 08:20:42 +00:00
Mario
50e9a12ca5 Merge branch 'fix-public-permissions-in-display' into 'dev'
FIX: Display urls won't show to permitted remote observers

See merge request hubzilla/core!1909
2021-02-14 16:16:26 +00:00
M. Dent
d6b259bb27 FIX: Display urls won't show to permitted remote observers 2021-02-14 17:16:25 +01:00
Mario
f94b046333 changelog
(cherry picked from commit 5e8e6dc458)
2021-02-13 21:23:04 +01:00
Mario
5e8e6dc458 changelog 2021-02-13 20:20:46 +00:00
Mario
9751efb709 version 5.2.2 2021-02-13 21:17:13 +01:00
Mario
7b2f53cc69 fix ping_site() issue
(cherry picked from commit 22e0175ab7)
2021-02-13 21:15:49 +01:00
Mario
22e0175ab7 fix ping_site() issue 2021-02-13 19:30:15 +00:00
Mario
0ffb09aa40 onepoll: add date_begin argument to poll url 2021-02-11 21:05:45 +00:00
Mario
8054d7ad66 remove logging 2021-02-11 21:01:16 +00:00
Mario
d3e70acacd make encode_item_collection() deal with extra query args 2021-02-11 21:00:10 +00:00
Mario
6f520cadb7 actor will be stored in the next step decode_note() 2021-02-11 11:13:06 +00:00
Mario
becdd64257 update 1242 2021-02-10 20:59:30 +00:00
Mario
464a0634d6 use (un)obscurify 2021-02-10 20:40:28 +00:00
Mario
391db61629 revert z_(un)obscure() until (un)obscurify() will be implemented and a update will take care of the data in db 2021-02-10 19:27:00 +00:00
Mario
e6450acc03 version 2021-02-09 19:13:32 +00:00
Mario
e75ae17662 whitespace 2021-02-09 14:09:26 +00:00
Mario
3b3c93f9b3 undo accidental revert in last commit 2021-02-09 14:05:00 +00:00
Mario
b4693870ba port Lib/Crypto from zap 2021-02-09 13:50:03 +00:00
Mario
5aee2f172e restructure keyutiÃls tests 2021-02-08 20:05:05 +00:00
Mario
6b8b42fb21 fix line separators 2021-02-08 16:16:56 +00:00
Mario
320e95aaae composer 2021-02-08 16:08:31 +00:00
Mario
1bcf84f275 fix test 2021-02-08 16:04:56 +00:00
Mario
a8e0bd1f12 keyutils tests 2021-02-08 13:37:48 +00:00
Mario
eb05e5a205 revert include/crypto to its previous state for reference - we are now using Lib/Keyutils for key conversion 2021-02-08 10:55:35 +00:00
Mario
d316d9436b mixed up variables 2021-02-08 10:17:05 +00:00
Max Kostikov
b2e4a4b2b1 Merge branch 'dev' into 'dev'
Use datetime interval in public tag cloud query to support queueworker deduplication

See merge request hubzilla/core!1908
2021-02-06 10:41:33 +00:00
Max Kostikov
e1d622c49f Use datetime interval in public tag cloud query to support queueworker deduplication 2021-02-06 11:36:22 +01:00
Max Kostikov
8bb77bcfd6 Fix new Imagemagick object 2021-02-05 15:32:09 +01:00
Mario Vavti
a9070382e7 bump version 2021-02-04 22:26:29 +01:00
Mario Vavti
9e22641425 add Lib/Keyutils 2021-02-04 22:20:55 +01:00
Mario Vavti
19007dd8eb move key conversion to separate lib 2021-02-04 22:16:48 +01:00
Mario Vavti
03e1f5f8a4 remove unused function 2021-02-04 21:49:25 +01:00
Mario Vavti
6bb73e14b6 key conversion functions cleanup 2021-02-04 21:31:37 +01:00
Mario Vavti
41f84dabcc use phpseclib for key transformations 2021-02-04 21:21:22 +01:00
Mario Vavti
cd79d12e5b phpseclib missing files 2021-02-04 21:05:17 +01:00
Mario Vavti
a6162d3134 downgrade phpseclib to version 2 2021-02-04 21:01:25 +01:00
Mario Vavti
34b28cd8d3 fix wrong operand 2021-02-03 10:22:34 +01:00
Mario Vavti
9a170791e4 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2021-02-03 10:12:02 +01:00
Mario
44b559fb1d Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2021-02-02 12:58:01 +00:00
Mario
2167d12b3f composer add phpseclib 2021-02-02 12:57:46 +00:00
Mario Vavti
e312c381d8 import_xchan() $arr photo structure has changed 2021-02-02 11:47:38 +01:00
Mario Vavti
af6f7f244e Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2021-02-02 10:58:28 +01:00
Mario Vavti
f3f49cf80f fix php8 issues 2021-02-02 10:58:10 +01:00
Mario
08c9152abd fix getting mimetype via getimagesize() and do not default to image/jpeg yet if it could not be found 2021-02-01 22:58:55 +00:00
Mario
70fa7ad8d0 too many arguments 2021-02-01 20:52:35 +00:00
Mario
cd081ac077 remove unused/commented out code 2021-02-01 14:32:28 +00:00
Mario
197338a727 remove logging 2021-02-01 09:30:22 +00:00
Mario
61e7791d31 Merge branch 'dev' into 'dev'
Better profile photo fetch processing

See merge request hubzilla/core!1906
2021-02-01 08:53:10 +00:00
Max Kostikov
de91d2c804 Better profile photo fetch processing 2021-02-01 09:53:09 +01:00
Mario
11f5550512 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2021-01-31 20:37:29 +00:00
Mario
d99611e7dd add fetch_provider hook 2021-01-31 20:37:16 +00:00
Max Kostikov
c0933c90e8 Fix copypaste 2021-01-31 15:26:55 +01:00
Max Kostikov
21b3ba38e7 Fix polish plurals function 2021-01-31 12:05:02 +01:00
Max Kostikov
bac87a8aec Fix polish plurals function 2021-01-31 12:04:26 +01:00
Max Kostikov
a235917d48 Merge branch 'translation-pl' into 'dev'
New fixes & translations

See merge request hubzilla/core!1907
2021-01-30 18:40:37 +00:00
Andrzej Budziński
d2eb10d7ff Fixes (!1905):
- view/pl/hmessages.po
- view/pl/hstrings.php
2021-01-30 18:42:47 +01:00
Andrzej Budziński
89bf71b227 New fixes & translatosns:
- doc/pl/tutorials/*: 100%
- doc/pl/checking_account_guota_usage.bb: 100%
- doc/pl/member/member_guide.bb: fixes
- doc/pl/admin/hub_snapshots.md: fixes
- view/pl/hmessage.po: fixes
- view/pl/hstrings.po: fixes to generated code
2021-01-30 14:03:39 +01:00
Mario
7686b48723 code format only 2021-01-29 07:36:56 +00:00
Mario
840dbbe8ba code format only 2021-01-28 15:50:34 +00:00
Mario
ab4863a2e0 AS discovery for mod profile 2021-01-28 15:44:57 +00:00
Mario
8c2442eca5 AS channel discovery with custom access header 2021-01-28 14:57:37 +00:00
Mario Vavti
8b78e18fb8 keep file permissions in util folder at 755 2021-01-27 11:56:58 +01:00
Mario
66640a206e fix issue in view/pl/hstrings.php 2021-01-27 10:35:17 +00:00
Mario
15c90371e0 Merge branch 'customjotheaders' into 'dev'
Custom "headers" in item creation form.

See merge request hubzilla/core!1901
2021-01-27 10:25:26 +00:00
M. Dent
00fe7bb1bb Custom "headers" in item creation form. 2021-01-27 11:25:26 +01:00
Mario
a2728167bc Merge branch 'dev' into 'dev'
Rebuild public tags cloud not often than once per 5 mins.

See merge request hubzilla/core!1900
2021-01-27 10:23:59 +00:00
Max Kostikov
6326605c99 Revert "Fix directory permissions on create"
This reverts commit 85c5e1178a57865ad977c260725da2839ebb4d98
2021-01-27 11:23:59 +01:00
Mario
7cd4f60922 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2021-01-27 10:15:37 +00:00
Mario
af719fea40 fix file permissions. 755 for dirs, 644 for files 2021-01-27 10:15:26 +00:00
Max Kostikov
0af458768f Fix wrong redbasic theme permissions 2021-01-27 12:14:30 +02:00
Mario
3ba46873ba Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2021-01-27 09:59:40 +00:00
Mario
f4cc91f0f5 Merge branch 'translation-pl' into 'dev'
Translation pl

Polish translations (used on hub.hubzilla.pl)
- view/pl: 100%
- doc/pl: ~40%
- doc/context/pl: 100%
- doc/macros/pl: 100%

See merge request hubzilla/core!1902
2021-01-27 09:57:30 +00:00
Andrzej S. Budziński
f813671b67 Merge branch 'translation-pl' into 'dev'
Translation pl

Polish translations (used on hub.hubzilla.pl)
- view/pl: 100%
- doc/pl: ~40%
- doc/context/pl: 100%
- doc/macros/pl: 100%

See merge request hubzilla/core!1902
2021-01-27 10:57:30 +01:00
Mario
74f8f2d956 thread listener improvements 2021-01-26 12:11:01 +00:00
Mario
f0ee4c3cef port fix from zap: catch a complex edge case where some public stream comments were not being delivered and should have been 2021-01-26 10:35:24 +00:00
Mario
6878445319 use mail envelope instead of lock icon for direct messages 2021-01-26 10:29:03 +00:00
Mario
de34dac6cc port youtube embed fix from zap 2021-01-26 09:56:28 +00:00
Mario
1c8d298f3f Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2021-01-26 09:21:21 +00:00
Mario
777af6e7ad Libzot::fetch_conversation() fixes 2021-01-26 09:21:16 +00:00
Mario Vavti
82dbdf7c70 fix issues in Activity::encode_item_collection() after recent changes 2021-01-26 10:07:41 +01:00
Mario Vavti
4cf05891d7 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2021-01-25 21:52:29 +01:00
Mario Vavti
d4198223bc invoke channel discovery by hash instead of address and add thread listeners only if we also send them the post 2021-01-25 21:52:17 +01:00
Mario
1b4bbcc891 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2021-01-25 20:28:03 +00:00
Mario
0e9d99c603 expose manual public item import from searchbar, set commen_policy in Activity::store() to what we get if we get something otherwise default to authenticated, comments by the owner have the relay flag set and therefor $perm will be not be set to post_comments - always check if we own the parent in lib/libzot (not only if $perm = send_stream) if otherwise not allowed 2021-01-25 20:27:50 +00:00
Charlie Root
3ed444b4b4 Run storageconv from web server user 2021-01-25 18:35:28 +02:00
Mario
77793e17c0 Merge branch 'dev' into 'dev'
Add support filesystem storage for xchan profile photos

See merge request hubzilla/core!1898
2021-01-24 20:03:35 +00:00
Max Kostikov
552796286e Add support filesystem storage for xchan profile photos 2021-01-24 21:03:34 +01:00
Mario
e486442eb1 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2021-01-24 19:55:50 +00:00
Mario
2035828042 revert externals/zotfeed functionality due to scaling issues. Save zotfeed consumers that are not our contacts in thread listeners 2021-01-24 19:55:29 +00:00
Mario
4fbedb6750 extra check for item_private in fetch_and_store_parents() 2021-01-24 15:00:01 +00:00
Max Kostikov
6b0c61ac6b Merge branch 'dev' into 'dev'
Variable typo

See merge request hubzilla/core!1897
2021-01-23 20:57:47 +00:00
Max Kostikov
0a13c794ab Variable typo 2021-01-23 21:55:50 +01:00
Max Kostikov
a53f286467 Merge branch 'dev' into 'dev'
Don't fetch profile photos from own hub

See merge request hubzilla/core!1896
2021-01-23 20:47:06 +00:00
Max Kostikov
e4ed5ed264 Do not store multiple profile images thumbnails 2021-01-23 21:45:20 +01:00
Max Kostikov
74441f2f00 Don't fetch profile photos from own hub 2021-01-23 21:38:03 +01:00
Max Kostikov
007de17702 Merge branch 'dev' into 'dev'
Bump DB update version

See merge request hubzilla/core!1895
2021-01-23 15:24:44 +00:00
Max Kostikov
ecf2e4e0ee Bump DB update version 2021-01-23 16:22:29 +01:00
Max Kostikov
03910453a9 Merge branch 'dev' into 'dev'
Dev sync

See merge request kostikov/core!3
2021-01-23 13:07:09 +00:00
Max Kostikov
30962dadbf Merge branch 'dev' into 'dev'
# Conflicts:
#   Zotlabs/Daemon/Cache_query.php
#   include/contact_widgets.php
#   include/taxonomy.php
2021-01-23 14:04:42 +01:00
Max Kostikov
33951dc1e4 Remove duplicated profile photos 2021-01-23 14:00:38 +01:00
Max Kostikov
893847c649 Fix duplicate profile photos creation for clones 2021-01-23 13:58:05 +01:00
Mario
fbbc53838c fix ramsey/uuid exception 2021-01-23 12:35:02 +00:00
Max Kostikov
7bc0340106 Encode SQL query array 2021-01-22 15:39:48 +01:00
Max Kostikov
bfb9f10234 Encode SQL query array 2021-01-22 15:38:40 +01:00
Max Kostikov
3f34c73f09 Decode SQL query array 2021-01-22 15:37:49 +01:00
Mario
92f420f77c cleanup 2021-01-22 10:42:58 +00:00
Mario Vavti
78716c42d6 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2021-01-22 11:16:43 +01:00
Mario Vavti
e6aed4fb8e implement externals via zot6 and zotfeed - part 2 2021-01-22 11:12:39 +01:00
Mario
064effe5fd fix encode_item_collection() 2021-01-22 10:11:27 +00:00
Mario
93ac3c985f implement externals via zot6 and zotfeed - part 1 2021-01-22 10:06:50 +00:00
Mario
fe97b63e0b Merge branch 'dev' into 'dev'
Implement SQL query background caching

See merge request hubzilla/core!1894
2021-01-21 09:08:53 +01:00
Max Kostikov
3836e75c89 Implement SQL query background caching 2021-01-21 09:08:53 +01:00
Max Kostikov
28ae78c579 Higher log level 2021-01-21 08:16:15 +01:00
Mario
bdd6d878f1 cleanup lib/libsync 2021-01-21 07:09:19 +00:00
Max Kostikov
8134e9cae0 Process channel categories list in background 2021-01-20 22:28:38 +01:00
Max Kostikov
70ee41f252 Process public tags cloud in background 2021-01-20 22:24:00 +01:00
Max Kostikov
491dffd9b7 Implement SQL query background caching 2021-01-20 22:18:27 +01:00
Max Kostikov
ad42890a0b Swap key and cat for running pid tracking 2021-01-20 22:15:01 +01:00
Mario
5a971a3731 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2021-01-20 21:14:29 +00:00
Max Kostikov
ab4455c54c Merge branch 'dev' into 'dev'
Dev sync

See merge request kostikov/core!2
2021-01-20 22:12:15 +01:00
Max Kostikov
6cca06f641 Merge branch 'dev' into 'dev'
Use Zot6 on pinned content sync between clones

See merge request hubzilla/core!1893
2021-01-20 22:09:21 +01:00
Mario
c5d37a0831 remove logging 2021-01-20 20:43:51 +00:00
Mario
57645386b2 looks like we get arrays or json strings here for some reason 2021-01-20 20:42:59 +00:00
Mario
b242347fa1 onepoll via zot6 to /zotfeed which implements an outbox 2021-01-20 20:17:50 +00:00
Max Kostikov
15b2aa660b Update Pin.php 2021-01-20 13:53:09 +01:00
Max Kostikov
4da4f2367f Use Zot6 on pinned content sync between clones 2021-01-20 13:18:48 +01:00
Max Kostikov
9612a69a64 Merge branch 'dev' into 'dev'
Dev sync

See merge request kostikov/core!1
2021-01-20 13:15:40 +01:00
Mario
4e9d8e1a83 fix abandon days setting for onepoll 2021-01-18 21:10:59 +00:00
Mario
6083bfea2f lib/activity cleanup and remove unused code - requires addon update 2021-01-18 20:39:23 +00:00
Mario
08264f8d11 more cleanup daemon/thumbnail 2021-01-18 14:35:40 +00:00
Mario
8b93136773 more cleanup daemon/queue 2021-01-18 14:35:00 +00:00
Mario
c7a82a6a84 more cleanup daemon/poller 2021-01-18 14:33:19 +00:00
Mario
ef67e18161 more cleanup daemon/onepoll 2021-01-18 14:29:01 +00:00
Mario
08d2fb4ed4 more cleanup daemon/onedirsync 2021-01-18 14:24:44 +00:00
Mario
836637621d more cleanup daemon/notifier 2021-01-18 14:23:23 +00:00
Mario
6e7a2d0d96 more cleanup daemon/master 2021-01-18 14:13:58 +00:00
Mario
101005f3d2 more cleanup daemon/importfile 2021-01-18 14:11:29 +00:00
Mario
8f88543478 more cleanup daemon/importdoc 2021-01-18 14:10:38 +00:00
Mario
f1ac5bb667 more cleanup daemon/gprobe 2021-01-18 14:09:48 +00:00
Mario
8e5df2dd22 more cleanup daemon/externals 2021-01-18 14:08:31 +00:00
Mario
441525750f more cleanup daemon/expire 2021-01-18 14:02:37 +00:00
Mario
9acfc44ac9 cleanup daemon/expire 2021-01-18 14:00:21 +00:00
Mario
d5bd09b983 cleanup daemon/deliver_hooks, daemon/directory 2021-01-18 13:49:58 +00:00
Mario
45350179b4 cleanup daemon/deliver 2021-01-18 13:41:34 +00:00
Mario
d0f3d2b2a5 cleanup daemon/curlauth 2021-01-18 13:40:01 +00:00
Mario
3742fe80fc only var can be passed by reference, cleanup 2021-01-18 13:37:54 +00:00
Mario
e191966e69 only var can be passed by reference, cleanup 2021-01-18 13:36:47 +00:00
Mario
2c8e122008 cleanup daemon/checksites 2021-01-18 13:29:48 +00:00
Mario
2729f466d5 cleanup 2021-01-18 13:23:29 +00:00
Mario
f4b71fbec1 cleanup 2021-01-18 13:21:13 +00:00
Mario
6695225492 cleanup 2021-01-18 13:08:13 +00:00
Mario
4f74d1d877 cleanup 2021-01-18 13:00:39 +00:00
Mario
bee84e9b00 whitespace 2021-01-18 12:56:07 +00:00
Mario
faaa2d4472 $match should be array 2021-01-18 11:21:37 +00:00
Mario
917c6caa14 force arg is not used anymore in drop_item_lolevel() 2021-01-18 08:46:37 +00:00
Mario
cd59c67c67 fix undefined variable 2021-01-18 08:43:08 +00:00
Mario
37f1b774b7 missing import 2021-01-17 15:19:00 +00:00
Mario
828636847e get_item_elements() check against zot6 2021-01-17 14:13:31 +00:00
Mario
06b5f71075 port util/connect to Lib/Connect 2021-01-17 14:06:35 +00:00
Mario
8d37a4239a mark_orphan_hubsxchans() check against zot6 2021-01-17 13:56:23 +00:00
Mario
a925b08e80 get_bookmark_link() check against zot6 2021-01-17 13:52:55 +00:00
Mario
46aefd8883 fix fetch vcard menu entry for zot6 connections 2021-01-17 13:41:27 +00:00
Mario
38a48de826 app_render() check against zot6 2021-01-17 13:35:13 +00:00
Mario
254e30bea1 version 5.2.1 2021-01-16 10:33:46 +01:00
Mario
a16692eeb0 changelog
(cherry picked from commit 485a232ae6)
2021-01-16 10:33:13 +01:00
Mario
485a232ae6 changelog 2021-01-16 09:31:51 +00:00
Mario
d3f8118874 wrong logic
(cherry picked from commit 0d544e2294)
2021-01-16 10:18:29 +01:00
Mario
0d544e2294 wrong logic 2021-01-16 09:17:45 +00:00
Mario
cb3131a166 also check for zot6
(cherry picked from commit 3bcb322156)
2021-01-16 10:14:16 +01:00
Mario
3105f514e4 make attach_upgrade() catch entries where only display_path is missing
(cherry picked from commit 42812078c5)
2021-01-16 10:13:43 +01:00
Mario
395b427787 cleanup mod like 2021-01-16 09:09:54 +00:00
Mario
4d63c37c38 HTTPSig::get_zotfinger_key() only takes the id arg 2021-01-15 21:23:14 +00:00
Mario
a2776ade81 exec is marked deprecated 2021-01-15 21:19:07 +00:00
Mario
5f5b3f3d4c remove unused global var 2021-01-15 21:02:13 +00:00
Mario
60b76c53fc fix undefined var 2021-01-15 20:58:31 +00:00
Mario
e55ea8b126 undefined variable $filename 2021-01-15 20:52:18 +00:00
Mario
889581e35b wrong variable name 2021-01-15 20:36:48 +00:00
Mario
f7222d43c9 only vars can be passed by reference 2021-01-15 20:26:22 +00:00
Mario
1e474c9689 unused variable and missing break statement 2021-01-15 20:14:48 +00:00
Mario
50fb658776 fix undefined variable 2021-01-15 20:10:44 +00:00
Mario
dde0f3a403 formatting 2021-01-15 20:03:49 +00:00
Mario
597d7bd532 formatting 2021-01-15 20:02:03 +00:00
Mario
aa27f93a9c cleanup unused/undefined variables 2021-01-15 20:00:47 +00:00
Mario
ae4b5231bb fix undefined vars in mod cal 2021-01-15 19:37:47 +00:00
Mario
28ef42a424 make functions public static 2021-01-15 19:31:50 +00:00
Mario
70233ea903 remove redundant import and add ext-zip to composer 2021-01-15 19:28:15 +00:00
Mario
63c15c2c8d remove redundant import 2021-01-15 19:11:14 +00:00
Mario
3e1f387b2b Receiver::run() does not take an argument 2021-01-15 19:09:27 +00:00
Mario
77c777512c fix issue in unused function 2021-01-15 19:04:20 +00:00
Mario
02059fb663 bump composer php version 2021-01-15 19:00:04 +00:00
Mario
3205429d24 more wiki issues 2021-01-15 18:57:56 +00:00
Mario
aa8eb9522f wiki issues 2021-01-15 18:55:07 +00:00
Mario
5030157246 argument must be of type boolean 2021-01-15 18:39:07 +00:00
Mario
a3bc9251bf $msg must be array 2021-01-15 18:37:08 +00:00
Mario
5a325cfa7b remove unused variables 2021-01-15 17:21:33 +00:00
Mario
583d3b5580 whitespace 2021-01-15 15:49:22 +00:00
Mario
43e3663721 fix wrong/undefined variables and add sleep interval to notifier calls 2021-01-15 15:48:17 +00:00
Mario
9f8a512eb5 only var can be passed by reference 2021-01-15 15:07:54 +00:00
Mario
3bcb322156 also check for zot6 2021-01-15 15:06:07 +00:00
Mario
1e645cabd4 style fixes 2021-01-15 15:00:53 +00:00
Mario
ee82763d45 add ext-json to composer 2021-01-15 14:47:26 +00:00
Mario
42812078c5 make attach_upgrade() catch entries where only display_path is missing 2021-01-15 10:00:13 +00:00
Mario
83f0c3d1dd some work to fix r_preview in list mode 2021-01-14 14:28:35 +00:00
Mario
e5a70744c0 update changelog
(cherry picked from commit 299c4bda1b)
2021-01-13 11:35:06 +01:00
Mario
5eefdc6485 Merge branch '5.2RC' 2021-01-13 09:50:53 +00:00
Mario
4d2bcbc583 release 5.2 2021-01-13 09:48:47 +00:00
Mario
299c4bda1b update changelog 2021-01-13 09:47:44 +00:00
Mario
f4b9291d42 Merge branch 'dev' into 5.2RC 2021-01-13 09:39:55 +00:00
Mario
b7afc905ec Revert "keyid adapt for backward compatibility to current release part 2"
This reverts commit efb8a29b5f.
2021-01-13 09:34:38 +00:00
Mario
01bd846433 Revert "keyid adapt for backward compatibility to current release"
This reverts commit ff100a499a.
2021-01-13 09:34:03 +00:00
Mario
08f717d4fc Merge branch 'dev' into 5.2RC 2021-01-13 09:01:31 +00:00
Mario
b9fd87b004 do not turn the groups own direkt messages into group items - fixes #1510 2021-01-13 08:54:58 +00:00
Mario
1615f2c79a Merge branch 'dev' into 5.2RC 2021-01-12 09:08:28 +00:00
Mario
f430db0de7 changelog 2021-01-12 09:04:32 +00:00
Mario
32eb603643 lukasreschke/id3parser is not maintained anymore. fix it so that composer dump-autoload will not complain 2021-01-12 08:52:08 +00:00
Mario
c3f387f22a more changelog 2021-01-12 08:35:22 +00:00
Mario
8703caff5f restrict length of short profile title/description to 190characters to omit sql warnings about too long string data 2021-01-12 08:25:09 +00:00
Mario
c5d50c9e47 Ãupdate changelog 2021-01-11 20:33:17 +00:00
Mario
fed4e3e03a Ãupdate changelog 2021-01-11 20:32:33 +00:00
Mario
9d1f73e179 5.2RC4 2021-01-11 19:02:26 +00:00
Mario
ba164d9488 Merge branch 'dev' into 5.2RC 2021-01-11 19:01:02 +00:00
Mario
3fe67eb646 more libzotdir
(cherry picked from commit e339e897ff)
2021-01-11 19:55:07 +01:00
Mario
12ba2c30b9 can not access global from statc method 2021-01-11 08:59:16 +00:00
Mario Vavti
7c1b41019e missing constant definition 2021-01-10 22:42:57 +01:00
Mario Vavti
707110e5a7 sync_directories() omit known dead sites 2021-01-10 21:46:31 +01:00
Mario Vavti
ba9a9cb016 undefined variable 2021-01-10 21:32:42 +01:00
Mario
c1c75c4b67 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2021-01-10 00:32:45 +00:00
Mario
0446349b89 missing use statement 2021-01-10 00:32:34 +00:00
Mario Vavti
915cb44601 typo 2021-01-09 23:06:56 +01:00
Mario
17a153fb6d Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2021-01-09 21:54:55 +00:00
Mario
e339e897ff more libzotdir 2021-01-09 21:54:41 +00:00
Mario
6b57f163bd fix markup
(cherry picked from commit 4ace4819ff)
2021-01-09 22:05:40 +01:00
Mario
4ace4819ff fix markup 2021-01-09 22:04:47 +01:00
mjfriaza
ce893122af Update Spanish translation
(cherry picked from commit c90d1fc8ef)
2021-01-09 22:02:35 +01:00
Mario
fb5188a8c6 Merge remote-tracking branch 'codeberg/dev' into dev 2021-01-09 21:01:24 +00:00
hubzilla
c17f452fc7 Merge pull request 'Update Spanish translation' (#2) from mjfriaza/hubzilla:dev into dev
Reviewed-on: https://codeberg.org/hubzilla/hubzilla/pulls/2
2021-01-09 21:59:22 +01:00
Mario
71b0f54b7a update sbom 2021-01-09 20:55:40 +00:00
Mario
d387d021fe update sbom 2021-01-09 20:54:48 +00:00
Mario
d6fefc3603 5.2RC3 2021-01-09 20:34:21 +00:00
Mario
efb8a29b5f keyid adapt for backward compatibility to current release part 2 2021-01-09 20:20:48 +00:00
Mario
ff100a499a keyid adapt for backward compatibility to current release 2021-01-09 19:57:55 +00:00
Mario
d89dc65330 remove redundant mail.apd
(cherry picked from commit 898df6287a)
2021-01-09 20:33:12 +01:00
Mario
fa41527f85 fix some php8 fatal errors
(cherry picked from commit 2522d42c71)
2021-01-09 20:32:40 +01:00
Mario
f48d844e42 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2021-01-09 19:27:46 +00:00
Mario
898df6287a remove redundant mail.apd 2021-01-09 19:27:32 +00:00
Mario
2522d42c71 fix some php8 fatal errors 2021-01-09 20:22:47 +01:00
Mario
39c5e85564 RC2 2021-01-09 15:50:57 +01:00
Mario
1294c05a91 version 2021-01-09 13:27:57 +00:00
Mario
64f802d4f6 fix error in sql query
(cherry picked from commit 0e2af40329)
2021-01-09 14:25:41 +01:00
Mario
61e782389c more streamline keyid 2021-01-09 13:24:32 +00:00
Mario
7cfb230a5e streamline keyid 2021-01-09 13:22:43 +00:00
Mario
0e2af40329 fix error in sql query 2021-01-09 13:05:31 +00:00
Mario
7f51ff0a8d set resource_type = group_item and resource_id = original mid for forum items so we do not need to query the body for the original mid on edit. 2021-01-08 21:27:06 +00:00
Mario Vavti
d1a61c6dce allow deletes for e.g. w2w posts where we are the author but item wall is not set. ownership is checked at the receiving side anyway 2021-01-08 13:12:01 +01:00
mjfriaza
c90d1fc8ef Update Spanish translation 2021-01-08 11:29:32 +01:00
Mario
42cd046e90 RC1 2021-01-06 20:37:04 +01:00
Mario
52fa350138 error in logic
(cherry picked from commit 16082456df)
2021-01-06 20:35:16 +01:00
Mario
4ea8357c6a remove logging
(cherry picked from commit 49cc69ecc5)
2021-01-06 20:35:03 +01:00
Mario
dd0da70b06 filter out self and child folders from the folder list
(cherry picked from commit a0c8e1959a)
2021-01-06 20:34:49 +01:00
Mario
d80f2a621d simplify attach_folder_select_list()
(cherry picked from commit c7010dac3c)
2021-01-06 20:33:59 +01:00
Mario
16082456df error in logic 2021-01-06 19:32:36 +00:00
Mario
49cc69ecc5 remove logging 2021-01-06 19:27:26 +00:00
Mario
a0c8e1959a filter out self and child folders from the folder list 2021-01-06 19:26:40 +00:00
Mario
c7010dac3c simplify attach_folder_select_list() 2021-01-06 19:22:29 +00:00
Mario
99bfc3aaa0 version 5.3 2021-01-05 08:48:30 +00:00
Mario
43b3922803 dump autoload 2021-01-05 08:45:23 +00:00
Mario
ca70ad1a9f version and strings 2021-01-05 08:44:10 +00:00
Mario Vavti
a250419b59 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2021-01-04 20:36:37 +01:00
Mario Vavti
291644f29d fix issue where categories were not saved on forum wall post 2021-01-04 20:36:24 +01:00
Mario
d4e97ab64c more work on tiles 2021-01-04 13:43:46 +00:00
Mario
e92f98d3c6 rounded corners 2021-01-04 11:14:01 +00:00
Mario
999aac19de missing translateable string and adapt icons 2021-01-04 11:09:12 +00:00
Mario
b2f6e5673d some work on the tiles view 2021-01-04 10:58:41 +00:00
Mario
f0d1c962a7 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2021-01-03 20:18:05 +00:00
Mario
6999b8d9b4 fix no channel_id provided for contact_remove() in reply_purge(). fix wrong notifier command 2021-01-03 20:17:45 +00:00
Max Kostikov
46e704d507 Merge branch 'dev' into 'dev'
Update Russian translation

See merge request hubzilla/core!1892
2021-01-03 17:05:03 +01:00
Max Kostikov
308e94ea79 Update hstrings.php 2021-01-03 16:43:45 +01:00
Max Kostikov
0c839b2738 Update hmessages.po 2021-01-03 16:43:22 +01:00
Mario
cff5859c59 mod cloud strings 2021-01-03 14:28:02 +00:00
Mario
6d95f5fc98 files_ng: slightly change the way we display link bbcode 2021-01-03 10:07:54 +00:00
Mario
7684861249 do not check against undefined variable 2021-01-02 21:37:06 +00:00
Mario
9759cb7075 fix typo 2021-01-02 21:18:49 +00:00
Mario
b3a5f9bef4 wrong variable 2021-01-02 21:10:47 +00:00
Mario
3e3b6cc1e1 wrong variable 2021-01-02 21:01:42 +00:00
Mario
474103dc82 remove unused code and fix width and height not defined 2021-01-02 20:56:18 +00:00
Mario
092a8f2d05 fix wrong variable 2021-01-02 20:39:58 +00:00
Mario
2bcf0c354a fix wrong variable 2021-01-02 20:39:47 +00:00
Mario
73cc756cac fix wrong variable 2021-01-02 20:38:56 +00:00
Mario
6091c2dba0 fix wrong variable 2021-01-02 20:38:44 +00:00
Mario
2862a73253 fix typo 2021-01-02 20:38:11 +00:00
Mario
850c3f2b6a fix typos 2021-01-02 18:58:20 +00:00
Mario
98f3e4cbd3 set is_owner does not need to be a per item flag. fix post button visible for collections 2021-01-02 18:53:23 +00:00
Mario
efc8ed4845 make share title h3 2021-01-02 11:20:03 +00:00
Mario
0bc4c7d1a0 version 5.0.8 2020-12-30 15:01:17 +00:00
Mario
be2e754d78 changelog
(cherry picked from commit 817e72846e)
2020-12-30 15:59:13 +01:00
Mario
817e72846e changelog 2020-12-30 14:55:00 +00:00
Mario
220768bffc escape both single and double quotes for the notifications title. fixes issue #1503
(cherry picked from commit 11d61a744d)
2020-12-30 15:40:15 +01:00
Mario Vavti
3cd64bcb22 random_profile: return zot6 entries
(cherry picked from commit 5cefdbf985)
2020-12-30 15:40:03 +01:00
Mario Vavti
86bfb07c29 dirserach: return zot6 entries
(cherry picked from commit 5485f96625)
2020-12-30 15:39:48 +01:00
Max Kostikov
ad08bd62aa Revert "Fix sync item with Zot connections"
This reverts commit 3db4aa69440553788d8f46cf4bbfb38ca4f09130


(cherry picked from commit c063fe0720)
2020-12-30 15:39:33 +01:00
Max Kostikov
d79cab0680 Deduplicate contacts list on autocomplete
(cherry picked from commit d889547b26)
2020-12-30 15:38:26 +01:00
Mario
d1d6f7d838 sse: fix issue with direct message notificationss
(cherry picked from commit d5eeb948d5)
2020-12-30 15:38:09 +01:00
Max Kostikov
e31a7e5c9d Do not revalidate cached photos
(cherry picked from commit ca051e943f)
2020-12-30 15:37:47 +01:00
Max Kostikov
e6f0d9887c Implement Imagemagick resources consumption limiting
(cherry picked from commit 36d89d02e1)
2020-12-30 15:37:28 +01:00
Mario
2855d84fba owa specify key
(cherry picked from commit f2258d4202)
2020-12-30 15:36:25 +01:00
Mario
3c19648a56 fix issue where an array was passed to get_key() instead of a string
(cherry picked from commit 81a1aedeb9)
2020-12-30 15:35:38 +01:00
Mario
8db367c743 remove fallback code - it will not be required if compression is dismissed 2020-12-30 14:30:39 +00:00
Mario
2c4fabba35 store zip files without compression 2020-12-30 14:12:08 +00:00
Mario
dff42ffb41 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2020-12-29 20:16:35 +00:00
Mario
11d61a744d escape both single and double quotes for the notifications title. fixes issue #1503 2020-12-29 20:16:23 +00:00
Mario Vavti
5cefdbf985 random_profile: return zot6 entries 2020-12-29 20:37:23 +01:00
Mario Vavti
5485f96625 dirserach: return zot6 entries 2020-12-29 20:36:41 +01:00
Mario
af0f46d23d Merge branch 'cloneissue' into 'dev'
Fix sync comments with clones

See merge request hubzilla/core!1889
2020-12-29 15:50:33 +01:00
Max Kostikov
c063fe0720 Revert "Fix sync item with Zot connections"
This reverts commit 3db4aa69440553788d8f46cf4bbfb38ca4f09130
2020-12-29 15:50:32 +01:00
Mario
203ba7343c Merge branch 'autocomplete' into 'dev'
Deduplicate contacts list on autocomplete

See merge request hubzilla/core!1891
2020-12-29 11:49:52 +01:00
Max Kostikov
d889547b26 Deduplicate contacts list on autocomplete 2020-12-29 11:49:52 +01:00
Mario
b66e19dc43 Merge branch 'photocache' into 'dev'
Do not revalidate cached photos

See merge request hubzilla/core!1890
2020-12-29 11:49:33 +01:00
Mario
c84e3334bf Merge branch 'tuneimagick' into 'dev'
Implement Imagemagick resources consumption limiting

See merge request hubzilla/core!1888
2020-12-29 11:49:11 +01:00
Mario
d5eeb948d5 sse: fix issue with direct message notificationss 2020-12-28 13:19:40 +00:00
Mario
9670833a5d files_ng: provide a fallback in case the server timed out on compressing the zip file 2020-12-28 10:12:25 +00:00
Max Kostikov
ca051e943f Do not revalidate cached photos 2020-12-26 14:24:04 +01:00
Max Kostikov
36d89d02e1 Implement Imagemagick resources consumption limiting 2020-12-26 14:10:56 +01:00
Mario
f4bfa77942 version bump 2020-12-23 09:16:45 +00:00
Mario
f2258d4202 owa specify key 2020-12-23 08:32:59 +00:00
Mario
d56bf34326 fix javascript warning 2020-12-23 08:22:31 +00:00
Mario
9fa3dee522 remove deprecated forum autocomplete code 2020-12-23 08:19:11 +00:00
Mario
7ee2192c29 provide some info and remove unused code 2020-12-22 13:33:54 +00:00
Mario
3a38292bab files_ng: improve download handlÃing 2020-12-22 13:23:20 +00:00
Mario
60cbb65d84 files_ng: omit parent folders of a download 2020-12-22 09:01:52 +00:00
Mario
d118ab71e6 files_ng: implement directory and bulk file download 2020-12-21 21:37:10 +00:00
Mario
81a1aedeb9 fix issue where an array was passed to get_key() instead of a string 2020-12-21 21:31:52 +00:00
Mario
1fd576436b changelog
(cherry picked from commit 638f7a1c89)
2020-12-21 09:44:38 +01:00
Mario
fac05e7dcd version 5.0.7 2020-12-21 09:05:29 +01:00
Max Kostikov
eef3126f0b Fix CardDAV address book ID
(cherry picked from commit 6579007ca0)
2020-12-21 09:04:36 +01:00
Max Kostikov
2df5a2a66d Use Zot6 for CardDAV and CalDAV sync between clones
(cherry picked from commit c596fb14bb)
2020-12-21 09:04:26 +01:00
Mario Vavti
01e7e3c24a handle owa with hubloc_id_url only
(cherry picked from commit ed4bf1c13d)
2020-12-21 09:04:04 +01:00
Mario
8112dee91e do not json_encode the attach array - fixes #1499
(cherry picked from commit 5b24225251)
2020-12-21 09:03:46 +01:00
Mario
638f7a1c89 changelog 2020-12-21 08:03:17 +00:00
Max Kostikov
5de4c3cc3f Merge branch 'dev' into 'dev'
Use Zot6 for CardDAV and CalDAV sync between clones

See merge request hubzilla/core!1886
2020-12-20 00:01:50 +01:00
Max Kostikov
6579007ca0 Fix CardDAV address book ID 2020-12-19 23:57:14 +01:00
Max Kostikov
c596fb14bb Use Zot6 for CardDAV and CalDAV sync between clones 2020-12-19 22:58:17 +01:00
Max Kostikov
116fc4e00d Merge branch 'dev' into 'dev'
Dev sync

See merge request kostikov/core!4
2020-12-19 22:02:51 +01:00
Mario
57f6f54f29 refresh_all will be called from the notifier in Daemon/Directory 2020-12-19 15:21:34 +00:00
Mario
8640e6d1df deprecate ! and !! forum tags 2020-12-18 13:26:51 +00:00
Mario
801583fd07 flag forums where we do not have post permissions and filter them from the acl selector 2020-12-18 12:40:36 +00:00
Mario Vavti
4987534eba Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2020-12-18 10:02:43 +01:00
Mario Vavti
ed4bf1c13d handle owa with hubloc_id_url only 2020-12-18 10:02:13 +01:00
Mario
5b24225251 do not json_encode the attach array - fixes #1499 2020-12-17 18:57:04 +00:00
Mario
886be8c452 changelog for version 5.0.6
(cherry picked from commit 269efb9c1e)
2020-12-17 14:46:08 +01:00
Mario
269efb9c1e changelog for version 5.0.6 2020-12-17 13:45:14 +00:00
Mario Vavti
612448e4ae update to fix empty hubloc_id_url caused by clone import bug for zot hublocs which was fixed in 4693069a06 2020-12-17 13:29:15 +00:00
Mario Vavti
82db19d54c restrict owa to zot6 and zot network until the hubloc madness with activitypub and possibly also diaspora will be solved
(cherry picked from commit 7ebba75fa2)
2020-12-17 14:26:32 +01:00
Mario
06aa3e6b8c fix issue with abconfig when cloning a channel
(cherry picked from commit f13bff2a76)
2020-12-17 14:26:00 +01:00
Mario
abf985c69e owa: dismiss deleted hublocs
(cherry picked from commit 006a409eb8)
2020-12-17 14:25:06 +01:00
Mario
c176b54f6b use refresh_all in mod import
(cherry picked from commit 59f1c038fe)
2020-12-17 14:24:49 +01:00
Mario
b24e691e7e try to fix more hubloc anomalies: use refresh_all in remove_obsolete_hublocs() and use Libzot::encode_locations() instead of zot_encode_locations() in notifier
(cherry picked from commit dec4ceabb5)
2020-12-17 14:24:16 +01:00
Mario
c2e43dc1b0 fix missing hubloc_id_url for zot hubloc when importing a channel
(cherry picked from commit 4693069a06)
2020-12-17 14:23:09 +01:00
Mario
7b7739c32c try to prevent hubloc confusion in some places
(cherry picked from commit 61cfeb5bdb749319357912d958cd13304b895bce)

(cherry picked from commit 634ace552d)
2020-12-17 14:22:44 +01:00
Mario
269172406f make gprobe look for zot6 only
(cherry picked from commit 1d3437aa419adde319d2a3f5d98e7f8fe4418f27)

(cherry picked from commit 751a1ba969)
2020-12-17 14:20:58 +01:00
Mario
4c054d6de9 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2020-12-17 12:27:49 +00:00
Mario Vavti
34a58369f2 update to fix empty hubloc_id_url caused by clone import bug for zot hublocs which was fixed in 4693069a06 2020-12-17 13:27:11 +01:00
Mario Vavti
59b4764a15 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2020-12-17 12:46:33 +01:00
Mario Vavti
7ebba75fa2 restrict owa to zot6 and zot network until the hubloc madness with activitypub and possibly also diaspora will be solved 2020-12-17 12:46:22 +01:00
Mario
b2e80efe3f files_ng: provide bbcode snippets in the info panel 2020-12-17 10:04:24 +00:00
Mario
b4b566318a files_ng: fix regression in finding the right path in certain situations and add a info panel with attach and zrl bbcode 2020-12-16 16:57:56 +00:00
Mario
27df896a9c files_ng: implement lockview 2020-12-16 08:26:19 +00:00
Mario
8188a551f3 fix regression in files aclselect 2020-12-15 12:12:38 +00:00
Mario
f13bff2a76 fix issue with abconfig when cloning a channel 2020-12-15 11:29:45 +00:00
Mario
59f1c038fe use refresh_all in mod import 2020-12-15 10:04:22 +00:00
Mario
006a409eb8 owa: dismiss deleted hublocs 2020-12-15 08:40:02 +00:00
Mario
dec4ceabb5 try to fix more hubloc anomalies: use refresh_all in remove_obsolete_hublocs() and use Libzot::encode_locations() instead of zot_encode_locations() in notifier 2020-12-15 08:36:14 +00:00
Mario
4a902dbbbe fix file sync issues 2020-12-14 22:06:47 +00:00
Mario
8e488e2913 handle removal of terms in attach_delete() when deleting a ressource 2020-12-14 21:56:19 +00:00
Mario
e58e27ce22 sync categories 2020-12-14 21:38:49 +00:00
Mario
78c0926a64 improve when to show link to parent path 2020-12-14 20:22:13 +00:00
Mario
4693069a06 fix missing hubloc_id_url for zot hubloc when importing a channel 2020-12-14 14:06:07 +00:00
Mario
70e529ef5d add another parent element to wrap the tools 2020-12-14 11:17:36 +00:00
Mario
2a154f8c9a merge branch files_ng into dev 2020-12-14 11:02:20 +00:00
Mario
634ace552d try to prevent hubloc confusion in some places
(cherry picked from commit 61cfeb5bdb749319357912d958cd13304b895bce)
2020-12-12 22:41:38 +01:00
Mario
751a1ba969 make gprobe look for zot6 only
(cherry picked from commit 1d3437aa419adde319d2a3f5d98e7f8fe4418f27)
2020-12-12 22:41:11 +01:00
Mario
d95573741d changelog 2020-12-12 19:02:28 +00:00
Max Kostikov
faf4bcdd62 Remove duplicate delete terms query
(cherry picked from commit a27c593a2a)
2020-12-12 19:56:24 +01:00
Mario
badae90051 Merge branch 'dev' into 'dev'
Remove duplicate delete terms query

See merge request hubzilla/core!1885
2020-12-12 19:44:01 +01:00
Max Kostikov
a27c593a2a Remove duplicate delete terms query 2020-12-12 19:43:57 +01:00
Mario
f699442bec bump version 2020-12-12 19:40:49 +01:00
Mario
8720931a53 fix hubloc issue in mod getfile
(cherry picked from commit b0b9b9f28974f9016e47491e81876224c57a7e3b)

(cherry picked from commit 8c1c49a45e)
2020-12-12 19:36:42 +01:00
Max Kostikov
600dcdfc58 Remove duplicate delete terms query 2020-12-12 10:10:32 +01:00
Max Kostikov
a4b83327c2 Merge branch 'dev' into 'dev'
Dev sync

See merge request kostikov/core!3
2020-12-12 10:07:39 +01:00
Mario
8c1c49a45e fix hubloc issue in mod getfile
(cherry picked from commit b0b9b9f28974f9016e47491e81876224c57a7e3b)
2020-12-11 12:35:54 +01:00
Mario
b1f0014429 Merge branch 'dev' into 'dev'
Skip profile photo query from addons for undefined channel id

See merge request hubzilla/core!1884
2020-12-07 11:08:41 +01:00
Max Kostikov
d984918c75 Skip profile photo query from addons for undefined channel id 2020-12-07 11:08:41 +01:00
Mario
21ac4b5139 remove announce activity from response activites array
(cherry picked from commit 52c78c757ae73082ed29e48707b2313e65020db3)
2020-12-07 11:03:03 +01:00
Max Kostikov
92eb7a0be4 Formatting 2020-12-04 14:45:27 +01:00
Max Kostikov
b26b1c0820 Skip profile photo query from addons for undefined channel id 2020-12-04 14:36:29 +01:00
Max Kostikov
a9dd6d6bdb Merge branch 'dev' into 'dev'
Dev sync

See merge request kostikov/core!2
2020-12-04 14:33:34 +01:00
Mario
d60c53cd12 version 5.0.4 2020-12-01 08:46:22 +00:00
Mario
6b0fe6e0a0 changelog
(cherry picked from commit 9c7ec55b40)
2020-12-01 09:45:09 +01:00
Mario
9c7ec55b40 changelog 2020-12-01 08:43:59 +00:00
Mario
28f1f4cbdc missing parenthesis
(cherry picked from commit 45b41f0787)
2020-12-01 09:38:59 +01:00
Mario
508b3ce730 Ãfix regerssion in updating the primary
(cherry picked from commit c47434634d)
2020-12-01 09:38:48 +01:00
Mario
87ecc61fb4 dismiss title in response activity
(cherry picked from commit eb2ad3fc438544192cda95d88a4c2a54ec1e0014)

(cherry picked from commit b89355b9d8)
2020-12-01 09:38:17 +01:00
Mario
ce4d664abc Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2020-12-01 08:31:50 +00:00
Mario
45b41f0787 missing parenthesis 2020-12-01 08:31:27 +00:00
Mario
c47434634d Ãfix regerssion in updating the primary 2020-12-01 08:31:15 +00:00
Mario
b89355b9d8 dismiss title in response activity
(cherry picked from commit eb2ad3fc438544192cda95d88a4c2a54ec1e0014)
2020-11-28 11:40:03 +01:00
Mario
3f40d6f7b7 run composer install --no-dev 2020-11-27 11:09:48 +00:00
Mario
155daac8ad run composer install --no-dev 2020-11-27 11:08:45 +00:00
Mario
f9d24d07dd composer autoload dump 2020-11-27 10:50:46 +00:00
Mario
d91e35e197 bring back require but with the correct path 2020-11-27 10:47:24 +00:00
Mario
a967dd9d13 fix languagedetect warnming 2020-11-27 08:04:41 +00:00
Mario
f4bb7bcbff update composer libs 2020-11-27 08:04:00 +00:00
Mario
0f6166da00 Merge branch 'dev' 2020-11-26 18:43:53 +00:00
Mario
07e5b8295e changelog 2020-11-26 18:41:51 +00:00
Mario
9afdf86961 coverage config 2020-11-26 12:10:16 +00:00
Mario
f4f1974be0 those would require dbunit 2020-11-26 12:01:15 +00:00
Mario
6f6399ca0f fix test 2020-11-26 11:43:07 +00:00
Mario
5018c0fbb8 add dms/phpunit-arraysubset-asserts 2020-11-26 11:37:13 +00:00
Mario
188975ccbd update gitlab-ci 2020-11-26 11:20:16 +00:00
Mario
5e1addc75e revert folder renaming 2020-11-26 11:14:40 +00:00
Mario
138beeac41 wrong path 2020-11-26 10:24:00 +00:00
Mario
187364d94a set xdebug.mode=coverage in php.ini 2020-11-26 10:21:13 +00:00
Mario
6e74e76fcd update phpunit.xml 2020-11-26 10:12:35 +00:00
Mario
615424d272 update ci file 2020-11-26 10:04:33 +00:00
Mario
d40a7a609e run vendor/bin/phpunit --migrate-configuration 2020-11-26 10:03:39 +00:00
Mario
0ec40f00a9 minor adjustion 2020-11-26 09:52:24 +00:00
Mario
de054026f2 try phpunit 9, remove dbunit (not compatible and abandoned), re-enable xdebug 2020-11-26 09:26:37 +00:00
Mario
175b45d1ed update php-mock 2020-11-26 08:56:38 +00:00
Mario
e236b77817 more psr-4 autoloading standard 2020-11-26 08:48:09 +00:00
Mario
21cd4a1b48 psr-4 autoloading standard 2020-11-26 08:43:03 +00:00
Mario
e9a50371f5 comment out xdebug 2020-11-26 08:30:06 +00:00
Mario
71f8a08e5f update phpunit 2020-11-26 08:19:51 +00:00
Mario
4419c93d80 this should not be required anymore 2020-11-26 07:58:57 +00:00
Mario
fcc13ce02c version 2020-11-25 18:45:37 +00:00
Mario
941db04260 add a uuid version 5 based uuid to imported feeds. if rewrite author for sourced items, also rewrite mid to be fetchable 2020-11-25 13:52:27 +00:00
Mario
87d7a3053a do not reset item_origin to 1 for deleted items to prevent possible looping and do not set item_uplink for sourced rss items - we can not sen anything to them. 2020-11-25 11:01:25 +00:00
Mario
ae11b2c281 profile_load() requires channel_address 2020-11-24 22:14:24 +00:00
Mario
f43577ec27 add logging 2020-11-23 21:26:52 +00:00
Mario
c648c38fb0 fix warning 2020-11-23 20:23:17 +00:00
Mario
34d54fd309 simplify code and fix issue with categories 2020-11-23 19:57:28 +00:00
Mario
891b1428cc do not use chanlink_url() at this place 2020-11-23 18:23:46 +00:00
Mario
453dd38e51 missing include 2020-11-23 14:01:04 +00:00
Mario
f59aefd3d9 store actor of fetched acivities 2020-11-23 09:10:53 +00:00
Mario
451468d129 fix mod item issue with remote channels 2020-11-22 16:37:20 +00:00
Mario
c0adf31da9 fix like issue with remote channels 2020-11-22 13:07:03 +00:00
Mario
bb43c57b07 make simple update more simple again 2020-11-21 20:57:50 +00:00
Mario
6c94bbc93f collase the updated content 2020-11-21 20:52:38 +00:00
Mario
50422c608f fix #1492 2020-11-21 20:35:38 +00:00
Mario
7639157a49 restrict returned html usage to local_channel() until some issues will be worked out 2020-11-21 20:15:05 +00:00
Mario
f74cfaec5f fix pubstream id issue 2020-11-21 10:22:23 +00:00
Mario
d559b4a201 deliver to local hub first 2020-11-21 10:21:14 +00:00
Mario
2d4064aca4 returning the rendered html when liking a post or comment 2020-11-20 20:38:10 +00:00
Mario
337d8ea78c minor cleanup 2020-11-20 14:42:46 +00:00
Mario
4c0a26dbf9 move post_comment() handling via ctrl-enter out of handle_comment_form() - to many issues with multiple triggers 2020-11-20 10:45:35 +00:00
Mario
885edd6261 version 2020-11-20 09:15:19 +00:00
Mario
011de75706 returning the rendered html when posting a comment will make the following update (and its implication in mod pubstream) obsolete 2020-11-20 09:14:46 +00:00
Mario
852e456d44 this is silly but it seems to be required for firefox to stop scrolling in certain conditions 2020-11-18 20:34:41 +00:00
Mario
18136788e4 be more specific 2020-11-18 20:33:32 +00:00
Mario
f1101808b7 fix regression in relation to pustream notifications 2020-11-18 17:09:53 +00:00
Mario
791d5098a0 fix regression 2020-11-18 12:28:20 +00:00
Mario
f2fd12fbe5 Do away with auto updates except for our own actions. We might consider to re-implement this for single thread view like eg /display. Instead of calculating scroll positions during updates, keep track of expanded items and set the expanded state when updating - this fixes issue #1488 2020-11-18 09:52:44 +00:00
Mario
b5ab77908e implement submit on ctrl-enter for post editor and comments 2020-11-17 09:09:36 +00:00
Mario
5750e6cada Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2020-11-16 09:34:08 +00:00
Mario
394aa76a8f changelog 2020-11-16 09:33:57 +00:00
Mario
35c4deb884 work around an edge case in acl selector
(cherry picked from commit e7c83a81c7)
2020-11-16 10:31:14 +01:00
1460 changed files with 140282 additions and 65523 deletions

0
.gitignore vendored Executable file → Normal file
View File

View File

@@ -40,7 +40,8 @@ before_script:
- curl -sS https://getcomposer.org/installer | php
# Install dev libraries from composer
- php ./composer.phar install --no-progress
# php.ini settings
- echo 'xdebug.mode=coverage' >> /usr/local/etc/php/php.ini
# hidden job definition with template for MySQL/MariaDB
.job_template_mysql: &job_definition_mysql

0
.homeinstall/zotserver-setup.sh Executable file → Normal file
View File

0
.openshift/action_hooks/deploy Executable file → Normal file
View File

0
.openshift/cron/weekly/chronograph Executable file → Normal file
View File

319
CHANGELOG
View File

@@ -1,3 +1,214 @@
Hubzilla 5.4.2 (2021-03-15)
- Fix translation plural variable
- Fix issue with following/unfollowing a thread
- Fix rendering of long text in xchan vcard
- Fix local link for rss content if rewrite author is sets
- Fix regression in mod display
Addons
- Pubcrawl: fix issue with following/unfollowing a thread
- Pubcrawl: more robust implementation of mastodon remote reply
- Photocache: remove suffix from the cached photo URL
Hubzilla 5.4.1 (2021-03-09)
- Fix profile not found if not logged in
- Fix summary not reset on cancel
- Fix summary not saved with aoutosave draft
- Fix unexpected trigger of buttons when pressing enter in input fields
- Fix spanish plural expression
- Fix undefined page-end on non dynamic pages
Addons
- Pubcrawl: fix regression in pubcrawl_follow_mod_init()
Hubzilla 5.4 (2021-03-08)
- Add new connections to privacy group independend from the default privacy group settings
- group_add() return group hash to save a lookup
- Do not poll feeds if feed contacts setting is disabled
- Deprecate sticky_kit library in favor of CSS position sticky solution
- Trigger endless scroll loading at the end of content instead of end of window height
- Implement experimental zap export compatibility
- Deprecate the [summary] tag in favor of a separate input field for the summary
- Adjust error reporting for PHP8
- Rely on php.ini default value for pcre.backtrack_limit
- PHP8 compatibility (experimental)
- Introduce Lib/Crypto (ported from zap)
- Introduce Lib/Keyutils which now implements phpseclib v2
- Improve profile photo fetching
- Introduce fetch_provider hook
- Implement ActivityStreams discovery in mod profile
- Implement ActivityStreams discovery in mod channel
- Streamline OS folder and file permissions
- Add polish translations
- Implement ThreadListener in mod activity_match
- Improve ThreadListener handling
- Use mail envelope instead of lock icon for direct messages
- Implement ASCollection in Libzot::fetch_conversation()
- Invoke channel discovery by hash instead of address in mod channel
- Implement manual public item import for zot6, activitypub and diaspora via search
- Default photo storage to filesystem instead of DB for new installations
- Support filesystem storage for xchan profile photos
- Deprecate Daemon/Externals
- Implement SQL query background caching
- Process channel categories list in background
- Port util/connect to Lib/Connect
Bugfixes
- Fix visible/empty notifications for blocked contacts items
- Fix issue where URL fragment was turned into hashtag if the hashtag existed elsewhere in the post (issue #1518)
- Fix audio and video embeds for media sources without media format extension
- Fix issue where zot package was saved in iconf instead of the decoded activity
- Fix duplicate id in post preview
- Fix display issue of restricted content in mod display
- Fix issue where comments were not delivered to the public stream
- Fix issue where profile photos were stored multiple times and remove duplicates
- Fix pinned items sync between clones
- Fix r_preview for list mode in mod channel and mod network
Addons
- Pubcrawl: deal with mastodons remote replies
- Diaspora: reduce xchan network confusion in several places
- Diaspora: fix mentions if multiple xchan networks exists
- Diaspora: fix comments on comments
- Pubcrawl: do not re-use broken signed messages
- Pubcrawl: fix parsing of images with description (core issue #1519)
- Pubcrawl: use the signed message from the attachment (iconfig) when relaying
- Diaspora: implement browser to browser encrypted messages as base64 encoded string
- Pubcrawl: implement browser to browser encrypted messages as base64 encoded string
- Diaspora: support post summary
- Pubcrawl: fix summary aka content warning
- PHP8 compatibility (experimental)
- Tripleaes: removed
- Reflect core crypto changes
- Photocache: improve mimetype detection
- Diaspora: implement mnanual fetch provider
- Diaspora: implement send participation
- Pubcrawl: deprecate pubcrawl_is_as_request() in favor of the core version in Lib/ActivityStreams
- Diaspora: prefer zot identity for inbound comments if available
- Pubcrawl: return zotfeed results in mod outbox
- Queueworker: improved deduplication by adding a uuid
- Superblock: fix syncing with clones regression
- Queueworker: improve SQL query in GetWorkerCount()
- Queueworker: fix issue in workersleep handling
Hubzilla 5.2.2 (2021-02-13)
- Fix issue with ping_site()
Hubzilla 5.2.1 (2021-01-16)
- Fix attach_upgrade() to catch all broken entries in attach
- Fix collect_recipients() public policy filter for zot6
- Fix leaking of duplicate tasks in queueworker
Hubzilla 5.2 (2021-01-13)
- Use libzotdir for directory
- Streamline usage of channel url for keyId
- Basic work on PHP8 compatibility
- Improve performance for forum post edit action
- Improve File App tiles view
- Update es strings
- Update ru strings
- Implement directory download via zip files in Files App
- Implement bulk file download via zip files in Files App
- Deprecate ! and !! forum tags - use direct messages to post to forums
- Do not show forums where we do not have permission to post in ACL selector
- Implement lockview for Files App
- Implement file and directory rename functionality Files App
- Implement file and directory copy functionality in Files App
- Implement file and directory move functionality in Files App
- Implement categories for files and directories in Files App
- Implement drag and drop move action for files and directories in Files App
- Implement bulk file actions for move, copy, categories and permissions
- Implement a files categories widget
- Implement a breadcrumb view for file paths
- Rewrite xchan_vcard template
- Update composer libs
Bugfixes
- Fix direct messages by forum channel turned into group item
- Fix ID3Parser composer autoload
- Fix issue where directory_fallback_servers were not accessible from static function
- Fix missing constant defenition for HUBLOC_OFFLINE
- Fix sync_directories() including known dead sites
- Fix undefined variable in poller preventing Onedirsync from running
- Fix w2w posts not editable/deletable from local server
- Fix issue where categories were not saved on forum wall posts
- Fix no channel_id provided for contact_remove() in reply_purge()
- Fix typo in notifier command
- Fix profile title/description allowed more than 191 characters
Addons
- Queueworker: cleanup whitespace
- Queueworker: add some tweaks to prevent deadlocks for postgresql
- Flashcards: compatibility for the changes in the Files App
- Openstreemap: fix hostname parsing from URL
- Openstreemap: fix content security policy
- Pubcrawl: fix peertube video display
- Pubcrawl: deliver updates to anyone owning the item
Hubzilla 5.0.8 (2020-12-30)
- Fix single quotes not escaped in the notifications title (issue 1503)
- Return zot6 xchans for random_profile()
- Return zot6 entries in dirsearch
- Fix comment sync issue
- Fix duplicate entries in contact autocomplete
- Fix issue where direct message notifications where not displayed for wall items
- Do not revalidate cached photos
- Implement imagemagic resource consumption limiting
- Specify key in mod owa
- Fix issue where array was passed to get_key()
Hubzilla 5.0.7 (2020-12-21)
- Fix CardDAV addressbook ID
- Use Zot6 for CardDAV and CalDAV sync between clones
- Handle owa with hubloc_id_url only
- Fix attachment in comment not visible after commenting - issue #1499
Hubzilla 5.0.6 (2020-12-17)
- Fix zot hublocs with empty hubloc_id_url in DB caused by clone import bug
- Only look for zot6 and zot hublocs in mod owa
- Fix abconfig issue when cloning a channel
- Call notifier with refresh_all instead of location when importing a clone
- Use Libzot::encode_locations() instead of zot_encode_locations() in notifier
- Fix missing zot hubloc hubloc_id_url when importing a clone
- Implement Libzot::zot_record_preferred() in various places to prevent hubloc confusion
Addons
- Fix wrong redirect path for check_form_security_token_redirectOnErr() in various addons
Hubzilla 5.0.5 (2020-12-12)
- Fix hubloc issue in mod getfile
- Remove duplicate SQL query
Hubzilla 5.0.4 (2020-12-01)
- Fix regression updating the primary
- Dismiss title in response activities
Hubzilla 5.0.3 (2020-11-26)
- Upgrade phpunit to version 9
- Remove dbunit because its not maintained anymore
- Add uuid version 5 based uuid's to imported feeds
- Fix potential delivery loop
- Fix actor of fetched activities not stored
- Improve update mechanism for comments and likes to prevent page jumps
- Fix issue where channel suggestions was suggesting oneself
- Do not auto-update except for own actions
- Introduce ctrl-enter shortcut to send comments and posts
Addons
Pubcrawl: improve addressing of mentioned actors
Hubzilla 5.0.2 (2020-11-16)
- Fix edge case in acl selector
- Fix ping_site()
@@ -14,7 +225,7 @@ Hubzilla 5.0.2 (2020-11-16)
Hubzilla 5.0.1 (2020-11-12)
- Fix share title size
- Fix share title size
- Fix issue where hublocs could get mixed up between different protocols
Addons
@@ -330,7 +541,7 @@ Hubzilla 4.2 (2019-06-04)
Hubzilla 4.0.3 (2019-04-26)
- Add attachments to zot6 event objects
- Add zot6 to federated transports
- Add zot6 to federated transports
- Update import/export to handle zot6 hublocs and xchans
- Update fix_system_urls() to handle zot6 hublocs
- Fix infinite loop using postgres as backend
@@ -383,7 +594,7 @@ Hubzilla 4.0.1 (2019-03-21)
- Perform zot6 discovery in import_author_xchan
- Fix authenticated fetches
- Port zot_record_preferred() from zap
Addons:
- Pubcrawl: deliver comments to abook contacts and thread participants
- Pubcrawl: fix can_comment_on_post()
@@ -597,7 +808,7 @@ Hubzilla 3.8.3 (2018-11-05)
- Fix forum notifications count not correct
- Fix gallery addon which broke mod apps in some situations
- Fix wiki_list widget not working on every page respectively level
Hubzilla 3.8.2 (2018-10-29)
- Merge unmerged changes from dev into master
@@ -613,7 +824,7 @@ Hubzilla 3.8.2 (2018-10-29)
- Look for for matches in the entire string when suggesting emojis
- Add [summary] bbcode to autocomplete list
- Update blueimp_upload to version 9.23
- Update spanish strings
- Update spanish strings
Addons
- Cart: don't allow items to be added unless user is logged into the Grid.
@@ -671,7 +882,7 @@ Hubzilla 3.8 (2018-10-19)
- Sanitise vcard fields
- Don't sync system apps
Bugfixes
- Fix issue with timeago plurals
- Fix issue with HTTP signatures
@@ -730,7 +941,7 @@ Hubzilla 3.8 (2018-10-19)
Hubzilla 3.6 (2018-07-25)
- Update jquery.timeago library
- Implement Hookable CSP
- ActivityStreams: accept header changes to support plume
- ActivityStreams: accept header changes to support plume
- Streamline inconsistencies in addon naming
- SECURITY: hash the session_id in logs
- Update justified gallery library
@@ -743,9 +954,9 @@ Hubzilla 3.6 (2018-07-25)
- Make droping posts of removed connections more memory efficient
- Refactor getOutainfo() for DAV storage
- Optionally report total available space when uploading
- SECURITY: provide option to disable the cloud 'root' directory and make the cloud module require a target channel nickname
- SECURITY: provide option to disable the cloud 'root' directory and make the cloud module require a target channel nickname
- Add plink and llink to viewsource
- Add new 'filter by name' feature
- Add new 'filter by name' feature
- Remove network tabs
- New activity filter widget
- New activity order widget
@@ -787,8 +998,8 @@ Hubzilla 3.6 (2018-07-25)
- Fix sys channels visible in dirsearch
- Fix remote_self not working correctly
- Fix photos not syncing properly if destination is a postgres site
- Fix wrong hubloc_url for activitypub hublocs
- Fix z_check_dns() for BSD
- Fix wrong hubloc_url for activitypub hublocs
- Fix z_check_dns() for BSD
- Fix not null violation in oauth1
- Fix DB issues with oauth2 on postgresql
- Fix 'anybody authenticated' not correctly handled in can_comment_on_post()
@@ -1350,10 +1561,10 @@ Hubzilla 2.6.2 (2017-08-31)
Hubzilla 2.6.1 (2017-08-18)
- Fix a regression with dav clients
- Raise install requirements
Plugins/Addon
- Diaspora: fix PHP warning
- GNU-Social: fix PHP warning
- GNU-Social: fix PHP warning
Hubzilla 2.6 (2017-08-16)
@@ -1361,18 +1572,18 @@ Hubzilla 2.6 (2017-08-16)
- Consolidate disable_discover_tab config
- Fix some bbcode to markdown conversion issues
- Improved finding of recursive attachment permissions
- Smaller line-height for notification badges
- Smaller line-height for notification badges
- Bluegrid schema removed - will be added again if someone is willing to maintain it
- Improved file_activity()
- DB - add index for item.obj_type
- Add options flag to bb_to_markdown() so we can distinguish between diaspora use and other use and therefore filter and adjust content selectively
- Close the apps-menu if the notifications-menu is open and vice versa
- Close the apps-menu if the notifications-menu is open and vice versa
- Remove redundant call to jquery ready function in photo albums view
- Remove borders from navbar toggler in mobile view
- Improve the formatting of shares when converting from bbcode to markdown
- Suppress fopen errors from dav
- Make local channel (not our own) nav menus appear similar to what we are used from remote channels
- Indicate the selected channel in the dropdown menu if the feature is enabled
- Indicate the selected channel in the dropdown menu if the feature is enabled
- Provide a mechanism to mark apps active in the app tray
- Allow wildcard tag and category searches
- Improved installer
@@ -1384,7 +1595,7 @@ Hubzilla 2.6 (2017-08-16)
- Update htmlpurifier to version 4.9.3
- Update sabre/http to version 4.2.3
- Add optimize-autoloader to composer config
- Missing abook_{my,their}_perms in pg schema and missing keys in mysql schema
- Missing abook_{my,their}_perms in pg schema and missing keys in mysql schema
- Provide a gender icon on the profile sidebar within reason
- Provide more comprehensible information on the admin summary page
- Upgrade blueimp from 9.8 to 9.18
@@ -1450,7 +1661,7 @@ Hubzilla 2.6 (2017-08-16)
Cdav addon moved to core
head_add_css() needs a preceding '/' to find files in the addons dir
New addon code syntax highlighting (moved from core to addon)
Pubsubhubbub: specify a minimum number of records - otherwise it defaults to zero
Pubsubhubbub: specify a minimum number of records - otherwise it defaults to zero
Hubzilla 2.4 (2017-05-31)
@@ -1804,10 +2015,10 @@ Hubzilla 1.14 (2016-10-13)
- Start grouping addons by server_role
Hubzilla 1.12
- extensible permissions so you can create a new permission rule such as "can write to my wiki" or "can see me naked".
- guest access tokens can do anything you let them, including create posts and administer your channel
- extensible permissions so you can create a new permission rule such as "can write to my wiki" or "can see me naked".
- guest access tokens can do anything you let them, including create posts and administer your channel
- ACLs can be set on files and directories prior to creation.
- ACL tool can now be used in multiple forms within a page
- ACL tool can now be used in multiple forms within a page
- a myriad of new drag/drop features (drop files or photos into /cloud or a post, or drop link into a post or comment, etc.)
- multiple file uploads
- improvements to website import
@@ -1832,7 +2043,7 @@ Hubzilla 1.10
Wiki:
Lots of enhanced functionality, usability improvements, and bugfixes from v1.8
Turned into an optional feature (default on) but disabled in UNO
Sync:
Sync:
Items are now relocated (links patched) when syncing to clones
Access Tokens:
New feature - allows members to create access controlled guest logins and create/share 'dropbox' style links to protected resources.
@@ -1840,7 +2051,7 @@ Hubzilla 1.10
Use icons instead of iconic text constructs
Only request geolocation permission when creating a post, not on page load
provide 'redeliver' option on Delivery Report page for when things really stuff up
CalDAV/CardDAV management pages with heaps of functionality
CalDAV/CardDAV management pages with heaps of functionality
Lib:
z_fetch_url() updated to accept different request methods and request bodies
item_store(), item_store_update() now return the stored items
@@ -1864,7 +2075,7 @@ Hubzilla 1.10
issues with 'use existing photo' for profile photo
layout editor "list all layouts" returned empty
oembed - better detect video file URLs so they aren't loaded into memory.
handcrafted bbcode tables could end up with way too much whitespace due to CRLF translation
handcrafted bbcode tables could end up with way too much whitespace due to CRLF translation
refresh permissions whitescreen in 1.8
force immediate profile photo update on local site
regression: 'save bookmarks' post action missing
@@ -1889,7 +2100,7 @@ Hubzilla 1.8
Documentation:
Clarify privacy rights of commenters w/r/t conversation owners, as this policy is network dependent.
Wiki (Git backed):
Brand new feature. We'll call it experimental until it has undergone a bit more testing.
Brand new feature. We'll call it experimental until it has undergone a bit more testing.
Account Cloning:
Regression on clone channel creation created a new channel name each time.
New issue (fixed) with directory creation on cloned file content
@@ -1912,7 +2123,7 @@ Hubzilla 1.8
Experimental PDO database driver
Creation of Daemon Master class and port all daemon (background task) interfaces to use it
Create separate class for each of 'Cron', 'Cron daily', and 'Cron weekly'.
Always run a Cron maintenance task if not run in the last four hours
Always run a Cron maintenance task if not run in the last four hours
Refactor the template classes
Refactor the ConversationItem mess into ThreadItem and ThreadStream
Refactor Apps, Enotify, and Chat library code
@@ -1920,7 +2131,7 @@ Hubzilla 1.8
Created WebServer class for top level
Remove mcrypt dependencies (deprecated in PHP 7.1)
Remove all reserved (including merely 'not recommended') words as DB table column names
Provide mutex lock on DB logging to prevent recursion under rare failure modes.
Provide mutex lock on DB logging to prevent recursion under rare failure modes.
Bugfixes:
Remove db_close function on page end - not needed and will not work with persistent DB connections.
Undefined ref_session_write
@@ -1940,7 +2151,7 @@ Hubzilla 1.8
CalDAV/CardDAV plugin provided
Issue sending Diaspora 'like' activities from sources that did not propagate the DCV
Allow 'superblock' to work across API calls from third party clients
statistics.json: use 'zot' as protocol
statistics.json: use 'zot' as protocol
Issues fixed during testing of ability to follow Diaspora tags
Parse issue with Diaspora reshare content
Chess: moved to main repo, ported to 1.8
@@ -1952,7 +2163,7 @@ Hubzilla 1.6
Plugin hook interface adapted to call static class methods
Context help improved dramatically with content for the most accessed pages.
Reverted a compatibility change to support GNU-social events. We copied their feed format and their feed format is wrong (XML namespace collisions).
Provide a querystring attribute to CSS/JS resources to avoid caching issues when our code changes (which is often).
Provide a querystring attribute to CSS/JS resources to avoid caching issues when our code changes (which is often).
Fix javascript detection and allow either positive or negative detection.
Refactor the plugin hook registration procedure, provide 'unregister all' ability.
Fix RSD (Real Simple Discovery) which has been broken for some time.
@@ -1961,7 +2172,7 @@ Hubzilla 1.6
Update font-awesome to 4.6.1
Update SabreDAV to 3.0 (PHP version requirements prevent us from pushing it further at this time)
Help text added to cmdline utilities config and pconfig
Reworking of the database logging facility to avoid the rare but troublesome recursion when the log facility needed to query the DB internally to obtain config parameters.
Reworking of the database logging facility to avoid the rare but troublesome recursion when the log facility needed to query the DB internally to obtain config parameters.
Implement singleton delivery (emulate nomadic identity to singleton networks and services)
Fix empty album name in photo activities when photo is stored in top level folder.
Allow engineering units to be used in service class data size restrictions (400M, 1G, etc.)
@@ -1969,7 +2180,7 @@ Hubzilla 1.6
Admin interface provided to manage external resource repositories
Oembed security reworked. Now all sources are filtered by default unless blocked.
Remove the date-string version and use only STD_VERSION
Add categories and categorisation filtering and the ability to edit all apps (including system apps) for a given channel
Add categories and categorisation filtering and the ability to edit all apps (including system apps) for a given channel
Ensure the ability to translate names of all system apps (except those provided in addons)
Provide ability to add categories to content from channel sources
Lots of work on the presentation of the ACL widget to enhance usability and intuitiveness
@@ -1983,24 +2194,24 @@ Hubzilla 1.6
Provide some extra security checks to import data and files to prevent mischief
Block CalDAV/CardDAV namespace reserved words from being used as a channel nickname/redress since Sabre is somewhat inflexible in this regard
Plugins:
Diaspora
markdown translator work needed to eradicate the Diaspora Comment Virus.
Diaspora
markdown translator work needed to eradicate the Diaspora Comment Virus.
upgrade all inbound paths with the most recent protocol changes (several of these)
convert 'diaspora_meta' (Diaspora Comment Virus) to iconfig and eradicate from sites with Diaspora disabled
implement social relay and allow following tags
upgrade statistics.json to NodeInfo. Currently hubzilla sites are tagged as 'redmatrix' because the NodeInfo schema lacks extensibility and project names are used to designate protocol compatibility rather than protocol names.
Std-embeds
New addon to allow a handful of corporate providers to run unfiltered embed code (youtube, vimeo, soundcloud)
New addon to allow a handful of corporate providers to run unfiltered embed code (youtube, vimeo, soundcloud)
Various:
upgrade font-awesome icons and adapt a few addons to Objects and the new hook interface and new controller interface
Hubzilla 1.4
[This list may appear brief, but encompasses a huge amount of re-writing and re-factoring
of the internal code structure to gain long-term performance and stability and provide a standard
interface to alternate protocol federation plugins which were made possible by the UNO configuration.
UNO is a configuration of hubzilla introduced in 1.3 with reduced complexity and which provides
improved protocol federation potential to other networks by virtue of removing nomadic identity
(which is not possible to model or work around using other network protocols).]
UNO is a configuration of hubzilla introduced in 1.3 with reduced complexity and which provides
improved protocol federation potential to other networks by virtue of removing nomadic identity
(which is not possible to model or work around using other network protocols).]
Implement channel move operation for UNO configuration
Remove bookmark references in UNO (which has no bookmarks by default)
@@ -2023,10 +2234,10 @@ Hubzilla 1.4
Rework detection of JavaScript to avoid reload penalty under normal operation
Changed primary directory server to a hubzilla server
Plugins:
Diaspora - switch to alternate XML parser to avoid storing compound objects
Diaspora - switch to alternate XML parser to avoid storing compound objects
GNU-Social - Huge amounts of work, federation somewhat working now, several issues remain
Friendica - Initial federation work (not yet published)
Hubzilla 1.3
Admin Security configuration page created which consolidates several previously hidden settings:
Communication white/black lists
@@ -2042,26 +2253,26 @@ Hubzilla 1.3
"pubsites" module UI reworked
item-meta ("iconfig") created which implements arbitrary storage for item metadata for plugins
abook-meta ("abconfig") created which implements arbitrary storage for connection metadata for plugins
"Strict transport security header" made optional as it conflicts with some existing Apache/nginx configurations
"Hubzilla UNO" (Hubzilla with radically simplified and locked site settings) implemented as an install configuration.
"Strict transport security header" made optional as it conflicts with some existing Apache/nginx configurations
"Hubzilla UNO" (Hubzilla with radically simplified and locked site settings) implemented as an install configuration.
.well-known directory conflict worked out to support LetsEncrypt cert ownership checks without disrupting webfinger and other internal uses of .well-known
Lots of work on 'zcards' which are self-contained HTML representations of a channel including cover photos, profile photos, and some text information
Long standing bug uncovered which failed to properly restrict the lower time limit for public feed requests
A number of fixes to "readmore" to fix page jumping
Bugfix: persons other than the channel owner who have permission to upload photos to a channel could not do so if the js_upload plugin/addon was enabled
Siteinfo incorrectly identifying secondary directory servers
Allow admin to set and lock features when UNO is configured
Allow admin to set and lock features when UNO is configured
Atom feeds: alter how events are formatted to be compatible with GNU-social
Allow guest/visitor access to view personal calendar
Moved several more classes to "composer format" and provided an autoloader.
Bugfix: require existing password to change password
Bugfix: allow relative_date() to be translated to Polish which has more than two plural forms.
Bugfix: allow relative_date() to be translated to Polish which has more than two plural forms.
Plugin API: add "requires" keyword to module header to indicate dependent addons
ActivityStreams improvements and cleanup: photo and file activities
UI cleanup for editing profile when multiple profiles enabled
Removed the "markdown" feature as there are numerous issues and no maintainer.
Provide "footer" bbcode to ease theming of post footer content
Bugfix: install issues caused by composer code refactor and typo in postgres load file
Bugfix: install issues caused by composer code refactor and typo in postgres load file
Plugins:
keepout - "block public on steroids"
pubsubhubbub - provides PuSH support to Atom feeds, required for GNU-social federation
@@ -2069,7 +2280,7 @@ Hubzilla 1.3
Diaspora protocol - some work to ease migration to the new signing format
Diaspost - disabled; numerous issues and no maintainer
smileybutton - theme work and fixed compatibility with other jot-tools plugins
Hubzilla 1.2
Provide extra HTTP security headers (several of them).
@@ -2079,7 +2290,7 @@ Hubzilla 1.2
Add locked features to siteinfo report to aid remote debugging
Provide version compatibility checking to plugins (minversion, maxversion, and minphpversion)
Account config storage
Provide optional integrated registration and channel create form
Provide optional integrated registration and channel create form
cli utility for managing addons
issue with sharing photo "items"
cover photo manager: upload, crop, and store
@@ -2101,7 +2312,7 @@ Hubzilla 1.2
proc_run modified to use exec() instead of proc_open() - causing issues on some PHP installations
remote delegation failure under a specific set of circumstances which we were finally able to duplicate
Delegation section of Channel Manager was missing names and contained useless notification icons.
Change "expire" channel setting to show system limit if there is one.
Change "expire" channel setting to show system limit if there is one.
Regression: provide a one-click ignore of pending connection
Config to control directory keyword generation on client and server.
"Collections" renamed to "Privacy Groups", documentation improved
@@ -2154,11 +2365,11 @@ Hubzilla 1.1
Addons/Plugins:
Pageheader addon ported from Friendica
Hubwall (allow admin to send email to all accounts on this hub) created
GNU-social - queueing added
Diaspora - fixes for various failures to update profile photos, updates to queue API
GNU-social - queueing added
Diaspora - fixes for various failures to update profile photos, updates to queue API
Cross Domain Authenticated Chess (Andrew Manning's repository)
And... the normal "lots of bugs fixed, translations updated, and documentation improved"
And... the normal "lots of bugs fixed, translations updated, and documentation improved"

31
SBOM.md
View File

@@ -3,30 +3,31 @@
|Name|Version|License|Source|
|----|-------|-------|------|
|blueimp/jquery-file-upload|10.31.0.0|MIT|https://github.com/vkhramtsov/jQuery-File-Upload.git|
|brick/math|0.9.2.0|MIT|https://github.com/brick/math.git|
|bshaffer/oauth2-server-php|1.11.1.0|MIT|https://github.com/bshaffer/oauth2-server-php.git|
|commerceguys/intl|1.0.5.0|MIT|https://github.com/commerceguys/intl.git|
|commerceguys/intl|1.0.7.0|MIT|https://github.com/commerceguys/intl.git|
|desandro/imagesloaded|4.1.4.0|MIT|https://github.com/desandro/imagesloaded.git|
|ezyang/htmlpurifier|4.13.0.0|LGPL-2.1-or-later|https://github.com/ezyang/htmlpurifier.git|
|league/html-to-markdown|4.10.0.0|MIT|https://github.com/thephpleague/html-to-markdown.git|
|lukasreschke/id3parser|0.0.3.0|GPL|https://github.com/LukasReschke/ID3Parser.git|
|michelf/php-markdown|1.9.0.0|BSD-3-Clause|https://github.com/michelf/php-markdown.git|
|paragonie/random_compat|9.99.99.0|MIT|https://github.com/paragonie/random_compat.git|
|pear/text_languagedetect|1.0.0.0|BSD-2-Clause|https://github.com/pear/Text_LanguageDetect.git|
|pear/text_languagedetect|1.0.1.0|BSD-2-Clause|https://github.com/pear/Text_LanguageDetect.git|
|phpseclib/phpseclib|2.0.30.0|MIT|https://github.com/phpseclib/phpseclib.git|
|psr/log|1.1.3.0|MIT|https://github.com/php-fig/log.git|
|ramsey/uuid|3.9.3.0|MIT|https://github.com/ramsey/uuid.git|
|sabre/dav|4.1.1.0|BSD-3-Clause|https://github.com/sabre-io/dav.git|
|sabre/event|5.1.0.0|BSD-3-Clause|https://github.com/sabre-io/event.git|
|sabre/http|5.1.0.0|BSD-3-Clause|https://github.com/sabre-io/http.git|
|sabre/uri|2.2.0.0|BSD-3-Clause|https://github.com/sabre-io/uri.git|
|sabre/vobject|4.3.1.0|BSD-3-Clause|https://github.com/sabre-io/vobject.git|
|sabre/xml|2.2.1.0|BSD-3-Clause|https://github.com/sabre-io/xml.git|
|simplepie/simplepie|1.5.5.0|BSD-3-Clause|https://github.com/simplepie/simplepie.git|
|smarty/smarty|3.1.36.0|LGPL-3.0|https://github.com/smarty-php/smarty.git|
|symfony/polyfill-ctype|1.13.1.0|MIT|https://github.com/symfony/polyfill-ctype.git|
|twbs/bootstrap|4.5.2.0|MIT|https://github.com/twbs/bootstrap.git|
|ramsey/collection|1.1.3.0|MIT|https://github.com/ramsey/collection.git|
|ramsey/uuid|4.1.1.0|MIT|https://github.com/ramsey/uuid.git|
|sabre/dav|4.1.5.0|BSD-3-Clause|https://github.com/sabre-io/dav.git|
|sabre/event|5.1.2.0|BSD-3-Clause|https://github.com/sabre-io/event.git|
|sabre/http|5.1.1.0|BSD-3-Clause|https://github.com/sabre-io/http.git|
|sabre/uri|2.2.1.0|BSD-3-Clause|https://github.com/sabre-io/uri.git|
|sabre/vobject|4.3.5.0|BSD-3-Clause|https://github.com/sabre-io/vobject.git|
|sabre/xml|2.2.3.0|BSD-3-Clause|https://github.com/sabre-io/xml.git|
|simplepie/simplepie|1.5.6.0|BSD-3-Clause|https://github.com/simplepie/simplepie.git|
|smarty/smarty|3.1.38.0|LGPL-3.0|https://github.com/smarty-php/smarty.git|
|symfony/polyfill-ctype|1.22.0.0|MIT|https://github.com/symfony/polyfill-ctype.git|
|twbs/bootstrap|4.6.0.0|MIT|https://github.com/twbs/bootstrap.git|
|fullcalendar/fullcalendar|4.4.2.0|MIT|https://github.com/fullcalendar/fullcalendar.git|
|miromannino/Justified-Gallery|3.8.1.0|MIT|https://github.com/miromannino/Justified-Gallery.git|
|fengyuanchen/cropperjs|1.5.7.0|MIT|https://github.com/fengyuanchen/cropperjs.git|
|ForkAwesome/Fork-Awesome|1.1.7.0|MIT,SIL OFL,CC BY 3.0|https://github.com/ForkAwesome/Fork-Awesome.git|
|leafo/sticky-kit|1.1.2.0|MIT|https://github.com/leafo/sticky-kit.git|
|jquery/jquery|3.5.1.0|MIT|https://github.com/jquery/jquery.git|

View File

@@ -54,7 +54,7 @@ class AccessList {
* * \e string \b channel_deny_gid => string of denied gids
*/
function __construct($channel) {
if($channel) {
if ($channel) {
$this->allow_cid = $channel['channel_allow_cid'];
$this->allow_gid = $channel['channel_allow_gid'];
$this->deny_cid = $channel['channel_deny_cid'];
@@ -99,7 +99,6 @@ class AccessList {
$this->allow_gid = $arr['allow_gid'];
$this->deny_cid = $arr['deny_cid'];
$this->deny_gid = $arr['deny_gid'];
$this->explicit = $explicit;
}

View File

@@ -2,6 +2,7 @@
namespace Zotlabs\Access;
use App;
use Zotlabs\Lib\PConfig;
/**
@@ -39,10 +40,10 @@ class PermissionLimits {
*/
static public function Std_Limits() {
$limits = [];
$perms = Permissions::Perms();
$perms = Permissions::Perms();
foreach($perms as $k => $v) {
if(strstr($k, 'view'))
foreach ($perms as $k => $v) {
if (strstr($k, 'view'))
$limits[$k] = PERMS_PUBLIC;
else
$limits[$k] = PERMS_SPECIFIC;
@@ -77,14 +78,14 @@ class PermissionLimits {
* * \b array with all permission limits, if $perm is not set
*/
static public function Get($channel_id, $perm = '') {
if($perm) {
if ($perm) {
return intval(PConfig::Get($channel_id, 'perm_limits', $perm));
}
PConfig::Load($channel_id);
if(array_key_exists($channel_id, \App::$config)
&& array_key_exists('perm_limits', \App::$config[$channel_id]))
return \App::$config[$channel_id]['perm_limits'];
if (array_key_exists($channel_id, App::$config)
&& array_key_exists('perm_limits', App::$config[$channel_id]))
return App::$config[$channel_id]['perm_limits'];
return false;
}

View File

@@ -218,13 +218,13 @@ class PermissionRoles {
// set permissionlimits for this permission here, for example:
// if($perm === 'mynewperm')
// \Zotlabs\Access\PermissionLimits::Set($uid,$perm,1);
// PermissionLimits::Set($uid,$perm,1);
if($perm === 'view_wiki')
\Zotlabs\Access\PermissionLimits::Set($uid, $perm, PERMS_PUBLIC);
PermissionLimits::Set($uid, $perm, PERMS_PUBLIC);
if($perm === 'write_wiki')
\Zotlabs\Access\PermissionLimits::Set($uid, $perm, PERMS_SPECIFIC);
PermissionLimits::Set($uid, $perm, PERMS_SPECIFIC);
// set autoperms here if applicable
@@ -262,11 +262,11 @@ class PermissionRoles {
case 'view_wiki':
set_abconfig($uid,$ab['abook_xchan'],'my_perms',$perm,
intval(get_abconfig($uid,$ab['abook_xchan'],'my_perms','view_pages')));
break;
case 'write_wiki':
set_abconfig($uid,$ab['abook_xchan'],'my_perms',$perm,
intval(get_abconfig($uid,$ab['abook_xchan'],'my_perms','write_pages')));
break;
default:
break;
}
@@ -317,4 +317,4 @@ class PermissionRoles {
return $roles;
}
}
}

View File

@@ -75,7 +75,7 @@ class Permissions {
$x = [
'permissions' => $perms,
'filter' => $filter
'filter' => $filter
];
/**
* @hooks permissions_list
@@ -84,7 +84,7 @@ class Permissions {
*/
call_hooks('permissions_list', $x);
return($x['permissions']);
return ($x['permissions']);
}
/**
@@ -96,10 +96,10 @@ class Permissions {
*/
static public function BlockedAnonPerms() {
$res = [];
$res = [];
$perms = PermissionLimits::Std_limits();
foreach($perms as $perm => $limit) {
if($limit != PERMS_PUBLIC) {
foreach ($perms as $perm => $limit) {
if ($limit != PERMS_PUBLIC) {
$res[] = $perm;
}
}
@@ -111,7 +111,7 @@ class Permissions {
*/
call_hooks('write_perms', $x);
return($x['permissions']);
return ($x['permissions']);
}
/**
@@ -120,20 +120,20 @@ class Permissions {
* Converts [ 0 => 'view_stream', ... ]
* to [ 'view_stream' => 1 ] for any permissions in $arr;
* Undeclared permissions which exist in Perms() are added and set to 0.
*
*
* @param array $arr
* @return array
*/
static public function FilledPerms($arr) {
if(is_null($arr)) {
if (is_null($arr)) {
btlogger('FilledPerms: null');
$arr = [];
}
$everything = self::Perms();
$ret = [];
foreach($everything as $k => $v) {
if(in_array($k, $arr))
$ret = [];
foreach ($everything as $k => $v) {
if (in_array($k, $arr))
$ret[$k] = 1;
else
$ret[$k] = 0;
@@ -155,9 +155,9 @@ class Permissions {
*/
static public function OPerms($arr) {
$ret = [];
if($arr) {
foreach($arr as $k => $v) {
$ret[] = [ 'name' => $k, 'value' => $v ];
if ($arr) {
foreach ($arr as $k => $v) {
$ret[] = ['name' => $k, 'value' => $v];
}
}
return $ret;
@@ -170,15 +170,16 @@ class Permissions {
* @return boolean|array
*/
static public function FilledAutoperms($channel_id) {
if(! intval(get_pconfig($channel_id,'system','autoperms')))
if (!intval(get_pconfig($channel_id, 'system', 'autoperms')))
return false;
$arr = [];
$r = q("select * from pconfig where uid = %d and cat = 'autoperms'",
intval($channel_id)
);
if($r) {
foreach($r as $rr) {
if ($r) {
foreach ($r as $rr) {
$arr[$rr['k']] = intval($rr['v']);
}
}
@@ -193,11 +194,11 @@ class Permissions {
* @return boolean true if all perms from $p1 exist also in $p2
*/
static public function PermsCompare($p1, $p2) {
foreach($p1 as $k => $v) {
if(! array_key_exists($k, $p2))
foreach ($p1 as $k => $v) {
if (!array_key_exists($k, $p2))
return false;
if($p1[$k] != $p2[$k])
if ($p1[$k] != $p2[$k])
return false;
}
@@ -214,18 +215,18 @@ class Permissions {
*/
static public function connect_perms($channel_id) {
$my_perms = [];
$permcat = null;
$my_perms = [];
$permcat = null;
$automatic = 0;
// If a default permcat exists, use that
$pc = ((feature_enabled($channel_id,'permcats')) ? get_pconfig($channel_id,'system','default_permcat') : 'default');
if(! in_array($pc, [ '','default' ])) {
$pcp = new Zlib\Permcat($channel_id);
$pc = ((feature_enabled($channel_id, 'permcats')) ? get_pconfig($channel_id, 'system', 'default_permcat') : 'default');
if (!in_array($pc, ['', 'default'])) {
$pcp = new Zlib\Permcat($channel_id);
$permcat = $pcp->fetch($pc);
if($permcat && $permcat['perms']) {
foreach($permcat['perms'] as $p) {
if ($permcat && $permcat['perms']) {
foreach ($permcat['perms'] as $p) {
$my_perms[$p['name']] = $p['value'];
}
}
@@ -235,15 +236,15 @@ class Permissions {
// and if there was no permcat or a default permcat, set the perms
// from the role
$role = get_pconfig($channel_id,'system','permissions_role');
if($role) {
$role = get_pconfig($channel_id, 'system', 'permissions_role');
if ($role) {
$xx = PermissionRoles::role_perms($role);
if($xx['perms_auto'])
if ($xx['perms_auto'])
$automatic = 1;
if((! $my_perms) && ($xx['perms_connect'])) {
if ((!$my_perms) && ($xx['perms_connect'])) {
$default_perms = $xx['perms_connect'];
$my_perms = Permissions::FilledPerms($default_perms);
$my_perms = Permissions::FilledPerms($default_perms);
}
}
@@ -251,11 +252,11 @@ class Permissions {
// it is likely a custom permissions role. First see if there are any
// automatic permissions.
if(! $my_perms) {
if (!$my_perms) {
$m = Permissions::FilledAutoperms($channel_id);
if($m) {
if ($m) {
$automatic = 1;
$my_perms = $m;
$my_perms = $m;
}
}
@@ -263,35 +264,35 @@ class Permissions {
// custom perms but they are not automatic. They will be stored in abconfig with
// the channel's channel_hash (the 'self' connection).
if(! $my_perms) {
if (!$my_perms) {
$r = q("select channel_hash from channel where channel_id = %d",
intval($channel_id)
);
if($r) {
if ($r) {
$x = q("select * from abconfig where chan = %d and xchan = '%s' and cat = 'my_perms'",
intval($channel_id),
dbesc($r[0]['channel_hash'])
);
if($x) {
foreach($x as $xv) {
if ($x) {
foreach ($x as $xv) {
$my_perms[$xv['k']] = intval($xv['v']);
}
}
}
}
return ( [ 'perms' => $my_perms, 'automatic' => $automatic ] );
return (['perms' => $my_perms, 'automatic' => $automatic]);
}
static public function serialise($p) {
$n = [];
if($p) {
foreach($p as $k => $v) {
if(intval($v)) {
if ($p) {
foreach ($p as $k => $v) {
if (intval($v)) {
$n[] = $k;
}
}
}
return implode(',',$n);
return implode(',', $n);
}
}

View File

@@ -2,13 +2,12 @@
namespace Zotlabs\Daemon;
require_once('include/zot.php');
class Addon {
static public function run($argc,$argv) {
static public function run($argc, $argv) {
call_hooks('daemon_addon',$argv);
call_hooks('daemon_addon', $argv);
}
}

View File

@@ -2,7 +2,6 @@
namespace Zotlabs\Daemon;
class Cache_embeds {
static public function run($argc,$argv) {

View File

@@ -0,0 +1,36 @@
<?php
namespace Zotlabs\Daemon;
use Zotlabs\Lib\Cache;
class Cache_query {
static public function run($argc, $argv) {
if(! $argc == 3)
return;
$key = $argv[1];
$pid = get_config('procid', $key, false);
if ($pid && (function_exists('posix_kill') ? posix_kill($pid, 0) : true)) {
logger($key . ': procedure already run with pid ' . $pid, LOGGER_DEBUG);
return;
}
$pid = getmypid();
set_config('procid', $key, $pid);
array_shift($argv);
array_shift($argv);
$arr = json_decode(base64_decode($argv[0]), true);
$r = call_user_func_array('q', $arr);
if($r)
Cache::set($key, serialize($r));
del_config('procid', $key);
}
}

View File

@@ -6,34 +6,35 @@ require_once('include/hubloc.php');
class Checksites {
static public function run($argc,$argv) {
static public function run($argc, $argv) {
logger('checksites: start');
if(($argc > 1) && ($argv[1]))
if (($argc > 1) && ($argv[1]))
$site_id = $argv[1];
if($site_id)
if ($site_id)
$sql_options = " and site_url = '" . dbesc($argv[1]) . "' ";
$days = intval(get_config('system','sitecheckdays'));
if($days < 1)
$days = intval(get_config('system', 'sitecheckdays'));
if ($days < 1)
$days = 30;
$r = q("select * from site where site_dead = 0 and site_update < %s - INTERVAL %s and site_type = %d $sql_options ",
db_utcnow(), db_quoteinterval($days . ' DAY'),
db_utcnow(),
db_quoteinterval($days . ' DAY'),
intval(SITE_TYPE_ZOT)
);
if(! $r)
if (!$r)
return;
foreach($r as $rr) {
if(! strcasecmp($rr['site_url'],z_root()))
foreach ($r as $rr) {
if (!strcasecmp($rr['site_url'], z_root()))
continue;
$x = ping_site($rr['site_url']);
if($x['success']) {
if ($x['success']) {
logger('checksites: ' . $rr['site_url']);
q("update site set site_update = '%s' where site_url = '%s' ",
dbesc(datetime_convert()),

58
Zotlabs/Daemon/Convo.php Normal file
View File

@@ -0,0 +1,58 @@
<?php
namespace Zotlabs\Daemon;
use Zotlabs\Lib\Activity;
use Zotlabs\Lib\ActivityStreams;
use Zotlabs\Lib\ASCollection;
class Convo {
static public function run($argc, $argv) {
logger('convo invoked: ' . print_r($argv, true));
if ($argc != 4) {
return;
}
$id = $argv[1];
$channel_id = intval($argv[2]);
$contact_hash = $argv[3];
$channel = channelx_by_n($channel_id);
if (!$channel) {
return;
}
$r = q("SELECT abook.*, xchan.* FROM abook left join xchan on abook_xchan = xchan_hash
WHERE abook_channel = %d and abook_xchan = '%s' LIMIT 1",
intval($channel_id),
dbesc($contact_hash)
);
if (!$r) {
return;
}
$contact = array_shift($r);
$obj = new ASCollection($id, $channel);
$messages = $obj->get();
if ($messages) {
foreach ($messages as $message) {
if (is_string($message)) {
$message = Activity::fetch($message, $channel);
}
// set client flag because comments will probably just be objects and not full blown activities
// and that lets us use implied_create
$AS = new ActivityStreams($message);
if ($AS->is_valid() && is_array($AS->obj)) {
$item = Activity::decode_note($AS);
Activity::store($channel, $contact['abook_xchan'], $AS, $item);
}
}
}
}
}

View File

@@ -6,14 +6,14 @@ use Zotlabs\Lib\Libsync;
class Cron {
static public function run($argc,$argv) {
static public function run($argc, $argv) {
$maxsysload = intval(get_config('system','maxloadavg'));
if($maxsysload < 1)
$maxsysload = intval(get_config('system', 'maxloadavg'));
if ($maxsysload < 1)
$maxsysload = 50;
if(function_exists('sys_getloadavg')) {
if (function_exists('sys_getloadavg')) {
$load = sys_getloadavg();
if(intval($load[0]) > $maxsysload) {
if (intval($load[0]) > $maxsysload) {
logger('system: load ' . $load . ' too high. Cron deferred to next scheduled run.');
return;
}
@@ -21,17 +21,18 @@ class Cron {
// Check for a lockfile. If it exists, but is over an hour old, it's stale. Ignore it.
$lockfile = 'store/[data]/cron';
if((file_exists($lockfile)) && (filemtime($lockfile) > (time() - 3600))
&& (! get_config('system','override_cron_lockfile'))) {
if ((file_exists($lockfile)) && (filemtime($lockfile) > (time() - 3600))
&& (!get_config('system', 'override_cron_lockfile'))) {
logger("cron: Already running");
return;
}
// Create a lockfile. Needs two vars, but $x doesn't need to contain anything.
$x = '';
file_put_contents($lockfile, $x);
logger('cron: start');
// run queue delivery process in the background
Master::Summon(array('Queue'));
@@ -46,7 +47,7 @@ class Cron {
db_utcnow(),
db_quoteinterval('3 MINUTE')
);
// expire any expired mail
q("delete from mail where expires > '%s' and expires < %s ",
@@ -54,19 +55,23 @@ class Cron {
db_utcnow()
);
$interval = get_config('system', 'delivery_interval', 3);
// expire any expired items
$r = q("select id,item_wall from item where expires > '2001-01-01 00:00:00' and expires < %s
and item_deleted = 0 ",
db_utcnow()
);
if($r) {
if ($r) {
require_once('include/items.php');
foreach($r as $rr) {
drop_item($rr['id'],false,(($rr['item_wall']) ? DROPITEM_PHASE1 : DROPITEM_NORMAL));
if($rr['item_wall']) {
foreach ($r as $rr) {
drop_item($rr['id'], false, (($rr['item_wall']) ? DROPITEM_PHASE1 : DROPITEM_NORMAL));
if ($rr['item_wall']) {
// The notifier isn't normally invoked unless item_drop is interactive.
Master::Summon( [ 'Notifier', 'drop', $rr['id'] ] );
Master::Summon(['Notifier', 'drop', $rr['id']]);
if ($interval)
@time_sleep_until(microtime(true) + (float)$interval);
}
}
}
@@ -78,9 +83,9 @@ class Cron {
dbesc(NULL_DATE),
db_utcnow()
);
if($r) {
if ($r) {
require_once('include/security.php');
foreach($r as $rr) {
foreach ($r as $rr) {
atoken_delete($rr['atoken_id']);
}
}
@@ -90,33 +95,33 @@ class Cron {
// or dead entries.
$r = q("select channel_id from channel where channel_dirdate < %s - INTERVAL %s and channel_removed = 0",
db_utcnow(),
db_utcnow(),
db_quoteinterval('30 DAY')
);
if($r) {
foreach($r as $rr) {
Master::Summon(array('Directory',$rr['channel_id'],'force'));
if($interval)
@time_sleep_until(microtime(true) + (float) $interval);
if ($r) {
foreach ($r as $rr) {
Master::Summon(array('Directory', $rr['channel_id'], 'force'));
if ($interval)
@time_sleep_until(microtime(true) + (float)$interval);
}
}
// Clean expired photos from cache
$r = q("SELECT DISTINCT xchan, content FROM photo WHERE photo_usage = %d AND expires < %s - INTERVAL %s",
intval(PHOTO_CACHE),
db_utcnow(),
db_quoteinterval(get_config('system','active_expire_days', '30') . ' DAY')
db_quoteinterval(get_config('system', 'active_expire_days', '30') . ' DAY')
);
if($r) {
if ($r) {
q("DELETE FROM photo WHERE photo_usage = %d AND expires < %s - INTERVAL %s",
intval(PHOTO_CACHE),
db_utcnow(),
db_quoteinterval(get_config('system','active_expire_days', '30') . ' DAY')
db_quoteinterval(get_config('system', 'active_expire_days', '30') . ' DAY')
);
foreach($r as $rr) {
foreach ($r as $rr) {
$file = dbunescbin($rr['content']);
if(is_file($file)) {
if (is_file($file)) {
@unlink($file);
@rmdir(dirname($file));
logger('info: deleted cached photo file ' . $file, LOGGER_DEBUG);
@@ -130,27 +135,29 @@ class Cron {
$r = q("select id from item where item_delayed = 1 and created <= %s and created > '%s' ",
db_utcnow(),
dbesc(datetime_convert('UTC','UTC','now - 2 days'))
dbesc(datetime_convert('UTC', 'UTC', 'now - 2 days'))
);
if($r) {
foreach($r as $rr) {
if ($r) {
foreach ($r as $rr) {
$x = q("update item set item_delayed = 0 where id = %d",
intval($rr['id'])
);
if($x) {
if ($x) {
$z = q("select * from item where id = %d",
intval($message_id)
intval($rr['id'])
);
if($z) {
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) ]
[
'item' => [encode_item($sync_item[0], true)]
]
);
}
Master::Summon(array('Notifier','wall-new',$rr['id']));
Master::Summon(array('Notifier', 'wall-new', $rr['id']));
if ($interval)
@time_sleep_until(microtime(true) + (float)$interval);
}
}
}
@@ -163,27 +170,22 @@ class Cron {
require_once('include/attach.php');
attach_upgrade();
$abandon_days = intval(get_config('system','account_abandon_days'));
if($abandon_days < 1)
$abandon_days = 0;
// once daily run birthday_updates and then expire in background
// FIXME: add birthday updates, both locally and for xprof for use
// by directory servers
$d1 = intval(get_config('system','last_expire_day'));
$d2 = intval(datetime_convert('UTC','UTC','now','d'));
$d1 = intval(get_config('system', 'last_expire_day'));
$d2 = intval(datetime_convert('UTC', 'UTC', 'now', 'd'));
// Allow somebody to staggger daily activities if they have more than one site on their server,
// or if it happens at an inconvenient (busy) hour.
$h1 = intval(get_config('system','cron_hour'));
$h2 = intval(datetime_convert('UTC','UTC','now','G'));
$h1 = intval(get_config('system', 'cron_hour'));
$h2 = intval(datetime_convert('UTC', 'UTC', 'now', 'G'));
if(($d2 != $d1) && ($h1 == $h2)) {
if (($d2 != $d1) && ($h1 == $h2)) {
Master::Summon(array('Cron_daily'));
}
@@ -192,14 +194,14 @@ class Cron {
$r = q("select xchan_photo_l, xchan_hash from xchan where xchan_photo_l != '' and xchan_photo_m = ''
and xchan_photo_date < %s - INTERVAL %s",
db_utcnow(),
db_utcnow(),
db_quoteinterval('1 DAY')
);
if($r) {
if ($r) {
require_once('include/photo/photo_driver.php');
foreach($r as $rr) {
foreach ($r as $rr) {
$photos = import_xchan_photo($rr['xchan_photo_l'], $rr['xchan_hash'], false, true);
$x = q("update xchan set xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s'
q("update xchan set xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s'
where xchan_hash = '%s'",
dbesc($photos[0]),
dbesc($photos[1]),
@@ -213,31 +215,28 @@ class Cron {
// pull in some public posts
$disable_discover_tab = get_config('system','disable_discover_tab') || get_config('system','disable_discover_tab') === false;
if(! $disable_discover_tab)
/* $disable_discover_tab = get_config('system', 'disable_discover_tab') || get_config('system', 'disable_discover_tab') === false;
if (!$disable_discover_tab)
Master::Summon(array('Externals'));
*/
$generation = 0;
$restart = false;
$restart = false;
if(($argc > 1) && ($argv[1] == 'restart')) {
$restart = true;
if (($argc > 1) && ($argv[1] == 'restart')) {
$restart = true;
$generation = intval($argv[2]);
if(! $generation)
if (!$generation)
return;
}
reload_plugins();
$d = datetime_convert();
// TODO check to see if there are any cronhooks before wasting a process
if(! $restart)
if (!$restart)
Master::Summon(array('Cronhooks'));
set_config('system','lastcron',datetime_convert());
set_config('system', 'lastcron', datetime_convert());
//All done - clear the lockfile
@unlink($lockfile);

View File

@@ -2,9 +2,11 @@
namespace Zotlabs\Daemon;
use Zotlabs\Lib\Libzotdir;
class Cron_daily {
static public function run($argc,$argv) {
static public function run($argc, $argv) {
logger('cron_daily: start');
@@ -13,15 +15,12 @@ class Cron_daily {
*
*/
require_once('include/dir_fns.php');
check_upstream_directory();
Libzotdir::check_upstream_directory();
// Fire off the Cron_weekly process if it's the correct day.
$d3 = intval(datetime_convert('UTC','UTC','now','N'));
if($d3 == 7) {
$d3 = intval(datetime_convert('UTC', 'UTC', 'now', 'N'));
if ($d3 == 7) {
Master::Summon(array('Cron_weekly'));
}
@@ -52,8 +51,8 @@ class Cron_daily {
// Clean up emdedded content cache
q("DELETE FROM cache WHERE updated < %s - INTERVAL %s",
db_utcnow(),
db_quoteinterval(get_config('system','active_expire_days', '30') . ' DAY')
db_utcnow(),
db_quoteinterval(get_config('system', 'active_expire_days', '30') . ' DAY')
);
//update statistics in config
@@ -67,8 +66,8 @@ class Cron_daily {
// expire old delivery reports
$keep_reports = intval(get_config('system','expire_delivery_reports'));
if($keep_reports === 0)
$keep_reports = intval(get_config('system', 'expire_delivery_reports'));
if ($keep_reports === 0)
$keep_reports = 10;
q("delete from dreport where dreport_time < %s - INTERVAL %s",
@@ -80,18 +79,16 @@ class Cron_daily {
downgrade_accounts();
// If this is a directory server, request a sync with an upstream
// directory at least once a day, up to once every poll interval.
// directory at least once a day, up to once every poll interval.
// Pull remote changes and push local changes.
// potential issue: how do we keep from creating an endless update loop?
// potential issue: how do we keep from creating an endless update loop?
$dirmode = get_config('system','directory_mode');
$dirmode = get_config('system', 'directory_mode');
if($dirmode == DIRECTORY_MODE_SECONDARY || $dirmode == DIRECTORY_MODE_PRIMARY) {
require_once('include/dir_fns.php');
sync_directories($dirmode);
if ($dirmode == DIRECTORY_MODE_SECONDARY || $dirmode == DIRECTORY_MODE_PRIMARY) {
Libzotdir::sync_directories($dirmode);
}
Master::Summon(array('Expire'));
Master::Summon(array('Cli_suggest'));
@@ -99,9 +96,10 @@ class Cron_daily {
z6_discover();
call_hooks('cron_daily',datetime_convert());
$date = datetime_convert();
call_hooks('cron_daily', $date);
set_config('system','last_expire_day',intval(datetime_convert('UTC','UTC','now','d')));
set_config('system', 'last_expire_day', intval(datetime_convert('UTC', 'UTC', 'now', 'd')));
/**
* End Cron Daily

View File

@@ -4,21 +4,22 @@ namespace Zotlabs\Daemon;
class Cron_weekly {
static public function run($argc,$argv) {
static public function run($argc, $argv) {
/**
* Cron Weekly
*
*
* Actions in the following block are executed once per day only on Sunday (once per week).
*
*/
call_hooks('cron_weekly',datetime_convert());
$date = datetime_convert();
call_hooks('cron_weekly', $date);
z_check_cert();
prune_hub_reinstalls();
mark_orphan_hubsxchans();
// Find channels that were removed in the last three weeks, but
@@ -31,8 +32,8 @@ class Cron_weekly {
db_utcnow(), db_quoteinterval('21 DAY'),
db_utcnow(), db_quoteinterval('10 DAY')
);
if($r) {
foreach($r as $rv) {
if ($r) {
foreach ($r as $rv) {
channel_remove_final($rv['channel_id']);
}
}
@@ -43,14 +44,14 @@ class Cron_weekly {
db_utcnow(), db_quoteinterval('14 DAY')
);
$dirmode = intval(get_config('system','directory_mode'));
if($dirmode === DIRECTORY_MODE_SECONDARY || $dirmode === DIRECTORY_MODE_PRIMARY) {
logger('regdir: ' . print_r(z_fetch_url(get_directory_primary() . '/regdir?f=&url=' . urlencode(z_root()) . '&realm=' . urlencode(get_directory_realm())),true));
$dirmode = intval(get_config('system', 'directory_mode'));
if ($dirmode === DIRECTORY_MODE_SECONDARY || $dirmode === DIRECTORY_MODE_PRIMARY) {
logger('regdir: ' . print_r(z_fetch_url(get_directory_primary() . '/regdir?f=&url=' . urlencode(z_root()) . '&realm=' . urlencode(get_directory_realm())), true));
}
// Check for dead sites
Master::Summon(array('Checksites'));
// update searchable doc indexes
Master::Summon(array('Importdoc'));

View File

@@ -2,6 +2,8 @@
namespace Zotlabs\Daemon;
use App;
// generate a curl compatible cookie file with an authenticated session for the given channel_id.
// If this file is then used with curl and the destination url is sent through zid() or manually
// manipulated to add a zid, it should allow curl to provide zot magic-auth across domains.
@@ -10,15 +12,15 @@ namespace Zotlabs\Daemon;
class CurlAuth {
static public function run($argc,$argv) {
static public function run($argc, $argv) {
if($argc != 2)
if ($argc != 2)
return;
\App::$session->start();
App::$session->start();
$_SESSION['authenticated'] = 1;
$_SESSION['uid'] = $argv[1];
$_SESSION['uid'] = $argv[1];
$x = session_id();
@@ -29,14 +31,14 @@ class CurlAuth {
$output = '';
if($e) {
if ($e) {
$lines = file($f);
if($lines) {
foreach($lines as $line) {
if(strlen($line) > 0 && $line[0] != '#' && substr_count($line, "\t") == 6) {
if ($lines) {
foreach ($lines as $line) {
if (strlen($line) > 0 && $line[0] != '#' && substr_count($line, "\t") == 6) {
$tokens = explode("\t", $line);
$tokens = array_map('trim', $tokens);
if($tokens[4] > time()) {
if ($tokens[4] > time()) {
$output .= $line . "\n";
}
}
@@ -46,9 +48,9 @@ class CurlAuth {
}
}
$t = time() + (24 * 3600);
file_put_contents($f, $output . 'HttpOnly_' . \App::get_hostname() . "\tFALSE\t/\tTRUE\t$t\tPHPSESSID\t" . $x, (($e) ? FILE_APPEND : 0));
file_put_contents($f, $output . 'HttpOnly_' . App::get_hostname() . "\tFALSE\t/\tTRUE\t$t\tPHPSESSID\t" . $x, (($e) ? FILE_APPEND : 0));
file_put_contents($c,$x);
file_put_contents($c, $x);
return;
}

View File

@@ -5,25 +5,25 @@ namespace Zotlabs\Daemon;
require_once('include/queue_fn.php');
class Deliver {
static public function run($argc,$argv) {
if($argc < 2)
static public function run($argc, $argv) {
if ($argc < 2)
return;
logger('deliver: invoked: ' . print_r($argv,true), LOGGER_DATA);
logger('deliver: invoked: ' . print_r($argv, true), LOGGER_DATA);
for($x = 1; $x < $argc; $x ++) {
for ($x = 1; $x < $argc; $x++) {
if(! $argv[$x])
if (!$argv[$x])
continue;
$r = q("select * from outq where outq_hash = '%s'",
dbesc($argv[$x])
);
if($r) {
queue_deliver($r[0],true);
if ($r) {
queue_deliver($r[0], true);
}
}

View File

@@ -2,21 +2,18 @@
namespace Zotlabs\Daemon;
require_once('include/zot.php');
class Deliver_hooks {
static public function run($argc,$argv) {
static public function run($argc, $argv) {
if($argc < 2)
if ($argc < 2)
return;
$r = q("select * from item where id = '%d'",
intval($argv[1])
);
if($r)
call_hooks('notifier_normal',$r[0]);
if ($r)
call_hooks('notifier_normal', $r[0]);
}
}

View File

@@ -8,40 +8,40 @@ use Zotlabs\Lib\Queue;
class Directory {
static public function run($argc,$argv){
static public function run($argc, $argv) {
if($argc < 2)
if ($argc < 2)
return;
$force = false;
$force = false;
$pushall = true;
if($argc > 2) {
if($argv[2] === 'force')
if ($argc > 2) {
if ($argv[2] === 'force')
$force = true;
if($argv[2] === 'nopush')
if ($argv[2] === 'nopush')
$pushall = false;
}
}
logger('directory update', LOGGER_DEBUG);
$dirmode = get_config('system','directory_mode');
if($dirmode === false)
$dirmode = get_config('system', 'directory_mode');
if ($dirmode === false)
$dirmode = DIRECTORY_MODE_NORMAL;
$x = q("select * from channel where channel_id = %d limit 1",
intval($argv[1])
);
if(! $x)
if (!$x)
return;
$channel = $x[0];
if($dirmode != DIRECTORY_MODE_NORMAL) {
if ($dirmode != DIRECTORY_MODE_NORMAL) {
// this is an in-memory update and we don't need to send a network packet.
Libzotdir::local_dir_update($argv[1],$force);
Libzotdir::local_dir_update($argv[1], $force);
q("update channel set channel_dirdate = '%s' where channel_id = %d",
dbesc(datetime_convert()),
@@ -49,8 +49,8 @@ class Directory {
);
// Now update all the connections
if($pushall)
Master::Summon(array('Notifier','refresh_all',$channel['channel_id']));
if ($pushall)
Master::Summon(array('Notifier', 'refresh_all', $channel['channel_id']));
return;
}
@@ -63,14 +63,12 @@ class Directory {
// ensure the upstream directory is updated
$packet = Libzot::build_packet($channel,(($force) ? 'force_refresh' : 'refresh'));
$z = Libzot::zot($url,$packet,$channel);
$packet = Libzot::build_packet($channel, (($force) ? 'force_refresh' : 'refresh'));
$z = Libzot::zot($url, $packet, $channel);
// re-queue if unsuccessful
if(! $z['success']) {
if (!$z['success']) {
/** @FIXME we aren't updating channel_dirdate if we have to queue
* the directory packet. That means we'll try again on the next poll run.
@@ -95,8 +93,8 @@ class Directory {
}
// Now update all the connections
if($pushall)
Master::Summon(array('Notifier','refresh_all',$channel['channel_id']));
if ($pushall)
Master::Summon(array('Notifier', 'refresh_all', $channel['channel_id']));
}
}

View File

@@ -5,23 +5,24 @@ namespace Zotlabs\Daemon;
class Expire {
static public function run($argc,$argv){
static public function run($argc, $argv) {
cli_startup();
$pid = get_config('expire', 'procid', false);
$pid = get_config('procid', 'expire', false);
if ($pid && (function_exists('posix_kill') ? posix_kill($pid, 0) : true)) {
logger('Expire: procedure already run with pid ' . $pid, LOGGER_DEBUG);
return;
logger('procedure already run with pid ' . $pid, LOGGER_DEBUG);
return;
}
$pid = getmypid();
set_config('expire', 'procid', $pid);
set_config('procid', 'expire', $pid);
// 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",
db_utcnow(), db_quoteinterval('10 DAY')
db_utcnow(),
db_quoteinterval('10 DAY')
);
if ($r) {
foreach ($r as $rr) {
@@ -32,23 +33,22 @@ class Expire {
// physically remove anything that has been deleted for more than two months
/** @FIXME - this is a wretchedly inefficient query */
$r = q("delete from item where item_pending_remove = 1 and changed < %s - INTERVAL %s",
db_utcnow(), db_quoteinterval('36 DAY')
q("delete from item where item_pending_remove = 1 and changed < %s - INTERVAL %s",
db_utcnow(),
db_quoteinterval('36 DAY')
);
/** @FIXME make this optional as it could have a performance impact on large sites */
if (intval(get_config('system', 'optimize_items')))
q("optimize table item");
logger('expire: start with pid ' . $pid, LOGGER_DEBUG);
$site_expire = intval(get_config('system', 'default_expire_days'));
$commented_days = intval(get_config('system','active_expire_days'));
$site_expire = intval(get_config('system', 'default_expire_days'));
$commented_days = intval(get_config('system', 'active_expire_days'));
logger('site_expire: ' . $site_expire);
$r = q("SELECT channel_id, channel_system, channel_address, channel_expire_days from channel where true");
$r = dbq("SELECT channel_id, channel_system, channel_address, channel_expire_days from channel where true");
if ($r) {
foreach ($r as $rr) {
@@ -64,11 +64,12 @@ class Expire {
$channel_expire = $service_class_expire;
else
$channel_expire = $site_expire;
if (intval($channel_expire) && (intval($channel_expire) < intval($rr['channel_expire_days'])) ||
intval($rr['channel_expire_days'] == 0)) {
$expire_days = $channel_expire;
} else {
}
else {
$expire_days = $rr['channel_expire_days'];
}
@@ -93,13 +94,13 @@ class Expire {
}
logger('Expire: sys interval: ' . $expire_days, LOGGER_DEBUG);
if ($expire_days)
item_expire($x['channel_id'], $expire_days, $commented_days);
logger('Expire: sys: done', LOGGER_DEBUG);
}
del_config('expire', 'procid');
del_config('procid', 'expire');
}
}

View File

@@ -2,97 +2,180 @@
namespace Zotlabs\Daemon;
require_once('include/zot.php');
use Zotlabs\Lib\Activity;
use Zotlabs\Lib\ActivityStreams;
use Zotlabs\Lib\ASCollection;
require_once('include/channel.php');
class Externals {
static public function run($argc,$argv){
static public function run($argc, $argv) {
$total = 0;
logger('externals: start');
$importer = get_sys_channel();
$total = 0;
$attempts = 0;
logger('externals: startup', LOGGER_DEBUG);
// pull in some public posts
while ($total == 0 && $attempts < 3) {
$arr = ['url' => ''];
call_hooks('externals_url_select', $arr);
while($total == 0 && $attempts < 3) {
$arr = array('url' => '');
call_hooks('externals_url_select',$arr);
if($arr['url']) {
if ($arr['url']) {
$url = $arr['url'];
}
}
else {
$randfunc = db_getfunc('RAND');
// fixme this query does not deal with directory realms.
// fixme this query does not deal with directory realms.
$r = q("select site_url, site_pull from site where site_url != '%s' and site_flags != %d and site_type = %d and site_dead = 0 order by $randfunc limit 1",
$r = q("select site_url, site_pull from site where site_url != '%s'
and site_flags != %d and site_type = %d
and site_dead = 0 and site_project like '%s' and site_version > '5.3.1' order by $randfunc limit 1",
dbesc(z_root()),
intval(DIRECTORY_MODE_STANDALONE),
intval(SITE_TYPE_ZOT)
intval(SITE_TYPE_ZOT),
dbesc('hubzilla%')
);
if($r)
if ($r)
$url = $r[0]['site_url'];
}
$blacklisted = false;
if(! check_siteallowed($url)) {
if (!check_siteallowed($url)) {
logger('blacklisted site: ' . $url);
$blacklisted = true;
}
$attempts ++;
$attempts++;
// make sure we can eventually break out if somebody blacklists all known sites
if($blacklisted) {
if($attempts > 20)
if ($blacklisted) {
if ($attempts > 20)
break;
$attempts --;
$attempts--;
continue;
}
if($url) {
if($r[0]['site_pull'] > NULL_DATE)
$mindate = urlencode(datetime_convert('','',$r[0]['site_pull'] . ' - 1 day'));
else {
$days = get_config('externals','since_days');
if($days === false)
$days = 15;
$mindate = urlencode(datetime_convert('','','now - ' . intval($days) . ' days'));
}
if ($url) {
$feedurl = $url . '/zotfeed?f=&mindate=' . $mindate;
$max = intval(get_config('system', 'max_imported_posts', 30));
if (intval($max)) {
logger('externals: fetching outbox');
logger('externals: pulling public content from ' . $feedurl, LOGGER_DEBUG);
$feed_url = $url . '/zotfeed';
$obj = new ASCollection($feed_url, $importer, 0, $max);
$messages = $obj->get();
$x = z_fetch_url($feedurl);
if(($x) && ($x['success'])) {
q("update site set site_pull = '%s' where site_url = '%s'",
dbesc(datetime_convert()),
dbesc($url)
);
$j = json_decode($x['body'],true);
if($j['success'] && $j['messages']) {
$sys = get_sys_channel();
foreach($j['messages'] as $message) {
// on these posts, clear any route info.
$message['route'] = '';
$results = process_delivery(array('hash' => 'undefined'), get_item_elements($message),
array(array('hash' => $sys['xchan_hash'])), false, true);
$total ++;
if ($messages) {
foreach ($messages as $message) {
if (is_string($message)) {
$message = Activity::fetch($message, $importer);
}
$AS = new ActivityStreams($message);
if ($AS->is_valid() && is_array($AS->obj)) {
$item = Activity::decode_note($AS);
Activity::store($importer, $importer['xchan_hash'], $AS, $item, true);
$total++;
}
}
logger('externals: import_public_posts: ' . $total . ' messages imported', LOGGER_DEBUG);
}
logger('externals: import_public_posts: ' . $total . ' messages imported', LOGGER_DEBUG);
}
}
}
return;
/* $total = 0;
$attempts = 0;
logger('externals: startup', LOGGER_DEBUG);
// pull in some public posts
while ($total == 0 && $attempts < 3) {
$arr = ['url' => ''];
call_hooks('externals_url_select', $arr);
if ($arr['url']) {
$url = $arr['url'];
}
else {
$randfunc = db_getfunc('RAND');
// fixme this query does not deal with directory realms.
$r = q("select site_url, site_pull from site where site_url != '%s' and site_flags != %d and site_type = %d and site_dead = 0 order by $randfunc limit 1",
dbesc(z_root()),
intval(DIRECTORY_MODE_STANDALONE),
intval(SITE_TYPE_ZOT)
);
if ($r)
$url = $r[0]['site_url'];
}
$blacklisted = false;
if (!check_siteallowed($url)) {
logger('blacklisted site: ' . $url);
$blacklisted = true;
}
$attempts++;
// make sure we can eventually break out if somebody blacklists all known sites
if ($blacklisted) {
if ($attempts > 20)
break;
$attempts--;
continue;
}
if ($url) {
if ($r[0]['site_pull'] > NULL_DATE)
$mindate = urlencode(datetime_convert('', '', $r[0]['site_pull'] . ' - 1 day'));
else {
$days = get_config('externals', 'since_days');
if ($days === false)
$days = 15;
$mindate = urlencode(datetime_convert('', '', 'now - ' . intval($days) . ' days'));
}
$feedurl = $url . '/zotfeed?f=&mindate=' . $mindate;
logger('externals: pulling public content from ' . $feedurl, LOGGER_DEBUG);
$x = z_fetch_url($feedurl);
if (($x) && ($x['success'])) {
q("update site set site_pull = '%s' where site_url = '%s'",
dbesc(datetime_convert()),
dbesc($url)
);
$j = json_decode($x['body'], true);
if ($j['success'] && $j['messages']) {
$sys = get_sys_channel();
foreach ($j['messages'] as $message) {
// on these posts, clear any route info.
$message['route'] = '';
process_delivery(['hash' => 'undefined'], get_item_elements($message),
[['hash' => $sys['xchan_hash']]], false, true);
$total++;
}
logger('externals: import_public_posts: ' . $total . ' messages imported', LOGGER_DEBUG);
}
}
}
}*/
}
}

View File

@@ -9,27 +9,27 @@ use Zotlabs\Lib\Zotfinger;
// performs zot_finger on $argv[1], which is a hex_encoded webbie/reddress
class Gprobe {
static public function run($argc,$argv) {
static public function run($argc, $argv) {
if($argc != 2)
if ($argc != 2)
return;
$url = hex2bin($argv[1]);
if(! strpos($url,'@'))
if (!strpos($url, '@'))
return;
$r = q("select * from hubloc where hubloc_addr = '%s' limit 1",
$r = q("select * from hubloc where hubloc_addr = '%s' and hubloc_network = 'zot6' limit 1",
dbesc($url)
);
if(! $r) {
if (!$r) {
$href = Webfinger::zot_url(punify($url));
if($href) {
if ($href) {
$zf = Zotfinger::exec($href, null);
}
if(is_array($zf) && array_path_exists('signature/signer',$zf) && $zf['signature']['signer'] === $href && intval($zf['signature']['header_valid'])) {
$xc = Libzot::import_xchan($zf['data']);
if (is_array($zf) && array_path_exists('signature/signer', $zf) && $zf['signature']['signer'] === $href && intval($zf['signature']['header_valid'])) {
Libzot::import_xchan($zf['data']);
}
}

14
Zotlabs/Daemon/Importdoc.php Executable file → Normal file
View File

@@ -5,7 +5,7 @@ namespace Zotlabs\Daemon;
class Importdoc {
static public function run($argc,$argv) {
static public function run($argc, $argv) {
require_once('include/help.php');
@@ -16,20 +16,20 @@ 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') {
if ($files) {
foreach ($files as $fi) {
if ($fi === 'doc/html') {
continue;
}
if(is_dir($fi)) {
if (is_dir($fi)) {
self::update_docs_dir("$fi/*");
}
else {
// don't update media content
if(strpos(z_mime_content_type($fi),'text') === 0) {
if (strpos(z_mime_content_type($fi), 'text') === 0) {
store_doc_file($fi);
}
}

View File

@@ -6,22 +6,21 @@ use Zotlabs\Lib\Libsync;
class Importfile {
static public function run($argc,$argv){
static public function run($argc, $argv) {
logger('Importfile: ' . print_r($argv,true));
logger('Importfile: ' . print_r($argv, true));
if($argc < 3)
if ($argc < 3)
return;
$channel = channelx_by_n($argv[1]);
if(! $channel)
if (!$channel)
return;
$srcfile = $argv[2];
$folder = (($argc > 3) ? $argv[3] : '');
$dstname = (($argc > 4) ? $argv[4] : '');
$hash = random_string();
$hash = random_string();
$arr = [
'src' => $srcfile,
@@ -35,15 +34,15 @@ class Importfile {
'replace' => true
];
if($folder)
if ($folder)
$arr['folder'] = $folder;
attach_store($channel,$channel['channel_hash'],'import',$arr);
attach_store($channel, $channel['channel_hash'], 'import', $arr);
$sync = attach_export_data($channel, $hash);
if ($sync)
Libsync::build_sync_packet($channel['channel_id'], ['file' => [$sync]]);
$sync = attach_export_data($channel,$hash);
if($sync)
Libsync::build_sync_packet($channel['channel_id'],array('file' => array($sync)));
return;
}
}

View File

@@ -2,58 +2,57 @@
namespace Zotlabs\Daemon;
if(array_search( __file__ , get_included_files()) === 0) {
if (array_search(__file__, get_included_files()) === 0) {
require_once('include/cli_startup.php');
array_shift($argv);
$argc = count($argv);
if($argc)
Master::Release($argc,$argv);
if ($argc)
Master::Release($argc, $argv);
return;
}
class Master {
static public function Summon($arr) {
$hookinfo = [
'argv'=>$arr
'argv' => $arr
];
call_hooks ('daemon_master_summon',$hookinfo);
call_hooks('daemon_master_summon', $hookinfo);
$arr = $hookinfo['argv'];
$arr = $hookinfo['argv'];
$argc = count($arr);
if ((!is_array($arr) || (count($arr) < 1))) {
logger("Summon handled by hook.",LOGGER_DEBUG);
if ((!is_array($arr) || ($argc < 1))) {
logger("Summon handled by hook.", LOGGER_DEBUG);
return;
}
$phpbin = get_config('system','phpbin','php');
proc_run($phpbin,'Zotlabs/Daemon/Master.php',$arr);
$phpbin = get_config('system', 'phpbin', 'php');
proc_run($phpbin, 'Zotlabs/Daemon/Master.php', $arr);
}
static public function Release($argc,$argv) {
static public function Release($argc, $argv) {
cli_startup();
$hookinfo = [
'argv'=>$argv
'argv' => $argv
];
call_hooks ('daemon_master_release',$hookinfo);
call_hooks('daemon_master_release', $hookinfo);
$argv = $hookinfo['argv'];
$argc = count($argv);
if ((!is_array($argv) || (count($argv) < 1))) {
logger("Release handled by hook.",LOGGER_DEBUG);
if ((!is_array($argv) || ($argc < 1))) {
logger("Release handled by hook.", LOGGER_DEBUG);
return;
}
logger('Master: release: ' . json_encode($argv), LOGGER_ALL,LOG_DEBUG);
$cls = '\\Zotlabs\\Daemon\\' . $argv[0];
$cls::run($argc,$argv);
logger('Master: release: ' . json_encode($argv), LOGGER_ALL, LOG_DEBUG);
$cls = '\\Zotlabs\\Daemon\\' . $argv[0];
$cls::run($argc, $argv);
}
}

View File

@@ -14,29 +14,28 @@ require_once('include/items.php');
require_once('include/bbcode.php');
/*
* This file was at one time responsible for doing all deliveries, but this caused
* big problems on shared hosting systems, where the process might get killed by the
* hosting provider and nothing would get delivered.
* big problems on shared hosting systems, where the process might get killed by the
* hosting provider and nothing would get delivered.
* It now only delivers one message under certain cases, and invokes a queued
* delivery mechanism (include/deliver.php) to deliver individual contacts at
* delivery mechanism (include/deliver.php) to deliver individual contacts at
* controlled intervals.
* This has a much better chance of surviving random processes getting killed
* by the hosting provider.
* by the hosting provider.
*
* The basic flow is:
* Identify the type of message
* Collect any information that needs to be sent
* Convert it into a suitable generic format for sending
* Figure out who the recipients are and if we need to relay
* Figure out who the recipients are and if we need to relay
* through a conversation owner
* Once we know what recipients are involved, collect a list of
* Once we know what recipients are involved, collect a list of
* destination sites
* Build and store a queue item for each unique site and invoke
* a delivery process for each site or a small number of sites (1-3)
* and add a slight delay between each delivery invocation if desired (usually)
*
*
*/
/*
@@ -61,7 +60,7 @@ require_once('include/bbcode.php');
*
* and ITEM_ID is the id of the item in the database that needs to be sent to others.
*
* ZOT
* ZOT
* permission_create abook_id
* permission_accept abook_id
* permission_reject abook_id
@@ -81,198 +80,198 @@ require_once('include/bbcode.php');
*/
class Notifier {
static public function run($argc,$argv){
static public function run($argc, $argv) {
if($argc < 3)
if ($argc < 3)
return;
logger('notifier: invoked: ' . print_r($argv,true), LOGGER_DEBUG);
logger('notifier: invoked: ' . print_r($argv, true), LOGGER_DEBUG);
$cmd = $argv[1];
$item_id = $argv[2];
if(! $item_id)
if (!$item_id)
return;
$sys = get_sys_channel();
$deliveries = array();
$deliveries = [];
$request = false;
$mail = false;
$top_level = false;
$location = false;
$recipients = array();
$url_recipients = array();
$normal_mode = true;
$packet_type = 'undefined';
$request = false;
$mail = false;
$location = false;
$recipients = [];
$normal_mode = true;
$packet_type = 'undefined';
if($cmd === 'mail' || $cmd === 'single_mail') {
if ($cmd === 'mail' || $cmd === 'single_mail') {
$normal_mode = false;
$mail = true;
$private = true;
$message = q("SELECT * FROM mail WHERE id = %d LIMIT 1",
intval($item_id)
$mail = true;
$private = true;
$message = q("SELECT * FROM mail WHERE id = %d LIMIT 1",
intval($item_id)
);
if(! $message) {
if (!$message) {
return;
}
xchan_mail_query($message[0]);
$uid = $message[0]['channel_id'];
$uid = $message[0]['channel_id'];
$recipients[] = $message[0]['from_xchan']; // include clones
$recipients[] = $message[0]['to_xchan'];
$item = $message[0];
$item = $message[0];
$encoded_item = encode_mail($item);
$s = q("select * from channel where channel_id = %d limit 1",
intval($item['channel_id'])
intval($uid)
);
if($s)
if ($s)
$channel = $s[0];
}
elseif($cmd === 'request') {
$channel_id = $item_id;
$xchan = $argv[3];
elseif ($cmd === 'request') {
$channel_id = $item_id;
$xchan = $argv[3];
$request_message_id = $argv[4];
$s = q("select * from channel where channel_id = %d limit 1",
intval($channel_id)
);
if($s)
if ($s)
$channel = $s[0];
$private = true;
$private = true;
$recipients[] = $xchan;
$packet_type = 'request';
$normal_mode = false;
$packet_type = 'request';
$normal_mode = false;
}
elseif($cmd === 'keychange') {
elseif ($cmd === 'keychange') {
$channel = channelx_by_n($item_id);
$r = q("select abook_xchan from abook where abook_channel = %d",
$r = q("select abook_xchan from abook where abook_channel = %d",
intval($item_id)
);
if($r) {
foreach($r as $rr) {
if ($r) {
foreach ($r as $rr) {
$recipients[] = $rr['abook_xchan'];
}
}
$private = false;
$private = false;
$packet_type = 'keychange';
$normal_mode = false;
}
elseif(in_array($cmd, [ 'permission_update', 'permission_reject', 'permission_accept', 'permission_create' ])) {
// Get the (single) recipient
elseif (in_array($cmd, ['permission_update', 'permission_reject', 'permission_accept', 'permission_create'])) {
// Get the (single) recipient
$r = q("select * from abook left join xchan on abook_xchan = xchan_hash where abook_id = %d and abook_self = 0",
intval($item_id)
);
if($r) {
if ($r) {
$uid = $r[0]['abook_channel'];
// Get the sender
$channel = channelx_by_n($uid);
if($channel) {
$perm_update = array('sender' => $channel, 'recipient' => $r[0], 'success' => false, 'deliveries' => '');
if ($channel) {
$perm_update = ['sender' => $channel, 'recipient' => $r[0], 'success' => false, 'deliveries' => ''];
if($cmd === 'permission_create')
call_hooks('permissions_create',$perm_update);
elseif($cmd === 'permission_accept')
call_hooks('permissions_accept',$perm_update);
elseif($cmd === 'permission_reject')
call_hooks('permissions_reject',$perm_update);
if ($cmd === 'permission_create')
call_hooks('permissions_create', $perm_update);
elseif ($cmd === 'permission_accept')
call_hooks('permissions_accept', $perm_update);
elseif ($cmd === 'permission_reject')
call_hooks('permissions_reject', $perm_update);
else
call_hooks('permissions_update',$perm_update);
call_hooks('permissions_update', $perm_update);
if($perm_update['success']) {
if($perm_update['deliveries']) {
if ($perm_update['success']) {
if ($perm_update['deliveries']) {
$deliveries[] = $perm_update['deliveries'];
do_delivery($deliveries);
}
return;
return;
}
else {
$recipients[] = $r[0]['abook_xchan'];
$private = false;
$packet_type = 'refresh';
$packet_recips = array(array('guid' => $r[0]['xchan_guid'],'guid_sig' => $r[0]['xchan_guid_sig'],'hash' => $r[0]['xchan_hash']));
$recipients[] = $r[0]['abook_xchan'];
$private = false;
$packet_type = 'refresh';
$packet_recips = [['guid' => $r[0]['xchan_guid'], 'guid_sig' => $r[0]['xchan_guid_sig'], 'hash' => $r[0]['xchan_hash']]];
}
}
}
}
elseif($cmd === 'refresh_all') {
elseif ($cmd === 'refresh_all') {
logger('notifier: refresh_all: ' . $item_id);
$uid = $item_id;
$uid = $item_id;
$channel = channelx_by_n($item_id);
$r = q("select abook_xchan from abook where abook_channel = %d",
intval($item_id)
$r = q("select abook_xchan from abook where abook_channel = %d",
intval($uid)
);
if($r) {
foreach($r as $rr) {
if ($r) {
foreach ($r as $rr) {
$recipients[] = $rr['abook_xchan'];
}
}
$private = false;
$private = false;
$packet_type = 'refresh';
}
elseif($cmd === 'location') {
elseif ($cmd === 'location') {
logger('notifier: location: ' . $item_id);
$s = q("select * from channel where channel_id = %d limit 1",
intval($item_id)
);
if($s)
if ($s)
$channel = $s[0];
$uid = $item_id;
$recipients = array();
$r = q("select abook_xchan from abook where abook_channel = %d",
intval($item_id)
$uid = $item_id;
$recipients = [];
$r = q("select abook_xchan from abook where abook_channel = %d",
intval($uid)
);
if($r) {
foreach($r as $rr) {
if ($r) {
foreach ($r as $rr) {
$recipients[] = $rr['abook_xchan'];
}
}
$encoded_item = array('locations' => zot_encode_locations($channel),'type' => 'location', 'encoding' => 'zot');
$target_item = array('aid' => $channel['channel_account_id'],'uid' => $channel['channel_id']);
$private = false;
$packet_type = 'location';
$location = true;
$encoded_item = ['locations' => Libzot::encode_locations($channel), 'type' => 'location', 'encoding' => 'zot'];
$target_item = ['aid' => $channel['channel_account_id'], 'uid' => $channel['channel_id']];
$private = false;
$packet_type = 'location';
$location = true;
}
elseif($cmd === 'purge') {
elseif ($cmd === 'purge') {
$xchan = $argv[3];
logger('notifier: purge: ' . $item_id . ' => ' . $xchan);
if (! $xchan) {
if (!$xchan) {
return;
}
$channel = channelx_by_n($item_id);
$recipients[] = $xchan;
$private = true;
$packet_type = 'purge';
$channel = channelx_by_n($item_id);
$recipients[] = $xchan;
$private = true;
$packet_type = 'purge';
$packet_recips[] = ['hash' => $xchan];
}
elseif($cmd === 'purge_all') {
elseif ($cmd === 'purge_all') {
logger('notifier: purge_all: ' . $item_id);
$channel = channelx_by_n($item_id);
$recipients = [];
$r = q("select abook_xchan from abook where abook_channel = %d and abook_self = 0",
$r = q("select abook_xchan from abook where abook_channel = %d and abook_self = 0",
intval($item_id)
);
if (! $r) {
if (!$r) {
return;
}
foreach ($r as $rr) {
$recipients[] = $rr['abook_xchan'];
$recipients[] = $rr['abook_xchan'];
$packet_recips[] = ['hash' => $rr['abook_xchan']];
}
$private = false;
$private = false;
$packet_type = 'purge';
@@ -287,34 +286,31 @@ class Notifier {
intval($item_id)
);
if(! $r)
if (!$r)
return;
xchan_query($r);
$r = fetch_post_tags($r);
$target_item = $r[0];
if(in_array($target_item['author']['xchan_network'], ['rss', 'anon'])) {
if (in_array($target_item['author']['xchan_network'], ['rss', 'anon'])) {
logger('notifier: target item author is not a fetchable actor', LOGGER_DEBUG);
return;
}
$deleted_item = false;
if(intval($target_item['item_deleted'])) {
if (intval($target_item['item_deleted'])) {
logger('notifier: target item ITEM_DELETED', LOGGER_DEBUG);
$deleted_item = true;
}
if(! in_array(intval($target_item['item_type']), [ ITEM_TYPE_POST ] )) {
$hookinfo=[
'targetitem'=>$target_item,
'deliver'=>false
if (!in_array(intval($target_item['item_type']), [ITEM_TYPE_POST])) {
$hookinfo = [
'targetitem' => $target_item,
'deliver' => false
];
if (intval($target_item['item_type'] == ITEM_TYPE_CUSTOM)) {
call_hooks('customitem_deliver',$hookinfo);
call_hooks('customitem_deliver', $hookinfo);
}
if (!$hookinfo['deliver']) {
@@ -328,14 +324,20 @@ class Notifier {
// Check for non published items, but allow an exclusion for transmitting hidden file activities
if(intval($target_item['item_unpublished']) || intval($target_item['item_delayed']) ||
intval($target_item['item_blocked']) ||
( intval($target_item['item_hidden']) && ($target_item['obj_type'] !== ACTIVITY_OBJ_FILE))) {
if (intval($target_item['item_unpublished']) || intval($target_item['item_delayed']) ||
intval($target_item['item_blocked']) ||
(intval($target_item['item_hidden']) && ($target_item['obj_type'] !== ACTIVITY_OBJ_FILE))) {
logger('notifier: target item not published, so not forwardable', LOGGER_DEBUG);
return;
}
if(strpos($target_item['postopts'],'nodeliver') !== false) {
// follow/unfollow is for internal use only
if (in_array($target_item['verb'], [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);
return;
}
@@ -343,17 +345,16 @@ class Notifier {
$s = q("select * from channel left join xchan on channel_hash = xchan_hash where channel_id = %d limit 1",
intval($target_item['uid'])
);
if($s)
if ($s)
$channel = $s[0];
if($channel['channel_hash'] !== $target_item['author_xchan'] && $channel['channel_hash'] !== $target_item['owner_xchan']) {
if ($channel['channel_hash'] !== $target_item['author_xchan'] && $channel['channel_hash'] !== $target_item['owner_xchan']) {
logger("notifier: Sending channel {$channel['channel_hash']} is not owner {$target_item['owner_xchan']} or author {$target_item['author_xchan']}", LOGGER_NORMAL, LOG_WARNING);
return;
}
if($target_item['mid'] === $target_item['parent_mid']) {
$parent_item = $target_item;
if ($target_item['mid'] === $target_item['parent_mid']) {
$parent_item = $target_item;
$top_level_post = true;
}
else {
@@ -362,58 +363,56 @@ class Notifier {
intval($target_item['parent'])
);
if(! $r)
if (!$r)
return;
if(strpos($r[0]['postopts'],'nodeliver') !== false) {
if (strpos($r[0]['postopts'], 'nodeliver') !== false) {
logger('notifier: target item is undeliverable', LOGGER_DEBUG, LOG_NOTICE);
return;
}
xchan_query($r);
$r = fetch_post_tags($r);
$parent_item = $r[0];
$parent_item = $r[0];
$top_level_post = false;
}
// avoid looping of discover items 12/4/2014
if($sys && $parent_item['uid'] == $sys['channel_id'])
if ($sys && $parent_item['uid'] == $sys['channel_id'])
return;
$encoded_item = encode_item($target_item);
// Re-use existing signature unless the activity type changed to a Tombstone, which won't verify.
$m = ((intval($target_item['item_deleted'])) ? '' : get_iconfig($target_item,'activitystreams','signed_data'));
$m = ((intval($target_item['item_deleted'])) ? '' : get_iconfig($target_item, 'activitypub', 'signed_data'));
if($m) {
$activity = json_decode($m,true);
if ($m) {
$activity = json_decode($m, true);
}
else {
$activity = array_merge(['@context' => [
ACTIVITYSTREAMS_JSONLD_REV,
'https://w3id.org/security/v1',
z_root() . ZOT_APSCHEMA_REV
]], Activity::encode_activity($target_item)
]], Activity::encode_activity($target_item)
);
}
}
logger('target_item: ' . print_r($target_item,true), LOGGER_DEBUG);
logger('encoded: ' . print_r($activity,true), LOGGER_DEBUG);
logger('target_item: ' . print_r($target_item, true), LOGGER_DEBUG);
logger('encoded: ' . print_r($activity, true), LOGGER_DEBUG);
// Send comments to the owner to re-deliver to everybody in the conversation
// We only do this if the item in question originated on this site. This prevents looping.
// To clarify, a site accepting a new comment is responsible for sending it to the owner for relay.
// Relaying should never be initiated on a post that arrived from elsewhere.
// Relaying should never be initiated on a post that arrived from elsewhere.
// We should normally be able to rely on ITEM_ORIGIN, but start_delivery_chain() incorrectly set this
// flag on comments for an extended period. So we'll also call comment_local_origin() which looks at
// the hostname in the message_id and provides a second (fallback) opinion.
$relay_to_owner = (((! $top_level_post) && (intval($target_item['item_origin'])) && comment_local_origin($target_item)) ? true : false);
// the hostname in the message_id and provides a second (fallback) opinion.
$relay_to_owner = (((!$top_level_post) && (intval($target_item['item_origin'])) && comment_local_origin($target_item)) ? true : false);
$uplink = false;
@@ -425,88 +424,79 @@ class Notifier {
// tag_deliver'd post which needs to be sent back to the original author
if(($cmd === 'uplink') && intval($parent_item['item_uplink']) && (! $top_level_post)) {
logger('notifier: uplink');
if (($cmd === 'uplink') && intval($parent_item['item_uplink']) && (!$top_level_post)) {
logger('notifier: uplink');
$uplink = true;
}
}
if(($relay_to_owner || $uplink) && ($cmd !== 'relay')) {
if (($relay_to_owner || $uplink) && ($cmd !== 'relay')) {
logger('notifier: followup relay', LOGGER_DEBUG);
$recipients = array(($uplink) ? $parent_item['source_xchan'] : $parent_item['owner_xchan']);
$private = true;
if(! $encoded_item['flags'])
$encoded_item['flags'] = array();
$recipients = [($uplink) ? $parent_item['source_xchan'] : $parent_item['owner_xchan']];
$private = true;
if (!$encoded_item['flags'])
$encoded_item['flags'] = [];
$encoded_item['flags'][] = 'relay';
$upstream = true;
$upstream = true;
}
else {
logger('notifier: normal distribution', LOGGER_DEBUG);
if($cmd === 'relay')
if ($cmd === 'relay')
logger('notifier: owner relay');
$upstream = false;
// if our parent is a tag_delivery recipient, uplink to the original author causing
// a delivery fork.
if(($parent_item) && intval($parent_item['item_uplink']) && (! $top_level_post) && ($cmd !== 'uplink')) {
// a delivery fork.
if (($parent_item) && intval($parent_item['item_uplink']) && (!$top_level_post) && ($cmd !== 'uplink')) {
// don't uplink a relayed post to the relay owner
if($parent_item['source_xchan'] !== $parent_item['owner_xchan']) {
if ($parent_item['source_xchan'] !== $parent_item['owner_xchan']) {
logger('notifier: uplinking this item');
Master::Summon(array('Notifier','uplink',$item_id));
Master::Summon(['Notifier', 'uplink', $item_id]);
}
}
$private = false;
$recipients = collect_recipients($parent_item,$private);
$private = false;
$recipients = collect_recipients($parent_item, $private);
if ($top_level_post) {
// remove clones who will receive the post via sync
$recipients = array_diff($recipients, [ $target_item['owner_xchan'] ]);
}
$recipients = array_diff($recipients, [$target_item['owner_xchan']]);
}
// FIXME add any additional recipients such as mentions, etc.
// don't send deletions onward for other people's stuff
// TODO verify this is needed - copied logic from same place in old code
if(intval($target_item['item_deleted']) && (! intval($target_item['item_wall']))) {
logger('notifier: ignoring delete notification for non-wall item', LOGGER_NORMAL, LOG_NOTICE);
return;
}
}
}
$walltowall = (($top_level_post && $channel['xchan_hash'] === $target_item['author_xchan']) ? true : false);
$walltowall = (($top_level_post && $channel['xchan_hash'] === $target_item['author_xchan']) ? true : false);
// Generic delivery section, we have an encoded item and recipients
// Now start the delivery process
$x = $encoded_item;
$x = $encoded_item;
$x['title'] = 'private';
$x['body'] = 'private';
logger('notifier: encoded item: ' . print_r($x,true), LOGGER_DATA, LOG_DEBUG);
$x['body'] = 'private';
logger('notifier: encoded item: ' . print_r($x, true), LOGGER_DATA, LOG_DEBUG);
//logger('notifier: encoded activity: ' . print_r($activity,true), LOGGER_DATA, LOG_DEBUG);
stringify_array_elms($recipients);
if(! $recipients) {
if (!$recipients) {
logger('no recipients');
return;
}
// logger('notifier: recipients: ' . print_r($recipients,true), LOGGER_NORMAL, LOG_DEBUG);
$env_recips = (($private) ? array() : null);
$env_recips = (($private) ? [] : null);
$details = q("select xchan_hash, xchan_network, xchan_addr, xchan_guid, xchan_guid_sig from xchan where xchan_hash in (" . protect_sprintf(implode(',',$recipients)) . ")");
$details = q("select xchan_hash, xchan_network, xchan_addr, xchan_guid, xchan_guid_sig from xchan where xchan_hash in (" . protect_sprintf(implode(',', $recipients)) . ")");
$recip_list = array();
$recip_list = [];
if($details) {
foreach($details as $d) {
$recip_list[] = $d['xchan_addr'] . ' (' . $d['xchan_hash'] . ')';
if($private) {
if ($details) {
foreach ($details as $d) {
$recip_list[] = $d['xchan_addr'] . ' (' . $d['xchan_hash'] . ')';
if ($private) {
$env_recips[] = [
'guid' => $d['xchan_guid'],
'guid_sig' => $d['xchan_guid_sig'],
@@ -542,8 +532,8 @@ class Notifier {
];
call_hooks('notifier_process', $narr);
if($narr['queued']) {
foreach($narr['queued'] as $pq)
if ($narr['queued']) {
foreach ($narr['queued'] as $pq)
$deliveries[] = $pq;
}
@@ -553,26 +543,26 @@ class Notifier {
$env_recips = $narr['env_recips'];
$packet_recips = $narr['packet_recips'];
if(($private) && (! $env_recips)) {
if (($private) && (!$env_recips)) {
// shouldn't happen
logger('notifier: private message with no envelope recipients.' . print_r($argv,true), LOGGER_NORMAL, LOG_NOTICE);
logger('notifier: private message with no envelope recipients.' . print_r($argv, true), LOGGER_NORMAL, LOG_NOTICE);
}
logger('notifier: recipients (may be delivered to more if public): ' . print_r($recip_list,true), LOGGER_DEBUG);
logger('notifier: recipients (may be delivered to more if public): ' . print_r($recip_list, true), LOGGER_DEBUG);
// Now we have collected recipients (except for external mentions, FIXME)
// Let's reduce this to a set of hubs; checking that the site is not dead.
$hubs = q("select hubloc.*, site.site_crypto, site.site_flags, site.site_version, site.site_project, site.site_dead from hubloc left join site on site_url = hubloc_url
where hubloc_hash in (" . protect_sprintf(implode(',',$recipients)) . ")
$hubs = q("select hubloc.*, site.site_crypto, site.site_flags, site.site_version, site.site_project, site.site_dead from hubloc left join site on site_url = hubloc_url
where hubloc_hash in (" . protect_sprintf(implode(',', $recipients)) . ")
and hubloc_error = 0 and hubloc_deleted = 0"
);
// public posts won't make it to the local public stream unless there's a recipient on this site.
// public posts won't make it to the local public stream unless there's a recipient on this site.
// This code block sees if it's a public post and localhost is missing, and if so adds an entry for the local sys channel to the $hubs list
if (! $private) {
if (!$private) {
$found_localhost = false;
if ($hubs) {
foreach ($hubs as $h) {
@@ -582,8 +572,8 @@ class Notifier {
}
}
}
if (! $found_localhost) {
$localhub = q("select hubloc.*, site.site_crypto, site.site_flags, site.site_version, site.site_project, site.site_dead from hubloc
if (!$found_localhost) {
$localhub = q("select hubloc.*, site.site_crypto, site.site_flags, site.site_version, site.site_project, site.site_dead from hubloc
left join site on site_url = hubloc_url where hubloc_id_url = '%s' and hubloc_error = 0 and hubloc_deleted = 0",
dbesc(z_root() . '/channel/sys')
);
@@ -592,14 +582,14 @@ class Notifier {
}
}
}
if(! $hubs) {
if (!$hubs) {
logger('notifier: no hubs', LOGGER_NORMAL, LOG_NOTICE);
return;
}
/**
* Reduce the hubs to those that are unique. For zot hubs, we need to verify uniqueness by the sitekey,
* Reduce the hubs to those that are unique. For zot hubs, we need to verify uniqueness by the sitekey,
* since it may have been a re-install which has not yet been detected and pruned.
* For other networks which don't have or require sitekeys, we'll have to use the URL
*/
@@ -612,48 +602,55 @@ class Notifier {
$hub_env = []; // per-hub envelope so we don't broadcast the entire envelope to all
$dead = []; // known dead hubs - report them as undeliverable
foreach($hubs as $hub) {
foreach ($hubs as $hub) {
if (intval($hub['site_dead'])) {
$dead[] = $hub;
continue;
}
if($env_recips) {
foreach($env_recips as $er) {
if($hub['hubloc_hash'] === $er['hash']) {
if(! array_key_exists($hub['hubloc_host'] . $hub['hubloc_sitekey'], $hub_env)) {
if ($env_recips) {
foreach ($env_recips as $er) {
if ($hub['hubloc_hash'] === $er['hash']) {
if (!array_key_exists($hub['hubloc_host'] . $hub['hubloc_sitekey'], $hub_env)) {
$hub_env[$hub['hubloc_host'] . $hub['hubloc_sitekey']] = [];
}
$hub_env[$hub['hubloc_host'] . $hub['hubloc_sitekey']][] = $er;
}
}
}
if($hub['hubloc_network'] == 'zot') {
if(! in_array($hub['hubloc_sitekey'],$keys)) {
if ($hub['hubloc_network'] == 'zot') {
if (!in_array($hub['hubloc_sitekey'], $keys)) {
$hublist[] = $hub['hubloc_host'] . ' ' . $hub['hubloc_network'];
$dhubs[] = $hub;
$keys[] = $hub['hubloc_sitekey'];
}
}
else {
if(! in_array($hub['hubloc_url'],$urls)) {
$hublist[] = $hub['hubloc_host'] . ' ' . $hub['hubloc_network'];
$dhubs[] = $hub;
$urls[] = $hub['hubloc_url'];
if (!in_array($hub['hubloc_url'], $urls)) {
if ($hub['hubloc_url'] === z_root()) {
//deliver to local hub first
array_unshift($hublist, $hub['hubloc_host'] . ' ' . $hub['hubloc_network']);
array_unshift($dhubs, $hub);
}
else {
$hublist[] = $hub['hubloc_host'] . ' ' . $hub['hubloc_network'];
$dhubs[] = $hub;
}
$urls[] = $hub['hubloc_url'];
}
}
}
logger('notifier: will notify/deliver to these hubs: ' . print_r($hublist,true), LOGGER_DEBUG, LOG_DEBUG);
logger('notifier: will notify/deliver to these hubs: ' . print_r($hublist, true), LOGGER_DEBUG, LOG_DEBUG);
foreach($dhubs as $hub) {
foreach ($dhubs as $hub) {
logger('notifier_hub: ' . $hub['hubloc_url'],LOGGER_DEBUG);
logger('notifier_hub: ' . $hub['hubloc_url'], LOGGER_DEBUG);
if(! in_array($hub['hubloc_network'], [ 'zot','zot6' ])) {
if (!in_array($hub['hubloc_network'], ['zot', 'zot6'])) {
$narr = [
'channel' => $channel,
'upstream' => $upstream,
@@ -680,9 +677,9 @@ class Notifier {
];
call_hooks('notifier_hub',$narr);
if($narr['queued']) {
foreach($narr['queued'] as $pq)
call_hooks('notifier_hub', $narr);
if ($narr['queued']) {
foreach ($narr['queued'] as $pq)
$deliveries[] = $pq;
}
continue;
@@ -698,43 +695,43 @@ class Notifier {
// will invoke a delivery to those connections which are connected to just that
// hub instance.
if($cmd === 'single_mail' || $cmd === 'single_activity') {
if ($cmd === 'single_mail' || $cmd === 'single_activity') {
continue;
}
if(! in_array($hub['hubloc_network'], [ 'zot','zot6' ])) {
if (!in_array($hub['hubloc_network'], ['zot', 'zot6'])) {
continue;
}
// Do not change this to a uuid as long as we have traditional zot servers
// in the loop. The signature verification step can't handle dashes in the
// hashes.
// in the loop. The signature verification step can't handle dashes in the
// hashes.
$hash = random_string(48);
$hash = random_string(48);
$packet = null;
$pmsg = '';
if($packet_type === 'refresh' || $packet_type === 'purge') {
if($hub['hubloc_network'] === 'zot6') {
$packet = Libzot::build_packet($channel, $packet_type, ids_to_array($packet_recips,'hash'));
if ($packet_type === 'refresh' || $packet_type === 'purge') {
if ($hub['hubloc_network'] === 'zot6') {
$packet = Libzot::build_packet($channel, $packet_type, ids_to_array($packet_recips, 'hash'));
}
else {
$packet = zot_build_packet($channel,$packet_type,(($packet_recips) ? $packet_recips : null));
$packet = zot_build_packet($channel, $packet_type, (($packet_recips) ? $packet_recips : null));
}
}
if($packet_type === 'keychange' && $hub['hubloc_network'] === 'zot') {
$pmsg = get_pconfig($channel['channel_id'],'system','keychange');
$packet = zot_build_packet($channel,$packet_type,(($packet_recips) ? $packet_recips : null));
if ($packet_type === 'keychange' && $hub['hubloc_network'] === 'zot') {
$pmsg = get_pconfig($channel['channel_id'], 'system', 'keychange');
$packet = zot_build_packet($channel, $packet_type, (($packet_recips) ? $packet_recips : null));
}
elseif($packet_type === 'request' && $hub['hubloc_network'] === 'zot') {
$env = (($hub_env && $hub_env[$hub['hubloc_host'] . $hub['hubloc_sitekey']]) ? $hub_env[$hub['hubloc_host'] . $hub['hubloc_sitekey']] : '');
$packet = zot_build_packet($channel,$packet_type,$env,$hub['hubloc_sitekey'],$hub['site_crypto'],
$hash, array('message_id' => $request_message_id)
elseif ($packet_type === 'request' && $hub['hubloc_network'] === 'zot') {
$env = (($hub_env && $hub_env[$hub['hubloc_host'] . $hub['hubloc_sitekey']]) ? $hub_env[$hub['hubloc_host'] . $hub['hubloc_sitekey']] : '');
$packet = zot_build_packet($channel, $packet_type, $env, $hub['hubloc_sitekey'], $hub['site_crypto'],
$hash, ['message_id' => $request_message_id]
);
}
if($packet) {
if ($packet) {
Queue::insert(
[
'hash' => $hash,
@@ -750,57 +747,56 @@ class Notifier {
else {
$env = (($hub_env && $hub_env[$hub['hubloc_host'] . $hub['hubloc_sitekey']]) ? $hub_env[$hub['hubloc_host'] . $hub['hubloc_sitekey']] : '');
if($hub['hubloc_network'] === 'zot6') {
if ($hub['hubloc_network'] === 'zot6') {
$zenv = [];
if($env) {
foreach($env as $e) {
if ($env) {
foreach ($env as $e) {
$zenv[] = $e['hash'];
}
}
$packet_type = (($upstream || $uplink) ? 'response' : 'activity');
$packet_type = (($upstream || $uplink) ? 'response' : 'activity');
// block zot private reshares from zot6, as this could cause a number of privacy issues
// due to parenting differences between the reshare implementations. In zot a reshare is
// a standalone parent activity and in zot6 it is a followup/child of the original activity.
// For public reshares, some comments to the reshare on the zot fork will not make it to zot6
// due to these different message models. This cannot be prevented at this time.
// due to these different message models. This cannot be prevented at this time.
if($packet_type === 'activity' && $activity['type'] === 'Announce' && intval($target_item['item_private'])) {
if ($packet_type === 'activity' && $activity['type'] === 'Announce' && intval($target_item['item_private'])) {
continue;
}
$packet = Libzot::build_packet($channel,$packet_type,$zenv,$activity,'activitystreams',(($private) ? $hub['hubloc_sitekey'] : null),$hub['site_crypto']);
$packet = Libzot::build_packet($channel, $packet_type, $zenv, $activity, 'activitystreams', (($private) ? $hub['hubloc_sitekey'] : null), $hub['site_crypto']);
}
else {
// currently zot6 delivery is only performed on normal items and not sync items or mail or anything else
// Eventually we will do this for all deliveries, but for now ensure this is precisely what we are dealing
// Eventually we will do this for all deliveries, but for now ensure this is precisely what we are dealing
// with before switching to zot6 as the primary zot6 handler checks for the existence of a message delivery report
// to trigger dequeue'ing
$z6 = (($encoded_item && $encoded_item['type'] === 'activity' && (! array_key_exists('allow_cid',$encoded_item))) ? true : false);
if($z6) {
$packet = zot6_build_packet($channel,'notify',$env, json_encode($encoded_item), (($private) ? $hub['hubloc_sitekey'] : null), $hub['site_crypto'],$hash);
$z6 = (($encoded_item && $encoded_item['type'] === 'activity' && (!array_key_exists('allow_cid', $encoded_item))) ? true : false);
if ($z6) {
$packet = zot6_build_packet($channel, 'notify', $env, json_encode($encoded_item), (($private) ? $hub['hubloc_sitekey'] : null), $hub['site_crypto'], $hash);
}
else {
$packet = zot_build_packet($channel,'notify',$env, (($private) ? $hub['hubloc_sitekey'] : null), $hub['site_crypto'],$hash);
$packet = zot_build_packet($channel, 'notify', $env, (($private) ? $hub['hubloc_sitekey'] : null), $hub['site_crypto'], $hash);
}
}
// remove this after most hubs have updated to version 5.0
if(stripos($hub['site_project'], 'hubzilla') !== false && version_compare($hub['site_version'], '4.7.3', '<=')) {
if($encoded_item['type'] === 'mail') {
$encoded_item['from']['network'] = 'zot';
if (stripos($hub['site_project'], 'hubzilla') !== false && version_compare($hub['site_version'], '4.7.3', '<=')) {
if ($encoded_item['type'] === 'mail') {
$encoded_item['from']['network'] = 'zot';
$encoded_item['from']['guid_sig'] = str_replace('sha256.', '', $encoded_item['from']['guid_sig']);
}
else {
$encoded_item['owner']['network'] = 'zot';
$encoded_item['owner']['network'] = 'zot';
$encoded_item['owner']['guid_sig'] = str_replace('sha256.', '', $encoded_item['owner']['guid_sig']);
if(strpos($encoded_item['author']['url'], z_root()) === 0) {
$encoded_item['author']['network'] = 'zot';
if (strpos($encoded_item['author']['url'], z_root()) === 0) {
$encoded_item['author']['network'] = 'zot';
$encoded_item['author']['guid_sig'] = str_replace('sha256.', '', $encoded_item['author']['guid_sig']);
}
}
@@ -819,7 +815,7 @@ class Notifier {
);
// only create delivery reports for normal undeleted items
if(is_array($target_item) && array_key_exists('postopts',$target_item) && (! $target_item['item_deleted']) && (! get_config('system','disable_dreport'))) {
if (is_array($target_item) && array_key_exists('postopts', $target_item) && (!$target_item['item_deleted']) && (!get_config('system', 'disable_dreport'))) {
q("insert into dreport ( dreport_mid, dreport_site, dreport_recip, dreport_result, dreport_time, dreport_xchan, dreport_queue ) values ( '%s','%s','%s','%s','%s','%s','%s' ) ",
dbesc($target_item['mid']),
dbesc($hub['hubloc_host']),
@@ -832,25 +828,25 @@ class Notifier {
}
}
$deliveries[] = $hash;
$deliveries[] = $hash;
}
if($normal_mode) {
if ($normal_mode) {
$x = q("select * from hook where hook = 'notifier_normal'");
if($x) {
Master::Summon( [ 'Deliver_hooks', $target_item['id'] ] );
if ($x) {
Master::Summon(['Deliver_hooks', $target_item['id']]);
}
}
if($deliveries)
if ($deliveries)
do_delivery($deliveries);
logger('notifier: basic loop complete.', LOGGER_DEBUG);
if ($dead) {
foreach ($dead as $deceased) {
if (is_array($target_item) && (! $target_item['item_deleted']) && (! get_config('system','disable_dreport'))) {
q("insert into dreport ( dreport_mid, dreport_site, dreport_recip, dreport_name, dreport_result, dreport_time, dreport_xchan, dreport_queue )
if (is_array($target_item) && (!$target_item['item_deleted']) && (!get_config('system', 'disable_dreport'))) {
q("insert into dreport ( dreport_mid, dreport_site, dreport_recip, dreport_name, dreport_result, dreport_time, dreport_xchan, dreport_queue )
values ( '%s', '%s','%s','%s','%s','%s','%s','%s' ) ",
dbesc($target_item['mid']),
dbesc($deceased['hubloc_host']),
@@ -865,7 +861,7 @@ class Notifier {
}
}
call_hooks('notifier_end',$target_item);
call_hooks('notifier_end', $target_item);
logger('notifer: complete.');
return;

View File

@@ -2,31 +2,34 @@
namespace Zotlabs\Daemon;
use Zotlabs\Lib\Libzot;
use Zotlabs\Lib\Libzotdir;
require_once('include/zot.php');
require_once('include/dir_fns.php');
class Onedirsync {
static public function run($argc,$argv) {
static public function run($argc, $argv) {
logger('onedirsync: start ' . intval($argv[1]));
if(($argc > 1) && (intval($argv[1])))
if (($argc > 1) && (intval($argv[1])))
$update_id = intval($argv[1]);
if(! $update_id) {
if (!$update_id) {
logger('onedirsync: no update');
return;
}
$r = q("select * from updates where ud_id = %d limit 1",
intval($update_id)
);
if(! $r)
if (!$r)
return;
if(($r[0]['ud_flags'] & UPDATE_FLAGS_UPDATED) || (! $r[0]['ud_addr']))
if (($r[0]['ud_flags'] & UPDATE_FLAGS_UPDATED) || (!$r[0]['ud_addr']))
return;
// Have we probed this channel more recently than the other directory server
@@ -38,8 +41,8 @@ class Onedirsync {
dbesc($r[0]['ud_date']),
intval(UPDATE_FLAGS_UPDATED)
);
if($x) {
$y = q("update updates set ud_flags = ( ud_flags | %d ) where ud_addr = '%s' and ( ud_flags & %d ) = 0 and ud_date != '%s'",
if ($x) {
q("update updates set ud_flags = ( ud_flags | %d ) where ud_addr = '%s' and ( ud_flags & %d ) = 0 and ud_date != '%s'",
intval(UPDATE_FLAGS_UPDATED),
dbesc($r[0]['ud_addr']),
intval(UPDATE_FLAGS_UPDATED),
@@ -50,11 +53,14 @@ class Onedirsync {
// ignore doing an update if this ud_addr refers to a known dead hubloc
$h = q("select * from hubloc where hubloc_addr = '%s' limit 1",
$h = q("select * from hubloc where hubloc_addr = '%s'",
dbesc($r[0]['ud_addr'])
);
if(($h) && ($h[0]['hubloc_status'] & HUBLOC_OFFLINE)) {
$y = q("update updates set ud_flags = ( ud_flags | %d ) where ud_addr = '%s' and ( ud_flags & %d ) = 0 ",
$h = Libzot::zot_record_preferred($h);
if (($h) && ($h['hubloc_status'] & HUBLOC_OFFLINE)) {
q("update updates set ud_flags = ( ud_flags | %d ) where ud_addr = '%s' and ( ud_flags & %d ) = 0 ",
intval(UPDATE_FLAGS_UPDATED),
dbesc($r[0]['ud_addr']),
intval(UPDATE_FLAGS_UPDATED)
@@ -63,13 +69,13 @@ class Onedirsync {
return;
}
// we might have to pull this out some day, but for now update_directory_entry()
// we might have to pull this out some day, but for now update_directory_entry()
// runs zot_finger() and is kind of zot specific
if($h && $h[0]['hubloc_network'] !== 'zot')
if ($h && !in_array($h['hubloc_network'], ['zot6', 'zot']))
return;
update_directory_entry($r[0]);
Libzotdir::update_directory_entry($r[0]);
return;
}

View File

@@ -2,68 +2,70 @@
namespace Zotlabs\Daemon;
use Zotlabs\Lib\Activity;
use Zotlabs\Lib\ActivityStreams;
use Zotlabs\Lib\ASCollection;
use Zotlabs\Lib\Libzot;
require_once('include/zot.php');
require_once('include/socgraph.php');
class Onepoll {
static public function run($argc,$argv) {
static public function run($argc, $argv) {
logger('onepoll: start');
if(($argc > 1) && (intval($argv[1])))
if (($argc > 1) && (intval($argv[1])))
$contact_id = intval($argv[1]);
if(! $contact_id) {
if (!$contact_id) {
logger('onepoll: no contact');
return;
}
$d = datetime_convert();
$sql_extra = '';
$allow_feeds = get_config('system', 'feed_contacts');
if(!$allow_feeds) {
$sql_extra = ' and abook_feed = 0 ';
}
$contacts = q("SELECT abook.*, xchan.*, account.*
FROM abook LEFT JOIN account on abook_account = account_id left join xchan on xchan_hash = abook_xchan
where abook_id = %d
FROM abook LEFT JOIN account on abook_account = account_id left join xchan on xchan_hash = abook_xchan
where abook_id = %d $sql_extra
and abook_pending = 0 and abook_archived = 0 and abook_blocked = 0 and abook_ignored = 0
AND (( account_flags = %d ) OR ( account_flags = %d )) limit 1",
intval($contact_id),
intval(ACCOUNT_OK),
intval(ACCOUNT_UNVERIFIED)
);
);
if(! $contacts) {
if (!$contacts) {
logger('onepoll: abook_id not found: ' . $contact_id);
return;
}
$contact = $contacts[0];
$t = $contact['abook_updated'];
$contact = array_shift($contacts);
$importer_uid = $contact['abook_channel'];
$r = q("SELECT * from channel left join xchan on channel_hash = xchan_hash where channel_id = %d limit 1",
intval($importer_uid)
);
if(! $r)
if (!$r)
return;
$importer = $r[0];
logger("onepoll: poll: ({$contact['id']}) IMPORTER: {$importer['xchan_name']}, CONTACT: {$contact['xchan_name']}");
$last_update = ((($contact['abook_updated'] === $contact['abook_created']) || ($contact['abook_updated'] <= NULL_DATE))
? datetime_convert('UTC','UTC','now - 7 days')
: datetime_convert('UTC','UTC',$contact['abook_updated'] . ' - 2 days')
$last_update = ((($contact['abook_updated'] === $contact['abook_created']) || ($contact['abook_updated'] <= NULL_DATE))
? datetime_convert('UTC', 'UTC', 'now - 7 days')
: datetime_convert('UTC', 'UTC', $contact['abook_updated'] . ' - 2 days')
);
if($contact['xchan_network'] === 'rss') {
if ($contact['xchan_network'] === 'rss') {
logger('onepoll: processing feed ' . $contact['xchan_name'], LOGGER_DEBUG);
$alive = handle_feed($importer['channel_id'],$contact_id,$contact['xchan_hash']);
$alive = handle_feed($importer['channel_id'], $contact_id, $contact['xchan_hash']);
if ($alive) {
q("update abook set abook_connected = '%s' where abook_id = %d",
dbesc(datetime_convert()),
@@ -72,22 +74,22 @@ class Onepoll {
}
return;
}
if(! in_array($contact['xchan_network'],['zot','zot6']))
if (!in_array($contact['xchan_network'], ['zot', 'zot6']))
return;
// update permissions
if($contact['xchan_network'] === 'zot6')
$x = Libzot::refresh($contact,$importer);
if ($contact['xchan_network'] === 'zot6')
$x = Libzot::refresh($contact, $importer);
if($contact['xchan_network'] === 'zot')
$x = zot_refresh($contact,$importer);
if ($contact['xchan_network'] === 'zot')
$x = zot_refresh($contact, $importer);
$responded = false;
$updated = datetime_convert();
$connected = datetime_convert();
if(! $x) {
if (!$x) {
// mark for death by not updating abook_connected, this is caught in include/poller.php
q("update abook set abook_updated = '%s' where abook_id = %d",
dbesc($updated),
@@ -103,83 +105,68 @@ class Onepoll {
$responded = true;
}
if(! $responded)
if (!$responded)
return;
if($contact['xchan_connurl']) {
$fetch_feed = true;
$x = null;
$fetch_feed = true;
$x = null;
// They haven't given us permission to see their stream
// They haven't given us permission to see their stream
$can_view_stream = intval(get_abconfig($importer_uid,$contact['abook_xchan'],'their_perms','view_stream'));
$can_view_stream = intval(get_abconfig($importer_uid, $contact['abook_xchan'], 'their_perms', 'view_stream'));
if(! $can_view_stream)
$fetch_feed = false;
if (!$can_view_stream)
$fetch_feed = false;
// we haven't given them permission to send us their stream
// we haven't given them permission to send us their stream
$can_send_stream = intval(get_abconfig($importer_uid,$contact['abook_xchan'],'my_perms','send_stream'));
if(! $can_send_stream)
$fetch_feed = false;
$can_send_stream = intval(get_abconfig($importer_uid, $contact['abook_xchan'], 'my_perms', 'send_stream'));
if($fetch_feed) {
if (!$can_send_stream)
$fetch_feed = false;
if(strpos($contact['xchan_connurl'],z_root()) === 0) {
// local channel - save a network fetch
$c = channelx_by_hash($contact['xchan_hash']);
if($c) {
$x = [
'success' => true,
'body' => json_encode( [
'success' => true,
'messages' => zot_feed($c['channel_id'], $importer['xchan_hash'], [ 'mindate' => $last_update ])
])
];
}
if ($fetch_feed && $contact['xchan_network'] !== 'zot') {
$max = intval(get_config('system', 'max_imported_posts', 30));
if (intval($max)) {
$cl = get_xconfig($contact['abook_xchan'], 'activitypub', 'collections');
if (is_array($cl) && $cl) {
$url = ((array_key_exists('outbox', $cl)) ? $cl['outbox'] : '');
}
else {
// remote fetch
$feedurl = str_replace('/poco/','/zotfeed/',$contact['xchan_connurl']);
$feedurl .= '?f=&mindate=' . urlencode($last_update) . '&zid=' . $importer['channel_address'] . '@' . \App::get_hostname();
$recurse = 0;
$x = z_fetch_url($feedurl, false, $recurse, [ 'session' => true ]);
$url = str_replace('/poco/', '/zotfeed/', $contact['xchan_connurl']);
}
logger('feed_update: ' . print_r($x,true), LOGGER_DATA);
}
if(($x) && ($x['success'])) {
$total = 0;
logger('onepoll: feed update ' . $contact['xchan_name'] . ' ' . $feedurl);
$j = json_decode($x['body'],true);
if($j['success'] && $j['messages']) {
foreach($j['messages'] as $message) {
$results = process_delivery(array('hash' => $contact['xchan_hash']), get_item_elements($message),
array(array('hash' => $importer['xchan_hash'])), false);
logger('onepoll: feed_update: process_delivery: ' . print_r($results,true), LOGGER_DATA);
$total ++;
if ($url) {
logger('fetching outbox');
$url = $url . '?date_begin=' . urlencode($last_update);
$obj = new ASCollection($url, $importer, 0, $max);
$messages = $obj->get();
if ($messages) {
foreach ($messages as $message) {
if (is_string($message)) {
$message = Activity::fetch($message, $importer);
}
$AS = new ActivityStreams($message);
if ($AS->is_valid() && is_array($AS->obj)) {
$item = Activity::decode_note($AS);
Activity::store($importer, $contact['abook_xchan'], $AS, $item);
}
}
}
logger("onepoll: $total messages processed");
}
}
}
// update the poco details for this connection
if($contact['xchan_connurl']) {
$r = q("SELECT xlink_id from xlink
where xlink_xchan = '%s' and xlink_updated > %s - INTERVAL %s and xlink_static = 0 limit 1",
intval($contact['xchan_hash']),
db_utcnow(), db_quoteinterval('1 DAY')
);
if(! $r) {
poco_load($contact['xchan_hash'],$contact['xchan_connurl']);
}
$r = q("SELECT xlink_id from xlink where xlink_xchan = '%s' and xlink_updated > %s - INTERVAL %s and xlink_static = 0 limit 1",
intval($contact['xchan_hash']),
db_utcnow(), db_quoteinterval('1 DAY')
);
if (!$r) {
poco_load($contact['xchan_hash'], $contact['xchan_connurl']);
}
return;

View File

@@ -4,73 +4,67 @@ namespace Zotlabs\Daemon;
class Poller {
static public function run($argc,$argv) {
static public function run($argc, $argv) {
$maxsysload = intval(get_config('system','maxloadavg'));
if($maxsysload < 1)
$maxsysload = intval(get_config('system', 'maxloadavg'));
if ($maxsysload < 1)
$maxsysload = 50;
if(function_exists('sys_getloadavg')) {
if (function_exists('sys_getloadavg')) {
$load = sys_getloadavg();
if(intval($load[0]) > $maxsysload) {
if (intval($load[0]) > $maxsysload) {
logger('system: load ' . $load . ' too high. Poller deferred to next scheduled run.');
return;
}
}
$interval = intval(get_config('system','poll_interval'));
if(! $interval)
$interval = ((get_config('system','delivery_interval') === false) ? 3 : intval(get_config('system','delivery_interval')));
$interval = intval(get_config('system', 'poll_interval'));
if (!$interval)
$interval = ((get_config('system', 'delivery_interval') === false) ? 3 : intval(get_config('system', 'delivery_interval')));
// Check for a lockfile. If it exists, but is over an hour old, it's stale. Ignore it.
$lockfile = 'store/[data]/poller';
if((file_exists($lockfile)) && (filemtime($lockfile) > (time() - 3600))
&& (! get_config('system','override_poll_lockfile'))) {
if ((file_exists($lockfile)) && (filemtime($lockfile) > (time() - 3600))
&& (!get_config('system', 'override_poll_lockfile'))) {
logger("poller: Already running");
return;
}
// Create a lockfile. Needs two vars, but $x doesn't need to contain anything.
$x = '';
file_put_contents($lockfile, $x);
logger('poller: start');
$manual_id = 0;
$generation = 0;
$force = false;
$force = false;
$restart = false;
if(($argc > 1) && ($argv[1] == 'force'))
if (($argc > 1) && ($argv[1] == 'force'))
$force = true;
if(($argc > 1) && ($argv[1] == 'restart')) {
$restart = true;
if (($argc > 1) && ($argv[1] == 'restart')) {
$generation = intval($argv[2]);
if(! $generation)
if (!$generation)
return;
}
if(($argc > 1) && intval($argv[1])) {
if (($argc > 1) && intval($argv[1])) {
$manual_id = intval($argv[1]);
$force = true;
}
$sql_extra = (($manual_id) ? " AND abook_id = " . intval($manual_id) . " " : "");
reload_plugins();
$d = datetime_convert();
// Only poll from those with suitable relationships
$abandon_sql = (($abandon_days)
? sprintf(" AND account_lastlog > %s - INTERVAL %s ", db_utcnow(), db_quoteinterval(intval($abandon_days).' DAY'))
: ''
$abandon_days = intval(get_config('system', 'account_abandon_days', 0));
$abandon_sql = (($abandon_days)
? sprintf(" AND account_lastlog > %s - INTERVAL %s ", db_utcnow(), db_quoteinterval(intval($abandon_days) . ' DAY'))
: ''
);
$randfunc = db_getfunc('RAND');
$contacts = q("SELECT abook.abook_updated, abook.abook_connected, abook.abook_feed,
abook.abook_channel, abook.abook_id, abook.abook_archived, abook.abook_pending,
abook.abook_ignored, abook.abook_blocked,
@@ -85,118 +79,117 @@ class Poller {
intval(ACCOUNT_UNVERIFIED) // FIXME
);
if($contacts) {
if ($contacts) {
foreach ($contacts as $contact) {
foreach($contacts as $contact) {
$update = false;
$update = false;
$t = $contact['abook_updated'];
$c = $contact['abook_connected'];
if(intval($contact['abook_feed'])) {
$min = service_class_fetch($contact['abook_channel'],'minimum_feedcheck_minutes');
if(! $min)
$min = intval(get_config('system','minimum_feedcheck_minutes'));
if(! $min)
if (intval($contact['abook_feed'])) {
$min = service_class_fetch($contact['abook_channel'], 'minimum_feedcheck_minutes');
if (!$min)
$min = intval(get_config('system', 'minimum_feedcheck_minutes'));
if (!$min)
$min = 60;
$x = datetime_convert('UTC','UTC',"now - $min minutes");
if($c < $x) {
Master::Summon(array('Onepoll',$contact['abook_id']));
if($interval)
@time_sleep_until(microtime(true) + (float) $interval);
$x = datetime_convert('UTC', 'UTC', "now - $min minutes");
if ($c < $x) {
Master::Summon(['Onepoll', $contact['abook_id']]);
if ($interval)
@time_sleep_until(microtime(true) + (float)$interval);
}
continue;
}
if(! in_array($contact['xchan_network'],['zot','zot6']))
if (!in_array($contact['xchan_network'], ['zot', 'zot6']))
continue;
if($c == $t) {
if(datetime_convert('UTC','UTC', 'now') > datetime_convert('UTC','UTC', $t . " + 1 day"))
if ($c == $t) {
if (datetime_convert('UTC', 'UTC', 'now') > datetime_convert('UTC', 'UTC', $t . " + 1 day"))
$update = true;
}
else {
// if we've never connected with them, start the mark for death countdown from now
if($c <= NULL_DATE) {
$r = q("update abook set abook_connected = '%s' where abook_id = %d",
if ($c <= NULL_DATE) {
q("update abook set abook_connected = '%s' where abook_id = %d",
dbesc(datetime_convert()),
intval($contact['abook_id'])
);
$c = datetime_convert();
$c = datetime_convert();
$update = true;
}
// He's dead, Jim
if(strcmp(datetime_convert('UTC','UTC', 'now'),datetime_convert('UTC','UTC', $c . " + 30 day")) > 0) {
$r = q("update abook set abook_archived = 1 where abook_id = %d",
if (strcmp(datetime_convert('UTC', 'UTC', 'now'), datetime_convert('UTC', 'UTC', $c . " + 30 day")) > 0) {
q("update abook set abook_archived = 1 where abook_id = %d",
intval($contact['abook_id'])
);
$update = false;
continue;
}
if(intval($contact['abook_archived'])) {
$update = false;
if (intval($contact['abook_archived'])) {
continue;
}
// might be dead, so maybe don't poll quite so often
// recently deceased, so keep up the regular schedule for 3 days
if((strcmp(datetime_convert('UTC','UTC', 'now'),datetime_convert('UTC','UTC', $c . " + 3 day")) > 0)
&& (strcmp(datetime_convert('UTC','UTC', 'now'),datetime_convert('UTC','UTC', $t . " + 1 day")) > 0))
if ((strcmp(datetime_convert('UTC', 'UTC', 'now'), datetime_convert('UTC', 'UTC', $c . " + 3 day")) > 0)
&& (strcmp(datetime_convert('UTC', 'UTC', 'now'), datetime_convert('UTC', 'UTC', $t . " + 1 day")) > 0))
$update = true;
// After that back off and put them on a morphine drip
if(strcmp(datetime_convert('UTC','UTC', 'now'),datetime_convert('UTC','UTC', $t . " + 2 day")) > 0) {
if (strcmp(datetime_convert('UTC', 'UTC', 'now'), datetime_convert('UTC', 'UTC', $t . " + 2 day")) > 0) {
$update = true;
}
}
if(intval($contact['abook_pending']) || intval($contact['abook_archived']) || intval($contact['abook_ignored']) || intval($contact['abook_blocked']))
if (intval($contact['abook_pending']) || intval($contact['abook_archived']) || intval($contact['abook_ignored']) || intval($contact['abook_blocked']))
continue;
if((! $update) && (! $force))
continue;
if ((!$update) && (!$force))
continue;
Master::Summon(array('Onepoll',$contact['abook_id']));
if($interval)
@time_sleep_until(microtime(true) + (float) $interval);
Master::Summon(['Onepoll', $contact['abook_id']]);
if ($interval)
@time_sleep_until(microtime(true) + (float)$interval);
}
}
if($dirmode == DIRECTORY_MODE_SECONDARY || $dirmode == DIRECTORY_MODE_PRIMARY) {
$dirmode = intval(get_config('system', 'directory_mode'));
if ($dirmode == DIRECTORY_MODE_SECONDARY || $dirmode == DIRECTORY_MODE_PRIMARY) {
$r = q("SELECT u.ud_addr, u.ud_id, u.ud_last FROM updates AS u INNER JOIN (SELECT ud_addr, max(ud_id) AS ud_id FROM updates WHERE ( ud_flags & %d ) = 0 AND ud_addr != '' AND ( ud_last <= '%s' OR ud_last > %s - INTERVAL %s ) GROUP BY ud_addr) AS s ON s.ud_id = u.ud_id ",
intval(UPDATE_FLAGS_UPDATED),
dbesc(NULL_DATE),
db_utcnow(), db_quoteinterval('7 DAY')
);
if($r) {
foreach($r as $rr) {
if ($r) {
foreach ($r as $rr) {
// If they didn't respond when we attempted before, back off to once a day
// After 7 days we won't bother anymore
if($rr['ud_last'] > NULL_DATE)
if($rr['ud_last'] > datetime_convert('UTC','UTC', 'now - 1 day'))
if ($rr['ud_last'] > NULL_DATE)
if ($rr['ud_last'] > datetime_convert('UTC', 'UTC', 'now - 1 day'))
continue;
Master::Summon(array('Onedirsync',$rr['ud_id']));
if($interval)
@time_sleep_until(microtime(true) + (float) $interval);
Master::Summon(['Onedirsync', $rr['ud_id']]);
if ($interval)
@time_sleep_until(microtime(true) + (float)$interval);
}
}
}
}
set_config('system','lastpoll',datetime_convert());
set_config('system', 'lastpoll', datetime_convert());
//All done - clear the lockfile

View File

@@ -7,12 +7,12 @@ require_once('include/zot.php');
class Queue {
static public function run($argc,$argv) {
static public function run($argc, $argv) {
require_once('include/items.php');
require_once('include/bbcode.php');
if($argc > 1)
if ($argc > 1)
$queue_id = $argv[1];
else
$queue_id = EMPTY_STR;
@@ -25,10 +25,9 @@ class Queue {
$r = q("select outq_posturl from outq where outq_created < %s - INTERVAL %s",
db_utcnow(), db_quoteinterval('3 DAY')
);
if($r) {
foreach($r as $rr) {
$site_url = '';
$h = parse_url($rr['outq_posturl']);
if ($r) {
foreach ($r as $rr) {
$h = parse_url($rr['outq_posturl']);
$desturl = $h['scheme'] . '://' . $h['host'] . (($h['port']) ? ':' . $h['port'] : '');
q("update site set site_dead = 1 where site_dead = 0 and site_url = '%s' and site_update < %s - INTERVAL %s",
dbesc($desturl),
@@ -37,11 +36,11 @@ class Queue {
}
}
$r = q("DELETE FROM outq WHERE outq_created < %s - INTERVAL %s",
q("DELETE FROM outq WHERE outq_created < %s - INTERVAL %s",
db_utcnow(), db_quoteinterval('3 DAY')
);
if($queue_id) {
if ($queue_id) {
$r = q("SELECT * FROM outq WHERE outq_hash = '%s' LIMIT 1",
dbesc($queue_id)
);
@@ -54,7 +53,7 @@ class Queue {
// so that we don't start off a thousand deliveries for a couple of dead hubs.
// The zot driver will deliver everything destined for a single hub once contact is made (*if* contact is made).
// Other drivers will have to do something different here and may need their own query.
// Note: this requires some tweaking as new posts to long dead hubs once a day will keep them in the
// "every 15 minutes" category. We probably need to prioritise them when inserted into the queue
// or just prior to this query based on recent and long-term delivery history. If we have good reason to believe
@@ -67,7 +66,7 @@ class Queue {
db_utcnow()
);
while ($r) {
foreach($r as $rv) {
foreach ($r as $rv) {
queue_deliver($rv);
}
$r = q("SELECT *,$sqlrandfunc as rn FROM outq WHERE outq_delivered = 0 and outq_scheduled < %s order by rn limit 1",
@@ -75,10 +74,10 @@ class Queue {
);
}
}
if(! $r)
if (!$r)
return;
foreach($r as $rv) {
foreach ($r as $rv) {
queue_deliver($rv);
}
}

View File

@@ -5,30 +5,30 @@ namespace Zotlabs\Daemon;
class Thumbnail {
static public function run($argc,$argv) {
static public function run($argc, $argv) {
if(! $argc == 2)
if (!$argc == 2)
return;
$c = q("select * from attach where hash = '%s' ",
dbesc($argv[1])
);
if(! $c)
if (!$c)
return;
$attach = $c[0];
$preview_style = intval(get_config('system','thumbnail_security',0));
$preview_width = intval(get_config('system','thumbnail_width',300));
$preview_height = intval(get_config('system','thumbnail_height',300));
$preview_style = intval(get_config('system', 'thumbnail_security', 0));
$preview_width = intval(get_config('system', 'thumbnail_width', 300));
$preview_height = intval(get_config('system', 'thumbnail_height', 300));
$p = [
'attach' => $attach,
'preview_style' => $preview_style,
'preview_width' => $preview_width,
'preview_height' => $preview_height,
'thumbnail' => null
'thumbnail' => null
];
/**
@@ -40,39 +40,39 @@ class Thumbnail {
* * \e string \b thumbnail
*/
call_hooks('thumbnail',$p);
if($p['thumbnail']) {
call_hooks('thumbnail', $p);
if ($p['thumbnail']) {
return;
}
$default_controller = null;
$files = glob('Zotlabs/Thumbs/*.php');
if($files) {
foreach($files as $f) {
$clsname = '\\Zotlabs\\Thumbs\\' . ucfirst(basename($f,'.php'));
if(class_exists($clsname)) {
if ($files) {
foreach ($files as $f) {
$clsname = '\\Zotlabs\\Thumbs\\' . ucfirst(basename($f, '.php'));
if (class_exists($clsname)) {
$x = new $clsname();
if(method_exists($x,'Match')) {
if (method_exists($x, 'Match')) {
$matched = $x->Match($attach['filetype']);
if($matched) {
$x->Thumb($attach,$preview_style,$preview_width,$preview_height);
if ($matched) {
$x->Thumb($attach, $preview_style, $preview_width, $preview_height);
}
}
if(method_exists($x,'MatchDefault')) {
$default_matched = $x->MatchDefault(substr($attach['filetype'],0,strpos($attach['filetype'],'/')));
if($default_matched) {
if (method_exists($x, 'MatchDefault')) {
$default_matched = $x->MatchDefault(substr($attach['filetype'], 0, strpos($attach['filetype'], '/')));
if ($default_matched) {
$default_controller = $x;
}
}
}
}
}
if(($default_controller)
&& ((! file_exists(dbunescbin($attach['content']) . '.thumb'))
if (($default_controller)
&& ((!file_exists(dbunescbin($attach['content']) . '.thumb'))
|| (filectime(dbunescbin($attach['content']) . 'thumb') < (time() - 60)))) {
$default_controller->Thumb($attach,$preview_style,$preview_width,$preview_height);
$default_controller->Thumb($attach, $preview_style, $preview_width, $preview_height);
}
}
}

View File

@@ -1,6 +1,6 @@
<?php
namespace Zotlabs\Identity\BasicId;
namespace Zotlabs\Identity;
class BasicId {

View File

@@ -1,5 +1,5 @@
<?php
namespace Zotlabs\Identity\ProfilePhoto;
namespace Zotlabs\Identity;
class ProfilePhoto {

View File

@@ -0,0 +1,150 @@
<?php
namespace Zotlabs\Lib;
/**
* Class for dealing with fetching ActivityStreams collections (ordered or unordered, normal or paged).
* Construct with either an existing object or url and an optional channel to sign requests.
* $direction is 0 (default) to fetch from the beginning, and 1 to fetch from the end and reverse order the resultant array.
* An optional limit to the number of records returned may also be specified.
* Use $class->get() to return an array of collection members.
*/
class ASCollection {
private $channel = null;
private $nextpage = null;
private $limit = 0;
private $direction = 0; // 0 = forward, 1 = reverse
private $data = [];
private $history = [];
function __construct($obj, $channel = null, $direction = 0, $limit = 0) {
$this->channel = $channel;
$this->direction = $direction;
$this->limit = $limit;
if (is_array($obj)) {
$data = $obj;
}
if (is_string($obj)) {
$data = Activity::fetch($obj, $channel);
$this->history[] = $obj;
}
if (!is_array($data)) {
return;
}
if (!in_array($data['type'], ['Collection', 'OrderedCollection', 'OrderedCollectionPage'])) {
return false;
}
if ($this->direction) {
if (array_key_exists('last', $data) && $data['last']) {
$this->nextpage = $data['last'];
}
}
else {
if (array_key_exists('first', $data) && $data['first']) {
$this->nextpage = $data['first'];
}
}
if (isset($data['items']) && is_array($data['items'])) {
$this->data = (($this->direction) ? array_reverse($data['items']) : $data['items']);
}
elseif (isset($data['orderedItems']) && is_array($data['orderedItems'])) {
$this->data = (($this->direction) ? array_reverse($data['orderedItems']) : $data['orderedItems']);
}
if ($this->limit) {
if (count($this->data) > $limit) {
$this->data = array_slice($this->data, 0, $limit);
return;
}
}
do {
$x = $this->next();
} while ($x);
}
function get() {
return $this->data;
}
function next() {
if (!$this->nextpage) {
return false;
}
if (is_array($this->nextpage)) {
$data = $this->nextpage;
}
if (is_string($this->nextpage)) {
if (in_array($this->nextpage, $this->history)) {
// recursion detected
return false;
}
$data = Activity::fetch($this->nextpage, $this->channel);
$this->history[] = $this->nextpage;
}
if (!is_array($data)) {
return false;
}
if (!in_array($data['type'], ['CollectionPage', 'OrderedCollectionPage'])) {
return false;
}
$this->setnext($data);
if (isset($data['items']) && is_array($data['items'])) {
$this->data = array_merge($this->data, (($this->direction) ? array_reverse($data['items']) : $data['items']));
}
elseif (isset($data['orderedItems']) && is_array($data['orderedItems'])) {
$this->data = array_merge($this->data, (($this->direction) ? array_reverse($data['orderedItems']) : $data['orderedItems']));
}
if ($this->limit) {
if (count($this->data) > $this->limit) {
$this->data = array_slice($this->data, 0, $this->limit);
$this->nextpage = false;
return true;
}
}
return true;
}
function setnext($data) {
if ($this->direction) {
if (array_key_exists('prev', $data) && $data['prev']) {
$this->nextpage = $data['prev'];
}
elseif (array_key_exists('first', $data) && $data['first']) {
$this->nextpage = $data['first'];
}
else {
$this->nextpage = false;
}
}
else {
if (array_key_exists('next', $data) && $data['next']) {
$this->nextpage = $data['next'];
}
elseif (array_key_exists('last', $data) && $data['last']) {
$this->nextpage = $data['last'];
}
else {
$this->nextpage = false;
}
}
logger('nextpage: ' . $this->nextpage, LOGGER_DEBUG);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -7,25 +7,24 @@ namespace Zotlabs\Lib;
*
* Parses an ActivityStream JSON string.
*/
class ActivityStreams {
public $raw = null;
public $data = null;
public $valid = false;
public $deleted = false;
public $id = '';
public $parent_id = '';
public $type = '';
public $actor = null;
public $obj = null;
public $tgt = null;
public $origin = null;
public $owner = null;
public $signer = null;
public $ldsig = null;
public $sigok = false;
public $recips = null;
public $raw = null;
public $data = null;
public $valid = false;
public $deleted = false;
public $id = '';
public $parent_id = '';
public $type = '';
public $actor = null;
public $obj = null;
public $tgt = null;
public $origin = null;
public $owner = null;
public $signer = null;
public $ldsig = null;
public $sigok = false;
public $recips = null;
public $raw_recips = null;
/**
@@ -37,29 +36,29 @@ class ActivityStreams {
*/
function __construct($string) {
$this->raw = $string;
$this->raw = $string;
if(is_array($string)) {
if (is_array($string)) {
$this->data = $string;
}
else {
$this->data = json_decode($string, true);
}
if($this->data) {
if ($this->data) {
// verify and unpack JSalmon signature if present
if(is_array($this->data) && array_key_exists('signed',$this->data)) {
if (is_array($this->data) && array_key_exists('signed', $this->data)) {
$ret = JSalmon::verify($this->data);
$tmp = JSalmon::unpack($this->data['data']);
if($ret && $ret['success']) {
if($ret['signer']) {
$saved = json_encode($this->data,JSON_UNESCAPED_SLASHES);
$this->data = $tmp;
$this->data['signer'] = $ret['signer'];
if ($ret && $ret['success']) {
if ($ret['signer']) {
$saved = json_encode($this->data, JSON_UNESCAPED_SLASHES);
$this->data = $tmp;
$this->data['signer'] = $ret['signer'];
$this->data['signed_data'] = $saved;
if($ret['hubloc']) {
if ($ret['hubloc']) {
$this->data['hubloc'] = $ret['hubloc'];
}
}
@@ -68,57 +67,57 @@ class ActivityStreams {
$this->valid = true;
if(array_key_exists('type',$this->data) && array_key_exists('actor',$this->data) && array_key_exists('object',$this->data)) {
if($this->data['type'] === 'Delete' && $this->data['actor'] === $this->data['object']) {
if (array_key_exists('type', $this->data) && array_key_exists('actor', $this->data) && array_key_exists('object', $this->data)) {
if ($this->data['type'] === 'Delete' && $this->data['actor'] === $this->data['object']) {
$this->deleted = $this->data['actor'];
$this->valid = false;
$this->valid = false;
}
}
}
if($this->is_valid()) {
if ($this->is_valid()) {
$this->id = $this->get_property_obj('id');
$this->type = $this->get_primary_type();
$this->actor = $this->get_actor('actor','','');
$this->actor = $this->get_actor('actor', '', '');
$this->obj = $this->get_compound_property('object');
$this->tgt = $this->get_compound_property('target');
$this->origin = $this->get_compound_property('origin');
$this->recips = $this->collect_recips();
$this->ldsig = $this->get_compound_property('signature');
if($this->ldsig) {
$this->signer = $this->get_compound_property('creator',$this->ldsig);
if($this->signer && is_array($this->signer) && array_key_exists('publicKey',$this->signer) && is_array($this->signer['publicKey']) && $this->signer['publicKey']['publicKeyPem']) {
$this->sigok = LDSignatures::verify($this->data,$this->signer['publicKey']['publicKeyPem']);
if ($this->ldsig) {
$this->signer = $this->get_compound_property('creator', $this->ldsig);
if ($this->signer && is_array($this->signer) && array_key_exists('publicKey', $this->signer) && is_array($this->signer['publicKey']) && $this->signer['publicKey']['publicKeyPem']) {
$this->sigok = LDSignatures::verify($this->data, $this->signer['publicKey']['publicKeyPem']);
}
}
if(! $this->obj) {
$this->obj = $this->data;
if (!$this->obj) {
$this->obj = $this->data;
$this->type = 'Create';
if(! $this->actor) {
$this->actor = $this->get_actor('attributedTo',$this->obj);
if (!$this->actor) {
$this->actor = $this->get_actor('attributedTo', $this->obj);
}
}
// fetch recursive or embedded activities
if ($this->obj && is_array($this->obj) && array_key_exists('object',$this->obj)) {
if ($this->obj && is_array($this->obj) && array_key_exists('object', $this->obj)) {
$this->obj['object'] = $this->get_compound_property($this->obj['object']);
}
if($this->obj && is_array($this->obj) && $this->obj['actor'])
$this->obj['actor'] = $this->get_actor('actor',$this->obj);
if($this->tgt && is_array($this->tgt) && $this->tgt['actor'])
$this->tgt['actor'] = $this->get_actor('actor',$this->tgt);
if ($this->obj && is_array($this->obj) && $this->obj['actor'])
$this->obj['actor'] = $this->get_actor('actor', $this->obj);
if ($this->tgt && is_array($this->tgt) && $this->tgt['actor'])
$this->tgt['actor'] = $this->get_actor('actor', $this->tgt);
$this->parent_id = $this->get_property_obj('inReplyTo');
if((! $this->parent_id) && is_array($this->obj)) {
if ((!$this->parent_id) && is_array($this->obj)) {
$this->parent_id = $this->obj['inReplyTo'];
}
if((! $this->parent_id) && is_array($this->obj)) {
if ((!$this->parent_id) && is_array($this->obj)) {
$this->parent_id = $this->obj['id'];
}
}
@@ -147,19 +146,19 @@ class ActivityStreams {
function collect_recips($base = '', $namespace = '') {
$x = [];
$fields = [ 'to', 'cc', 'bto', 'bcc', 'audience'];
foreach($fields as $f) {
$fields = ['to', 'cc', 'bto', 'bcc', 'audience'];
foreach ($fields as $f) {
$y = $this->get_compound_property($f, $base, $namespace);
if($y) {
if (! is_array($this->raw_recips)) {
if ($y) {
if (!is_array($this->raw_recips)) {
$this->raw_recips = [];
}
if (! is_array($y)) {
$y = [ $y ];
if (!is_array($y)) {
$y = [$y];
}
$this->raw_recips[$f] = $y;
$x = array_merge($x, $y);
$x = array_merge($x, $y);
}
}
// not yet ready for prime time
@@ -167,21 +166,21 @@ class ActivityStreams {
return $x;
}
function expand($arr,$base = '',$namespace = '') {
function expand($arr, $base = '', $namespace = '') {
$ret = [];
// right now use a hardwired recursion depth of 5
for($z = 0; $z < 5; $z ++) {
if(is_array($arr) && $arr) {
foreach($arr as $a) {
if(is_array($a)) {
for ($z = 0; $z < 5; $z++) {
if (is_array($arr) && $arr) {
foreach ($arr as $a) {
if (is_array($a)) {
$ret[] = $a;
}
else {
$x = $this->get_compound_property($a,$base,$namespace);
if($x) {
$ret = array_merge($ret,$x);
$x = $this->get_compound_property($a, $base, $namespace);
if ($x) {
$ret = array_merge($ret, $x);
}
}
}
@@ -202,33 +201,33 @@ class ActivityStreams {
*/
function get_namespace($base, $namespace) {
if(! $namespace)
if (!$namespace)
return '';
$key = null;
foreach( [ $this->data, $base ] as $b ) {
if(! $b)
foreach ([$this->data, $base] as $b) {
if (!$b)
continue;
if(array_key_exists('@context', $b)) {
if(is_array($b['@context'])) {
foreach($b['@context'] as $ns) {
if(is_array($ns)) {
foreach($ns as $k => $v) {
if($namespace === $v)
if (array_key_exists('@context', $b)) {
if (is_array($b['@context'])) {
foreach ($b['@context'] as $ns) {
if (is_array($ns)) {
foreach ($ns as $k => $v) {
if ($namespace === $v)
$key = $k;
}
}
else {
if($namespace === $ns) {
if ($namespace === $ns) {
$key = '';
}
}
}
}
else {
if($namespace === $b['@context']) {
if ($namespace === $b['@context']) {
$key = '';
}
}
@@ -248,14 +247,14 @@ class ActivityStreams {
*/
function get_property_obj($property, $base = '', $namespace = '') {
$prefix = $this->get_namespace($base, $namespace);
if($prefix === null)
if ($prefix === null)
return null;
$base = (($base) ? $base : $this->data);
$base = (($base) ? $base : $this->data);
$propname = (($prefix) ? $prefix . ':' : '') . $property;
if(! is_array($base)) {
btlogger('not an array: ' . print_r($base,true));
if (!is_array($base)) {
btlogger('not an array: ' . print_r($base, true));
return null;
}
@@ -279,14 +278,14 @@ class ActivityStreams {
}
static function is_an_actor($s) {
return (in_array($s, [ 'Application','Group','Organization','Person','Service' ]));
return (in_array($s, ['Application', 'Group', 'Organization', 'Person', 'Service']));
}
static function is_response_activity($s) {
if (! $s) {
if (!$s) {
return false;
}
return (in_array($s, [ 'Like', 'Dislike', 'Flag', 'Block', 'Announce', 'Accept', 'Reject', 'TentativeAccept', 'TentativeReject', 'emojiReaction', 'EmojiReaction', 'EmojiReact' ]));
return (in_array($s, ['Like', 'Dislike', 'Flag', 'Block', 'Accept', 'Reject', 'TentativeAccept', 'TentativeReject', 'emojiReaction', 'EmojiReaction', 'EmojiReact']));
}
/**
@@ -298,25 +297,25 @@ class ActivityStreams {
* @return NULL|mixed
*/
function get_actor($property,$base='',$namespace = '') {
function get_actor($property, $base = '', $namespace = '') {
$x = $this->get_property_obj($property, $base, $namespace);
if($this->is_url($x)) {
if ($this->is_url($x)) {
// SECURITY: If we have already stored the actor profile, re-generate it
// SECURITY: If we have already stored the actor profile, re-generate it
// from cached data - don't refetch it from the network
$r = q("select * from xchan left join hubloc on xchan_hash = hubloc_hash where hubloc_id_url = '%s' limit 1",
dbesc($x)
);
if($r) {
$y = Activity::encode_person($r[0]);
if ($r) {
$y = Activity::encode_person($r[0]);
$y['cached'] = true;
return $y;
}
}
$actor = $this->get_compound_property($property,$base,$namespace,true);
if(is_array($actor) && self::is_an_actor($actor['type'])) {
if(array_key_exists('id',$actor) && (! array_key_exists('inbox',$actor))) {
$actor = $this->get_compound_property($property, $base, $namespace, true);
if (is_array($actor) && self::is_an_actor($actor['type'])) {
if (array_key_exists('id', $actor) && (!array_key_exists('inbox', $actor))) {
$actor = $this->fetch_property($actor['id']);
}
return $actor;
@@ -336,7 +335,7 @@ class ActivityStreams {
*/
function get_compound_property($property, $base = '', $namespace = '', $first = false) {
$x = $this->get_property_obj($property, $base, $namespace);
if($this->is_url($x)) {
if ($this->is_url($x)) {
$y = $this->fetch_property($x);
if (is_array($y)) {
$x = $y;
@@ -344,23 +343,23 @@ class ActivityStreams {
}
// verify and unpack JSalmon signature if present
if(is_array($x) && array_key_exists('signed',$x)) {
if (is_array($x) && array_key_exists('signed', $x)) {
$ret = JSalmon::verify($x);
$tmp = JSalmon::unpack($x['data']);
if($ret && $ret['success']) {
if($ret['signer']) {
$saved = json_encode($x,JSON_UNESCAPED_SLASHES);
$x = $tmp;
$x['signer'] = $ret['signer'];
if ($ret && $ret['success']) {
if ($ret['signer']) {
$saved = json_encode($x, JSON_UNESCAPED_SLASHES);
$x = $tmp;
$x['signer'] = $ret['signer'];
$x['signed_data'] = $saved;
if($ret['hubloc']) {
if ($ret['hubloc']) {
$x['hubloc'] = $ret['hubloc'];
}
}
}
}
if($first && is_array($x) && array_key_exists(0,$x)) {
if ($first && is_array($x) && array_key_exists(0, $x)) {
return $x[0];
}
@@ -374,7 +373,7 @@ class ActivityStreams {
* @return boolean
*/
function is_url($url) {
if(($url) && (! is_array($url)) && (strpos($url, 'http') === 0)) {
if (($url) && (!is_array($url)) && (strpos($url, 'http') === 0)) {
return true;
}
@@ -389,13 +388,13 @@ class ActivityStreams {
* @return NULL|mixed
*/
function get_primary_type($base = '', $namespace = '') {
if(! $base)
if (!$base)
$base = $this->data;
$x = $this->get_property_obj('type', $base, $namespace);
if(is_array($x)) {
foreach($x as $y) {
if(strpos($y, ':') === false) {
if (is_array($x)) {
foreach ($x as $y) {
if (strpos($y, ':') === false) {
return $y;
}
}
@@ -409,15 +408,32 @@ class ActivityStreams {
return $x;
}
static function is_as_request() {
static function is_as_request($channel = null) {
$x = getBestSupportedMimeType([
'application/ld+json;profile="https://www.w3.org/ns/activitystreams"',
'application/activity+json',
'application/ld+json;profile="http://www.w3.org/ns/activitystreams"'
]);
$hookdata = [];
if ($channel)
$hookdata['channel'] = $channel;
return(($x) ? true : false);
$hookdata['data'] = ['application/x-zot-activity+json'];
call_hooks('is_as_request', $hookdata);
$x = getBestSupportedMimeType($hookdata['data']);
return (($x) ? true : false);
}
static function get_accept_header_string($channel = null) {
$hookdata = [];
if ($channel)
$hookdata['channel'] = $channel;
$hookdata['data'] = 'application/x-zot-activity+json';
call_hooks('get_accept_header_string', $hookdata);
return $hookdata['data'];
}

View File

@@ -307,7 +307,7 @@ class Apps {
}
}
}
if($ret) {
if(isset($ret)) {
if($translate)
self::translate_system_apps($ret);
@@ -524,7 +524,7 @@ class Apps {
}
elseif(remote_channel()) {
$observer = \App::get_observer();
if($observer && $observer['xchan_network'] === 'zot') {
if($observer && in_array($observer['xchan_network'], ['zot6', 'zot'])) {
// some folks might have xchan_url redirected offsite, use the connurl
$x = parse_url($observer['xchan_connurl']);
if($x) {

206
Zotlabs/Lib/Crypto.php Normal file
View File

@@ -0,0 +1,206 @@
<?php
namespace Zotlabs\Lib;
use Exception;
class Crypto {
public static $openssl_algorithms = [
// zot6 nickname, opensslname, keylength, ivlength
['aes256ctr', 'aes-256-ctr', 32, 16],
['camellia256cfb', 'camellia-256-cfb', 32, 16],
['cast5cfb', 'cast5-cfb', 16, 8],
['aes256cbc', 'aes-256-cbc', 32, 16] // remove after legacy zot has been sunset
];
public static function methods() {
$ret = [];
foreach (self::$openssl_algorithms as $ossl) {
$ret[] = $ossl[0] . '.oaep';
}
call_hooks('crypto_methods', $ret);
return $ret;
}
public static function signing_methods() {
$ret = ['sha256'];
call_hooks('signing_methods', $ret);
return $ret;
}
public static function new_keypair($bits) {
$openssl_options = [
'digest_alg' => 'sha1',
'private_key_bits' => $bits,
'encrypt_key' => false
];
$conf = get_config('system', 'openssl_conf_file');
if ($conf) {
$openssl_options['config'] = $conf;
}
$result = openssl_pkey_new($openssl_options);
if (empty($result)) {
return false;
}
// Get private key
$response = ['prvkey' => '', 'pubkey' => ''];
openssl_pkey_export($result, $response['prvkey']);
// Get public key
$pkey = openssl_pkey_get_details($result);
$response['pubkey'] = $pkey["key"];
return $response;
}
public static function sign($data, $key, $alg = 'sha256') {
if (!$key) {
return false;
}
$sig = '';
openssl_sign($data, $sig, $key, $alg);
return $sig;
}
public static function verify($data, $sig, $key, $alg = 'sha256') {
if (!$key) {
return false;
}
try {
$verify = openssl_verify($data, $sig, $key, $alg);
} catch (Exception $e) {
$verify = (-1);
}
if ($verify === (-1)) {
while ($msg = openssl_error_string()) {
logger('openssl_verify: ' . $msg, LOGGER_NORMAL, LOG_ERR);
}
btlogger('openssl_verify: key: ' . $key, LOGGER_DEBUG, LOG_ERR);
}
return (($verify > 0) ? true : false);
}
public static function encapsulate($data, $pubkey, $alg) {
if (!($alg && $pubkey)) {
return $data;
}
$alg_base = $alg;
$padding = OPENSSL_PKCS1_PADDING;
$exts = explode('.', $alg);
if (count($exts) > 1) {
switch ($exts[1]) {
case 'oaep':
$padding = OPENSSL_PKCS1_OAEP_PADDING;
break;
default:
break;
}
$alg_base = $exts[0];
}
$method = null;
foreach (self::$openssl_algorithms as $ossl) {
if ($ossl[0] === $alg_base) {
$method = $ossl;
break;
}
}
if ($method) {
$result = ['encrypted' => true];
$key = openssl_random_pseudo_bytes(256);
$iv = openssl_random_pseudo_bytes(256);
$key1 = substr($key, 0, $method[2]);
$iv1 = substr($iv, 0, $method[3]);
$result['data'] = base64url_encode(openssl_encrypt($data, $method[1], $key1, OPENSSL_RAW_DATA, $iv1), true);
openssl_public_encrypt($key, $k, $pubkey, $padding);
openssl_public_encrypt($iv, $i, $pubkey, $padding);
$result['alg'] = $alg;
$result['key'] = base64url_encode($k, true);
$result['iv'] = base64url_encode($i, true);
return $result;
}
else {
$x = ['data' => $data, 'pubkey' => $pubkey, 'alg' => $alg, 'result' => $data];
call_hooks('crypto_encapsulate', $x);
return $x['result'];
}
}
public static function unencapsulate($data, $prvkey) {
if (!(is_array($data) && array_key_exists('encrypted', $data) && array_key_exists('alg', $data) && $data['alg'])) {
logger('not encrypted');
return $data;
}
$alg_base = $data['alg'];
$padding = OPENSSL_PKCS1_PADDING;
$exts = explode('.', $data['alg']);
if (count($exts) > 1) {
switch ($exts[1]) {
case 'oaep':
$padding = OPENSSL_PKCS1_OAEP_PADDING;
break;
default:
break;
}
$alg_base = $exts[0];
}
$method = null;
foreach (self::$openssl_algorithms as $ossl) {
if ($ossl[0] === $alg_base) {
$method = $ossl;
break;
}
}
if ($method) {
openssl_private_decrypt(base64url_decode($data['key']), $k, $prvkey, $padding);
openssl_private_decrypt(base64url_decode($data['iv']), $i, $prvkey, $padding);
return openssl_decrypt(base64url_decode($data['data']), $method[1], substr($k, 0, $method[2]), OPENSSL_RAW_DATA, substr($i, 0, $method[3]));
}
else {
$x = ['data' => $data, 'prvkey' => $prvkey, 'alg' => $data['alg'], 'result' => $data];
call_hooks('crypto_unencapsulate', $x);
return $x['result'];
}
}
}

View File

@@ -43,7 +43,7 @@ class Enotify {
dbesc($params['to_xchan'])
);
}
if ($x & $y) {
if ($x && $y) {
$sender = $x[0];
$recip = $y[0];
} else {
@@ -64,7 +64,7 @@ class Enotify {
$sitename = get_config('system','sitename');
$site_admin = sprintf( t('%s Administrator'), $sitename);
$opt_out1 = sprintf( t('This email was sent by %1$s at %2$s.'), t('$Projectname'), \App::get_hostname());
$opt_out2 = sprintf( t('To stop receiving these messages, please adjust your Notification Settings at %s'), z_root() . '/settings');
$opt_out2 = sprintf( t('To stop receiving these messages, please adjust your Notification Settings at %s'), z_root() . '/settings');
$hopt_out2 = sprintf( t('To stop receiving these messages, please adjust your %s.'), '<a href="' . z_root() . '/settings' . '">' . t('Notification Settings') . '</a>');
$sender_name = $product;
$hostname = \App::get_hostname();
@@ -80,7 +80,7 @@ class Enotify {
$sender_email = get_config('system','from_email');
if(! $sender_email)
$sender_email = 'Administrator' . '@' . $hostname;
$sender_name = get_config('system','from_email_name');
if(! $sender_name)
$sender_name = \Zotlabs\Lib\System::get_site_name();
@@ -108,7 +108,7 @@ class Enotify {
logger('notification invoked for an old item which may have been refetched.',LOGGER_DEBUG,LOG_INFO);
return;
}
}
}
else {
$title = $body = '';
}
@@ -181,7 +181,7 @@ class Enotify {
pop_lang();
return;
}
// if it's a post figure out who's post it is.
@@ -219,7 +219,7 @@ class Enotify {
$itemlink,
$p[0]['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]'),
@@ -230,15 +230,15 @@ class Enotify {
// Some mail softwares relies on subject field for threading.
// So, we cannot have different subjects for notifications of the same thread.
// Before this we have the name of the replier on the subject rendering
// Before this we have the name of the replier on the subject rendering
// differents subjects for messages on the same thread.
if($moderated)
$subject = sprintf( t('[$Projectname:Notify] Moderated Comment to conversation #%1$d by %2$s'), $parent_id, $sender['xchan_name']);
else
$subject = sprintf( t('[$Projectname:Notify] Comment to conversation #%1$d by %2$s'), $parent_id, $sender['xchan_name']);
$preamble = sprintf( t('%1$s commented on an item/conversation you have been following.'), $sender['xchan_name']);
$epreamble = $dest_str;
$preamble = sprintf( t('%1$s commented on an item/conversation you have been following.'), $sender['xchan_name']);
$epreamble = $dest_str;
$sitelink = t('Please visit %s to view and/or reply to the conversation.');
$tsitelink = sprintf( $sitelink, $siteurl );
@@ -247,7 +247,7 @@ class Enotify {
$tsitelink .= "\n\n" . sprintf( t('Please visit %s to approve or reject this comment.'), z_root() . '/moderate' );
$hsitelink .= "<br><br>" . sprintf( t('Please visit %s to approve or reject this comment.'), '<a href="' . z_root() . '/moderate">' . z_root() . '/moderate</a>' );
}
}
if ($params['type'] == NOTIFY_LIKE) {
@@ -278,7 +278,7 @@ class Enotify {
pop_lang();
return;
}
// if it's a post figure out who's post it is.
@@ -314,12 +314,12 @@ class Enotify {
// Some mail softwares relies on subject field for threading.
// So, we cannot have different subjects for notifications of the same thread.
// Before this we have the name of the replier on the subject rendering
// Before this we have the name of the replier on the subject rendering
// differents subjects for messages on the same thread.
$subject = sprintf( t('[$Projectname:Notify] Like received to conversation #%1$d by %2$s'), $parent_id, $sender['xchan_name']);
$preamble = sprintf( t('%1$s liked an item/conversation you created.'), $sender['xchan_name']);
$epreamble = $dest_str;
$preamble = sprintf( t('%1$s liked an item/conversation you created.'), $sender['xchan_name']);
$epreamble = $dest_str;
$sitelink = t('Please visit %s to view and/or reply to the conversation.');
$tsitelink = sprintf( $sitelink, $siteurl );
@@ -335,7 +335,7 @@ class Enotify {
$epreamble = sprintf( t('%1$s posted to [zrl=%2$s]your wall[/zrl]') ,
'[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]',
$params['link']);
$params['link']);
$sitelink = t('Please visit %s to view and/or reply to the conversation.');
$tsitelink = sprintf( $sitelink, $siteurl );
@@ -355,12 +355,12 @@ class Enotify {
pop_lang();
return;
}
$subject = sprintf( t('[$Projectname:Notify] %s tagged you') , $sender['xchan_name']);
$preamble = sprintf( t('%1$s tagged you at %2$s') , $sender['xchan_name'], $sitename);
$epreamble = sprintf( t('%1$s [zrl=%2$s]tagged you[/zrl].') ,
'[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]',
$params['link']);
$params['link']);
$sitelink = t('Please visit %s to view and/or reply to the conversation.');
$tsitelink = sprintf( $sitelink, $siteurl );
@@ -373,7 +373,7 @@ class Enotify {
$preamble = sprintf( t('%1$s poked you at %2$s') , $sender['xchan_name'], $sitename);
$epreamble = sprintf( t('%1$s [zrl=%2$s]poked you[/zrl].') ,
'[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]',
$params['link']);
$params['link']);
$subject = str_replace('poked', t($params['activity']), $subject);
$preamble = str_replace('poked', t($params['activity']), $preamble);
@@ -390,7 +390,7 @@ class Enotify {
$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]') ,
'[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]',
$itemlink);
$itemlink);
$sitelink = t('Please visit %s to view and/or reply to the conversation.');
$tsitelink = sprintf( $sitelink, $siteurl );
@@ -400,10 +400,10 @@ class Enotify {
if ($params['type'] == NOTIFY_INTRO) {
$subject = sprintf( t('[$Projectname:Notify] Introduction received'));
$preamble = sprintf( t('You\'ve received an new connection request from \'%1$s\' at %2$s'), $sender['xchan_name'], $sitename);
$preamble = sprintf( t('You\'ve received an new connection request from \'%1$s\' at %2$s'), $sender['xchan_name'], $sitename);
$epreamble = sprintf( t('You\'ve received [zrl=%1$s]a new connection request[/zrl] from %2$s.'),
$siteurl . '/connections/ifpending',
'[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]');
'[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]');
$body = sprintf( t('You may visit their profile at %s'),$sender['xchan_url']);
$sitelink = t('Please visit %s to approve or reject the connection request.');
@@ -414,11 +414,11 @@ class Enotify {
if ($params['type'] == NOTIFY_SUGGEST) {
$subject = sprintf( t('[$Projectname:Notify] Friend suggestion received'));
$preamble = sprintf( t('You\'ve received a friend suggestion from \'%1$s\' at %2$s'), $sender['xchan_name'], $sitename);
$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.'),
$itemlink,
'[zrl=' . $params['item']['url'] . ']' . $params['item']['name'] . '[/zrl]',
'[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]');
'[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]');
$body = t('Name:') . ' ' . $params['item']['name'] . "\n";
$body .= t('Photo:') . ' ' . $params['item']['photo'] . "\n";
@@ -462,7 +462,7 @@ class Enotify {
$sitelink = $h['sitelink'];
$tsitelink = $h['tsitelink'];
$hsitelink = $h['hsitelink'];
$itemlink = $h['itemlink'];
$itemlink = $h['itemlink'];
require_once('include/html2bbcode.php');
@@ -510,7 +510,7 @@ class Enotify {
// Mark some notifications as seen right away
// Note! The notification have to be created, because they are used to send emails
// So easiest solution to hide them from Notices is to mark them as seen right away.
// Another option would be to not add them to the DB, and change how emails are handled
// Another option would be to not add them to the DB, and change how emails are handled
// (probably would be better that way)
if (!$always_show_in_notices) {
@@ -555,7 +555,7 @@ class Enotify {
// wretched hack, but we don't want to duplicate all the preamble variations and we also don't want to screw up a translation
if ((\App::$language === 'en' || (! \App::$language)) && strpos($msg,', '))
$msg = substr($msg,strpos($msg,', ')+1);
$msg = substr($msg,strpos($msg,', ')+1);
$datarray['id'] = $notify_id;
$datarray['msg'] = $msg;
@@ -587,12 +587,12 @@ class Enotify {
$htmlversion = bbcode(stripslashes(str_replace(array("\\r","\\n"), array("","<br />\n"),$body)));
// use $_SESSION['zid_override'] to force zid() to use
// use $_SESSION['zid_override'] to force zid() to use
// the recipient address instead of the current observer
$_SESSION['zid_override'] = channel_reddress($recip);
$_SESSION['zrl_override'] = z_root() . '/channel/' . $recip['channel_address'];
$textversion = zidify_links($textversion);
$htmlversion = zidify_links($htmlversion);
@@ -754,7 +754,7 @@ class Enotify {
return $params['result'];
}
$fromName = email_header_encode(html_entity_decode($params['fromName'],ENT_QUOTES,'UTF-8'),'UTF-8');
$fromName = email_header_encode(html_entity_decode($params['fromName'],ENT_QUOTES,'UTF-8'),'UTF-8');
$messageSubject = email_header_encode(html_entity_decode($params['messageSubject'],ENT_QUOTES,'UTF-8'),'UTF-8');
// generate a mime boundary
@@ -767,8 +767,8 @@ class Enotify {
$messageHeader =
$params['additionalMailHeader'] .
"From: $fromName <{$params['fromEmail']}>" . PHP_EOL .
"Reply-To: $fromName <{$params['replyTo']}>" . PHP_EOL .
"MIME-Version: 1.0" . PHP_EOL .
"Reply-To: $fromName <{$params['replyTo']}>" . PHP_EOL .
"MIME-Version: 1.0" . PHP_EOL .
"Content-Type: multipart/alternative; boundary=\"{$mimeBoundary}\"";
// assemble the final multipart message body with the text and html types included
@@ -782,7 +782,7 @@ class Enotify {
$textBody . PHP_EOL .
"--" . $mimeBoundary . PHP_EOL . // text/html section
"Content-Type: text/html; charset=UTF-8" . PHP_EOL .
"Content-Transfer-Encoding: base64" . PHP_EOL . PHP_EOL .
"Content-Transfer-Encoding: base64" . PHP_EOL . PHP_EOL .
$htmlBody . PHP_EOL .
"--" . $mimeBoundary . "--" . PHP_EOL; // message ending
@@ -803,7 +803,7 @@ class Enotify {
require_once('include/conversation.php');
// Call localize_item to get a one line status for activities.
// Call localize_item to get a one line status for activities.
// This should set $item['localized'] to indicate we have a brief summary.
// and perhaps $item['shortlocalized'] for an even briefer summary
@@ -860,7 +860,7 @@ class Enotify {
//'b64mid' => ((in_array($item['verb'], [ACTIVITY_LIKE, ACTIVITY_DISLIKE])) ? 'b64.' . base64url_encode($item['thr_parent']) : 'b64.' . base64url_encode($item['mid'])),
'thread_top' => (($item['item_thread_top']) ? true : false),
'message' => bbcode(escape_tags($itemem_text)),
'body' => htmlentities(html2plain(bbcode($item['body']), 75, true), ENT_COMPAT, 'UTF-8', false),
'body' => htmlentities(html2plain(bbcode($item['body']), 75, true), ENT_QUOTES, 'UTF-8', false),
// these are for the superblock addon
'hash' => $item[$who]['xchan_hash'],
'uid' => $item['uid'],

55
Zotlabs/Lib/Hashpath.php Normal file
View File

@@ -0,0 +1,55 @@
<?php
namespace Zotlabs\Lib;
/*
* Zotlabs\Lib\Hashpath
*
* Creates hashed directory structures for fast access and resistance to overloading any single directory with files.
*
* Takes a $hash which could be any string
* a $prefix which is where to place the hash directory in the filesystem, default is current directory
* use an empty string for $prefix to place hash directories directly off the root directory
* an optional $depth and $slice (default is 2) to indicate the hash level
* $depth = 1, 256 directories, suitable for < 384K records/files
* $depth = 2, 65536 directories, suitable for < 98M records/files
* $depth = 3, 16777216 directories, suitable for < 2.5B records/files
* ...
* The total number of records anticipated divided by the number of hash directories should generally be kept to
* less than 1500 entries for optimum performance though this varies by operating system and filesystem type.
* ext4 uses 32 bit inode numbers (~4B record limit) so use caution or alternative filesystem types with $depth above 3.
* an optional $mkdir (boolean) to recursively create the directory (ignoring errors) before returning
*
* examples: for a $hash of 'abcdefg' and prefix of 'path' the following paths are returned for $depth = 1 and $depth = 3
* path/7d/7d1a54127b222502f5b79b5fb0803061152a44f92b37e23c6527baf665d4da9a
* path/7d/1a/54/7d1a54127b222502f5b79b5fb0803061152a44f92b37e23c6527baf665d4da9a
*
* see also: boot.php:os_mkdir() - here we provide the equivalent of mkdir -p with permissions of 770.
*
*/
class Hashpath {
static function path($hash, $prefix = '.', $depth = 1, $slice = 2, $mkdir = true, $alg = false) {
if ($alg)
$hash = hash($alg, $hash);
$start = 0;
if ($depth < 1)
$depth = 1;
$sluglen = $depth * $slice;
do {
$slug = substr($hash, $start, $slice);
$prefix .= '/' . $slug;
$start += $slice;
$sluglen -= $slice;
}
while ($sluglen);
if ($mkdir)
os_mkdir($prefix, STORAGE_DEFAULT_PERMISSIONS, true);
return $prefix . '/' . $hash;
}
}

View File

@@ -18,7 +18,7 @@ class JSalmon {
$precomputed = '.' . base64url_encode($data_type,true) . '.YmFzZTY0dXJs.UlNBLVNIQTI1Ng';
$signature = base64url_encode(rsa_sign($data . $precomputed, $key), true);
$signature = base64url_encode(Crypto::sign($data . $precomputed, $key), true);
return ([
'signed' => true,
@@ -40,21 +40,21 @@ class JSalmon {
$ret = [ 'results' => [] ];
if(! is_array($x)) {
return $false;
return false;
}
if(! ( array_key_exists('signed',$x) && $x['signed'])) {
return $false;
return false;
}
$signed_data = preg_replace('/\s+/','',$x['data']) . '.'
. base64url_encode($x['data_type'],true) . '.'
. base64url_encode($x['encoding'],true) . '.'
$signed_data = preg_replace('/\s+/','',$x['data']) . '.'
. base64url_encode($x['data_type'],true) . '.'
. base64url_encode($x['encoding'],true) . '.'
. base64url_encode($x['alg'],true);
$key = HTTPSig::get_key(EMPTY_STR,'zot6',base64url_decode($x['sigs']['key_id']));
logger('key: ' . print_r($key,true));
if($key['portable_id'] && $key['public_key']) {
if(rsa_verify($signed_data,base64url_decode($x['sigs']['value']),$key['public_key'])) {
if(Crypto::verify($signed_data,base64url_decode($x['sigs']['value']),$key['public_key'])) {
logger('verified');
$ret = [ 'success' => true, 'signer' => $key['portable_id'], 'hubloc' => $key['hubloc'] ];
}

99
Zotlabs/Lib/Keyutils.php Normal file
View File

@@ -0,0 +1,99 @@
<?php
namespace Zotlabs\Lib;
use phpseclib\Crypt\RSA;
use phpseclib\Math\BigInteger;
/**
* Keyutils
* Convert RSA keys between various formats
*/
class Keyutils {
/**
* @param string $m modulo
* @param string $e exponent
* @return string
*/
public static function meToPem($m, $e) {
$rsa = new RSA();
$rsa->loadKey([
'e' => new BigInteger($e, 256),
'n' => new BigInteger($m, 256)
]);
return $rsa->getPublicKey();
}
/**
* @param string key
* @return string
*/
public static function rsaToPem($key) {
$rsa = new RSA();
$rsa->setPublicKey($key);
return $rsa->getPublicKey(RSA::PUBLIC_FORMAT_PKCS8);
}
/**
* @param string key
* @return string
*/
public static function pemToRsa($key) {
$rsa = new RSA();
$rsa->setPublicKey($key);
return $rsa->getPublicKey(RSA::PUBLIC_FORMAT_PKCS1);
}
/**
* @param string $key key
* @param string $m reference modulo
* @param string $e reference exponent
*/
public static function pemToMe($key, &$m, &$e) {
$rsa = new RSA();
$rsa->loadKey($key);
$rsa->setPublicKey();
$m = $rsa->modulus->toBytes();
$e = $rsa->exponent->toBytes();
}
/**
* @param string $pubkey
* @return string
*/
public static function salmonKey($pubkey) {
self::pemToMe($pubkey, $m, $e);
return 'RSA' . '.' . base64url_encode($m, true) . '.' . base64url_encode($e, true);
}
/**
* @param string $key
* @return string
*/
public static function convertSalmonKey($key) {
if (strstr($key, ','))
$rawkey = substr($key, strpos($key, ',') + 1);
else
$rawkey = substr($key, 5);
$key_info = explode('.', $rawkey);
$m = base64url_decode($key_info[1]);
$e = base64url_decode($key_info[2]);
return self::meToPem($m, $e);
}
}

View File

@@ -12,7 +12,7 @@ class LDSignatures {
$ohash = self::hash(self::signable_options($data['signature']));
$dhash = self::hash(self::signable_data($data));
$x = rsa_verify($ohash . $dhash,base64_decode($data['signature']['signatureValue']), $pubkey);
$x = Crypto::verify($ohash . $dhash,base64_decode($data['signature']['signatureValue']), $pubkey);
logger('LD-verify: ' . intval($x));
return $x;
@@ -35,11 +35,11 @@ class LDSignatures {
$ohash = self::hash(self::signable_options($options));
$dhash = self::hash(self::signable_data($data));
$options['signatureValue'] = base64_encode(rsa_sign($ohash . $dhash,$channel['channel_prvkey']));
$options['signatureValue'] = base64_encode(Crypto::sign($ohash . $dhash,$channel['channel_prvkey']));
$signed = array_merge([
'@context' => [
ACTIVITYSTREAMS_JSONLD_REV,
'@context' => [
ACTIVITYSTREAMS_JSONLD_REV,
'https://w3id.org/security/v1' ],
],$options);
@@ -88,7 +88,7 @@ class LDSignatures {
return '';
jsonld_set_document_loader('jsonld_document_loader');
try {
$d = jsonld_normalize($data,[ 'algorithm' => 'URDNA2015', 'format' => 'application/nquads' ]);
}
@@ -117,7 +117,7 @@ class LDSignatures {
$precomputed = '.' . base64url_encode($data_type,false) . '.YmFzZTY0dXJs.UlNBLVNIQTI1Ng==';
$signature = base64url_encode(rsa_sign($data . $precomputed,$channel['channel_prvkey']));
$signature = base64url_encode(Crypto::sign($data . $precomputed,$channel['channel_prvkey']));
return ([
'id' => $arr['id'],

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -19,7 +19,6 @@ class Libzotdir {
*/
static function find_upstream_directory($dirmode) {
global $DIRECTORY_FALLBACK_SERVERS;
$preferred = get_config('system','directory_server');
@@ -31,7 +30,7 @@ class Libzotdir {
);
if(($r) && ($r[0]['site_flags'] & DIRECTORY_MODE_STANDALONE)) {
$preferred = '';
}
}
}
@@ -42,19 +41,21 @@ class Libzotdir {
* from our list of directory servers. However, if we're a directory
* server ourself, point at the local instance
* We will then set this value so this should only ever happen once.
* Ideally there will be an admin setting to change to a different
* Ideally there will be an admin setting to change to a different
* directory server if you don't like our choice or if circumstances change.
*/
$directory_fallback_servers = get_directory_fallback_servers();
$dirmode = intval(get_config('system','directory_mode'));
if ($dirmode == DIRECTORY_MODE_NORMAL) {
$toss = mt_rand(0,count($DIRECTORY_FALLBACK_SERVERS));
$preferred = $DIRECTORY_FALLBACK_SERVERS[$toss];
$toss = mt_rand(0,count($directory_fallback_servers));
$preferred = $directory_fallback_servers[$toss];
if(! $preferred) {
$preferred = DIRECTORY_FALLBACK_MASTER;
}
set_config('system','directory_server',$preferred);
}
}
else {
set_config('system','directory_server',z_root());
}
@@ -108,7 +109,7 @@ class Libzotdir {
$ret = get_config('directory', $setting);
// 'safemode' is the default if there is no observer or no established preference.
// 'safemode' is the default if there is no observer or no established preference.
if($setting === 'safemode' && $ret === false)
$ret = 1;
@@ -175,8 +176,8 @@ class Libzotdir {
*
* Checks the directory mode of this hub to see if it is some form of directory server. If it is,
* get the directory realm of this hub. Fetch a list of all other directory servers in this realm and request
* a directory sync packet. This will contain both directory updates and new ratings. Store these all in the DB.
* In the case of updates, we will query each of them asynchronously from a poller task. Ratings are stored
* a directory sync packet. This will contain both directory updates and new ratings. Store these all in the DB.
* In the case of updates, we will query each of them asynchronously from a poller task. Ratings are stored
* directly if the rater's signature matches.
*
* @param int $dirmode;
@@ -188,16 +189,17 @@ class Libzotdir {
return;
$realm = get_directory_realm();
if ($realm == DIRECTORY_REALM) {
$r = q("select * from site where (site_flags & %d) > 0 and site_url != '%s' and site_type = %d and ( site_realm = '%s' or site_realm = '') ",
$r = q("select * from site where (site_flags & %d) > 0 and site_url != '%s' and site_type = %d and ( site_realm = '%s' or site_realm = '') and site_dead = 0",
intval(DIRECTORY_MODE_PRIMARY|DIRECTORY_MODE_SECONDARY),
dbesc(z_root()),
intval(SITE_TYPE_ZOT),
dbesc($realm)
);
}
}
else {
$r = q("select * from site where (site_flags & %d) > 0 and site_url != '%s' and site_realm like '%s' and site_type = %d ",
$r = q("select * from site where (site_flags & %d) > 0 and site_url != '%s' and site_realm like '%s' and site_type = %d and site_dead = 0",
intval(DIRECTORY_MODE_PRIMARY|DIRECTORY_MODE_SECONDARY),
dbesc(z_root()),
dbesc(protect_sprintf('%' . $realm . '%')),
@@ -205,6 +207,8 @@ class Libzotdir {
);
}
// If there are no directory servers, setup the fallback master
/** @FIXME What to do if we're in a different realm? */
@@ -214,14 +218,14 @@ class Libzotdir {
[
'site_url' => DIRECTORY_FALLBACK_MASTER,
'site_flags' => DIRECTORY_MODE_PRIMARY,
'site_update' => NULL_DATE,
'site_update' => NULL_DATE,
'site_directory' => DIRECTORY_FALLBACK_MASTER . '/dirsearch',
'site_realm' => DIRECTORY_REALM,
'site_valid' => 1,
]
);
$r = q("select * from site where site_flags in (%d, %d) and site_url != '%s' and site_type = %d ",
$r = q("select * from site where site_flags in (%d, %d) and site_url != '%s' and site_type = %d and site_dead = 0",
intval(DIRECTORY_MODE_PRIMARY),
intval(DIRECTORY_MODE_SECONDARY),
dbesc(z_root()),
@@ -245,7 +249,6 @@ class Libzotdir {
$syncdate = (($rr['site_sync'] <= NULL_DATE) ? datetime_convert('UTC','UTC','now - 2 days') : $rr['site_sync']);
$x = z_fetch_url($rr['site_directory'] . '?f=&sync=' . urlencode($syncdate) . (($token) ? '&t=' . $token : ''));
if (! $x['success'])
continue;
@@ -273,7 +276,7 @@ class Libzotdir {
$ud_flags |= UPDATE_FLAGS_DELETED;
if (is_array($t['flags']) && in_array('forced',$t['flags']))
$ud_flags |= UPDATE_FLAGS_FORCED;
$z = q("insert into updates ( ud_hash, ud_guid, ud_date, ud_flags, ud_addr )
values ( '%s', '%s', '%s', %d, '%s' ) ",
dbesc($t['hash']),
@@ -308,12 +311,13 @@ class Libzotdir {
if ($ud['ud_addr'] && (! ($ud['ud_flags'] & UPDATE_FLAGS_DELETED))) {
$success = false;
$zf = [];
$href = Webfinger::zot_url(punify($ud['ud_addr']));
if($href) {
$zf = Zotfinger::exec($href);
}
if(is_array($zf) && array_path_exists('signature/signer',$zf) && $zf['signature']['signer'] === $href && intval($zf['signature']['header_valid'])) {
if(array_path_exists('signature/signer',$zf) && $zf['signature']['signer'] === $href && intval($zf['signature']['header_valid'])) {
$xc = Libzot::import_xchan($zf['data'], 0, $ud);
}
else {
@@ -338,7 +342,7 @@ class Libzotdir {
static function local_dir_update($uid, $force) {
logger('local_dir_update: uid: ' . $uid, LOGGER_DEBUG);
$p = q("select channel.channel_hash, channel_address, channel_timezone, channel_portable_id, profile.* from profile left join channel on channel_id = uid where uid = %d and is_default = 1",
@@ -354,7 +358,7 @@ class Libzotdir {
$profile['description'] = $p[0]['pdesc'];
$profile['birthday'] = $p[0]['dob'];
if ($age = age($p[0]['dob'],$p[0]['channel_timezone'],''))
if ($age = age($p[0]['dob'],$p[0]['channel_timezone'],''))
$profile['age'] = $age;
$profile['gender'] = $p[0]['gender'];
@@ -415,7 +419,7 @@ class Libzotdir {
dbesc($legacy_hash)
);
}
}
$ud_hash = random_string() . '@' . \App::get_hostname();
@@ -446,7 +450,7 @@ class Libzotdir {
$arr['xprof_hash'] = $hash;
$arr['xprof_dob'] = (($profile['birthday'] === '0000-00-00') ? $profile['birthday'] : datetime_convert('','',$profile['birthday'],'Y-m-d')); // !!!! check this for 0000 year
$arr['xprof_age'] = (($profile['age']) ? intval($profile['age']) : 0);
$arr['xprof_desc'] = (($profile['description']) ? htmlspecialchars($profile['description'], ENT_COMPAT,'UTF-8',false) : '');
$arr['xprof_desc'] = (($profile['description']) ? htmlspecialchars($profile['description'], ENT_COMPAT,'UTF-8',false) : '');
$arr['xprof_gender'] = (($profile['gender']) ? htmlspecialchars($profile['gender'], ENT_COMPAT,'UTF-8',false) : '');
$arr['xprof_marital'] = (($profile['marital']) ? htmlspecialchars($profile['marital'], ENT_COMPAT,'UTF-8',false) : '');
$arr['xprof_sexual'] = (($profile['sexual']) ? htmlspecialchars($profile['sexual'], ENT_COMPAT,'UTF-8',false) : '');
@@ -641,7 +645,7 @@ class Libzotdir {
dbesc(datetime_convert()),
intval($flags),
dbesc($addr)
);
);
}
else {
q("update updates set ud_flags = ( ud_flags | %d ) where ud_addr = '%s' and not (ud_flags & %d)>0 ",

View File

@@ -9,7 +9,7 @@ define ( 'NWIKI_ITEM_RESOURCE_TYPE', 'nwiki' );
class NativeWiki {
static public function listwikis($channel, $observer_hash) {
public static function listwikis($channel, $observer_hash) {
$sql_extra = item_permissions_sql($channel['channel_id'], $observer_hash);
$wikis = q("SELECT * FROM item
@@ -40,7 +40,7 @@ class NativeWiki {
}
function create_wiki($channel, $observer_hash, $wiki, $acl) {
public static function create_wiki($channel, $observer_hash, $wiki, $acl) {
$resource_id = new_uuid();
$uuid = new_uuid();
@@ -101,7 +101,7 @@ class NativeWiki {
}
}
function update_wiki($channel_id, $observer_hash, $arr, $acl) {
public static function update_wiki($channel_id, $observer_hash, $arr, $acl) {
$w = self::get_wiki($channel_id, $observer_hash, $arr['resource_id']);
$item = $w['wiki'];
@@ -156,7 +156,7 @@ class NativeWiki {
}
}
static public function sync_a_wiki_item($uid,$id,$resource_id) {
public static function sync_a_wiki_item($uid,$id,$resource_id) {
$r = q("SELECT * from item WHERE uid = %d AND ( id = %d OR ( resource_type = '%s' and resource_id = '%s' )) ",
@@ -185,7 +185,7 @@ class NativeWiki {
}
}
function delete_wiki($channel_id,$observer_hash,$resource_id) {
public static function delete_wiki($channel_id,$observer_hash,$resource_id) {
$w = self::get_wiki($channel_id,$observer_hash,$resource_id);
$item = $w['wiki'];
@@ -202,7 +202,7 @@ class NativeWiki {
}
static public function get_wiki($channel_id, $observer_hash, $resource_id) {
public static function get_wiki($channel_id, $observer_hash, $resource_id) {
$sql_extra = item_permissions_sql($channel_id,$observer_hash);
@@ -236,7 +236,7 @@ class NativeWiki {
}
static public function exists_by_name($uid, $urlName) {
public static function exists_by_name($uid, $urlName) {
$sql_extra = item_permissions_sql($uid);
@@ -258,7 +258,7 @@ class NativeWiki {
}
static public function get_permissions($resource_id, $owner_id, $observer_hash) {
public static function get_permissions($resource_id, $owner_id, $observer_hash) {
// TODO: For now, only the owner can edit
$sql_extra = item_permissions_sql($owner_id, $observer_hash);

View File

@@ -163,7 +163,7 @@ class NativeWikiPage {
return [ 'success' => true, 'page' => $page ];
}
return [ 'success' => false, 'item_id' => $c['item_id'], 'message' => t('Page not found') ];
return [ 'success' => false, 'message' => t('Page not found') ];
}
@@ -339,7 +339,6 @@ class NativeWikiPage {
}
static public function save_page($arr) {
$pageUrlName = ((array_key_exists('pageUrlName',$arr)) ? $arr['pageUrlName'] : '');
$content = ((array_key_exists('content',$arr)) ? $arr['content'] : '');
$resource_id = ((array_key_exists('resource_id',$arr)) ? $arr['resource_id'] : '');
@@ -385,7 +384,7 @@ class NativeWikiPage {
$ret = item_store($item, false, false);
if($ret['item_id'])
return array('message' => '', 'item_id' => $ret['item_id'], 'filename' => $filename, 'success' => true);
return array('message' => '', 'item_id' => $ret['item_id'], 'filename' => $pageUrlName, 'success' => true);
else
return array('message' => t('Page update failed.'), 'success' => false);
}
@@ -432,12 +431,12 @@ class NativeWikiPage {
$channel_id = ((array_key_exists('channel_id',$arr)) ? $arr['channel_id'] : 0);
if (! $commitHash) {
return array('content' => $content, 'message' => 'No commit was provided', 'success' => false);
return array('message' => 'No commit was provided', 'success' => false);
}
$w = Zlib\NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
if (!$w['wiki']) {
return array('content' => $content, 'message' => 'Error reading wiki', 'success' => false);
return array('message' => 'Error reading wiki', 'success' => false);
}
$x = $arr;
@@ -451,7 +450,7 @@ class NativeWikiPage {
$content = $loaded['body'];
return [ 'content' => $content, 'success' => true ];
}
return [ 'content' => $content, 'success' => false ];
return [ 'success' => false ];
}
}

View File

@@ -132,6 +132,7 @@ class PConfig {
// manage array value
$dbvalue = ((is_array($value)) ? serialize($value) : $value);
$dbvalue = ((is_bool($dbvalue)) ? intval($dbvalue) : $dbvalue);
$new = false;
$now = datetime_convert();
if (! $updated) {

View File

@@ -2,9 +2,6 @@
namespace Zotlabs\Lib;
use Zotlabs\Lib\Libzot;
class Queue {
static function update($id, $add_priority = 0) {
@@ -39,7 +36,7 @@ class Queue {
// queue item is less than 12 hours old, we'll schedule for fifteen
// minutes.
$r = q("UPDATE outq SET outq_scheduled = '%s' WHERE outq_posturl = '%s'",
q("UPDATE outq SET outq_scheduled = '%s' WHERE outq_posturl = '%s'",
dbesc(datetime_convert('UTC','UTC','now + 5 days')),
dbesc($x[0]['outq_posturl'])
);
@@ -88,7 +85,7 @@ class Queue {
static function set_delivered($id,$channel = 0) {
logger('queue: set delivered ' . $id,LOGGER_DEBUG);
$sql_extra = (($channel_id) ? " and outq_channel = " . intval($channel_id) . " " : '');
$sql_extra = (($channel['channel_id']) ? " and outq_channel = " . intval($channel['channel_id']) . " " : '');
// Set the next scheduled run date so far in the future that it will be expired
// long before it ever makes it back into the delivery chain.
@@ -230,11 +227,10 @@ class Queue {
logger('deliver: dest: ' . $outq['outq_posturl'], LOGGER_DEBUG);
if($outq['outq_posturl'] === z_root() . '/zot') {
// local delivery
$zot = new \Zotlabs\Zot6\Receiver(new \Zotlabs\Zot6\Zot6Handler(),$outq['outq_notify']);
$result = $zot->run(true);
$result = $zot->run();
logger('returned_json: ' . json_encode($result,JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES), LOGGER_DATA);
logger('deliver: local zot delivery succeeded to ' . $outq['outq_posturl']);
Libzot::process_response($outq['outq_posturl'],[ 'success' => true, 'body' => json_encode($result) ], $outq);

View File

@@ -2,8 +2,6 @@
namespace Zotlabs\Lib;
use Zotlabs\Lib\Activity;
class Share {
private $item = null;

View File

@@ -35,7 +35,7 @@ class ThreadItem {
public function __construct($data) {
$this->data = $data;
$this->toplevel = ($this->get_id() == $this->get_data_value('parent'));
$this->threaded = get_config('system','thread_allow');
@@ -98,10 +98,11 @@ class ThreadItem {
$conv = $this->get_conversation();
$observer = $conv->get_observer();
$lock = (((intval($item['item_private'])) || (($item['uid'] == local_channel()) && (strlen($item['allow_cid']) || strlen($item['allow_gid'])
$lock = (((intval($item['item_private'])) || (($item['uid'] == local_channel()) && (strlen($item['allow_cid']) || strlen($item['allow_gid'])
|| strlen($item['deny_cid']) || strlen($item['deny_gid']))))
? t('Private Message')
: false);
$locktype = $item['item_private'];
$shareable = ((($conv->get_profile_owner() == local_channel() && local_channel()) && ($item['item_private'] != 1)) ? true : false);
@@ -151,9 +152,9 @@ class ThreadItem {
if($observer && $observer['xchan_hash']
&& ($observer['xchan_hash'] == $this->get_data_value('author_xchan')
|| $observer['xchan_hash'] == $this->get_data_value('owner_xchan')
|| $observer['xchan_hash'] == $this->get_data_value('source_xchan')
&& ($observer['xchan_hash'] == $this->get_data_value('author_xchan')
|| $observer['xchan_hash'] == $this->get_data_value('owner_xchan')
|| $observer['xchan_hash'] == $this->get_data_value('source_xchan')
|| $this->get_data_value('uid') == local_channel()))
$dropping = true;
@@ -169,15 +170,15 @@ class ThreadItem {
'dropping' => $dropping,
'delete' => t('Delete'),
);
}
}
elseif(is_site_admin()) {
$drop = [ 'dropping' => true, 'delete' => t('Admin Delete') ];
}
// FIXME
if($observer_is_pageowner) {
if($observer_is_pageowner) {
$multidrop = array(
'select' => t('Select'),
'select' => t('Select'),
);
}
@@ -223,7 +224,7 @@ class ThreadItem {
if(! feature_enabled($conv->get_profile_owner(),'dislike'))
unset($conv_responses['dislike']);
$responses = get_responses($conv_responses,$response_verbs,$this,$item);
$my_responses = [];
@@ -254,7 +255,7 @@ class ThreadItem {
}
$showlike = ((x($conv_responses['like'],$item['mid'])) ? format_like($conv_responses['like'][$item['mid']],$conv_responses['like'][$item['mid'] . '-l'],'like',$item['mid']) : '');
$showdislike = ((x($conv_responses['dislike'],$item['mid']) && feature_enabled($conv->get_profile_owner(),'dislike'))
$showdislike = ((x($conv_responses['dislike'],$item['mid']) && feature_enabled($conv->get_profile_owner(),'dislike'))
? format_like($conv_responses['dislike'][$item['mid']],$conv_responses['dislike'][$item['mid'] . '-l'],'dislike',$item['mid']) : '');
/*
@@ -264,7 +265,7 @@ class ThreadItem {
*/
$this->check_wall_to_wall();
if($this->is_toplevel()) {
// FIXME check this permission
if(($conv->get_profile_owner() == local_channel()) && (! array_key_exists('real_uid',$item))) {
@@ -275,7 +276,7 @@ class ThreadItem {
);
}
}
}
else {
$is_comment = true;
}
@@ -349,7 +350,7 @@ class ThreadItem {
// $viewthread (below) is only valid in list mode. If this is a channel page, build the thread viewing link
// since we can't depend on llink or plink pointing to the right local location.
$owner_address = substr($item['owner']['xchan_addr'],0,strpos($item['owner']['xchan_addr'],'@'));
$viewthread = $item['llink'];
if($conv->get_mode() === 'channel')
@@ -357,7 +358,7 @@ class ThreadItem {
$comment_count_txt = sprintf( tt('%d comment','%d comments',$total_children),$total_children );
$list_unseen_txt = (($unseen_comments) ? sprintf( t('%d unseen'),$unseen_comments) : '');
$children = $this->get_children();
$has_tags = (($body['tags'] || $body['categories'] || $body['mentions'] || $body['attachments'] || $body['folders']) ? true : false);
@@ -386,7 +387,7 @@ class ThreadItem {
$tmp_item = array(
'template' => $this->get_template(),
'mode' => $mode,
'item_type' => intval($item['item_type']),
'item_type' => intval($item['item_type']),
//'type' => implode("",array_slice(explode("/",$item['verb']),-1)),
'body' => $body['html'],
'tags' => $body['tags'],
@@ -432,6 +433,7 @@ class ThreadItem {
'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')):''),
'lock' => $lock,
'locktype' => $locktype,
'delayed' => $item['item_delayed'],
'privacy_warning' => $privacy_warning,
'verified' => $verified,
@@ -518,8 +520,8 @@ class ThreadItem {
// 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']))
// 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)) {
@@ -539,7 +541,7 @@ class ThreadItem {
}
}
}
$result['private'] = $item['item_private'];
$result['toplevel'] = ($this->is_toplevel() ? 'toplevel_item' : '');
@@ -554,7 +556,7 @@ class ThreadItem {
return $result;
}
public function get_id() {
return $this->get_data_value('id');
}
@@ -609,7 +611,7 @@ class ThreadItem {
if(activity_match($item->get_data_value('verb'),ACTIVITY_LIKE) || activity_match($item->get_data_value('verb'),ACTIVITY_DISLIKE)) {
return false;
}
$item->set_parent($this);
$this->children[] = $item;
return end($this->children);
@@ -683,7 +685,7 @@ class ThreadItem {
*/
public function set_conversation($conv) {
$previous_mode = ($this->conversation ? $this->conversation->get_mode() : '');
$this->conversation = $conv;
// Set it on our children too
@@ -792,7 +794,7 @@ class ThreadItem {
if(!$this->is_toplevel() && !get_config('system','thread_allow')) {
return '';
}
$comment_box = '';
$conv = $this->get_conversation();
@@ -808,7 +810,7 @@ class ThreadItem {
$arr = array('comment_buttons' => '','id' => $this->get_id());
call_hooks('comment_buttons',$arr);
$comment_buttons = $arr['comment_buttons'];
$comment_box = replace_macros($template,array(
'$return_path' => '',
'$threaded' => $this->is_threaded(),
@@ -865,7 +867,7 @@ class ThreadItem {
if($conv->get_mode() === 'channel')
return;
if($this->is_toplevel() && ($this->get_data_value('author_xchan') != $this->get_data_value('owner_xchan'))) {
$this->owner_url = chanlink_hash($this->data['owner']['xchan_hash']);
$this->owner_photo = $this->data['owner']['xchan_photo_m'];

View File

@@ -5,7 +5,7 @@ namespace Zotlabs\Lib;
class Verify {
function create($type,$channel_id,$token,$meta) {
public static function create($type,$channel_id,$token,$meta) {
return q("insert into verify ( vtype, channel, token, meta, created ) values ( '%s', %d, '%s', '%s', '%s' )",
dbesc($type),
intval($channel_id),
@@ -15,7 +15,7 @@ class Verify {
);
}
function match($type,$channel_id,$token,$meta) {
public static function match($type,$channel_id,$token,$meta) {
$r = q("select id from verify where vtype = '%s' and channel = %d and token = '%s' and meta = '%s' limit 1",
dbesc($type),
intval($channel_id),
@@ -31,7 +31,7 @@ class Verify {
return false;
}
function get_meta($type,$channel_id,$token) {
public static function get_meta($type,$channel_id,$token) {
$r = q("select id, meta from verify where vtype = '%s' and channel = %d and token = '%s' limit 1",
dbesc($type),
intval($channel_id),
@@ -52,7 +52,7 @@ class Verify {
* @param string $type Verify type
* @param string $interval SQL compatible time interval
*/
function purge($type, $interval) {
public static function purge($type, $interval) {
q("delete from verify where vtype = '%s' and created < %s - INTERVAL %s",
dbesc($type),
db_utcnow(),

View File

@@ -21,9 +21,8 @@ class ZotURL {
}
$portable_url = substr($url,6);
$u = explode('/',$portable_url);
$u = explode('/',$portable_url);
$portable_id = $u[0];
$hosts = self::lookup($portable_id);
if(! $hosts) {
@@ -39,8 +38,8 @@ class ZotURL {
if($channel && $m) {
$headers = [
'Accept' => 'application/x-zot+json',
$headers = [
'Accept' => 'application/x-zot+json',
'Content-Type' => 'application/x-zot+json',
'X-Zot-Token' => random_string(),
'Digest' => HTTPSig::generate_digest_header($data),
@@ -50,9 +49,9 @@ class ZotURL {
$h = HTTPSig::create_sig($headers,$channel['channel_prvkey'],channel_url($channel),false);
}
else {
$h = [ 'Accept: application/x-zot+json' ];
$h = [ 'Accept: application/x-zot+json' ];
}
$result = [];
$redirects = 0;

View File

@@ -18,8 +18,8 @@ class Zotfinger {
if($channel && $m) {
$headers = [
'Accept' => 'application/x-zot+json',
$headers = [
'Accept' => 'application/x-zot+json',
'Content-Type' => 'application/x-zot+json',
'X-Zot-Token' => random_string(),
'Digest' => HTTPSig::generate_digest_header($data),
@@ -29,11 +29,10 @@ class Zotfinger {
$h = HTTPSig::create_sig($headers,$channel['channel_prvkey'],channel_url($channel),false);
}
else {
$h = [ 'Accept: application/x-zot+json' ];
$h = [ 'Accept: application/x-zot+json' ];
}
$result = [];
$result = [];
$redirects = 0;
$x = z_post_url($resource,$data,$redirects, [ 'headers' => $h ] );
@@ -44,11 +43,11 @@ class Zotfinger {
if ($verify) {
$result['signature'] = HTTPSig::verify($x, EMPTY_STR, 'zot6');
}
$result['data'] = json_decode($x['body'],true);
if($result['data'] && is_array($result['data']) && array_key_exists('encrypted',$result['data']) && $result['data']['encrypted']) {
$result['data'] = json_decode(crypto_unencapsulate($result['data'],get_config('system','prvkey')),true);
$result['data'] = json_decode(Crypto::unencapsulate($result['data'],get_config('system','prvkey')),true);
}
logger('decrypted: ' . print_r($result,true));

View File

@@ -2,6 +2,8 @@
namespace Zotlabs\Module;
use Zotlabs\Lib\Libzotdir;
require_once 'include/acl_selectors.php';
require_once 'include/group.php';
@@ -46,20 +48,20 @@ class Acl extends \Zotlabs\Web\Controller {
// 'a' => autocomplete connections (mod_connections, mod_poke, mod_sources, mod_photos)
// 'x' => nav search bar autocomplete (match any xchan)
// $_REQUEST['query'] contains autocomplete search text.
// List of channels whose connections to also suggest,
// 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());
// The different autocomplete libraries use different names for the search text
// parameter. Internally we'll use $search to represent the search text no matter
// what request variable it was attached to.
// what request variable it was attached to.
if(array_key_exists('query',$_REQUEST)) {
$search = $_REQUEST['query'];
}
if( (! local_channel()) && (! in_array($type, [ 'x', 'c', 'f' ])))
killme();
@@ -68,7 +70,7 @@ class Acl extends \Zotlabs\Web\Controller {
if(in_array($type, [ 'm', 'a', 'c', 'f' ])) {
// These queries require permission checking. We'll create a simple array of xchan_hash for those with
// the requisite permissions which we can check against.
// the requisite permissions which we can check against.
$x = q("select xchan from abconfig where chan = %d and cat = 'their_perms' and k = '%s' and v = '1'",
intval(local_channel()),
@@ -85,34 +87,34 @@ class Acl extends \Zotlabs\Web\Controller {
$sql_extra2 = "AND ( xchan_name LIKE " . protect_sprintf( "'%" . dbesc($search) . "%'" ) . " OR xchan_addr LIKE " . protect_sprintf( "'%" . dbesc(punify($search)) . ((strpos($search,'@') === false) ? "%@%'" : "%'")) . ") ";
$sql_extra2_xchan = "AND ( xchan_name LIKE " . protect_sprintf( "'" . dbesc($search) . "%'" ) . " OR xchan_addr LIKE " . protect_sprintf( "'" . dbesc(punify($search)) . ((strpos($search,'@') === false) ? "%@%'" : "%'")) . ") ";
// This horrible mess is needed because position also returns 0 if nothing is found.
// This horrible mess is needed because position also returns 0 if nothing is found.
// Would be MUCH easier if it instead returned a very large value
// Otherwise we could just
// Otherwise we could just
// order by LEAST(POSITION($search IN xchan_name),POSITION($search IN xchan_addr)).
$order_extra2 = "CASE WHEN xchan_name LIKE "
. protect_sprintf( "'%" . dbesc($search) . "%'" )
. " then POSITION('" . protect_sprintf(dbesc($search))
$order_extra2 = "CASE WHEN xchan_name LIKE "
. protect_sprintf( "'%" . dbesc($search) . "%'" )
. " then POSITION('" . protect_sprintf(dbesc($search))
. "' IN xchan_name) else position('" . protect_sprintf(dbesc(punify($search))) . "' IN xchan_addr) end, ";
$sql_extra3 = "AND ( xchan_addr like " . protect_sprintf( "'%" . dbesc(punify($search)) . "%'" ) . " OR xchan_name like " . protect_sprintf( "'%" . dbesc($search) . "%'" ) . " ) ";
}
else {
$sql_extra = $sql_extra2 = $sql_extra3 = "";
}
$groups = array();
$contacts = array();
if($type == '' || $type == 'g') {
// virtual groups based on private profile viewing ability
$r = q("select id, profile_guid, profile_name from profile where is_default = 0 and uid = %d",
intval(local_channel())
);
);
if($r) {
foreach($r as $rv) {
$groups[] = array(
@@ -130,19 +132,19 @@ class Acl extends \Zotlabs\Web\Controller {
// Normal privacy groups
$r = q("SELECT pgrp.id, pgrp.hash, pgrp.gname
FROM pgrp, pgrp_member
WHERE pgrp.deleted = 0 AND pgrp.uid = %d
FROM pgrp, pgrp_member
WHERE pgrp.deleted = 0 AND pgrp.uid = %d
AND pgrp_member.gid = pgrp.id
$sql_extra
GROUP BY pgrp.id
ORDER BY pgrp.gname
ORDER BY pgrp.gname
LIMIT %d OFFSET %d",
intval(local_channel()),
intval($count),
intval($start)
);
if($r) {
if($r) {
foreach($r as $g){
// logger('acl: group: ' . $g['gname'] . ' members: ' . group_get_members_xchan($g['id']));
$groups[] = array(
@@ -157,10 +159,10 @@ class Acl extends \Zotlabs\Web\Controller {
}
}
}
if($type == '' || $type == 'c' || $type === 'f') {
$extra_channels_sql = '';
$extra_channels_sql = '';
// Only include channels who allow the observer to view their connections
if($extra_channels) {
@@ -172,7 +174,7 @@ class Acl extends \Zotlabs\Web\Controller {
}
}
}
// Getting info from the abook is better for local users because it contains info about permissions
if(local_channel()) {
if($extra_channels_sql != '')
@@ -199,7 +201,7 @@ class Acl extends \Zotlabs\Web\Controller {
$r2 = array();
foreach($r1 as $rr) {
$x = atoken_xchan($rr);
$r2[] = [
$r2[] = [
'id' => 'a' . $rr['atoken_id'] ,
'hash' => $x['xchan_hash'],
'name' => $x['xchan_name'],
@@ -211,12 +213,12 @@ class Acl extends \Zotlabs\Web\Controller {
'abook_self' => 0
];
}
}
}
// add connections
$r = q("SELECT abook_id as id, xchan_hash as hash, xchan_name as name, xchan_photo_s as micro, xchan_url as url, xchan_addr as nick, abook_their_perms, xchan_pubforum, abook_flags, abook_self
FROM abook left join xchan on abook_xchan = xchan_hash
$r = q("SELECT abook_id as id, xchan_hash as hash, xchan_name as name, xchan_network as net, xchan_photo_s as micro, xchan_url as url, xchan_addr as nick, abook_their_perms, xchan_pubforum, abook_flags, abook_self
FROM abook left join xchan on abook_xchan = xchan_hash
WHERE (abook_channel = %d $extra_channels_sql) AND abook_blocked = 0 and abook_pending = 0 and xchan_deleted = 0 $sql_extra2 order by $order_extra2 xchan_name asc" ,
intval(local_channel())
);
@@ -225,28 +227,28 @@ class Acl extends \Zotlabs\Web\Controller {
}
else { // Visitors
$r = q("SELECT xchan_hash as id, xchan_hash as hash, xchan_name as name, xchan_photo_s as micro, xchan_url as url, xchan_addr as nick, 0 as abook_their_perms, 0 as abook_flags, 0 as abook_self
$r = q("SELECT xchan_hash as id, xchan_hash as hash, xchan_name as name, xchan_network as net, xchan_photo_s as micro, xchan_url as url, xchan_addr as nick, 0 as abook_their_perms, 0 as abook_flags, 0 as abook_self
FROM xchan left join xlink on xlink_link = xchan_hash
WHERE xlink_xchan = '%s' AND xchan_deleted = 0 $sql_extra2_xchan order by $order_extra2 xchan_name asc" ,
dbesc(get_observer_hash())
);
// Find contacts of extra channels
// This is probably more complicated than it needs to be
if($extra_channels_sql) {
// Build a list of hashes that we got previously so we don't get them again
$known_hashes = array("'".get_observer_hash()."'");
if($r)
foreach($r as $rr)
foreach($r as $rr)
$known_hashes[] = "'".$rr['hash']."'";
$known_hashes_sql = 'AND xchan_hash not in ('.join(',',$known_hashes).')';
$r2 = q("SELECT abook_id as id, xchan_hash as hash, xchan_name as name, xchan_photo_s as micro, xchan_url as url, xchan_addr as nick, abook_their_perms, abook_flags, abook_self
FROM abook left join xchan on abook_xchan = xchan_hash
$r2 = q("SELECT abook_id as id, xchan_hash as hash, xchan_name as name, xchan_network as net, xchan_photo_s as micro, xchan_url as url, xchan_addr as nick, abook_their_perms, abook_flags, abook_self
FROM abook left join xchan on abook_xchan = xchan_hash
WHERE abook_channel IN ($extra_channels_sql) $known_hashes_sql AND abook_blocked = 0 and abook_pending = 0 and abook_hidden = 0 and xchan_deleted = 0 $sql_extra2 order by $order_extra2 xchan_name asc");
if($r2)
$r = array_merge($r,$r2);
// Sort accoring to match position, then alphabetically. This could be avoided if the above two SQL queries could be combined into one, and the sorting could be done on the SQl server (like in the case of a local user)
$matchpos = function($x) use($search) {
$namepos = strpos($x['name'],$search);
@@ -269,22 +271,22 @@ class Acl extends \Zotlabs\Web\Controller {
}
}
if((count($r) < 100) && $type == 'c') {
$r2 = q("SELECT substr(xchan_hash,1,18) as id, xchan_hash as hash, xchan_name as name, xchan_photo_s as micro, xchan_url as url, xchan_addr as nick, 0 as abook_their_perms, 0 as abook_flags, 0 as abook_self
FROM xchan
$r2 = q("SELECT substr(xchan_hash,1,18) as id, xchan_hash as hash, xchan_name as name, xchan_network as net, xchan_photo_s as micro, xchan_url as url, xchan_addr as nick, 0 as abook_their_perms, 0 as abook_flags, 0 as abook_self
FROM xchan
WHERE xchan_deleted = 0 and not xchan_network in ('rss','anon','unknown') $sql_extra2_xchan order by $order_extra2 xchan_name asc"
);
if($r2) {
$r = array_merge($r,$r2);
$r = unique_multidim_array($r,'hash');
}
}
}
}
elseif($type == 'm') {
$r = array();
$z = q("SELECT xchan_hash as hash, xchan_name as name, xchan_addr as nick, xchan_photo_s as micro, xchan_url as url
$z = q("SELECT xchan_hash as hash, xchan_name as name, xchan_network as net, xchan_addr as nick, xchan_photo_s as micro, xchan_url as url
FROM abook left join xchan on abook_xchan = xchan_hash
WHERE abook_channel = %d
WHERE abook_channel = %d
and xchan_deleted = 0
and xchan_network IN ('zot', 'diaspora', 'friendica-over-diaspora')
$sql_extra3
@@ -298,18 +300,18 @@ class Acl extends \Zotlabs\Web\Controller {
}
}
}
}
elseif($type == 'a') {
$r = q("SELECT abook_id as id, xchan_name as name, xchan_hash as hash, xchan_addr as nick, xchan_photo_s as micro, xchan_network as network, xchan_url as url, xchan_addr as attag , abook_their_perms FROM abook left join xchan on abook_xchan = xchan_hash
$r = q("SELECT abook_id as id, xchan_name as name, xchan_network as net, xchan_hash as hash, xchan_addr as nick, xchan_photo_s as micro, xchan_url as url, xchan_addr as attag , abook_their_perms FROM abook left join xchan on abook_xchan = xchan_hash
WHERE abook_channel = %d
and xchan_deleted = 0
$sql_extra3
ORDER BY xchan_name ASC ",
intval(local_channel())
);
}
elseif($type == 'x') {
$r = $this->navbar_complete($a);
@@ -323,7 +325,7 @@ class Acl extends \Zotlabs\Web\Controller {
);
}
}
$o = array(
'start' => $start,
'count' => $count,
@@ -334,27 +336,34 @@ class Acl extends \Zotlabs\Web\Controller {
}
else
$r = array();
if($r) {
$i = count($contacts);
$x = [];
foreach($r as $g) {
if(in_array($g['network'],['rss','anon','unknown']) && ($type != 'a'))
if(in_array($g['net'],['rss','anon','unknown']) && ($type != 'a'))
continue;
$g['hash'] = urlencode($g['hash']);
if(! $g['nick']) {
$g['nick'] = $g['url'];
}
$clink = ($g['nick']) ? $g['nick'] : $g['url'];
$lkey = md5($clink);
if (! array_key_exists($lkey, $x))
$x[$lkey] = $i;
if(in_array($g['hash'],$permitted) && $type === 'f' && (! $noforums)) {
$contacts[] = array(
$contacts[$i] = array(
"type" => "c",
"photo" => "images/twopeople.png",
"name" => $g['name'],
"id" => urlencode($g['id']),
"xid" => $g['hash'],
"link" => (($g['nick']) ? $g['nick'] : $g['url']),
"link" => $clink,
"nick" => substr($g['nick'],0,strpos($g['nick'],'@')),
"self" => (intval($g['abook_self']) ? 'abook-self' : ''),
"taggable" => 'taggable',
@@ -362,24 +371,28 @@ class Acl extends \Zotlabs\Web\Controller {
);
}
if($type !== 'f') {
$contacts[] = array(
"type" => "c",
"photo" => $g['micro'],
"name" => $g['name'],
"id" => urlencode($g['id']),
"xid" => $g['hash'],
"link" => (($g['nick']) ? $g['nick'] : $g['url']),
"nick" => ((strpos($g['nick'],'@')) ? substr($g['nick'],0,strpos($g['nick'],'@')) : $g['nick']),
"self" => (intval($g['abook_self']) ? 'abook-self' : ''),
"taggable" => '',
"label" => '',
);
if (! array_key_exists($x[$lkey], $contacts) || ($contacts[$x[$lkey]]['net'] !== 'zot6' && ($g['net'] == 'zot6' || $g['net'] == 'zot'))) {
$contacts[$x[$lkey]] = array(
"type" => "c",
"photo" => $g['micro'],
"name" => $g['name'],
"id" => urlencode($g['id']),
"xid" => $g['hash'],
"link" => $clink,
"nick" => ((strpos($g['nick'],'@')) ? substr($g['nick'],0,strpos($g['nick'],'@')) : $g['nick']),
"self" => (intval($g['abook_self']) ? 'abook-self' : ''),
"taggable" => '',
"label" => '',
"net" => $g['net']
);
}
}
}
$i++;
}
}
$items = array_merge($groups, $contacts);
$o = array(
'start' => $start,
'count' => $count,
@@ -393,50 +406,50 @@ class Acl extends \Zotlabs\Web\Controller {
function navbar_complete(&$a) {
// logger('navbar_complete');
if(observer_prohibited()) {
return;
}
$dirmode = intval(get_config('system','directory_mode'));
$search = ((x($_REQUEST,'search')) ? htmlentities($_REQUEST['search'],ENT_COMPAT,'UTF-8',false) : '');
if(! $search || mb_strlen($search) < 2)
return array();
$star = false;
$address = false;
if(substr($search,0,1) === '@')
$search = substr($search,1);
if(substr($search,0,1) === '*') {
$star = true;
$search = substr($search,1);
}
if(strpos($search,'@') !== false) {
$address = true;
}
if(($dirmode == DIRECTORY_MODE_PRIMARY) || ($dirmode == DIRECTORY_MODE_STANDALONE)) {
$url = z_root() . '/dirsearch';
}
if(! $url) {
require_once("include/dir_fns.php");
$directory = find_upstream_directory($dirmode);
$directory = Libzotdir::find_upstream_directory($dirmode);
$url = $directory['url'] . '/dirsearch';
}
$token = get_config('system','realm_token');
$count = (x($_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)) : '');
$x = z_fetch_url($query);
if($x['success']) {
$t = 0;

View File

@@ -26,7 +26,12 @@ class Activity extends Controller {
$portable_id = EMPTY_STR;
$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 = sprintf(" and not verb in ('%s', '%s') ",
dbesc(ACTIVITY_FOLLOW),
dbesc(ACTIVITY_UNFOLLOW)
);
$item_normal = " and item.item_hidden = 0 and item.item_type = 0 and item.item_unpublished = 0 and item.item_delayed = 0 and item.item_blocked = 0 $item_normal_extra ";
$i = null;
@@ -86,7 +91,7 @@ class Activity extends Controller {
}
$parents_str = ids_to_querystr($i,'item_id');
$items = q("SELECT item.*, item.id AS item_id FROM item WHERE item.parent IN ( %s ) $item_normal ",
dbesc($parents_str)
);
@@ -143,8 +148,8 @@ class Activity extends Controller {
http_status_exit(403, 'Forbidden');
$i = ZlibActivity::encode_item_collection($nitems,'conversation/' . $item_id,'OrderedCollection');
if($portable_id) {
ThreadListener::store(z_root() . '/activity/' . $item_id,$portable_id);
if($portable_id && (! intval($items[0]['item_private']))) {
ThreadListener::store(z_root() . '/activity/' . $item_id, $portable_id);
}
if(! $i)
@@ -197,8 +202,12 @@ class Activity extends Controller {
}
}
$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 = sprintf(" and not verb in ('%s', '%s') ",
dbesc(ACTIVITY_FOLLOW),
dbesc(ACTIVITY_UNFOLLOW)
);
$item_normal = " and item.item_hidden = 0 and item.item_type = 0 and item.item_unpublished = 0 and item.item_delayed = 0 and item.item_blocked = 0 $item_normal_extra ";
$sigdata = HTTPSig::verify(EMPTY_STR);
if ($sigdata['portable_id'] && $sigdata['header_valid']) {
@@ -239,6 +248,16 @@ class Activity extends Controller {
xchan_query($r,true);
$items = fetch_post_tags($r,false);
if ($portable_id && (! intval($items[0]['item_private']))) {
$c = q("select abook_id from abook where abook_channel = %d and abook_xchan = '%s'",
intval($items[0]['uid']),
dbesc($portable_id)
);
if (! $c) {
ThreadListener::store(z_root() . '/activity/' . $item_id, $portable_id);
}
}
$channel = channelx_by_n($items[0]['uid']);
$x = array_merge( ['@context' => [

View File

@@ -63,9 +63,9 @@ class Article_edit extends \Zotlabs\Web\Controller {
if ($catsenabled){
$itm = fetch_post_tags($itm);
$cats = get_terms_oftype($itm[0]['term'], TERM_CATEGORY);
foreach ($cats as $cat) {
if (strlen($category))
$category .= ', ';
@@ -113,6 +113,7 @@ class Article_edit extends \Zotlabs\Web\Controller {
'post_id' => $post_id,
'visitor' => true,
'title' => htmlspecialchars($itm[0]['title'],ENT_COMPAT,'UTF-8'),
'summary' => htmlspecialchars($itm[0]['summary'],ENT_COMPAT,'UTF-8'),
'placeholdertitle' => t('Title (optional)'),
'pagetitle' => $card_title,
'profile_uid' => (intval($channel['channel_id'])),

View File

@@ -15,7 +15,7 @@ require_once('include/opengraph.php');
class Articles extends Controller {
function init() {
if(argc() > 1)
$which = argv(1);
@@ -28,13 +28,13 @@ class Articles extends Controller {
return;
}
}
profile_load($which);
}
function get($update = 0, $load = false) {
if(observer_prohibited(true)) {
return login();
}
@@ -56,7 +56,7 @@ class Articles extends Controller {
nav_set_selected('Articles');
head_add_link([
head_add_link([
'rel' => 'alternate',
'type' => 'application/json+oembed',
'href' => z_root() . '/oep?f=&url=' . urlencode(z_root() . '/' . App::$query_string),
@@ -65,7 +65,7 @@ class Articles extends Controller {
$category = (($_REQUEST['cat']) ? escape_tags(trim($_REQUEST['cat'])) : '');
if($category) {
$sql_extra2 .= protect_sprintf(term_item_parent_query(App::$profile['profile_uid'],'item', $category, TERM_CATEGORY));
}
@@ -74,24 +74,24 @@ class Articles extends Controller {
$datequery2 = ((x($_GET,'dbegin') && is_a_date_arg($_GET['dbegin'])) ? notags($_GET['dbegin']) : '');
$which = argv(1);
$selected_card = ((argc() > 2) ? argv(2) : '');
$_SESSION['return_url'] = App::$query_string;
$uid = local_channel();
$owner = App::$profile_uid;
$observer = App::get_observer();
$ob_hash = (($observer) ? $observer['xchan_hash'] : '');
if(! perm_is_allowed($owner,$ob_hash,'view_pages')) {
notice( t('Permission denied.') . EOL);
return;
}
$is_owner = ($uid && $uid == $owner);
$channel = channelx_by_n($owner);
if($channel) {
@@ -105,7 +105,7 @@ class Articles extends Controller {
else {
$channel_acl = [ 'allow_cid' => '', 'allow_gid' => '', 'deny_cid' => '', 'deny_gid' => '' ];
}
if(perm_is_allowed($owner,$ob_hash,'write_pages')) {
@@ -114,16 +114,15 @@ class Articles extends Controller {
'webpage' => ITEM_TYPE_ARTICLE,
'is_owner' => true,
'content_label' => t('Add Article'),
'button' => t('Create'),
'button' => t('Save'),
'nickname' => $channel['channel_address'],
'lockstate' => (($channel['channel_allow_cid'] || $channel['channel_allow_gid']
'lockstate' => (($channel['channel_allow_cid'] || $channel['channel_allow_gid']
|| $channel['channel_deny_cid'] || $channel['channel_deny_gid']) ? 'lock' : 'unlock'),
'acl' => (($is_owner) ? populate_acl($channel_acl, false,
'acl' => (($is_owner) ? populate_acl($channel_acl, false,
PermissionDescription::fromGlobalPermission('view_pages')) : ''),
'permissions' => $channel_acl,
'showacl' => (($is_owner) ? true : false),
'visitor' => true,
'body' => '[summary][/summary]',
'hide_location' => false,
'hide_voting' => false,
'profile_uid' => intval($owner),
@@ -147,12 +146,12 @@ class Articles extends Controller {
else {
$editor = '';
}
$itemspage = get_pconfig(local_channel(),'system','itemspage');
App::set_pager_itemspage(((intval($itemspage)) ? $itemspage : 10));
$pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(App::$pager['itemspage']), intval(App::$pager['start']));
$sql_extra = item_permissions_sql($owner);
$sql_item = '';
@@ -176,8 +175,8 @@ class Articles extends Controller {
$sql_extra2 .= " and item.item_thread_top != 0 ";
}
$r = q("select * from item
where item.uid = %d and item_type = %d
$r = q("select * from item
where item.uid = %d and item_type = %d
$sql_extra $sql_extra2 $sql_item order by item.created desc $pager_sql",
intval($owner),
intval(ITEM_TYPE_ARTICLE)
@@ -214,7 +213,7 @@ class Articles extends Controller {
opengraph_add_meta((! empty($items) ? $r[0] : []), $channel);
$mode = 'articles';
if(get_pconfig(local_channel(),'system','articles_list_mode') && (! $selected_card))
$page_mode = 'pager_list';
else

View File

@@ -1,61 +1,188 @@
<?php
namespace Zotlabs\Module;
use ZipArchive;
use Zotlabs\Web\Controller;
use Zotlabs\Lib\Verify;
require_once('include/security.php');
require_once('include/attach.php');
class Attach extends Controller {
class Attach extends \Zotlabs\Web\Controller {
function post() {
function init() {
if(argc() < 2) {
notice( t('Item not available.') . EOL);
$attach_ids = ((x($_REQUEST, 'attach_ids')) ? $_REQUEST['attach_ids'] : []);
$attach_path = ((x($_REQUEST, 'attach_path')) ? $_REQUEST['attach_path'] : '');
$channel_id = ((x($_REQUEST, 'channel_id')) ? intval($_REQUEST['channel_id']) : 0);
$channel = channelx_by_n($channel_id);
if (!$channel) {
notice(t('Channel not found.') . EOL);
return;
}
$r = attach_by_hash(argv(1),get_observer_hash(),((argc() > 2) ? intval(argv(2)) : 0));
if(! $r['success']) {
notice( $r['message'] . EOL);
$strip_str = '/cloud/' . $channel['channel_address'] . '/';
$count = strlen($strip_str);
$attach_path = substr($attach_path, $count);
if ($attach_ids) {
$zip_dir = 'store/[data]/' . $channel['channel_address'] . '/tmp';
if (!is_dir($zip_dir))
mkdir($zip_dir, STORAGE_DEFAULT_PERMISSIONS, true);
$token = random_string(32);
$zip_file = 'download_' . $token . '.zip';
$zip_path = $zip_dir . '/' . $zip_file;
$zip = new ZipArchive();
if ($zip->open($zip_path, ZipArchive::CREATE) === true) {
$zip_filename = self::zip_archive_handler($zip, $attach_ids, $attach_path);
$zip->close();
$meta = [
'zip_filename' => $zip_filename,
'zip_path' => $zip_path
];
Verify::create('zip_token', 0, $token, json_encode($meta));
json_return_and_die([
'success' => true,
'token' => $token
]);
}
}
}
function get() {
if (argc() < 2) {
notice(t('Item not available.') . EOL);
return;
}
$token = ((x($_REQUEST, 'token')) ? $_REQUEST['token'] : '');
if (argv(1) === 'download') {
$meta = Verify::get_meta('zip_token', 0, $token);
if (!$meta)
killme();
$meta = json_decode($meta, true);
header('Content-Type: application/zip');
header('Content-Disposition: attachment; filename="' . $meta['zip_filename'] . '"');
header('Content-Length: ' . filesize($meta['zip_path']));
$istream = fopen($meta['zip_path'], 'rb');
$ostream = fopen('php://output', 'wb');
if ($istream && $ostream) {
pipe_streams($istream, $ostream);
fclose($istream);
fclose($ostream);
}
unlink($meta['zip_path']);
killme();
}
$r = attach_by_hash(argv(1), get_observer_hash(), ((argc() > 2) ? intval(argv(2)) : 0));
if (!$r['success']) {
notice($r['message'] . EOL);
return;
}
$c = q("select channel_address from channel where channel_id = %d limit 1",
intval($r['data']['uid'])
);
if(! $c)
if (!$c)
return;
$unsafe_types = array('text/html','text/css','application/javascript');
if(in_array($r['data']['filetype'],$unsafe_types) && (! channel_codeallowed($r['data']['uid']))) {
header('Content-type: text/plain');
$unsafe_types = array('text/html', 'text/css', 'application/javascript');
if (in_array($r['data']['filetype'], $unsafe_types) && (!channel_codeallowed($r['data']['uid']))) {
header('Content-Type: text/plain');
}
else {
header('Content-type: ' . $r['data']['filetype']);
header('Content-Type: ' . $r['data']['filetype']);
}
header('Content-disposition: attachment; filename="' . $r['data']['filename'] . '"');
if(intval($r['data']['os_storage'])) {
$fname = dbunescbin($r['data']['content']);
if(strpos($fname,'store') !== false)
$istream = fopen($fname,'rb');
header('Content-Disposition: attachment; filename="' . $r['data']['filename'] . '"');
if (intval($r['data']['os_storage'])) {
$fname = $r['data']['content'];
if (strpos($fname, 'store') !== false)
$istream = fopen($fname, 'rb');
else
$istream = fopen('store/' . $c[0]['channel_address'] . '/' . $fname,'rb');
$ostream = fopen('php://output','wb');
if($istream && $ostream) {
pipe_streams($istream,$ostream);
$istream = fopen('store/' . $c[0]['channel_address'] . '/' . $fname, 'rb');
$ostream = fopen('php://output', 'wb');
if ($istream && $ostream) {
pipe_streams($istream, $ostream);
fclose($istream);
fclose($ostream);
}
}
else
echo dbunescbin($r['data']['content']);
echo $r['data']['content'];
killme();
}
public function zip_archive_handler($zip, $attach_ids, $attach_path, $pass = 1) {
$observer_hash = get_observer_hash();
$single = ((count($attach_ids) == 1) ? true : false);
$download_name = 'download.zip';
foreach ($attach_ids as $attach_id) {
$r = attach_by_id($attach_id, $observer_hash);
if (!$r['success']) {
continue;
}
if ($r['data']['is_dir'] && $single && $pass === 1)
$download_name = $r['data']['filename'] . '.zip';
$zip_path = $r['data']['display_path'];
if ($attach_path) {
$strip_str = $attach_path . '/';
$count = strlen($strip_str);
$zip_path = substr($r['data']['display_path'], $count);
}
if ($r['data']['is_dir']) {
$zip->addEmptyDir($zip_path);
$d = q("SELECT id FROM attach WHERE folder = '%s'",
dbesc($r['data']['hash'])
);
$attach_ids = ids_to_array($d);
self::zip_archive_handler($zip, $attach_ids, $attach_path, $pass++);
}
else {
$file_path = $r['data']['content'];
$zip->addFile($file_path, $zip_path);
// compressing can be ressource intensive - just store the data
$zip->setCompressionName($zip_path, ZipArchive::CM_STORE);
}
}
return $download_name;
}
}

View File

@@ -0,0 +1,203 @@
<?php
namespace Zotlabs\Module;
/**
* @file Zotlabs/Module/Attach_edit.php
*
*/
use App;
use Zotlabs\Web\Controller;
use Zotlabs\Lib\Libsync;
use Zotlabs\Access\AccessList;
class Attach_edit extends Controller {
function post() {
if (!local_channel() && !remote_channel()) {
return;
}
$attach_ids = ((x($_POST, 'attach_ids')) ? $_POST['attach_ids'] : []);
$attach_id = ((x($_POST, 'attach_id')) ? intval($_POST['attach_id']) : 0);
$channel_id = ((x($_POST, 'channel_id')) ? intval($_POST['channel_id']) : 0);
$dnd = ((x($_POST, 'dnd')) ? intval($_POST['dnd']) : 0);
$permissions = ((x($_POST, 'permissions')) ? intval($_POST['permissions']) : 0);
$return_path = ((x($_POST, 'return_path')) ? notags($_POST['return_path']) : 'cloud');
$delete = ((x($_POST, 'delete')) ? intval($_POST['delete']) : 0);
$newfolder = ((x($_POST, 'newfolder_' . $attach_id)) ? notags($_POST['newfolder_' . $attach_id]) : '');
if(! $newfolder)
$newfolder = ((x($_POST, 'newfolder')) ? notags($_POST['newfolder']) : '');
$newfilename = ((x($_POST, 'newfilename_' . $attach_id)) ? notags($_POST['newfilename_' . $attach_id]) : '');
$recurse = ((x($_POST, 'recurse_' . $attach_id)) ? intval($_POST['recurse_' . $attach_id]) : 0);
if(! $recurse)
$recurse = ((x($_POST, 'recurse')) ? intval($_POST['recurse']) : 0);
$notify = ((x($_POST, 'notify_edit_' . $attach_id)) ? intval($_POST['notify_edit_' . $attach_id]) : 0);
$copy = ((x($_POST, 'copy_' . $attach_id)) ? intval($_POST['copy_' . $attach_id]) : 0);
if(! $copy)
$copy = ((x($_POST, 'copy')) ? intval($_POST['copy']) : 0);
$categories = ((x($_POST, 'categories_' . $attach_id)) ? notags($_POST['categories_' . $attach_id]) : '');
if(! $categories)
$categories = ((x($_POST, 'categories')) ? notags($_POST['categories']) : '');
if($attach_id)
$attach_ids[] = $attach_id;
$single = ((count($attach_ids) === 1) ? true : false);
$channel = channelx_by_n($channel_id);
if (! $channel) {
notice(t('Channel not found.') . EOL);
return;
}
$nick = $channel['channel_address'];
$observer = App::get_observer();
$observer_hash = (($observer) ? $observer['xchan_hash'] : '');
$is_owner = ((local_channel() == $channel_id) ? true : false);
$ids_str = implode(',', $attach_ids);
$r = q("SELECT id, uid, hash, creator, folder, filename, is_photo, is_dir FROM attach WHERE id IN ( %s ) AND uid = %d",
dbesc($ids_str),
intval($channel_id)
);
if (! $r) {
notice(t('File not found.') . EOL);
return;
}
foreach ($r as $rr) {
$actions_done = '';
$attach_id = $rr['id'];
$resource = $rr['hash'];
$creator = $rr['creator'];
$folder = $rr['folder'];
$filename = $rr['filename'];
$is_photo = intval($rr['is_photo']);
$is_dir = intval($rr['is_dir']);
$admin_delete = false;
$is_creator = (($creator == $observer_hash) ? true : false);
$move = ((! $copy && ($folder !== $newfolder || (($single) ? $filename !== $newfilename : false))) ? true : false);
$perms = get_all_perms($channel_id, $observer_hash);
if (! ($perms['view_storage'] || is_site_admin())) {
notice( t('Permission denied.') . EOL);
continue;
}
if (! $perms['write_storage']) {
if (is_site_admin()) {
$admin_delete = true;
}
else {
notice( t('Permission denied.') . EOL);
continue;
}
}
if (!$is_owner && !$admin_delete) {
if(! $is_creator) {
notice( t('Permission denied.') . EOL);
continue;
}
}
if ($delete) {
attach_delete($channel_id, $resource, $is_photo);
$actions_done .= 'delete,';
}
if ($copy) {
if($is_dir && $resource == $newfolder) {
notice( t('Can not copy folder into itself.') . EOL);
continue;
}
$x = attach_copy($channel_id, $resource, $newfolder, (($single) ? $newfilename : ''));
if ($x['success'])
$resource = $x['resource_id'];
$actions_done .= 'copy,';
}
if ($move) {
if($is_dir && $resource == $newfolder) {
notice( sprintf(t('Can not move folder "%s" into itself.'), $filename) . EOL);
continue;
}
$x = attach_move($channel_id, $resource, $newfolder, (($single) ? $newfilename : ''));
$actions_done .= 'move,';
}
if(! $delete && ! $dnd) {
if ($single || (! $single && $categories)) {
q("DELETE FROM term WHERE uid = %d AND oid = %d AND otype = %d",
intval($channel_id),
intval($attach_id),
intval(TERM_OBJ_FILE)
);
$cat = explode(',', $categories);
if ($cat) {
foreach($cat as $term) {
$term = trim(escape_tags($term));
if ($term) {
$term_link = z_root() . '/cloud/' . $nick . '/?cat=' . $term;
store_item_tag($channel_id, $attach_id, TERM_OBJ_FILE, TERM_CATEGORY, $term, $term_link);
}
}
$actions_done .= 'cat_add,';
}
}
else {
q("DELETE FROM term WHERE uid = %d AND oid = %d AND otype = %d",
intval($channel_id),
intval($attach_id),
intval(TERM_OBJ_FILE)
);
$actions_done .= 'cat_remove,';
}
if ($is_owner && ($single || (! $single && $permissions))) {
$acl = new AccessList($channel);
$acl->set_from_array($_REQUEST);
$x = $acl->get();
attach_change_permissions($channel_id, $resource, $x['allow_cid'], $x['allow_gid'], $x['deny_cid'], $x['deny_gid'], $recurse, true);
$actions_done .= 'permissions,';
if ($notify) {
attach_store_item($channel, $observer, $resource);
$actions_done .= 'notify,';
}
}
}
if (! $admin_delete && $actions_done) {
$sync = attach_export_data($channel, $resource, (($delete) ? true : false));
if ($sync) {
Libsync::build_sync_packet($channel_id, ['file' => [$sync]]);
}
}
logger('attach_edit: ' . $actions_done);
}
if($dnd || $delete) {
json_return_and_die([ 'success' => true ]);
}
goaway($return_path);
}
}

View File

@@ -37,8 +37,6 @@ class Cal extends Controller {
$observer = App::get_observer();
App::$data['observer'] = $observer;
$observer_xchan = (($observer) ? $observer['xchan_hash'] : '');
head_set_icon(App::$data['channel']['xchan_photo_s']);
App::$page['htmlhead'] .= "<script> var profile_uid = " . ((App::$data['channel']) ? App::$data['channel']['channel_id'] : 0) . "; </script>" ;
@@ -159,10 +157,10 @@ class Cal extends Controller {
'timezone' => $tz,
'start'=> $start,
'end' => $end,
'drop' => $drop,
'drop' => false,
'allDay' => (($rr['adjust']) ? 0 : 1),
'title' => html_entity_decode($rr['summary'], ENT_COMPAT, 'UTF-8'),
'editable' => $edit ? true : false,
'editable' => false,
'item' => $rr,
'plink' => [$rr['plink'], t('Link to source')],
'description' => html_entity_decode($rr['description'], ENT_COMPAT, 'UTF-8'),
@@ -205,9 +203,9 @@ class Cal extends Controller {
'$prev' => t('Previous'),
'$next' => t('Next'),
'$today' => t('Today'),
'$title' => $title,
'$dtstart' => $dtstart,
'$dtend' => $dtend,
'$title' => '',
'$dtstart' => '',
'$dtend' => '',
'$nick' => $nick
]);

View File

@@ -63,9 +63,9 @@ class Card_edit extends \Zotlabs\Web\Controller {
if ($catsenabled){
$itm = fetch_post_tags($itm);
$cats = get_terms_oftype($itm[0]['term'], TERM_CATEGORY);
foreach ($cats as $cat) {
if (strlen($category))
$category .= ', ';
@@ -114,6 +114,7 @@ class Card_edit extends \Zotlabs\Web\Controller {
'post_id' => $post_id,
'visitor' => true,
'title' => htmlspecialchars($itm[0]['title'],ENT_COMPAT,'UTF-8'),
'summary' => htmlspecialchars($itm[0]['summary'],ENT_COMPAT,'UTF-8'),
'placeholdertitle' => t('Title (optional)'),
'pagetitle' => $card_title,
'profile_uid' => (intval($channel['channel_id'])),

View File

@@ -110,7 +110,7 @@ class Cards extends Controller {
'webpage' => ITEM_TYPE_CARD,
'is_owner' => true,
'content_label' => t('Add Card'),
'button' => t('Create'),
'button' => t('Save'),
'nickname' => $channel['channel_address'],
'lockstate' => (($channel['channel_allow_cid'] || $channel['channel_allow_gid']
|| $channel['channel_deny_cid'] || $channel['channel_deny_gid']) ? 'lock' : 'unlock'),

View File

@@ -5,6 +5,9 @@ use App;
use Zotlabs\Lib\Apps;
use Zotlabs\Web\Controller;
use Zotlabs\Web\HTTPSig;
use Zotlabs\Lib\Libzot;
use Zotlabs\Lib\Libsync;
require_once('include/event.php');
@@ -47,11 +50,12 @@ class Cdav extends Controller {
if($sigblock) {
$keyId = str_replace('acct:','',$sigblock['keyId']);
if($keyId) {
$r = q("select * from hubloc where hubloc_addr = '%s' limit 1",
$r = q("select * from hubloc where hubloc_id_url = '%s'",
dbesc($keyId)
);
if($r) {
$c = channelx_by_hash($r[0]['hubloc_hash']);
$r = Libzot::zot_record_preferred($r);
$c = channelx_by_hash($r['hubloc_hash']);
if($c) {
$a = q("select * from account where account_id = %d limit 1",
intval($c['channel_account_id'])
@@ -157,10 +161,10 @@ class Cdav extends Controller {
}
}
// Track CDAV updates from remote clients
$httpmethod = $_SERVER['REQUEST_METHOD'];
$httpmethod = $_SERVER['REQUEST_METHOD'];
if($httpmethod === 'PUT' || $httpmethod === 'DELETE') {
@@ -190,12 +194,12 @@ class Cdav extends Controller {
if($x = get_cdav_id($principalUri, explode("/", $httpuri)[4], $cdavtable)) {
$cdavdata = $this->get_cdav_data($x['id'], $cdavtable);
$etag = (isset($_SERVER['HTTP_IF_MATCH']) ? $_SERVER['HTTP_IF_MATCH'] : false);
// delete
if($httpmethod === 'DELETE' && $cdavdata['etag'] == $etag)
build_sync_packet($channel['channel_id'], [
Libsync::build_sync_packet($channel['channel_id'], [
$sync => [
'action' => 'delete_card',
'uri' => $cdavdata['uri'],
@@ -206,7 +210,7 @@ class Cdav extends Controller {
if($etag) {
// update
if($cdavdata['etag'] !== $etag)
build_sync_packet($channel['channel_id'], [
Libsync::build_sync_packet($channel['channel_id'], [
$sync => [
'action' => 'update_card',
'uri' => $cdavdata['uri'],
@@ -217,7 +221,7 @@ class Cdav extends Controller {
}
else {
// new
build_sync_packet($channel['channel_id'], [
Libsync::build_sync_packet($channel['channel_id'], [
$sync => [
'action' => 'import',
'uri' => $cdavdata['uri'],
@@ -280,7 +284,7 @@ class Cdav extends Controller {
$server->addPlugin(new \Sabre\CardDAV\VCFExportPlugin());
// And off we go!
$server->exec();
$server->start();
killme();
@@ -337,7 +341,7 @@ class Cdav extends Controller {
// set new calendar to be visible
set_pconfig(local_channel(), 'cdav_calendar' , $id[0], 1);
build_sync_packet($channel['channel_id'], [
Libsync::build_sync_packet($channel['channel_id'], [
'calendar' => [
'action' => 'create',
'uri' => $calendarUri,
@@ -413,7 +417,7 @@ class Cdav extends Controller {
$calendarData = $vcalendar->serialize();
$caldavBackend->createCalendarObject($id, $objectUri, $calendarData);
build_sync_packet($channel['channel_id'], [
Libsync::build_sync_packet($channel['channel_id'], [
'calendar' => [
'action' => 'import',
'uri' => $cdavdata['uri'],
@@ -444,7 +448,7 @@ class Cdav extends Controller {
$caldavBackend->updateCalendar($id, $patch);
$patch->commit();
build_sync_packet($channel['channel_id'], [
Libsync::build_sync_packet($channel['channel_id'], [
'calendar' => [
'action' => 'edit',
'uri' => $cdavdata['uri'],
@@ -510,7 +514,7 @@ class Cdav extends Controller {
$calendarData = $vcalendar->serialize();
$caldavBackend->updateCalendarObject($id, $uri, $calendarData);
build_sync_packet($channel['channel_id'], [
Libsync::build_sync_packet($channel['channel_id'], [
'calendar' => [
'action' => 'update_card',
'uri' => $cdavdata['uri'],
@@ -536,7 +540,7 @@ class Cdav extends Controller {
$caldavBackend->deleteCalendarObject($id, $uri);
build_sync_packet($channel['channel_id'], [
Libsync::build_sync_packet($channel['channel_id'], [
'calendar' => [
'action' => 'delete_card',
'uri' => $cdavdata['uri'],
@@ -594,7 +598,7 @@ class Cdav extends Controller {
$calendarData = $vcalendar->serialize();
$caldavBackend->updateCalendarObject($id, $uri, $calendarData);
build_sync_packet($channel['channel_id'], [
Libsync::build_sync_packet($channel['channel_id'], [
'calendar' => [
'action' => 'update_card',
'uri' => $cdavdata['uri'],
@@ -653,7 +657,7 @@ class Cdav extends Controller {
$carddavBackend->createAddressBook($principalUri, $addressbookUri, $properties);
build_sync_packet($channel['channel_id'], [
Libsync::build_sync_packet($channel['channel_id'], [
'addressbook' => [
'action' => 'create',
'uri' => $addressbookUri,
@@ -680,7 +684,7 @@ class Cdav extends Controller {
$carddavBackend->updateAddressBook($id, $patch);
$patch->commit();
build_sync_packet($channel['channel_id'], [
Libsync::build_sync_packet($channel['channel_id'], [
'addressbook' => [
'action' => 'edit',
'uri' => $cdavdata['uri'],
@@ -724,7 +728,7 @@ class Cdav extends Controller {
$cardData = $vcard->serialize();
$carddavBackend->createCard($id, $uri, $cardData);
build_sync_packet($channel['channel_id'], [
Libsync::build_sync_packet($channel['channel_id'], [
'addressbook' => [
'action' => 'import',
'uri' => $cdavdata['uri'],
@@ -762,8 +766,8 @@ class Cdav extends Controller {
$cardData = $vcard->serialize();
$carddavBackend->updateCard($id, $uri, $cardData);
build_sync_packet($channel['channel_id'], [
Libsync::build_sync_packet($channel['channel_id'], [
'addressbook' => [
'action' => 'update_card',
'uri' => $cdavdata['uri'],
@@ -788,7 +792,7 @@ class Cdav extends Controller {
$carddavBackend->deleteCard($id, $uri);
build_sync_packet($channel['channel_id'], [
Libsync::build_sync_packet($channel['channel_id'], [
'addressbook' => [
'action' => 'delete_card',
'uri' => $cdavdata['uri'],
@@ -804,7 +808,7 @@ class Cdav extends Controller {
$src = $_FILES['userfile']['tmp_name'];
if($src) {
$carddata = @file_get_contents($src);
if($_REQUEST['c_upload']) {
@@ -840,14 +844,14 @@ class Cdav extends Controller {
$objects = new \Sabre\VObject\Splitter\VCard($carddata);
$profile = \Sabre\VObject\Node::PROFILE_CARDDAV;
$backend = new \Sabre\CardDAV\Backend\PDO($pdo);
$cdavdata = $this->get_cdav_data($id, 'addressbooks');
}
$ids = [];
import_cdav_card($id, $ext, $table, $column, $objects, $profile, $backend, $ids, true);
build_sync_packet($channel['channel_id'], [
Libsync::build_sync_packet($channel['channel_id'], [
$sync => [
'action' => 'import',
'uri' => $cdavdata['uri'],
@@ -1013,7 +1017,7 @@ class Cdav extends Controller {
$catsenabled = feature_enabled(local_channel(), 'categories');
require_once('include/acl_selectors.php');
$accesslist = new \Zotlabs\Access\AccessList($channel);
$perm_defaults = $accesslist->get();
@@ -1167,7 +1171,7 @@ class Cdav extends Controller {
set_pconfig(local_channel(), 'cdav_calendar', $id, argv(4));
build_sync_packet(local_channel(), [
Libsync::build_sync_packet(local_channel(), [
'calendar' => [
'action' => 'switch',
'uri' => $cdavdata['uri'],
@@ -1190,7 +1194,7 @@ class Cdav extends Controller {
$caldavBackend->deleteCalendar($id);
build_sync_packet($channel['channel_id'], [
Libsync::build_sync_packet($channel['channel_id'], [
'calendar' => [
'action' => 'drop',
'uri' => $cdavdata['uri']
@@ -1409,7 +1413,7 @@ class Cdav extends Controller {
$carddavBackend->deleteAddressBook($id);
if($cdavdata)
build_sync_packet($channel['channel_id'], [
Libsync::build_sync_packet($channel['channel_id'], [
'addressbook' => [
'action' => 'drop',
'uri' => $cdavdata['uri']
@@ -1427,7 +1431,7 @@ class Cdav extends Controller {
return;
$uri = 'principals/' . $channel['channel_address'];
$r = q("select * from principals where uri = '%s' limit 1",
dbesc($uri)

View File

@@ -4,10 +4,13 @@ namespace Zotlabs\Module;
use App;
use Zotlabs\Web\Controller;
use Zotlabs\Lib\PermissionDescription;
use Zotlabs\Web\HTTPSig;
use Zotlabs\Lib\Activity;
use Zotlabs\Lib\ActivityStreams;
use Zotlabs\Lib\Crypto;
use Zotlabs\Lib\Libzot;
use Zotlabs\Lib\PermissionDescription;
use Zotlabs\Web\Controller;
use Zotlabs\Web\HTTPSig;
require_once('include/items.php');
require_once('include/security.php');
@@ -20,88 +23,117 @@ require_once('include/opengraph.php');
* @brief Channel Controller
*
*/
class Channel extends Controller {
function init() {
if(in_array(substr($_GET['search'],0,1),[ '@', '!', '?']))
goaway('search' . '?f=&search=' . $_GET['search']);
if (in_array(substr($_GET['search'], 0, 1), ['@', '!', '?']) || strpos($_GET['search'], 'https://') === 0)
goaway(z_root() . '/search?f=&search=' . $_GET['search']);
$which = null;
if(argc() > 1)
if (argc() > 1)
$which = argv(1);
if(! $which) {
if(local_channel()) {
if (!$which) {
if (local_channel()) {
$channel = App::get_channel();
if($channel && $channel['channel_address'])
$which = $channel['channel_address'];
if ($channel && $channel['channel_address'])
$which = $channel['channel_address'];
}
}
if(! $which) {
notice( t('You must be logged in to see this page.') . EOL );
if (!$which) {
notice(t('You must be logged in to see this page.') . EOL);
return;
}
$profile = 0;
$channel = App::get_channel();
if((local_channel()) && (argc() > 2) && (argv(2) === 'view')) {
$which = $channel['channel_address'];
if ((local_channel()) && (argc() > 2) && (argv(2) === 'view')) {
$which = $channel['channel_address'];
$profile = argv(1);
}
$channel = channelx_by_nick($which);
if(! $channel) {
if (!$channel) {
http_status_exit(404, 'Not found');
}
// handle zot6 channel discovery
// handle zot6 channel discovery
if (Libzot::is_zot_request()) {
if(Libzot::is_zot_request()) {
$sigdata = HTTPSig::verify(file_get_contents('php://input'), EMPTY_STR, 'zot6');
if($sigdata && $sigdata['signer'] && $sigdata['header_valid']) {
$data = json_encode(Libzot::zotinfo([ 'address' => $channel['channel_address'], 'target_url' => $sigdata['signer'] ]));
$s = q("select site_crypto, hubloc_sitekey from site left join hubloc on hubloc_url = site_url where hubloc_id_url = '%s' and hubloc_network = 'zot6' limit 1",
if ($sigdata && $sigdata['signer'] && $sigdata['header_valid']) {
$data = json_encode(Libzot::zotinfo(['address' => $channel['channel_address'], 'target_url' => $sigdata['signer']]));
$s = q("select site_crypto, hubloc_sitekey from site left join hubloc on hubloc_url = site_url where hubloc_id_url = '%s' and hubloc_network = 'zot6' limit 1",
dbesc($sigdata['signer'])
);
if($s) {
$data = json_encode(crypto_encapsulate($data,$s[0]['hubloc_sitekey'],Libzot::best_algorithm($s[0]['site_crypto'])));
if ($s) {
$data = json_encode(Crypto::encapsulate($data, $s[0]['hubloc_sitekey'], Libzot::best_algorithm($s[0]['site_crypto'])));
}
}
else {
$data = json_encode(Libzot::zotinfo([ 'address' => $channel['channel_address'] ]));
$data = json_encode(Libzot::zotinfo(['guid_hash' => $channel['channel_hash']]));
}
$headers = [
'Content-Type' => 'application/x-zot+json',
$headers = [
'Content-Type' => 'application/x-zot+json',
'Digest' => HTTPSig::generate_digest_header($data),
'(request-target)' => strtolower($_SERVER['REQUEST_METHOD']) . ' ' . $_SERVER['REQUEST_URI']
];
$h = HTTPSig::create_sig($headers,$channel['channel_prvkey'],channel_url($channel));
];
$h = HTTPSig::create_sig($headers, $channel['channel_prvkey'], channel_url($channel));
HTTPSig::set_headers($h);
echo $data;
killme();
}
if (ActivityStreams::is_as_request($channel)) {
if((local_channel()) && (argc() > 2) && (argv(2) === 'view')) {
$which = $channel['channel_address'];
// Somebody may attempt an ActivityStreams fetch on one of our message permalinks
// Make it do the right thing.
$mid = ((x($_REQUEST, 'mid')) ? $_REQUEST['mid'] : '');
if ($mid && strpos($mid, 'b64.') === 0) {
$decoded = @base64url_decode(substr($mid, 4));
if ($decoded) {
$mid = $decoded;
}
}
if ($mid) {
$obj = null;
if (strpos($mid, z_root() . '/item/') === 0) {
App::$argc = 2;
App::$argv = ['item', basename($mid)];
$obj = new Item();
}
if (strpos($mid, z_root() . '/activity/') === 0) {
App::$argc = 2;
App::$argv = ['activity', basename($mid)];
$obj = new Activity();
}
if ($obj) {
$obj->init();
}
}
as_return_and_die(Activity::encode_person($channel, true), $channel);
}
if ((local_channel()) && (argc() > 2) && (argv(2) === 'view')) {
$which = $channel['channel_address'];
$profile = argv(1);
}
head_add_link( [
'rel' => 'alternate',
head_add_link([
'rel' => 'alternate',
'type' => 'application/atom+xml',
'title' => t('Posts and comments'),
'href' => z_root() . '/feed/' . $which
]);
head_add_link( [
'rel' => 'alternate',
head_add_link([
'rel' => 'alternate',
'type' => 'application/atom+xml',
'title' => t('Only posts'),
'href' => z_root() . '/feed/' . $which . '?f=&top=1'
@@ -110,19 +142,19 @@ class Channel extends Controller {
// Run profile_load() here to make sure the theme is set before
// we start loading content
profile_load($which,$profile);
profile_load($which, $profile);
// Add Opengraph markup
$mid = ((x($_REQUEST,'mid')) ? $_REQUEST['mid'] : '');
if(strpos($mid,'b64.') === 0)
$mid = @base64url_decode(substr($mid,4));
if($mid)
$r = q("SELECT * FROM item WHERE mid = '%s' AND uid = %d AND item_private = 0 LIMIT 1",
dbesc($mid),
intval($channel['channel_id'])
);
$mid = ((x($_REQUEST, 'mid')) ? $_REQUEST['mid'] : '');
if (strpos($mid, 'b64.') === 0)
$mid = @base64url_decode(substr($mid, 4));
if ($mid)
$r = q("SELECT * FROM item WHERE mid = '%s' AND uid = %d AND item_private = 0 LIMIT 1",
dbesc($mid),
intval($channel['channel_id'])
);
opengraph_add_meta($r ? $r[0] : [], $channel);
}
@@ -130,107 +162,101 @@ class Channel extends Controller {
$noscript_content = get_config('system', 'noscript_content', '1');
if($load)
$_SESSION['loadtime'] = datetime_convert();
$category = $datequery = $datequery2 = '';
$mid = ((x($_REQUEST,'mid')) ? $_REQUEST['mid'] : '');
$mid = ((x($_REQUEST, 'mid')) ? $_REQUEST['mid'] : '');
if(strpos($mid,'b64.') === 0)
$decoded = @base64url_decode(substr($mid,4));
if($decoded)
if (strpos($mid, 'b64.') === 0)
$decoded = @base64url_decode(substr($mid, 4));
if ($decoded)
$mid = $decoded;
$datequery = ((x($_GET,'dend') && is_a_date_arg($_GET['dend'])) ? notags($_GET['dend']) : '');
$datequery2 = ((x($_GET,'dbegin') && is_a_date_arg($_GET['dbegin'])) ? notags($_GET['dbegin']) : '');
$datequery = ((x($_GET, 'dend') && is_a_date_arg($_GET['dend'])) ? notags($_GET['dend']) : '');
$datequery2 = ((x($_GET, 'dbegin') && is_a_date_arg($_GET['dbegin'])) ? notags($_GET['dbegin']) : '');
if(observer_prohibited(true)) {
if (observer_prohibited(true)) {
return login();
}
$category = ((x($_REQUEST,'cat')) ? $_REQUEST['cat'] : '');
$hashtags = ((x($_REQUEST,'tag')) ? $_REQUEST['tag'] : '');
$order = ((x($_GET,'order')) ? notags($_GET['order']) : 'post');
$static = ((array_key_exists('static',$_REQUEST)) ? intval($_REQUEST['static']) : 0);
$search = ((x($_GET,'search')) ? $_GET['search'] : EMPTY_STR);
$category = ((x($_REQUEST, 'cat')) ? $_REQUEST['cat'] : '');
$hashtags = ((x($_REQUEST, 'tag')) ? $_REQUEST['tag'] : '');
$order = ((x($_GET, 'order')) ? notags($_GET['order']) : 'post');
$search = ((x($_GET, 'search')) ? $_GET['search'] : EMPTY_STR);
$groups = array();
$groups = [];
$o = '';
if($update) {
if ($update) {
// Ensure we've got a profile owner if updating.
App::$profile['profile_uid'] = App::$profile_uid = $update;
}
$is_owner = (((local_channel()) && (App::$profile['profile_uid'] == local_channel())) ? true : false);
$channel = App::get_channel();
$channel = App::get_channel();
$observer = App::get_observer();
$ob_hash = (($observer) ? $observer['xchan_hash'] : '');
$ob_hash = (($observer) ? $observer['xchan_hash'] : '');
$perms = get_all_perms(App::$profile['profile_uid'],$ob_hash);
$perms = get_all_perms(App::$profile['profile_uid'], $ob_hash);
if(! $perms['view_stream']) {
if (!$perms['view_stream']) {
// We may want to make the target of this redirect configurable
if($perms['view_profile']) {
notice( t('Insufficient permissions. Request redirected to profile page.') . EOL);
goaway (z_root() . "/profile/" . App::$profile['channel_address']);
if ($perms['view_profile']) {
notice(t('Insufficient permissions. Request redirected to profile page.') . EOL);
goaway(z_root() . "/profile/" . App::$profile['channel_address']);
}
notice( t('Permission denied.') . EOL);
notice(t('Permission denied.') . EOL);
return;
}
if(! $update) {
if (!$update) {
nav_set_selected('Channel Home');
$static = channel_manual_conv_update(App::$profile['profile_uid']);
// search terms header
if($search) {
$o .= replace_macros(get_markup_template("section_title.tpl"),array(
'$title' => t('Search Results For:') . ' ' . htmlspecialchars($search, ENT_COMPAT,'UTF-8')
));
if ($search) {
$o .= replace_macros(get_markup_template("section_title.tpl"), [
'$title' => t('Search Results For:') . ' ' . htmlspecialchars($search, ENT_COMPAT, 'UTF-8')
]);
}
if($channel && $is_owner) {
$channel_acl = array(
if ($channel && $is_owner) {
$channel_acl = [
'allow_cid' => $channel['channel_allow_cid'],
'allow_gid' => $channel['channel_allow_gid'],
'deny_cid' => $channel['channel_deny_cid'],
'deny_gid' => $channel['channel_deny_gid']
);
'deny_cid' => $channel['channel_deny_cid'],
'deny_gid' => $channel['channel_deny_gid']
];
}
else {
$channel_acl = [ 'allow_cid' => '', 'allow_gid' => '', 'deny_cid' => '', 'deny_gid' => '' ];
$channel_acl = ['allow_cid' => '', 'allow_gid' => '', 'deny_cid' => '', 'deny_gid' => ''];
}
if($perms['post_wall']) {
if ($perms['post_wall']) {
$x = array(
'is_owner' => $is_owner,
'allow_location' => ((($is_owner || $observer) && (intval(get_pconfig(App::$profile['profile_uid'],'system','use_browser_location')))) ? true : false),
'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') : ''),
'permissions' => $channel_acl,
'showacl' => (($is_owner) ? 'yes' : ''),
'bang' => '',
'visitor' => (($is_owner || $observer) ? true : false),
'profile_uid' => App::$profile['profile_uid'],
$x = [
'is_owner' => $is_owner,
'allow_location' => ((($is_owner || $observer) && (intval(get_pconfig(App::$profile['profile_uid'], 'system', 'use_browser_location')))) ? true : false),
'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') : ''),
'permissions' => $channel_acl,
'showacl' => (($is_owner) ? 'yes' : ''),
'bang' => '',
'visitor' => (($is_owner || $observer) ? true : false),
'profile_uid' => App::$profile['profile_uid'],
'editor_autocomplete' => true,
'bbco_autocomplete' => 'bbcode',
'bbcode' => true,
'jotnets' => true,
'reset' => t('Reset form')
);
'bbco_autocomplete' => 'bbcode',
'bbcode' => true,
'jotnets' => true,
'reset' => t('Reset form')
];
$o .= status_editor($a,$x,false,'Channel');
$o .= status_editor($a, $x, false, 'Channel');
}
}
@@ -239,28 +265,30 @@ class Channel extends Controller {
/**
* Get permissions SQL - if $remote_contact is true, our remote user has been pre-verified and we already have fetched his/her groups
*/
$item_normal = " and item.item_hidden = 0 and item.item_type = 0 and item.item_deleted = 0
$item_normal = " and item.item_hidden = 0 and item.item_type = 0 and item.item_deleted = 0
and item.item_unpublished = 0 and item.item_pending_remove = 0
and item.item_blocked = 0 ";
if (! $is_owner)
$item_normal .= "and item.item_delayed = 0 ";
if (!$is_owner)
$item_normal .= "and item.item_delayed = 0 ";
$item_normal_update = item_normal_update();
$sql_extra = item_permissions_sql(App::$profile['profile_uid']);
$sql_extra = item_permissions_sql(App::$profile['profile_uid']);
if(feature_enabled(App::$profile['profile_uid'], 'channel_list_mode') && (! $mid))
if (feature_enabled(App::$profile['profile_uid'], 'channel_list_mode') && (!$mid))
$page_mode = 'list';
else
$page_mode = 'client';
$abook_uids = " and abook.abook_channel = " . intval(App::$profile['profile_uid']) . " ";
$simple_update = (($update) ? " AND item_unseen = 1 " : '');
$simple_update = '';
if ($update && $_SESSION['loadtime'])
$simple_update = " AND (( item_unseen = 1 AND item.changed > '" . datetime_convert('UTC', 'UTC', $_SESSION['loadtime']) . "' ) OR item.changed > '" . datetime_convert('UTC', 'UTC', $_SESSION['loadtime']) . "' ) ";
if($search) {
if ($search) {
$search = escape_tags($search);
if(strpos($search,'#') === 0) {
$sql_extra .= term_query('item',substr($search,1),TERM_HASHTAG,TERM_COMMUNITYTAG);
if (strpos($search, '#') === 0) {
$sql_extra .= term_query('item', substr($search, 1), TERM_HASHTAG, TERM_COMMUNITYTAG);
}
else {
$sql_extra .= sprintf(" AND (item.body like '%s' OR item.title like '%s') ",
@@ -270,31 +298,21 @@ class Channel extends Controller {
}
}
head_add_link([
head_add_link([
'rel' => 'alternate',
'type' => 'application/json+oembed',
'href' => z_root() . '/oep?f=&url=' . urlencode(z_root() . '/' . App::$query_string),
'title' => 'oembed'
]);
if($update && $_SESSION['loadtime'])
$simple_update = " AND (( item_unseen = 1 AND item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' ) OR item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' ) ";
if($load)
$simple_update = '';
if (($update) && (!$load)) {
if($static && $simple_update)
$simple_update .= " and author_xchan = '" . protect_sprintf(get_observer_hash()) . "' ";
if(($update) && (! $load)) {
if($mid) {
if ($mid) {
$r = q("SELECT parent AS item_id from item where mid like '%s' and uid = %d $item_normal_update
AND item_wall = 1 $simple_update $sql_extra limit 1",
dbesc($mid . '%'),
intval(App::$profile['profile_uid'])
);
$_SESSION['loadtime'] = datetime_convert();
}
else {
$r = q("SELECT parent AS item_id from item
@@ -306,67 +324,65 @@ class Channel extends Controller {
ORDER BY created DESC",
intval(App::$profile['profile_uid'])
);
$_SESSION['loadtime'] = datetime_convert();
}
}
else {
if(x($category)) {
$sql_extra2 .= protect_sprintf(term_item_parent_query(App::$profile['profile_uid'],'item', $category, TERM_CATEGORY));
if (x($category)) {
$sql_extra2 .= protect_sprintf(term_item_parent_query(App::$profile['profile_uid'], 'item', $category, TERM_CATEGORY));
}
if(x($hashtags)) {
$sql_extra2 .= protect_sprintf(term_item_parent_query(App::$profile['profile_uid'],'item', $hashtags, TERM_HASHTAG, TERM_COMMUNITYTAG));
if (x($hashtags)) {
$sql_extra2 .= protect_sprintf(term_item_parent_query(App::$profile['profile_uid'], 'item', $hashtags, TERM_HASHTAG, TERM_COMMUNITYTAG));
}
if($datequery) {
$sql_extra2 .= protect_sprintf(sprintf(" AND item.created <= '%s' ", dbesc(datetime_convert(date_default_timezone_get(),'',$datequery))));
$order = 'post';
if ($datequery) {
$sql_extra2 .= protect_sprintf(sprintf(" AND item.created <= '%s' ", dbesc(datetime_convert(date_default_timezone_get(), '', $datequery))));
$order = 'post';
}
if($datequery2) {
$sql_extra2 .= protect_sprintf(sprintf(" AND item.created >= '%s' ", dbesc(datetime_convert(date_default_timezone_get(),'',$datequery2))));
if ($datequery2) {
$sql_extra2 .= protect_sprintf(sprintf(" AND item.created >= '%s' ", dbesc(datetime_convert(date_default_timezone_get(), '', $datequery2))));
}
if($order === 'post')
if ($order === 'post')
$ordering = "created";
else
$ordering = "commented";
$itemspage = get_pconfig(local_channel(),'system','itemspage');
$itemspage = get_pconfig(local_channel(), 'system', 'itemspage');
App::set_pager_itemspage(((intval($itemspage)) ? $itemspage : 10));
$pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(App::$pager['itemspage']), intval(App::$pager['start']));
if($noscript_content || $load) {
if($mid) {
if ($noscript_content || $load) {
if ($mid) {
$r = q("SELECT parent AS item_id from item where mid like '%s' and uid = %d $item_normal
AND item_wall = 1 $sql_extra limit 1",
dbesc($mid . '%'),
intval(App::$profile['profile_uid'])
);
if (! $r) {
notice( t('Permission denied.') . EOL);
if (!$r) {
notice(t('Permission denied.') . EOL);
}
}
else {
$r = q("SELECT DISTINCT item.parent AS item_id, $ordering FROM item
$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
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
$sql_extra $sql_extra2
ORDER BY $ordering DESC, item_id $pager_sql ",
intval(App::$profile['profile_uid'])
);
}
}
else {
$r = array();
$r = [];
}
}
if($r) {
if ($r) {
$parents_str = ids_to_querystr($r,'item_id');
$parents_str = ids_to_querystr($r, 'item_id');
$r = q("SELECT item.*, item.id AS item_id
FROM item
@@ -379,86 +395,87 @@ class Channel extends Controller {
xchan_query($r);
$items = fetch_post_tags($r, true);
$items = conv_sort($items,$ordering);
$items = conv_sort($items, $ordering);
if($load && $mid && (! count($items))) {
if ($load && $mid && (!count($items))) {
// This will happen if we don't have sufficient permissions
// to view the parent item (or the item itself if it is toplevel)
notice( t('Permission denied.') . EOL);
notice(t('Permission denied.') . EOL);
}
} else {
$items = array();
}
else {
$items = [];
}
if((! $update) && (! $load)) {
// Add pinned content
if (!x($_REQUEST, 'mid') && !$search) {
$pinned = new \Zotlabs\Widget\Pinned;
$r = $pinned->widget(intval(App::$profile['profile_uid']), [ITEM_TYPE_POST]);
$o .= $r['html'];
}
if($decoded)
$mode = (($search) ? 'search' : 'channel');
if ((!$update) && (!$load)) {
if ($decoded)
$mid = 'b64.' . base64url_encode($mid);
// This is ugly, but we can't pass the profile_uid through the session to the ajax updater,
// because browser prefetching might change it on us. We have to deliver it with the page.
$maxheight = get_pconfig(App::$profile['profile_uid'],'system','channel_divmore_height');
if(! $maxheight)
$maxheight = get_pconfig(App::$profile['profile_uid'], 'system', 'channel_divmore_height');
if (!$maxheight)
$maxheight = 400;
$o .= '<div id="live-channel"></div>' . "\r\n";
$o .= "<script> var profile_uid = " . App::$profile['profile_uid']
. "; var netargs = '?f='; var profile_page = " . App::$pager['page']
. "; divmore_height = " . intval($maxheight) . "; </script>\r\n";
App::$page['htmlhead'] .= replace_macros(get_markup_template("build_query.tpl"),array(
'$baseurl' => z_root(),
'$pgtype' => 'channel',
'$uid' => ((App::$profile['profile_uid']) ? App::$profile['profile_uid'] : '0'),
'$gid' => '0',
'$cid' => '0',
'$cmin' => '(-1)',
'$cmax' => '(-1)',
'$star' => '0',
'$liked' => '0',
'$conv' => '0',
'$spam' => '0',
'$nouveau' => '0',
'$wall' => '1',
'$fh' => '0',
'$dm' => '0',
'$static' => $static,
'$page' => ((App::$pager['page'] != 1) ? App::$pager['page'] : 1),
'$search' => $search,
'$xchan' => '',
'$order' => (($order) ? urlencode($order) : ''),
'$list' => ((x($_REQUEST,'list')) ? intval($_REQUEST['list']) : 0),
'$file' => '',
'$cats' => (($category) ? urlencode($category) : ''),
'$tags' => (($hashtags) ? urlencode($hashtags) : ''),
'$mid' => (($mid) ? urlencode($mid) : ''),
'$verb' => '',
'$net' => '',
'$dend' => $datequery,
'$dbegin' => $datequery2
));
. "; divmore_height = " . intval($maxheight) . ";</script>\r\n";
App::$page['htmlhead'] .= replace_macros(get_markup_template("build_query.tpl"), [
'$baseurl' => z_root(),
'$pgtype' => 'channel',
'$uid' => ((App::$profile['profile_uid']) ? App::$profile['profile_uid'] : '0'),
'$gid' => '0',
'$cid' => '0',
'$cmin' => '(-1)',
'$cmax' => '(-1)',
'$star' => '0',
'$liked' => '0',
'$conv' => '0',
'$spam' => '0',
'$nouveau' => '0',
'$wall' => '1',
'$fh' => '0',
'$dm' => '0',
'$page' => ((App::$pager['page'] != 1) ? App::$pager['page'] : 1),
'$search' => $search,
'$xchan' => '',
'$order' => (($order) ? urlencode($order) : ''),
'$list' => ((x($_REQUEST, 'list')) ? intval($_REQUEST['list']) : 0),
'$file' => '',
'$cats' => (($category) ? urlencode($category) : ''),
'$tags' => (($hashtags) ? urlencode($hashtags) : ''),
'$mid' => (($mid) ? urlencode($mid) : ''),
'$verb' => '',
'$net' => '',
'$dend' => $datequery,
'$dbegin' => $datequery2,
'$conv_mode' => 'channel',
'$page_mode' => $page_mode
]);
}
// Add pinned content
if(! x($_REQUEST,'mid') && ! $search) {
$pinned = new \Zotlabs\Widget\Pinned;
$r = $pinned->widget(intval(App::$profile['profile_uid']), [ITEM_TYPE_POST]);
$o .= $r['html'];
}
$mode = (($search) ? 'search' : 'channel');
if($update) {
$o .= conversation($items,$mode,$update,$page_mode);
if ($update) {
$o .= conversation($items, $mode, $update, $page_mode);
}
else {
$o .= '<noscript>';
if($noscript_content) {
$o .= conversation($items,$mode,$update,'traditional');
if ($noscript_content) {
$o .= conversation($items, $mode, $update, 'traditional');
$o .= alt_pager(count($items));
}
else {
@@ -466,16 +483,18 @@ class Channel extends Controller {
}
$o .= '</noscript>';
$o .= conversation($items,$mode,$update,$page_mode);
$o .= conversation($items, $mode, $update, $page_mode);
if ($mid && $items[0]['title'])
App::$page['title'] = $items[0]['title'] . " - " . App::$page['title'];
}
if($mid)
if ($mid)
$o .= '<div id="content-complete"></div>';
$_SESSION['loadtime'] = datetime_convert();
return $o;
}
}

View File

@@ -1,7 +1,12 @@
<?php
namespace Zotlabs\Module;
use App;
use Zotlabs\Web\Controller;
use Zotlabs\Lib\Libsync;
use Zotlabs\Access\AccessList;
use Zotlabs\Daemon\Master;
require_once('include/conversation.php');
require_once('include/bbcode.php');
@@ -10,37 +15,37 @@ require_once('include/event.php');
require_once('include/items.php');
require_once('include/html2plain.php');
class Channel_calendar extends \Zotlabs\Web\Controller {
class Channel_calendar extends Controller {
function post() {
logger('post: ' . print_r($_REQUEST,true), LOGGER_DATA);
if(! local_channel())
return;
$event_id = ((x($_POST,'event_id')) ? intval($_POST['event_id']) : 0);
$event_hash = ((x($_POST,'event_hash')) ? $_POST['event_hash'] : '');
$xchan = ((x($_POST,'xchan')) ? dbesc($_POST['xchan']) : '');
logger('post: ' . print_r($_REQUEST, true), LOGGER_DATA);
$uid = local_channel();
if (!$uid)
return;
$event_id = ((x($_POST, 'event_id')) ? intval($_POST['event_id']) : 0);
$xchan = ((x($_POST, 'xchan')) ? dbesc($_POST['xchan']) : '');
// only allow editing your own events.
if(($xchan) && ($xchan !== get_observer_hash()))
if (($xchan) && ($xchan !== get_observer_hash()))
return;
$categories = escape_tags(trim($_POST['categories']));
// allday events have adjust = 0, normal events have adjust = 1
$adjust = intval($_POST['adjust']);
$start = datetime_convert((($adjust) ? $tz : 'UTC'), 'UTC', escape_tags($_REQUEST['dtstart']));
$timezone = ((x($_POST, 'timezone_select')) ? escape_tags(trim($_POST['timezone_select'])) : '');
$tz = (($timezone) ? $timezone : date_default_timezone_get());
$start = datetime_convert((($adjust) ? $tz : 'UTC'), 'UTC', escape_tags($_REQUEST['dtstart']));
$finish = datetime_convert((($adjust) ? $tz : 'UTC'), 'UTC', escape_tags($_REQUEST['dtend']));
$timezone = ((x($_POST,'timezone_select')) ? escape_tags(trim($_POST['timezone_select'])) : '');
$tz = (($timezone) ? $timezone : date_default_timezone_get());
if(! $adjust)
if (!$adjust)
$tz = 'UTC';
$summary = escape_tags(trim($_POST['summary']));
@@ -52,88 +57,86 @@ class Channel_calendar extends \Zotlabs\Web\Controller {
// It won't hurt anything, but somebody will file a bug report
// and we'll waste a bunch of time responding to it. Time that
// could've been spent doing something else.
if(strcmp($finish,$start) < 0 && !$nofinish) {
notice( t('Event can not end before it has started.') . EOL);
if(intval($_REQUEST['preview'])) {
echo( t('Unable to generate preview.'));
}
killme();
}
if((! $summary) || (! $start)) {
notice( t('Event title and start time are required.') . EOL);
if(intval($_REQUEST['preview'])) {
echo( t('Unable to generate preview.'));
if (strcmp($finish, $start) < 0) {
notice(t('Event can not end before it has started.') . EOL);
if (intval($_REQUEST['preview'])) {
echo(t('Unable to generate preview.'));
}
killme();
}
$channel = \App::get_channel();
$acl = new \Zotlabs\Access\AccessList(false);
if($event_id) {
if ((!$summary) || (!$start)) {
notice(t('Event title and start time are required.') . EOL);
if (intval($_REQUEST['preview'])) {
echo(t('Unable to generate preview.'));
}
killme();
}
$acl = new AccessList([]);
if ($event_id) {
$x = q("select * from event where id = %d and uid = %d limit 1",
intval($event_id),
intval(local_channel())
intval($uid)
);
if(! $x) {
notice( t('Event not found.') . EOL);
if(intval($_REQUEST['preview'])) {
echo( t('Unable to generate preview.'));
if (!$x) {
notice(t('Event not found.') . EOL);
if (intval($_REQUEST['preview'])) {
echo(t('Unable to generate preview.'));
killme();
}
return;
}
$acl->set($x[0]);
$created = $x[0]['created'];
$edited = datetime_convert();
$edited = datetime_convert();
}
else {
$created = $edited = datetime_convert();
$acl->set_from_array($_POST);
}
$post_tags = array();
$channel = \App::get_channel();
$ac = $acl->get();
$channel = App::get_channel();
$ac = $acl->get();
$str_contact_allow = $ac['allow_cid'];
$str_group_allow = $ac['allow_gid'];
$str_contact_deny = $ac['deny_cid'];
$str_group_deny = $ac['deny_gid'];
$str_contact_deny = $ac['deny_cid'];
$str_group_deny = $ac['deny_gid'];
$private = $acl->is_private();
require_once('include/text.php');
$results = linkify_tags($desc, local_channel());
$results = linkify_tags($desc, $uid);
if($results) {
if ($results) {
// Set permissions based on tag replacements
set_linkified_perms($results, $str_contact_allow, $str_group_allow, local_channel(), false, $private);
set_linkified_perms($results, $str_contact_allow, $str_group_allow, $uid, false, $private);
foreach($results as $result) {
foreach ($results as $result) {
$success = $result['success'];
if($success['replaced']) {
if ($success['replaced']) {
$post_tags[] = array(
'uid' => local_channel(),
'uid' => $uid,
'ttype' => $success['termtype'],
'otype' => TERM_OBJ_POST,
'term' => $success['term'],
'url' => $success['url']
);
);
}
}
}
if(strlen($categories)) {
$cats = explode(',',$categories);
foreach($cats as $cat) {
if (strlen($categories)) {
$cats = explode(',', $categories);
foreach ($cats as $cat) {
$post_tags[] = array(
'uid' => local_channel(),
'uid' => $uid,
'ttype' => TERM_CATEGORY,
'otype' => TERM_OBJ_POST,
'term' => trim($cat),
@@ -141,175 +144,170 @@ class Channel_calendar extends \Zotlabs\Web\Controller {
);
}
}
$datarray = array();
$datarray['dtstart'] = $start;
$datarray['dtend'] = $finish;
$datarray['summary'] = $summary;
$datarray['description'] = $desc;
$datarray['location'] = $location;
$datarray['etype'] = $type;
$datarray['adjust'] = $adjust;
$datarray['nofinish'] = 0;
$datarray['uid'] = local_channel();
$datarray['account'] = get_account_id();
$datarray['event_xchan'] = $channel['channel_hash'];
$datarray['allow_cid'] = $str_contact_allow;
$datarray['allow_gid'] = $str_group_allow;
$datarray['deny_cid'] = $str_contact_deny;
$datarray['deny_gid'] = $str_group_deny;
$datarray['private'] = intval($private);
$datarray['id'] = $event_id;
$datarray['created'] = $created;
$datarray['edited'] = $edited;
$datarray['timezone'] = $tz;
if(intval($_REQUEST['preview'])) {
$datarray = array();
$datarray['dtstart'] = $start;
$datarray['dtend'] = $finish;
$datarray['summary'] = $summary;
$datarray['description'] = $desc;
$datarray['location'] = $location;
$datarray['etype'] = $type;
$datarray['adjust'] = $adjust;
$datarray['nofinish'] = 0;
$datarray['uid'] = $uid;
$datarray['account'] = get_account_id();
$datarray['event_xchan'] = $channel['channel_hash'];
$datarray['allow_cid'] = $str_contact_allow;
$datarray['allow_gid'] = $str_group_allow;
$datarray['deny_cid'] = $str_contact_deny;
$datarray['deny_gid'] = $str_group_deny;
$datarray['private'] = intval($private);
$datarray['id'] = $event_id;
$datarray['created'] = $created;
$datarray['edited'] = $edited;
$datarray['timezone'] = $tz;
if (intval($_REQUEST['preview'])) {
$html = format_event_html($datarray);
echo $html;
killme();
}
$event = event_store_event($datarray);
if($post_tags)
if ($post_tags)
$datarray['term'] = $post_tags;
$item_id = event_store_item($datarray,$event);
if($item_id) {
$item_id = event_store_item($datarray, $event);
if ($item_id) {
$r = q("select * from item where id = %d",
intval($item_id)
);
if($r) {
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",
$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 ($z) {
Libsync::build_sync_packet($channel['channel_id'], array('event_item' => array(encode_item($sync_item[0], true)), 'event' => $z));
}
}
}
\Zotlabs\Daemon\Master::Summon(array('Notifier','event',$item_id));
Master::Summon(array('Notifier', 'event', $item_id));
killme();
}
function get() {
if(argc() > 2 && argv(1) == 'ical') {
if (argc() > 2 && argv(1) == 'ical') {
$event_id = argv(2);
require_once('include/security.php');
$sql_extra = permissions_sql(local_channel());
$r = q("select * from event where event_hash = '%s' $sql_extra limit 1",
dbesc($event_id)
);
if($r) {
if ($r) {
header('Content-type: text/calendar');
header('content-disposition: attachment; filename="' . t('event') . '-' . $event_id . '.ics"' );
header('content-disposition: attachment; filename="' . t('event') . '-' . $event_id . '.ics"');
echo ical_wrapper($r);
killme();
}
else {
notice( t('Event not found.') . EOL );
notice(t('Event not found.') . EOL);
return;
}
}
if(! local_channel()) {
notice( t('Permission denied.') . EOL);
if (!local_channel()) {
notice(t('Permission denied.') . EOL);
return;
}
if((argc() > 2) && (argv(1) === 'ignore') && intval(argv(2))) {
$r = q("update event set dismissed = 1 where id = %d and uid = %d",
intval(argv(2)),
intval(local_channel())
);
}
if((argc() > 2) && (argv(1) === 'unignore') && intval(argv(2))) {
$r = q("update event set dismissed = 0 where id = %d and uid = %d",
if ((argc() > 2) && (argv(1) === 'ignore') && intval(argv(2))) {
q("update event set dismissed = 1 where id = %d and uid = %d",
intval(argv(2)),
intval(local_channel())
);
}
$channel = \App::get_channel();
$mode = 'view';
$export = false;
$ignored = ((x($_REQUEST,'ignored')) ? " and dismissed = " . intval($_REQUEST['ignored']) . " " : '');
if ((argc() > 2) && (argv(1) === 'unignore') && intval(argv(2))) {
q("update event set dismissed = 0 where id = %d and uid = %d",
intval(argv(2)),
intval(local_channel())
);
}
if(argc() > 1) {
if(argc() > 2 && argv(1) === 'add') {
$mode = 'add';
$mode = 'view';
$export = false;
$ignored = ((x($_REQUEST, 'ignored')) ? " and dismissed = " . intval($_REQUEST['ignored']) . " " : '');
if (argc() > 1) {
if (argc() > 2 && argv(1) === 'add') {
$mode = 'add';
$item_id = intval(argv(2));
}
if(argc() > 2 && argv(1) === 'drop') {
$mode = 'drop';
if (argc() > 2 && argv(1) === 'drop') {
$mode = 'drop';
$event_id = argv(2);
}
if(argc() <= 2 && argv(1) === 'export') {
if (argc() <= 2 && argv(1) === 'export') {
$export = true;
}
if(argc() > 2 && intval(argv(1)) && intval(argv(2))) {
if (argc() > 2 && intval(argv(1)) && intval(argv(2))) {
$mode = 'view';
}
if(argc() <= 2) {
$mode = 'view';
if (argc() <= 2) {
$mode = 'view';
$event_id = argv(1);
}
}
if($mode === 'add') {
event_addtocal($item_id,local_channel());
if ($mode === 'add') {
event_addtocal($item_id, local_channel());
killme();
}
if($mode == 'view') {
if ($mode == 'view') {
/* edit/create form */
if($event_id) {
$r = q("SELECT * FROM event WHERE event_hash = '%s' AND uid = %d LIMIT 1",
if ($event_id) {
q("SELECT * FROM event WHERE event_hash = '%s' AND uid = %d LIMIT 1",
dbesc($event_id),
intval(local_channel())
);
if(count($r))
$orig_event = $r[0];
}
$channel = \App::get_channel();
if (argv(1) === 'json'){
if (x($_GET,'start')) $start = $_GET['start'];
if (x($_GET,'end')) $finish = $_GET['end'];
$channel = App::get_channel();
if (argv(1) === 'json') {
if (x($_GET, 'start')) $start = $_GET['start'];
if (x($_GET, 'end')) $finish = $_GET['end'];
}
$start = datetime_convert('UTC','UTC',$start);
$finish = datetime_convert('UTC','UTC',$finish);
$adjust_start = datetime_convert('UTC', date_default_timezone_get(), $start);
$start = datetime_convert('UTC', 'UTC', $start);
$finish = datetime_convert('UTC', 'UTC', $finish);
$adjust_start = datetime_convert('UTC', date_default_timezone_get(), $start);
$adjust_finish = datetime_convert('UTC', date_default_timezone_get(), $finish);
if (x($_GET,'id')){
$r = q("SELECT event.*, item.plink, item.item_flags, item.author_xchan, item.owner_xchan, item.id as item_id
if (x($_GET, 'id')) {
$r = q("SELECT event.*, item.plink, item.item_flags, item.author_xchan, item.owner_xchan, item.id as item_id
from event left join item on item.resource_id = event.event_hash
where item.resource_type = 'event' and event.uid = %d and event.id = %d limit 1",
intval(local_channel()),
intval($_GET['id'])
);
}
elseif($export) {
elseif ($export) {
$r = q("SELECT event.*, item.id as item_id
from event left join item on item.resource_id = event.event_hash
where event.uid = %d and event.dtstart > '%s' and event.dtend > event.dtstart",
@@ -335,104 +333,105 @@ class Channel_calendar extends \Zotlabs\Web\Controller {
dbesc($adjust_finish)
);
}
if($r && ! $export) {
if ($r && !$export) {
xchan_query($r);
$r = fetch_post_tags($r,true);
$r = fetch_post_tags($r, true);
$r = sort_by_date($r);
}
$events = [];
if($r) {
foreach($r as $rr) {
if ($r) {
foreach ($r as $rr) {
$start = (($rr['adjust']) ? datetime_convert('UTC', date_default_timezone_get(), $rr['dtstart'], 'c') : datetime_convert('UTC', 'UTC', $rr['dtstart'], 'c'));
if ($rr['nofinish']){
if ($rr['nofinish']) {
$end = null;
} else {
}
else {
$end = (($rr['adjust']) ? datetime_convert('UTC', date_default_timezone_get(), $rr['dtend'], 'c') : datetime_convert('UTC', 'UTC', $rr['dtend'], 'c'));
}
$catsenabled = feature_enabled(local_channel(),'categories');
$categories = '';
if($catsenabled){
if($rr['term']) {
$catsenabled = feature_enabled(local_channel(), 'categories');
$categories = '';
if ($catsenabled) {
if ($rr['term']) {
$cats = get_terms_oftype($rr['term'], TERM_CATEGORY);
foreach ($cats as $cat) {
if(strlen($categories))
if (strlen($categories))
$categories .= ', ';
$categories .= $cat['term'];
}
}
}
$edit = ((local_channel() && $rr['author_xchan'] == get_observer_hash()) ? array(z_root().'/events/'.$rr['event_hash'].'?expandform=1',t('Edit event'),'','') : false);
$drop = array(z_root().'/events/drop/'.$rr['event_hash'],t('Delete event'),'','');
$edit = ((local_channel() && $rr['author_xchan'] == get_observer_hash()) ? array(z_root() . '/events/' . $rr['event_hash'] . '?expandform=1', t('Edit event'), '', '') : false);
$drop = array(z_root() . '/events/drop/' . $rr['event_hash'], t('Delete event'), '', '');
$tz = get_iconfig($rr, 'event', 'timezone');
if(! $tz)
if (!$tz)
$tz = 'UTC';
$events[] = array(
'calendar_id' => 'channel_calendar',
'rw' => true,
'id'=>$rr['id'],
'uri' => $rr['event_hash'],
'timezone' => $tz,
'start'=> $start,
'end' => $end,
'drop' => $drop,
'allDay' => (($rr['adjust']) ? 0 : 1),
'title' => html_entity_decode($rr['summary'], ENT_COMPAT, 'UTF-8'),
'editable' => $edit ? true : false,
'item' => $rr,
'plink' => [$rr['plink'], t('Link to source')],
'rw' => true,
'id' => $rr['id'],
'uri' => $rr['event_hash'],
'timezone' => $tz,
'start' => $start,
'end' => $end,
'drop' => $drop,
'allDay' => (($rr['adjust']) ? 0 : 1),
'title' => html_entity_decode($rr['summary'], ENT_COMPAT, 'UTF-8'),
'editable' => $edit ? true : false,
'item' => $rr,
'plink' => [$rr['plink'], t('Link to source')],
'description' => html_entity_decode($rr['description'], ENT_COMPAT, 'UTF-8'),
'location' => html_entity_decode($rr['location'], ENT_COMPAT, 'UTF-8'),
'allow_cid' => expand_acl($rr['allow_cid']),
'allow_gid' => expand_acl($rr['allow_gid']),
'deny_cid' => expand_acl($rr['deny_cid']),
'deny_gid' => expand_acl($rr['deny_gid']),
'categories' => $categories
'location' => html_entity_decode($rr['location'], ENT_COMPAT, 'UTF-8'),
'allow_cid' => expand_acl($rr['allow_cid']),
'allow_gid' => expand_acl($rr['allow_gid']),
'deny_cid' => expand_acl($rr['deny_cid']),
'deny_gid' => expand_acl($rr['deny_gid']),
'categories' => $categories
);
}
}
if($export) {
if ($export) {
header('Content-type: text/calendar');
header('content-disposition: attachment; filename="' . t('calendar') . '-' . $channel['channel_address'] . '.ics"' );
header('content-disposition: attachment; filename="' . t('calendar') . '-' . $channel['channel_address'] . '.ics"');
echo ical_wrapper($r);
killme();
}
if (\App::$argv[1] === 'json'){
if (App::$argv[1] === 'json') {
json_return_and_die($events);
}
}
if($mode === 'drop' && $event_id) {
if ($mode === 'drop' && $event_id) {
$r = q("SELECT * FROM event WHERE event_hash = '%s' AND uid = %d LIMIT 1",
dbesc($event_id),
intval(local_channel())
);
$sync_event = $r[0];
if($r) {
if ($r) {
$r = q("delete from event where event_hash = '%s' and uid = %d",
dbesc($event_id),
intval(local_channel())
);
if($r) {
if ($r) {
$sync_event['event_deleted'] = 1;
Libsync::build_sync_packet(0,array('event' => array($sync_event)));
Libsync::build_sync_packet(0, array('event' => array($sync_event)));
$i = q("select * from item where resource_type = 'event' and resource_id = '%s' and uid = %d",
dbesc($event_id),
@@ -441,11 +440,11 @@ class Channel_calendar extends \Zotlabs\Web\Controller {
if ($i) {
$can_delete = false;
$can_delete = false;
$local_delete = true;
$ob_hash = get_observer_hash();
if($ob_hash && ($ob_hash === $i[0]['author_xchan'] || $ob_hash === $i[0]['owner_xchan'] || $ob_hash === $i[0]['source_xchan'])) {
if ($ob_hash && ($ob_hash === $i[0]['author_xchan'] || $ob_hash === $i[0]['owner_xchan'] || $ob_hash === $i[0]['source_xchan'])) {
$can_delete = true;
}
@@ -453,49 +452,49 @@ class Channel_calendar extends \Zotlabs\Web\Controller {
// If the item originated on this site+channel the deletion will propagate downstream.
// Otherwise just the local copy is removed.
if(is_site_admin()) {
if (is_site_admin()) {
$local_delete = true;
if(intval($i[0]['item_origin']))
if (intval($i[0]['item_origin']))
$can_delete = true;
}
if($can_delete || $local_delete) {
if ($can_delete || $local_delete) {
// if this is a different page type or it's just a local delete
// but not by the item author or owner, do a simple deletion
$complex = false;
$complex = false;
if(intval($i[0]['item_type']) || ($local_delete && (! $can_delete))) {
if (intval($i[0]['item_type']) || ($local_delete && (!$can_delete))) {
drop_item($i[0]['id']);
}
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'], true, DROPITEM_PHASE1);
$complex = true;
}
$ii = q("select * from item where id = %d",
intval($i[0]['id'])
);
if($ii) {
if ($ii) {
xchan_query($ii);
$sync_item = fetch_post_tags($ii);
Libsync::build_sync_packet($i[0]['uid'],array('item' => array(encode_item($sync_item[0],true))));
Libsync::build_sync_packet($i[0]['uid'], array('item' => array(encode_item($sync_item[0], true))));
}
if($complex) {
tag_deliver($i[0]['uid'],$i[0]['id']);
if ($complex) {
tag_deliver($i[0]['uid'], $i[0]['id']);
}
}
}
killme();
}
notice( t('Failed to remove event' ) . EOL);
notice(t('Failed to remove event') . EOL);
killme();
}
}
}
}

View File

@@ -70,7 +70,7 @@ class Chanview extends \Zotlabs\Web\Controller {
$zf = Zotfinger::exec($_REQUEST['url'], null);
if(array_path_exists('signature/signer',$zf) && $zf['signature']['signer'] === $_REQUEST['url'] && intval($zf['signature']['header_valid'])) {
Libzot::import_xchan($j);
Libzot::import_xchan($zf['data']);
$r = q("select * from xchan where xchan_url = '%s'",
dbesc($_REQUEST['url'])
);

View File

@@ -8,7 +8,11 @@ namespace Zotlabs\Module;
*/
use Sabre\DAV as SDAV;
use \Zotlabs\Storage;
use \Zotlabs\Web\Controller;
use \Zotlabs\Storage\BasicAuth;
use \Zotlabs\Storage\Directory;
use \Zotlabs\Storage\Browser;
// composer autoloader for SabreDAV
require_once('vendor/autoload.php');
@@ -20,7 +24,7 @@ require_once('include/attach.php');
* @brief Cloud Module.
*
*/
class Cloud extends \Zotlabs\Web\Controller {
class Cloud extends Controller {
/**
* @brief Fires up the SabreDAV server.
@@ -42,7 +46,7 @@ class Cloud extends \Zotlabs\Web\Controller {
$auth = new \Zotlabs\Storage\BasicAuth();
$auth = new BasicAuth();
$ob_hash = get_observer_hash();
@@ -72,7 +76,7 @@ class Cloud extends \Zotlabs\Web\Controller {
if($x !== \App::$query_string)
goaway(z_root() . '/' . $x);
$rootDirectory = new \Zotlabs\Storage\Directory('/', $auth);
$rootDirectory = new Directory('/', [], $auth);
// A SabreDAV server-object
$server = new SDAV\Server($rootDirectory);
@@ -85,7 +89,7 @@ class Cloud extends \Zotlabs\Web\Controller {
$is_readable = false;
// provide a directory view for the cloud in Hubzilla
$browser = new \Zotlabs\Storage\Browser($auth);
$browser = new Browser($auth);
$auth->setBrowserPlugin($browser);
$server->addPlugin($browser);
@@ -101,17 +105,17 @@ class Cloud extends \Zotlabs\Web\Controller {
// All we need to do now, is to fire up the server
$server->exec();
$server->start();
if($browser->build_page)
construct_page();
killme();
}
function DAVException($err) {
if($err instanceof \Sabre\DAV\Exception\NotFound) {
notice( t('Not found') . EOL);
}
@@ -126,7 +130,7 @@ class Cloud extends \Zotlabs\Web\Controller {
}
construct_page();
killme();
}

View File

@@ -109,6 +109,7 @@ class Connections extends \Zotlabs\Web\Controller {
case 'all':
$head = t('All');
break;
default:
$search_flags = " and abook_blocked = 0 and abook_ignored = 0 and abook_hidden = 0 and abook_archived = 0 and abook_not_here = 0 ";
$active = true;
@@ -238,7 +239,7 @@ class Connections extends \Zotlabs\Web\Controller {
}
$r = q("SELECT COUNT(abook.abook_id) AS total FROM abook left join xchan on abook.abook_xchan = xchan.xchan_hash
where abook_channel = %d and abook_self = 0 and xchan_deleted = 0 and xchan_orphan = 0 $sql_extra $sql_extra2 ",
where abook_channel = %d and abook_self = 0 and xchan_deleted = 0 and xchan_orphan = 0 $sql_extra ",
intval(local_channel())
);
if($r) {
@@ -247,7 +248,7 @@ class Connections extends \Zotlabs\Web\Controller {
}
$r = q("SELECT abook.*, xchan.* FROM abook left join xchan on abook.abook_xchan = xchan.xchan_hash
WHERE abook_channel = %d and abook_self = 0 and xchan_deleted = 0 and xchan_orphan = 0 $sql_extra $sql_extra2 ORDER BY $sql_order LIMIT %d OFFSET %d ",
WHERE abook_channel = %d and abook_self = 0 and xchan_deleted = 0 and xchan_orphan = 0 $sql_extra ORDER BY $sql_order LIMIT %d OFFSET %d ",
intval(local_channel()),
intval(App::$pager['itemspage']),
intval(App::$pager['start'])

View File

@@ -9,6 +9,7 @@ namespace Zotlabs\Module;
use App;
use Zotlabs\Lib\Apps;
use Zotlabs\Lib\Crypto;
use Zotlabs\Lib\Libzot;
use Zotlabs\Lib\Libsync;
use Zotlabs\Daemon\Master;
@@ -32,10 +33,10 @@ class Connedit extends Controller {
*/
function init() {
if(! local_channel())
return;
if((argc() >= 2) && intval(argv(1))) {
$r = q("SELECT abook.*, xchan.*
FROM abook left join xchan on abook_xchan = xchan_hash
@@ -47,54 +48,54 @@ class Connedit extends Controller {
App::$poi = array_shift($r);
}
}
$channel = App::get_channel();
if($channel)
head_set_icon($channel['xchan_photo_s']);
}
/* @brief Evaluate posted values and set changes
*
*/
function post() {
if(! local_channel())
return;
$contact_id = intval(argv(1));
if(! $contact_id)
return;
$channel = App::get_channel();
// TODO if configured for hassle-free permissions, we'll post the form with ajax as soon as the
// connection enable is toggled to a special autopost url and set permissions immediately, leaving
// the other form elements alone pending a manual submit of the form. The downside is that there
// will be a window of opportunity when the permissions have been set but before you've had a chance
// to review and possibly restrict them. The upside is we won't have to warn you that your connection
// can't do anything until you save the bloody form.
$autopost = (((argc() > 2) && (argv(2) === 'auto')) ? true : false);
$orig_record = q("SELECT * FROM abook WHERE abook_id = %d AND abook_channel = %d LIMIT 1",
intval($contact_id),
intval(local_channel())
);
if(! $orig_record) {
notice( t('Could not access contact record.') . EOL);
goaway(z_root() . '/connections');
return; // NOTREACHED
}
call_hooks('contact_edit_post', $_POST);
$vc = get_abconfig(local_channel(),$orig_record['abook_xchan'],'system','vcard');
$vcard = (($vc) ? \Sabre\VObject\Reader::read($vc) : null);
$vcard = (($vc) ? \Sabre\VObject\Reader::read($vc) : null);
$serialised_vcard = update_vcard($_REQUEST,$vcard);
if($serialised_vcard)
set_abconfig(local_channel(),$orig_record[0]['abook_xchan'],'system','vcard',$serialised_vcard);
@@ -107,8 +108,8 @@ class Connedit extends Controller {
$autoperms = null;
$is_self = false;
}
$profile_id = ((array_key_exists('profile_assign',$_POST)) ? $_POST['profile_assign'] : $orig_record[0]['abook_profile']);
if($profile_id) {
@@ -121,17 +122,17 @@ class Connedit extends Controller {
return;
}
}
$abook_incl = ((array_key_exists('abook_incl',$_POST)) ? escape_tags($_POST['abook_incl']) : $orig_record[0]['abook_incl']);
$abook_excl = ((array_key_exists('abook_excl',$_POST)) ? escape_tags($_POST['abook_excl']) : $orig_record[0]['abook_excl']);
$hidden = intval($_POST['hidden']);
$priority = intval($_POST['poll']);
if($priority > 5 || $priority < 0)
$priority = 0;
if(! array_key_exists('closeness',$_POST)) {
$_POST['closeness'] = 80;
}
@@ -139,15 +140,15 @@ class Connedit extends Controller {
if($closeness < 0 || $closeness > 99) {
$closeness = 80;
}
$rating = intval($_POST['rating']);
if($rating < (-10))
$rating = (-10);
if($rating > 10)
$rating = 10;
$rating_text = trim(escape_tags($_REQUEST['rating_text']));
$all_perms = Permissions::Perms();
if($all_perms) {
@@ -168,27 +169,27 @@ class Connedit extends Controller {
}
}
if(! is_null($autoperms))
if(! is_null($autoperms))
set_pconfig($channel['channel_id'],'system','autoperms',$autoperms);
$new_friend = false;
// only store a record and notify the directory if the rating changed
if(! $is_self) {
$signed = $orig_record[0]['abook_xchan'] . '.' . $rating . '.' . $rating_text;
$sig = base64url_encode(rsa_sign($signed,$channel['channel_prvkey']));
$sig = base64url_encode(Crypto::sign($signed,$channel['channel_prvkey']));
$rated = ((intval($rating) || strlen($rating_text)) ? true : false);
$record = 0;
$z = q("select * from xlink where xlink_xchan = '%s' and xlink_link = '%s' and xlink_static = 1 limit 1",
dbesc($channel['channel_hash']),
dbesc($orig_record[0]['abook_xchan'])
);
if($z) {
if(($z[0]['xlink_rating'] != $rating) || ($z[0]['xlink_rating_text'] != $rating_text)) {
$record = $z[0]['xlink_id'];
@@ -223,18 +224,18 @@ class Connedit extends Controller {
Master::Summon(array('Ratenotif','rating',$record));
}
}
if(($_REQUEST['pending']) && intval($orig_record[0]['abook_pending'])) {
$new_friend = true;
// @fixme it won't be common, but when you accept a new connection request
// the permissions will now be that of your permissions role and ignore
// any you may have set manually on the form. We'll probably see a bug if somebody
// tries to set the permissions *and* approve the connection in the same
// request. The workaround is to approve the connection, then go back and
// adjust permissions as desired.
$p = Permissions::connect_perms(local_channel());
$my_perms = $p['perms'];
if($my_perms) {
@@ -247,7 +248,7 @@ class Connedit extends Controller {
$abook_pending = (($new_friend) ? 0 : $orig_record[0]['abook_pending']);
$r = q("UPDATE abook SET abook_profile = '%s', abook_closeness = %d, abook_pending = %d,
abook_incl = '%s', abook_excl = '%s'
where abook_id = %d AND abook_channel = %d",
@@ -259,7 +260,7 @@ class Connedit extends Controller {
intval($contact_id),
intval(local_channel())
);
if($r)
info( t('Connection updated.') . EOL);
else
@@ -267,16 +268,16 @@ class Connedit extends Controller {
if(! intval(App::$poi['abook_self'])) {
if($new_friend) {
Master::Summon( [ 'Notifier', 'permission_accept', $contact_id ] );
Master::Summon( [ 'Notifier', 'permission_accept', $contact_id ] );
}
Master::Summon( [
'Notifier',
(($new_friend) ? 'permission_create' : 'permission_update'),
$contact_id
Master::Summon( [
'Notifier',
(($new_friend) ? 'permission_create' : 'permission_update'),
$contact_id
]);
}
if($new_friend) {
$default_group = $channel['channel_default_group'];
if($default_group) {
@@ -285,11 +286,11 @@ class Connedit extends Controller {
if($g)
group_add_member(local_channel(),'',App::$poi['abook_xchan'],$g['id']);
}
// Check if settings permit ("post new friend activity" is allowed, and
// friends in general or this friend in particular aren't hidden)
// and send out a new friend activity
$pr = q("select * from profile where uid = %d and is_default = 1 and hide_friends = 0",
intval($channel['channel_id'])
);
@@ -305,23 +306,23 @@ class Connedit extends Controller {
$xarr['deny_cid'] = $channel['channel_deny_cid'];
$xarr['deny_gid'] = $channel['channel_deny_gid'];
$xarr['item_private'] = (($xarr['allow_cid']||$xarr['allow_gid']||$xarr['deny_cid']||$xarr['deny_gid']) ? 1 : 0);
$xarr['body'] = '[zrl=' . $channel['xchan_url'] . ']' . $channel['xchan_name'] . '[/zrl]' . ' ' . t('is now connected to') . ' ' . '[zrl=' . App::$poi['xchan_url'] . ']' . App::$poi['xchan_name'] . '[/zrl]';
$xarr['body'] .= "\n\n\n" . '[zrl=' . App::$poi['xchan_url'] . '][zmg=80x80]' . App::$poi['xchan_photo_m'] . '[/zmg][/zrl]';
post_activity_item($xarr);
}
// pull in a bit of content if there is any to pull in
Master::Summon(array('Onepoll',$contact_id));
}
// Refresh the structure in memory with the new data
$r = q("SELECT abook.*, xchan.*
FROM abook left join xchan on abook_xchan = xchan_hash
WHERE abook_channel = %d and abook_id = %d LIMIT 1",
@@ -331,34 +332,34 @@ class Connedit extends Controller {
if($r) {
App::$poi = $r[0];
}
if($new_friend) {
$arr = array('channel_id' => local_channel(), 'abook' => App::$poi);
call_hooks('accept_follow', $arr);
}
$this->connedit_clone($a);
if(($_REQUEST['pending']) && (!$_REQUEST['done']))
goaway(z_root() . '/connections/ifpending');
return;
}
/* @brief Clone connection
*
*
*/
function connedit_clone(&$a) {
if(! App::$poi)
return;
$channel = App::get_channel();
$r = q("SELECT abook.*, xchan.*
FROM abook left join xchan on abook_xchan = xchan_hash
WHERE abook_channel = %d and abook_id = %d LIMIT 1",
@@ -368,40 +369,40 @@ class Connedit extends Controller {
if($r) {
App::$poi = array_shift($r);
}
$clone = App::$poi;
unset($clone['abook_id']);
unset($clone['abook_account']);
unset($clone['abook_channel']);
$abconfig = load_abconfig($channel['channel_id'],$clone['abook_xchan']);
if($abconfig)
$clone['abconfig'] = $abconfig;
Libsync::build_sync_packet(0 /* use the current local_channel */, array('abook' => array($clone)));
}
/* @brief Generate content of connection edit page
*
*
*/
function get() {
$sort_type = 0;
$o = '';
if(! local_channel()) {
notice( t('Permission denied.') . EOL);
return login();
}
$section = ((array_key_exists('section',$_REQUEST)) ? $_REQUEST['section'] : '');
$channel = App::get_channel();
$yes_no = array(t('No'),t('Yes'));
$connect_perms = Permissions::connect_perms(local_channel());
$o .= "<script>function connectDefaultShare() {
@@ -415,13 +416,13 @@ class Connedit extends Controller {
}
}
$o .= " }\n</script>\n";
if(argc() == 3) {
$contact_id = intval(argv(1));
if(! $contact_id)
return;
$cmd = argv(2);
$orig_record = q("SELECT abook.*, xchan.* FROM abook left join xchan on abook_xchan = xchan_hash
@@ -429,17 +430,17 @@ class Connedit extends Controller {
intval($contact_id),
intval(local_channel())
);
if(! count($orig_record)) {
notice( t('Could not access address book record.') . EOL);
goaway(z_root() . '/connections');
}
if($cmd === 'update') {
// pull feed and consume it, which should subscribe to the hub.
Master::Summon(array('Poller',$contact_id));
goaway(z_root() . '/connedit/' . $contact_id);
}
if($cmd === 'fetchvc') {
@@ -474,7 +475,7 @@ class Connedit extends Controller {
dbesc($orig_record[0]['xchan_hash'])
);
$cmd = 'refresh';
}
}
if($cmd === 'refresh') {
if($orig_record[0]['xchan_network'] === 'zot') {
@@ -486,13 +487,13 @@ class Connedit extends Controller {
notice( t('Refresh failed - channel is currently unavailable.') );
}
else {
// if you are on a different network we'll force a refresh of the connection basic info
Master::Summon(array('Notifier','permission_update',$contact_id));
}
goaway(z_root() . '/connedit/' . $contact_id);
}
if($cmd === 'block') {
if(abook_toggle_flag($orig_record[0],ABOOK_FLAG_BLOCKED)) {
$this->connedit_clone($a);
@@ -501,7 +502,7 @@ class Connedit extends Controller {
notice(t('Unable to set address book parameters.') . EOL);
goaway(z_root() . '/connedit/' . $contact_id);
}
if($cmd === 'ignore') {
if(abook_toggle_flag($orig_record[0],ABOOK_FLAG_IGNORED)) {
$this->connedit_clone($a);
@@ -510,7 +511,7 @@ class Connedit extends Controller {
notice(t('Unable to set address book parameters.') . EOL);
goaway(z_root() . '/connedit/' . $contact_id);
}
if($cmd === 'archive') {
if(abook_toggle_flag($orig_record[0],ABOOK_FLAG_ARCHIVED)) {
$this->connedit_clone($a);
@@ -519,7 +520,7 @@ class Connedit extends Controller {
notice(t('Unable to set address book parameters.') . EOL);
goaway(z_root() . '/connedit/' . $contact_id);
}
if($cmd === 'hide') {
if(abook_toggle_flag($orig_record[0],ABOOK_FLAG_HIDDEN)) {
$this->connedit_clone($a);
@@ -528,10 +529,10 @@ class Connedit extends Controller {
notice(t('Unable to set address book parameters.') . EOL);
goaway(z_root() . '/connedit/' . $contact_id);
}
// We'll prevent somebody from unapproving an already approved contact.
// Though maybe somebody will want this eventually (??)
if($cmd === 'approve') {
if(intval($orig_record[0]['abook_pending'])) {
if(abook_toggle_flag($orig_record[0],ABOOK_FLAG_PENDING)) {
@@ -542,10 +543,10 @@ class Connedit extends Controller {
}
goaway(z_root() . '/connedit/' . $contact_id);
}
if($cmd === 'drop') {
contact_remove(local_channel(), $orig_record[0]['abook_id']);
Master::Summon( [ 'Notifier', 'purge', local_channel(), $orig_record[0]['xchan_hash'] ] );
@@ -556,17 +557,17 @@ class Connedit extends Controller {
'entry_deleted' => true))
)
);
info( t('Connection has been removed.') . EOL );
if(x($_SESSION,'return_url'))
goaway(z_root() . '/' . $_SESSION['return_url']);
goaway(z_root() . '/contacts');
}
}
if(App::$poi) {
$abook_prev = 0;
$abook_next = 0;
@@ -595,14 +596,14 @@ class Connedit extends Controller {
}
$tools = array(
'view' => array(
'label' => t('View Profile'),
'url' => chanlink_cid($contact['abook_id']),
'sel' => '',
'title' => sprintf( t('View %s\'s profile'), $contact['xchan_name']),
),
'refresh' => array(
'label' => t('Refresh Permissions'),
'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/refresh',
@@ -616,14 +617,14 @@ class Connedit extends Controller {
'sel' => '',
'title' => t('Fetch updated photo'),
),
'recent' => array(
'label' => t('Recent Activity'),
'url' => z_root() . '/network/?f=&cid=' . $contact['abook_id'],
'sel' => '',
'title' => t('View recent posts and comments'),
),
'block' => array(
'label' => (intval($contact['abook_blocked']) ? t('Unblock') : t('Block')),
'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/block',
@@ -631,7 +632,7 @@ class Connedit extends Controller {
'title' => t('Block (or Unblock) all communications with this connection'),
'info' => (intval($contact['abook_blocked']) ? t('This connection is blocked!') : ''),
),
'ignore' => array(
'label' => (intval($contact['abook_ignored']) ? t('Unignore') : t('Ignore')),
'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/ignore',
@@ -639,7 +640,7 @@ class Connedit extends Controller {
'title' => t('Ignore (or Unignore) all inbound communications from this connection'),
'info' => (intval($contact['abook_ignored']) ? t('This connection is ignored!') : ''),
),
'archive' => array(
'label' => (intval($contact['abook_archived']) ? t('Unarchive') : t('Archive')),
'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/archive',
@@ -647,7 +648,7 @@ class Connedit extends Controller {
'title' => t('Archive (or Unarchive) this connection - mark channel dead but keep content'),
'info' => (intval($contact['abook_archived']) ? t('This connection is archived!') : ''),
),
'hide' => array(
'label' => (intval($contact['abook_hidden']) ? t('Unhide') : t('Hide')),
'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/hide',
@@ -655,18 +656,18 @@ class Connedit extends Controller {
'title' => t('Hide or Unhide this connection from your other connections'),
'info' => (intval($contact['abook_hidden']) ? t('This connection is hidden!') : ''),
),
'delete' => array(
'label' => t('Delete'),
'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/drop',
'sel' => '',
'title' => t('Delete this connection'),
),
);
if($contact['xchan_network'] === 'zot') {
if(in_array($contact['xchan_network'], ['zot6', 'zot'])) {
$tools['fetchvc'] = [
'label' => t('Fetch Vcard'),
'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/fetchvc',
@@ -684,24 +685,24 @@ class Connedit extends Controller {
'sel' => '',
'title' => t('Open Individual Permissions section by default'),
];
$self = false;
if(intval($contact['abook_self'])) {
$self = true;
$abook_prev = $abook_next = 0;
}
$vc = get_abconfig(local_channel(),$contact['abook_xchan'],'system','vcard');
$vctmp = (($vc) ? \Sabre\VObject\Reader::read($vc) : null);
$vctmp = (($vc) ? \Sabre\VObject\Reader::read($vc) : null);
$vcard = (($vctmp) ? get_vcard_array($vctmp,$contact['abook_id']) : [] );
if(! $vcard)
$vcard['fn'] = $contact['xchan_name'];
$tpl = get_markup_template("abook_edit.tpl");
if(Apps::system_app_installed(local_channel(),'Affinity Tool')) {
$sections['affinity'] = [
@@ -710,7 +711,7 @@ class Connedit extends Controller {
'sel' => '',
'title' => t('Open Set Affinity section by default'),
];
$labels = [
t('Me'),
t('Family'),
@@ -720,7 +721,7 @@ class Connedit extends Controller {
];
call_hooks('affinity_labels',$labels);
$label_str = '';
if($labels) {
foreach($labels as $l) {
if($label_str) {
@@ -731,11 +732,11 @@ class Connedit extends Controller {
$label_str .= "'" . $l . "'";
}
}
$slider_tpl = get_markup_template('contact_slider.tpl');
$slideval = intval($contact['abook_closeness']);
$slide = replace_macros($slider_tpl,array(
'$min' => 1,
'$val' => $slideval,
@@ -751,22 +752,22 @@ class Connedit extends Controller {
'title' => t('Open Custom Filter section by default'),
];
}
$rating_val = 0;
$rating_text = '';
$xl = q("select * from xlink where xlink_xchan = '%s' and xlink_link = '%s' and xlink_static = 1",
dbesc($channel['channel_hash']),
dbesc($contact['xchan_hash'])
);
if($xl) {
$rating_val = intval($xl[0]['xlink_rating']);
$rating_text = $xl[0]['xlink_rating_text'];
}
$rating_enabled = get_config('system','rating_enabled');
if($rating_enabled) {
$rating = replace_macros(get_markup_template('rating_slider.tpl'),array(
'$min' => -10,
@@ -776,28 +777,28 @@ class Connedit extends Controller {
else {
$rating = false;
}
$perms = array();
$channel = App::get_channel();
$global_perms = Permissions::Perms();
$existing = get_all_perms(local_channel(),$contact['abook_xchan'],false);
$unapproved = array('pending', t('Approve this connection'), '', t('Accept connection to allow communication'), array(t('No'),('Yes')));
$multiprofs = ((feature_enabled(local_channel(),'multi_profiles')) ? true : false);
if($slide && !$multiprofs)
$affinity = t('Set Affinity');
if(!$slide && $multiprofs)
$affinity = t('Set Profile');
if($slide && $multiprofs)
$affinity = t('Set Affinity & Profile');
$theirs = q("select * from abconfig where chan = %d and xchan = '%s' and cat = 'their_perms'",
intval(local_channel()),
dbesc($contact['abook_xchan'])
@@ -812,20 +813,20 @@ class Connedit extends Controller {
foreach($global_perms as $k => $v) {
$thisperm = get_abconfig(local_channel(),$contact['abook_xchan'],'my_perms',$k);
//fixme
$checkinherited = PermissionLimits::Get(local_channel(),$k);
// For auto permissions (when $self is true) we don't want to look at existing
// permissions because they are enabled for the channel owner
if((! $self) && ($existing[$k]))
$thisperm = "1";
$perms[] = array('perms_' . $k, $v, ((array_key_exists($k,$their_perms)) ? intval($their_perms[$k]) : ''),$thisperm, 1, (($checkinherited & PERMS_SPECIFIC) ? '' : '1'), '', $checkinherited);
}
$pcat = new Permcat(local_channel());
$pcatlist = $pcat->listing();
$permcats = [];
@@ -838,23 +839,23 @@ class Connedit extends Controller {
$locstr = locations_by_netid($contact['xchan_hash']);
if(! $locstr)
$locstr = unpunify($contact['xchan_url']);
$clone_warn = '';
$clonable = (in_array($contact['xchan_network'],['zot', 'zot6', 'rss']) ? true : false);
if(! $clonable) {
$clone_warn = '<strong>';
$clone_warn .= ((intval($contact['abook_not_here']))
$clone_warn .= ((intval($contact['abook_not_here']))
? t('This connection is unreachable from this location.')
: t('This connection may be unreachable from other channel locations.')
);
$clone_warn .= '</strong><br>' . t('Location independence is not supported by their network.');
}
if(intval($contact['abook_not_here']) && $unclonable)
$not_here = t('This connection is unreachable from this location. Location independence is not supported by their network.');
$o .= replace_macros($tpl, [
'$header' => (($self) ? t('Connection Default Permissions') : sprintf( t('Connection: %s'),$contact['xchan_name'])),
'$autoperms' => array('autoperms',t('Apply these permissions automatically'), ((get_pconfig(local_channel(),'system','autoperms')) ? 1 : 0), t('Connection requests will be approved without your interaction'), $yes_no),
@@ -910,7 +911,7 @@ class Connedit extends Controller {
'$name' => $contact['xchan_name'],
'$abook_prev' => $abook_prev,
'$abook_next' => $abook_next,
'$vcard_label' => t('Details'),
'$vcard_label' => t('Details'),
'$displayname' => $displayname,
'$name_label' => t('Name'),
'$org_label' => t('Organisation'),
@@ -939,13 +940,13 @@ class Connedit extends Controller {
'$zip_code' => t('ZIP Code'),
'$country' => t('Country')
]);
$arr = array('contact' => $contact,'output' => $o);
call_hooks('contact_edit', $arr);
return $arr['output'];
}
}
}
}

View File

@@ -51,11 +51,12 @@ class Dav extends \Zotlabs\Web\Controller {
if($sigblock) {
$keyId = str_replace('acct:','',$sigblock['keyId']);
if($keyId) {
$r = q("select * from hubloc where hubloc_addr = '%s' limit 1",
$r = q("select * from hubloc where hubloc_id_url = '%s'",
dbesc($keyId)
);
if($r) {
$c = channelx_by_hash($r[0]['hubloc_hash']);
$r = Libzot::zot_record_preferred($r);
$c = channelx_by_hash($r['hubloc_hash']);
if($c) {
$a = q("select * from account where account_id = %d limit 1",
intval($c['channel_account_id'])
@@ -99,7 +100,7 @@ class Dav extends \Zotlabs\Web\Controller {
$auth->setRealm(ucfirst(\Zotlabs\Lib\System::get_platform_name()) . ' ' . 'WebDAV');
$rootDirectory = new \Zotlabs\Storage\Directory('/', $auth);
$rootDirectory = new \Zotlabs\Storage\Directory('/', [], $auth);
// A SabreDAV server-object
$server = new SDAV\Server($rootDirectory);
@@ -123,7 +124,7 @@ class Dav extends \Zotlabs\Web\Controller {
// $server->addPlugin(new \Zotlabs\Storage\QuotaPlugin($auth));
// All we need to do now, is to fire up the server
$server->exec();
$server->start();
killme();
}

View File

@@ -4,6 +4,8 @@ namespace Zotlabs\Module;
use App;
use Zotlabs\Web\Controller;
use Zotlabs\Lib\Libzotdir;
require_once('include/socgraph.php');
require_once('include/dir_fns.php');
@@ -15,7 +17,7 @@ class Directory extends Controller {
function init() {
App::set_pager_itemspage(30);
if(local_channel() && x($_GET,'ignore')) {
q("insert into xign ( uid, xchan ) values ( %d, '%s' ) ",
intval(local_channel()),
@@ -26,12 +28,12 @@ class Directory extends Controller {
if(local_channel())
App::$profile_uid = local_channel();
$observer = get_observer_hash();
$global_changed = false;
$safe_changed = false;
$pubforums_changed = false;
if(array_key_exists('global',$_REQUEST)) {
$globaldir = intval($_REQUEST['global']);
$global_changed = true;
@@ -41,7 +43,7 @@ class Directory extends Controller {
if($observer)
set_xconfig($observer,'directory','globaldir',$globaldir);
}
if(array_key_exists('safe',$_REQUEST)) {
$safemode = intval($_REQUEST['safe']);
$safe_changed = true;
@@ -51,8 +53,8 @@ class Directory extends Controller {
if($observer)
set_xconfig($observer,'directory','safemode',$safemode);
}
if(array_key_exists('pubforums',$_REQUEST)) {
$pubforums = intval($_REQUEST['pubforums']);
$pubforums_changed = true;
@@ -64,52 +66,52 @@ class Directory extends Controller {
}
}
function get() {
if(observer_prohibited()) {
notice( t('Public access denied.') . EOL);
return;
}
if(get_config('system','block_public_directory',false) && (! get_observer_hash())) {
notice( t('Public access denied.') . EOL);
return;
}
$observer = get_observer_hash();
$globaldir = get_directory_setting($observer, 'globaldir');
$globaldir = Libzotdir::get_directory_setting($observer, 'globaldir');
// override your personal global search pref if we're doing a navbar search of the directory
if(intval($_REQUEST['navsearch']))
$globaldir = 1;
$safe_mode = get_directory_setting($observer, 'safemode');
$pubforums = get_directory_setting($observer, 'pubforums');
$safe_mode = Libzotdir::get_directory_setting($observer, 'safemode');
$pubforums = Libzotdir::get_directory_setting($observer, 'pubforums');
$o = '';
nav_set_selected('Directory');
if(x($_POST,'search'))
$search = notags(trim($_POST['search']));
else
$search = ((x($_GET,'search')) ? notags(trim(rawurldecode($_GET['search']))) : '');
if(strpos($search,'=') && local_channel() && feature_enabled(local_channel(), 'advanced_dirsearch'))
$advanced = $search;
$keywords = (($_GET['keywords']) ? $_GET['keywords'] : '');
// Suggest channels if no search terms or keywords are given
$suggest = (local_channel() && x($_REQUEST,'suggest')) ? $_REQUEST['suggest'] : '';
if($suggest) {
// the directory options have no effect in suggestion mode
$globaldir = 1;
$safe_mode = 1;
$type = 0;
@@ -120,7 +122,7 @@ class Directory extends Controller {
notice( t('No default suggestions were found.') . EOL);
return;
}
// Remember in which order the suggestions were
$addresses = array();
$common = array();
@@ -129,7 +131,7 @@ class Directory extends Controller {
$common[$rr['xchan_addr']] = ((intval($rr['total']) > 0) ? intval($rr['total']) - 1 : 0);
$addresses[$rr['xchan_addr']] = $index++;
}
// Build query to get info about suggested people
$advanced = '';
foreach(array_keys($addresses) as $address) {
@@ -137,13 +139,13 @@ class Directory extends Controller {
}
// Remove last space in the advanced query
$advanced = rtrim($advanced);
}
$tpl = get_markup_template('directory_header.tpl');
$dirmode = intval(get_config('system','directory_mode'));
$directory_admin = false;
if(($dirmode == DIRECTORY_MODE_PRIMARY) || ($dirmode == DIRECTORY_MODE_STANDALONE)) {
@@ -154,19 +156,19 @@ class Directory extends Controller {
}
if(! $url) {
$directory = find_upstream_directory($dirmode);
$directory = Libzotdir::find_upstream_directory($dirmode);
if((! $directory) || (! array_key_exists('url',$directory)) || (! $directory['url']))
logger('CRITICAL: No directory server URL');
$url = $directory['url'] . '/dirsearch';
}
$token = get_config('system','realm_token');
logger('mod_directory: URL = ' . $url, LOGGER_DEBUG);
$contacts = array();
if(local_channel()) {
$x = q("select abook_xchan from abook where abook_channel = %d",
intval(local_channel())
@@ -176,24 +178,24 @@ class Directory extends Controller {
$contacts[] = $xx['abook_xchan'];
}
}
if($url) {
$numtags = get_config('system','directorytags');
$kw = ((intval($numtags) > 0) ? intval($numtags) : 50);
if(get_config('system','disable_directory_keywords'))
$kw = 0;
$query = $url . '?f=&kw=' . $kw . (($safe_mode != 1) ? '&safe=' . $safe_mode : '');
if($token)
$query .= '&t=' . $token;
if(! $globaldir)
$query .= '&hub=' . App::get_hostname();
if($search)
$query .= '&name=' . urlencode($search) . '&keywords=' . urlencode($search);
if(strpos($search,'@'))
@@ -204,29 +206,29 @@ class Directory extends Controller {
$query .= '&query=' . urlencode($advanced);
if(! is_null($pubforums))
$query .= '&pubforums=' . intval($pubforums);
$directory_sort_order = get_config('system','directory_sort_order');
if(! $directory_sort_order)
$directory_sort_order = 'date';
$sort_order = ((x($_REQUEST,'order')) ? $_REQUEST['order'] : $directory_sort_order);
if($sort_order)
$query .= '&order=' . urlencode($sort_order);
if(App::$pager['page'] != 1)
$query .= '&p=' . App::$pager['page'];
logger('mod_directory: query: ' . $query);
$x = z_fetch_url($query);
logger('directory: return from upstream: ' . print_r($x,true), LOGGER_DATA);
if($x['success']) {
$t = 0;
$j = json_decode($x['body'],true);
if($j) {
if($j['results']) {
$results = $j['results'];
@@ -235,23 +237,23 @@ class Directory extends Controller {
}
$entries = array();
$photo = 'thumb';
foreach($results as $rr) {
$profile_link = chanlink_url($rr['url']);
$pdesc = (($rr['description']) ? $rr['description'] . '<br />' : '');
$connect_link = ((local_channel()) ? z_root() . '/follow?f=&url=' . urlencode($rr['address']) : '');
$connect_link = ((local_channel()) ? z_root() . '/follow?f=&url=' . urlencode($rr['address']) : '');
// Checking status is disabled ATM until someone checks the performance impact more carefully
//$online = remote_online_status($rr['address']);
$online = '';
if(in_array($rr['hash'],$contacts))
$connect_link = '';
$location = '';
if(strlen($rr['locale']))
$location .= $rr['locale'];
@@ -265,53 +267,53 @@ class Directory extends Controller {
$location .= ', ';
$location .= $rr['country'];
}
$age = '';
if(strlen($rr['birthday'])) {
if(($years = age($rr['birthday'],'UTC','')) > 0)
$age = $years;
}
$page_type = '';
$rating_enabled = get_config('system','rating_enabled');
if($rr['total_ratings'] && $rating_enabled)
$total_ratings = sprintf( tt("%d rating", "%d ratings", $rr['total_ratings']), $rr['total_ratings']);
else
$total_ratings = '';
$profile = $rr;
if ((x($profile,'locale') == 1)
|| (x($profile,'region') == 1)
|| (x($profile,'postcode') == 1)
|| (x($profile,'country') == 1))
$gender = ((x($profile,'gender') == 1) ? t('Gender: ') . $profile['gender']: False);
$marital = ((x($profile,'marital') == 1) ? t('Status: ') . $profile['marital']: False);
$homepage = ((x($profile,'homepage') == 1) ? t('Homepage: ') : False);
$homepageurl = ((x($profile,'homepage') == 1) ? html2plain($profile['homepage']) : '');
$homepageurl = ((x($profile,'homepage') == 1) ? html2plain($profile['homepage']) : '');
$hometown = ((x($profile,'hometown') == 1) ? html2plain($profile['hometown']) : False);
$about = ((x($profile,'about') == 1) ? zidify_links(bbcode($profile['about'], ['tryoembed' => false])) : False);
if ($about && $safe_mode) {
$about = html2plain($about);
}
$keywords = ((x($profile,'keywords')) ? $profile['keywords'] : '');
$out = '';
if($keywords) {
$keywords = str_replace(',',' ', $keywords);
$keywords = str_replace(' ',' ', $keywords);
$karr = explode(' ', $keywords);
if($karr) {
if(local_channel()) {
$r = q("select keywords from profile where uid = %d and is_default = 1 limit 1",
@@ -332,9 +334,9 @@ class Directory extends Controller {
$out .= '<a href="' . z_root() . '/directory/f=&keywords=' . urlencode($k) .'">' . $k . '</a>';
}
}
}
$entry = array(
'id' => ++$t,
'profile_link' => $profile_link,
@@ -366,7 +368,7 @@ class Directory extends Controller {
'about' => $about,
'about_label' => t('About:'),
'conn_label' => t('Connect'),
'forum_label' => t('Public Forum:'),
'forum_label' => t('Public Forum:'),
'connect' => $connect_link,
'online' => $online,
'kw' => (($out) ? t('Keywords: ') : ''),
@@ -378,36 +380,36 @@ class Directory extends Controller {
'common_count' => intval($common[$rr['address']]),
'safe' => $safe_mode
);
$arr = array('contact' => $rr, 'entry' => $entry);
call_hooks('directory_item', $arr);
unset($profile);
unset($location);
if(! $arr['entry']) {
continue;
}
}
if($sort_order == '' && $suggest) {
$entries[$addresses[$rr['address']]] = $arr['entry']; // Use the same indexes as originally to get the best suggestion first
}
else {
$entries[] = $arr['entry'];
}
}
ksort($entries); // Sort array by key so that foreach-constructs work as expected
if($j['keywords']) {
App::$data['directory_keywords'] = $j['keywords'];
}
logger('mod_directory: entries: ' . print_r($entries,true), LOGGER_DATA);
if($_REQUEST['aj']) {
if($entries) {
$o = replace_macros(get_markup_template('directajax.tpl'),array(
@@ -422,9 +424,9 @@ class Directory extends Controller {
}
else {
$maxheight = 94;
$dirtitle = (($globaldir) ? t('Global Directory') : t('Local Directory'));
$o .= "<script> var page_query = '" . escape_tags(urlencode($_GET['q'])) . "'; var extra_args = '" . extra_query_args() . "' ; divmore_height = " . intval($maxheight) . "; </script>";
$o .= replace_macros($tpl, array(
'$search' => $search,
@@ -442,10 +444,10 @@ class Directory extends Controller {
'$reversedate' => t('Oldest to Newest'),
'$suggest' => $suggest ? '&suggest=1' : ''
));
}
}
else {
if($_REQUEST['aj']) {
@@ -463,7 +465,7 @@ class Directory extends Controller {
}
return $o;
}
static public function reorder_results($results,$suggests) {
if(! $suggests)

View File

@@ -192,7 +192,7 @@ class Dirsearch extends Controller {
else {
$qlimit = " LIMIT " . intval($perpage) . " OFFSET " . intval($startrec);
if($return_total) {
$r = q("SELECT COUNT(xchan_hash) AS total FROM xchan left join xprof on xchan_hash = xprof_hash where $logic $sql_extra and xchan_network = 'zot' and xchan_hidden = 0 and xchan_orphan = 0 and xchan_deleted = 0 $safesql ");
$r = q("SELECT COUNT(xchan_hash) AS total FROM xchan left join xprof on xchan_hash = xprof_hash where $logic $sql_extra and xchan_network = 'zot6' and xchan_hidden = 0 and xchan_orphan = 0 and xchan_deleted = 0 $safesql ");
if($r) {
$ret['total_items'] = $r[0]['total'];
}
@@ -261,7 +261,7 @@ class Dirsearch extends Controller {
else {
$r = q("SELECT xchan.*, xprof.* from xchan left join xprof on xchan_hash = xprof_hash
where ( $logic $sql_extra ) $hub_query and xchan_network = 'zot' and xchan_system = 0 and xchan_hidden = 0 and xchan_orphan = 0 and xchan_deleted = 0
where ( $logic $sql_extra ) $hub_query and xchan_network = 'zot6' and xchan_system = 0 and xchan_hidden = 0 and xchan_orphan = 0 and xchan_deleted = 0
$safesql $order $qlimit "
);

View File

@@ -19,24 +19,21 @@ class Display extends \Zotlabs\Web\Controller {
if(argc() > 1) {
$module_format = substr(argv(1),strrpos(argv(1),'.') + 1);
if(! in_array($module_format,['atom','zot','json']))
$module_format = 'html';
$module_format = 'html';
}
if($load)
$_SESSION['loadtime'] = datetime_convert();
if(observer_prohibited()) {
notice( t('Public access denied.') . EOL);
return;
}
if(argc() > 1) {
$item_hash = argv(1);
if($module_format !== 'html') {
$item_hash = substr($item_hash,0,strrpos($item_hash,'.'));
}
}
if($_REQUEST['mid'])
$item_hash = $_REQUEST['mid'];
@@ -45,19 +42,19 @@ class Display extends \Zotlabs\Web\Controller {
notice( t('Item not found.') . EOL);
return;
}
$observer_is_owner = false;
if(local_channel() && (! $update)) {
$channel = \App::get_channel();
$channel_acl = array(
'allow_cid' => $channel['channel_allow_cid'],
'allow_gid' => $channel['channel_allow_gid'],
'deny_cid' => $channel['channel_deny_cid'],
'allow_cid' => $channel['channel_allow_cid'],
'allow_gid' => $channel['channel_allow_gid'],
'deny_cid' => $channel['channel_deny_cid'],
'deny_gid' => $channel['channel_deny_gid']
);
);
$x = array(
'is_owner' => true,
@@ -65,7 +62,7 @@ class Display extends \Zotlabs\Web\Controller {
'default_location' => $channel['channel_location'],
'nickname' => $channel['channel_address'],
'lockstate' => (($group || $cid || $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(), 'acl_dialog_post'),
'permissions' => $channel_acl,
'bang' => '',
'visitor' => true,
@@ -78,21 +75,21 @@ class Display extends \Zotlabs\Web\Controller {
'jotnets' => true,
'reset' => t('Reset form')
);
$o = '<div id="jot-popup">';
$o .= status_editor($a,$x,false,'Display');
$o .= '</div>';
}
// This page can be viewed by anybody so the query could be complicated
// First we'll see if there is a copy of the item which is owned by us - if we're logged in locally.
// If that fails (or we aren't logged in locally),
// If that fails (or we aren't logged in locally),
// query an item in which the observer (if logged in remotely) has cid or gid rights
// and if that fails, look for a copy of the post that has no privacy restrictions.
// and if that fails, look for a copy of the post that has no privacy restrictions.
// If we find the post, but we don't find a copy that we're allowed to look at, this fact needs to be reported.
// find a copy of the item somewhere
$target_item = null;
if(strpos($item_hash,'b64.') === 0)
@@ -103,7 +100,7 @@ class Display extends \Zotlabs\Web\Controller {
$r = q("select id, uid, mid, parent, parent_mid, thr_parent, verb, item_type, item_deleted, author_xchan, item_blocked from item where mid like '%s' limit 1",
dbesc($item_hash . '%')
);
if($r) {
$target_item = $r[0];
}
@@ -120,14 +117,14 @@ class Display extends \Zotlabs\Web\Controller {
if($target_item['item_blocked'] == ITEM_MODERATED) {
goaway(z_root() . '/moderate/' . $target_item['id']);
}
$r = null;
if($target_item['item_type'] == ITEM_TYPE_WEBPAGE) {
$x = q("select * from channel where channel_id = %d limit 1",
intval($target_item['uid'])
);
$y = q("select * from iconfig left join item on iconfig.iid = item.id
$y = q("select * from iconfig left join item on iconfig.iid = item.id
where item.uid = %d and iconfig.cat = 'system' and iconfig.k = 'WEBPAGE' and item.id = %d limit 1",
intval($target_item['uid']),
intval($target_item['parent'])
@@ -144,7 +141,7 @@ class Display extends \Zotlabs\Web\Controller {
$x = q("select * from channel where channel_id = %d limit 1",
intval($target_item['uid'])
);
$y = q("select * from iconfig left join item on iconfig.iid = item.id
$y = q("select * from iconfig left join item on iconfig.iid = item.id
where item.uid = %d and iconfig.cat = 'system' and iconfig.k = 'ARTICLE' and item.id = %d limit 1",
intval($target_item['uid']),
intval($target_item['parent'])
@@ -163,7 +160,7 @@ class Display extends \Zotlabs\Web\Controller {
intval($target_item['uid'])
);
$y = q("select * from iconfig left join item on iconfig.iid = item.id
$y = q("select * from iconfig left join item on iconfig.iid = item.id
where item.uid = %d and iconfig.cat = 'system' and iconfig.k = 'CARD' and item.id = %d limit 1",
intval($target_item['uid']),
intval($target_item['parent'])
@@ -182,37 +179,26 @@ class Display extends \Zotlabs\Web\Controller {
notice( t('Page not found.') . EOL);
return '';
}
$static = ((array_key_exists('static',$_REQUEST)) ? intval($_REQUEST['static']) : 0);
$simple_update = (($update) ? " AND item_unseen = 1 " : '');
$simple_update = '';
if($update && $_SESSION['loadtime'])
$simple_update = " AND (( item_unseen = 1 AND item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' ) OR item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' ) ";
if($load)
$simple_update = '';
if($static && $simple_update)
$simple_update .= " and item_thread_top = 0 and author_xchan = '" . protect_sprintf(get_observer_hash()) . "' ";
if((! $update) && (! $load)) {
$static = ((local_channel()) ? channel_manual_conv_update(local_channel()) : 1);
if((! $update) && (! $load)) {
// if the target item is not a post (eg a like) we want to address its thread parent
//$mid = ((($target_item['verb'] == ACTIVITY_LIKE) || ($target_item['verb'] == ACTIVITY_DISLIKE)) ? $target_item['thr_parent'] : $target_item['mid']);
$mid = $target_item['mid'];
// if we got a decoded hash we must encode it again before handing to javascript
// if we got a decoded hash we must encode it again before handing to javascript
if($decoded)
$mid = 'b64.' . base64url_encode($mid);
$o .= '<div id="live-display"></div>' . "\r\n";
$o .= "<script> var profile_uid = " . ((intval(local_channel())) ? local_channel() : (-1))
. "; var netargs = '?f='; var profile_page = " . \App::$pager['page'] . "; </script>\r\n";
\App::$page['htmlhead'] .= replace_macros(get_markup_template("build_query.tpl"),array(
'$baseurl' => z_root(),
'$pgtype' => 'display',
@@ -229,7 +215,6 @@ class Display extends \Zotlabs\Web\Controller {
'$dm' => '0',
'$nouveau' => '0',
'$wall' => '0',
'$static' => $static,
'$page' => ((\App::$pager['page'] != 1) ? \App::$pager['page'] : 1),
'$list' => ((x($_REQUEST,'list')) ? intval($_REQUEST['list']) : 0),
'$search' => '',
@@ -245,7 +230,7 @@ class Display extends \Zotlabs\Web\Controller {
'$mid' => (($mid) ? urlencode($mid) : '')
));
head_add_link([
head_add_link([
'rel' => 'alternate',
'type' => 'application/json+oembed',
'href' => z_root() . '/oep?f=&url=' . urlencode(z_root() . '/' . \App::$query_string),
@@ -258,7 +243,7 @@ class Display extends \Zotlabs\Web\Controller {
$item_normal = item_normal();
$item_normal_update = item_normal_update();
$sql_extra = public_permissions_sql($observer_hash);
$sql_extra = ((local_channel()) ? EMPTY_STR : item_permissions_sql(0, $observer_hash));
if($noscript_content || $load) {
@@ -275,8 +260,7 @@ class Display extends \Zotlabs\Web\Controller {
);
}
if(! $r) {
if($r === null) {
// in case somebody turned off public access to sys channel content using permissions
// make that content unsearchable by ensuring the owner uid can't match
@@ -284,20 +268,21 @@ class Display extends \Zotlabs\Web\Controller {
$sysid = 0;
$r = q("SELECT item.id as item_id from item
WHERE mid = '%s'
AND (((( item.allow_cid = '' AND item.allow_gid = '' AND item.deny_cid = ''
AND item.deny_gid = '' AND item_private = 0 )
WHERE ((mid = '%s'
AND (((( item.allow_cid = '' AND item.allow_gid = '' AND item.deny_cid = ''
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 )
$sql_extra )
OR uid = %d ))) OR
(mid = '%s' $sql_extra ))
$item_normal
limit 1",
dbesc($target_item['parent_mid']),
intval($sysid)
intval($sysid),
dbesc($target_item['parent_mid'])
);
}
}
elseif($update && !$load) {
$r = null;
@@ -315,29 +300,29 @@ class Display extends \Zotlabs\Web\Controller {
dbesc($target_item['parent_mid'])
);
}
if($r === null) {
// in case somebody turned off public access to sys channel content using permissions
// make that content unsearchable by ensuring the owner_xchan can't match
if(! perm_is_allowed($sysid,$observer_hash,'view_stream'))
$sysid = 0;
$r = q("SELECT item.parent AS item_id from item
WHERE parent_mid = '%s'
AND (((( item.allow_cid = '' AND item.allow_gid = '' AND item.deny_cid = ''
AND item.deny_gid = '' AND item_private = 0 )
$r = q("SELECT item.id as item_id from item
WHERE ((parent_mid = '%s'
AND (((( item.allow_cid = '' AND item.allow_gid = '' AND item.deny_cid = ''
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 )
$sql_extra )
$item_normal_update
$simple_update
OR uid = %d ))) OR
(parent_mid = '%s' $sql_extra ))
$item_normal
limit 1",
dbesc($target_item['parent_mid']),
intval($sysid)
intval($sysid),
dbesc($target_item['parent_mid'])
);
}
$_SESSION['loadtime'] = datetime_convert();
}
else {
$r = array();
}
@@ -345,7 +330,7 @@ class Display extends \Zotlabs\Web\Controller {
if($r) {
$parents_str = ids_to_querystr($r,'item_id');
if($parents_str) {
$items = q("SELECT item.*, item.id AS item_id
$items = q("SELECT item.*, item.id AS item_id
FROM item
WHERE parent in ( %s ) $item_normal ",
dbesc($parents_str)
@@ -358,10 +343,10 @@ class Display extends \Zotlabs\Web\Controller {
else {
$items = array();
}
switch($module_format) {
case 'html':
if ($update) {
@@ -380,7 +365,7 @@ class Display extends \Zotlabs\Web\Controller {
\App::$page['title'] = (($items[0]['title']) ? $items[0]['title'] . " - " . \App::$page['title'] : \App::$page['title']);
$o .= conversation($items, 'display', $update, 'client');
}
}
break;
@@ -397,7 +382,7 @@ class Display extends \Zotlabs\Web\Controller {
'$owner' => '',
'$profile_page' => xmlify(z_root() . '/display/' . $target_item['mid']),
));
$x = [ 'xml' => $atom, 'channel' => $channel, 'observer_hash' => $observer_hash, 'params' => $params ];
call_hooks('atom_feed_top',$x);
@@ -423,13 +408,13 @@ class Display extends \Zotlabs\Web\Controller {
header('Content-type: application/atom+xml');
echo $atom;
killme();
}
$o .= '<div id="content-complete"></div>';
if((($update && $load) || $noscript_content) && (! $items)) {
$r = q("SELECT id, item_deleted FROM item WHERE mid = '%s' LIMIT 1",
dbesc($item_hash)
);
@@ -438,16 +423,18 @@ class Display extends \Zotlabs\Web\Controller {
if(intval($r[0]['item_deleted'])) {
notice( t('Item has been removed.') . EOL );
}
else {
notice( t('Permission denied.') . EOL );
else {
notice( t('Permission denied.') . EOL );
}
}
else {
notice( t('Item not found.') . EOL );
}
}
$_SESSION['loadtime'] = datetime_convert();
return $o;
}

View File

@@ -58,9 +58,9 @@ class Editpost extends \Zotlabs\Web\Controller {
if ($catsenabled){
$itm = fetch_post_tags($itm);
$cats = get_terms_oftype($itm[0]['term'], TERM_CATEGORY);
foreach ($cats as $cat) {
if (strlen($category))
$category .= ', ';
@@ -95,6 +95,7 @@ class Editpost extends \Zotlabs\Web\Controller {
'defloc' => $channel['channel_location'],
'visitor' => true,
'title' => htmlspecialchars_decode($itm[0]['title'],ENT_COMPAT),
'summary' => htmlspecialchars_decode($itm[0]['summary'],ENT_COMPAT),
'category' => $category,
'showacl' => false,
'profile_uid' => $owner_uid,

View File

@@ -40,7 +40,8 @@ class Embedphotos extends \Zotlabs\Web\Controller {
if (!$href) {
json_return_and_die(array('errormsg' => 'Error retrieving link ' . $href, 'status' => false));
}
$resource_id = array_pop(explode('/', $href));
$arr = explode('/', $href);
$resource_id = array_pop($arr);
$x = self::photolink($resource_id);
if($x)
json_return_and_die(array('status' => true, 'photolink' => $x, 'resource_id' => $resource_id));

View File

@@ -15,12 +15,12 @@ class Fhublocs extends \Zotlabs\Web\Controller {
if(! is_site_admin())
return;
$o = '';
$r = q("select * from channel where channel_removed = 0");
$sitekey = get_config('system','pubkey');
if($r) {
foreach($r as $rr) {
@@ -38,14 +38,14 @@ class Fhublocs extends \Zotlabs\Web\Controller {
if($found) {
$o .= 'Hubloc exists for ' . $rr['channel_name'] . EOL;
continue;
}
}
}
$y = q("select xchan_addr from xchan where xchan_hash = '%s' limit 1",
dbesc($rr['channel_hash'])
);
if($y)
$primary_address = $y[0]['xchan_addr'];
$hub_address = channel_reddress($rr);
$primary = (($hub_address === $primary_address) ? 1 : 0);
@@ -56,9 +56,9 @@ class Fhublocs extends \Zotlabs\Web\Controller {
dbesc($rr['channel_hash']),
dbesc(z_root())
);
// Create a verified hub location pointing to this site.
/*
$h = hubloc_store_lowlevel(
[
@@ -69,7 +69,7 @@ class Fhublocs extends \Zotlabs\Web\Controller {
'hubloc_network' => 'zot',
'hubloc_primary' => $primary,
'hubloc_url' => z_root(),
'hubloc_url_sig' => base64url_encode(rsa_sign(z_root(),$rr['channel_prvkey'])),
'hubloc_url_sig' => base64url_encode(Crypto::sign(z_root(),$rr['channel_prvkey'])),
'hubloc_host' => \App::get_hostname(),
'hubloc_callback' => z_root() . '/post',
'hubloc_sitekey' => $sitekey
@@ -99,11 +99,11 @@ class Fhublocs extends \Zotlabs\Web\Controller {
$o . 'local hubloc created for ' . $rr['channel_name'] . EOL;
else
$o .= 'DB update failed for ' . $rr['channel_name'] . EOL;
}
return $o;
}
}
}

View File

@@ -11,17 +11,16 @@ 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($_FILES,true));
$channel = (($_REQUEST['channick']) ? channelx_by_nick($_REQUEST['channick']) : null);
if(! $channel) {
logger('channel not found');
killme();
}
$_REQUEST['source'] = 'file_upload';
if($channel['channel_id'] != local_channel()) {
@@ -40,13 +39,11 @@ class File_upload extends \Zotlabs\Web\Controller {
$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() . '/cloud/' . $channel['channel_address'] . '/' . $r['data']['display_path']);
goaway(z_root() . '/' . $_REQUEST['return_url']);
}
}
else {
@@ -54,8 +51,6 @@ class File_upload extends \Zotlabs\Web\Controller {
$matches = [];
$partial = false;
if(array_key_exists('HTTP_CONTENT_RANGE',$_SERVER)) {
$pm = preg_match('/bytes (\d*)\-(\d*)\/(\d*)/',$_SERVER['HTTP_CONTENT_RANGE'],$matches);
if($pm) {
@@ -69,7 +64,7 @@ class File_upload extends \Zotlabs\Web\Controller {
if($x['partial']) {
header('Range: bytes=0-' . (($x['length']) ? $x['length'] - 1 : 0));
json_return_and_die($result);
json_return_and_die($x);
}
else {
header('Range: bytes=0-' . (($x['size']) ? $x['size'] - 1 : 0));
@@ -83,7 +78,7 @@ class File_upload extends \Zotlabs\Web\Controller {
];
}
}
else {
else {
if(! array_key_exists('userfile',$_FILES)) {
$_FILES['userfile'] = [
'name' => $_FILES['files']['name'],
@@ -103,8 +98,9 @@ class File_upload extends \Zotlabs\Web\Controller {
}
}
goaway(z_root() . '/' . $_REQUEST['return_url']);
}
}

View File

@@ -31,7 +31,8 @@ class Filer extends \Zotlabs\Web\Controller {
intval(local_channel())
);
if($r) {
$x = q("update item set item_retained = 1 where id = %d and uid = %d",
$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())
);

View File

@@ -28,10 +28,14 @@ class Filerm extends \Zotlabs\Web\Controller {
intval($item_id),
dbesc($term)
);
$x = q("update item set item_retained = 0, changed = '%s' where id = %d and uid = %d",
dbesc(datetime_convert()),
intval($item_id),
intval(local_channel())
);
}
if(x($_SESSION,'return_url'))
goaway(z_root() . '/' . $_SESSION['return_url']);
killme();
}

View File

@@ -11,6 +11,9 @@ class Filestorage extends \Zotlabs\Web\Controller {
function post() {
notice( t('Deprecated!') . EOL);
return;
$channel_id = ((x($_POST, 'uid')) ? intval($_POST['uid']) : 0);
if((! $channel_id) || (! local_channel()) || ($channel_id != local_channel())) {
@@ -47,6 +50,9 @@ class Filestorage extends \Zotlabs\Web\Controller {
function get() {
notice( t('Deprecated!') . EOL);
return;
if(argc() > 1)
$which = argv(1);
else {
@@ -88,7 +94,7 @@ class Filestorage extends \Zotlabs\Web\Controller {
}
else {
notice( t('Permission denied.') . EOL);
if($json_return)
if($json_return)
json_return_and_die([ 'success' => false ]);
return;
}
@@ -102,24 +108,23 @@ class Filestorage extends \Zotlabs\Web\Controller {
if(! $r) {
notice( t('File not found.') . EOL);
if($json_return)
if($json_return)
json_return_and_die([ 'success' => false ]);
goaway(z_root() . '/cloud/' . $which);
}
if(local_channel() !== $owner) {
if((local_channel() !== $owner) && !$admin_delete) {
if($r[0]['creator'] && $r[0]['creator'] !== $ob_hash) {
notice( t('Permission denied.') . EOL);
if($json_return)
if($json_return)
json_return_and_die([ 'success' => false ]);
goaway(z_root() . '/cloud/' . $which);
}
}
$f = $r[0];
$channel = channelx_by_n($owner);
@@ -138,7 +143,7 @@ class Filestorage extends \Zotlabs\Web\Controller {
if($json_return)
json_return_and_die([ 'success' => true ]);
goaway(dirname($url));
//goaway(dirname($url));
}

View File

@@ -1,24 +1,26 @@
<?php
namespace Zotlabs\Module;
use Zotlabs\Lib\Crypto;
use Zotlabs\Web\HTTPSig;
use Zotlabs\Lib\Libzot;
/**
* module: getfile
*
*
* used for synchronising files and photos across clones
*
*
* The site initiating the file operation will send a sync packet to known clones.
* They will respond by building the DB structures they require, then will provide a
* post request to this site to grab the file data. This is sent as a stream direct to
* disk at the other end, avoiding memory issues.
*
* Since magic-auth cannot easily be used by the CURL process at the other end,
* we will require a signed request which includes a timestamp. This should not be
* used without SSL and is potentially vulnerable to replay if an attacker decrypts
* we will require a signed request which includes a timestamp. This should not be
* used without SSL and is potentially vulnerable to replay if an attacker decrypts
* the SSL traffic fast enough. The amount of time slop is configurable but defaults
* to 3 minutes.
*
*
*/
@@ -53,13 +55,13 @@ class Getfile extends \Zotlabs\Web\Controller {
$keyId = $sigblock['keyId'];
if($keyId) {
$r = q("select * from hubloc left join xchan on hubloc_hash = xchan_hash
where hubloc_addr = '%s' limit 1",
$r = q("select * from hubloc left join xchan on hubloc_hash = xchan_hash
where hubloc_id_url = '%s'",
dbesc(str_replace('acct:','',$keyId))
);
if($r) {
$hubloc = $r[0];
$verified = HTTPSig::verify('',$hubloc['xchan_pubkey']);
$hubloc = Libzot::zot_record_preferred($r);
$verified = HTTPSig::verify('',$hubloc['xchan_pubkey']);
if($verified && $verified['header_signed'] && $verified['header_valid'] && $hash == $hubloc['hubloc_hash']) {
$header_verified = true;
}
@@ -73,15 +75,15 @@ class Getfile extends \Zotlabs\Web\Controller {
logger('post: ' . print_r($_POST,true),LOGGER_DEBUG,LOG_INFO);
if($header_verified) {
logger('HTTPSig verified');
}
}
$channel = channelx_by_hash($hash);
if((! $channel) || (! $time) || (! $sig)) {
logger('error: missing info');
killme();
}
if(isset($_POST['resolution']))
$resolution = intval($_POST['resolution']);
elseif(substr($resource,-2,1) == '-') {
@@ -90,22 +92,22 @@ class Getfile extends \Zotlabs\Web\Controller {
}
else {
$resolution = (-1);
}
}
$slop = intval(get_pconfig($channel['channel_id'],'system','getfile_time_slop'));
if($slop < 1)
$slop = 3;
$d1 = datetime_convert('UTC','UTC',"now + $slop minutes");
$d2 = datetime_convert('UTC','UTC',"now - $slop minutes");
$d2 = datetime_convert('UTC','UTC',"now - $slop minutes");
if(! $header_verified) {
if(($time > $d1) || ($time < $d2)) {
logger('time outside allowable range');
killme();
}
if(! rsa_verify($hash . '.' . $time,base64url_decode($sig),$channel['channel_pubkey'])) {
if(! Crypto::verify($hash . '.' . $time,base64url_decode($sig),$channel['channel_pubkey'])) {
logger('verify failed.');
killme();
}
@@ -136,20 +138,20 @@ class Getfile extends \Zotlabs\Web\Controller {
else {
echo dbunescbin($r[0]['content']);
}
}
}
killme();
}
$r = attach_by_hash($resource,$channel['channel_hash'],$revision);
if(! $r['success']) {
logger('attach_by_hash failed: ' . $r['message']);
notice( $r['message'] . EOL);
return;
}
$unsafe_types = array('text/html','text/css','application/javascript');
if(in_array($r['data']['filetype'],$unsafe_types) && (! channel_codeallowed($channel['channel_id']))) {
header('Content-type: text/plain');
}

View File

@@ -1,100 +1,114 @@
<?php
namespace Zotlabs\Module;
use App;
use Zotlabs\Lib\Libzot;
use Zotlabs\Web\Controller;
use Zotlabs\Web\HTTPSig;
require_once('include/items.php');
require_once('include/conversation.php');
class Home extends \Zotlabs\Web\Controller {
class Home extends Controller {
function init() {
$ret = array();
call_hooks('home_init',$ret);
$ret = [];
call_hooks('home_init', $ret);
if (Libzot::is_zot_request()) {
$key = get_config('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());
HTTPSig::set_headers($h);
echo $ret;
killme();
}
$splash = ((argc() > 1 && argv(1) === 'splash') ? true : false);
$channel = \App::get_channel();
if(local_channel() && $channel && $channel['xchan_url'] && ! $splash) {
$channel = App::get_channel();
if (local_channel() && $channel && $channel['xchan_url'] && !$splash) {
$dest = (($ret['startpage']) ? $ret['startpage'] : '');
if(! $dest)
$dest = get_config('system','startpage');
if(! $dest)
if (!$dest)
$dest = get_config('system', 'startpage');
if (!$dest)
$dest = z_root() . '/network';
goaway($dest);
}
if(remote_channel() && (! $splash) && $_SESSION['atoken']) {
if (remote_channel() && (!$splash) && $_SESSION['atoken']) {
$r = q("select * from atoken where atoken_id = %d",
intval($_SESSION['atoken'])
);
if($r) {
if ($r) {
$x = channelx_by_n($r[0]['atoken_uid']);
if($x) {
if ($x) {
goaway(z_root() . '/channel/' . $x['channel_address']);
}
}
}
}
if(get_account_id() && ! $splash) {
if (get_account_id() && !$splash) {
goaway(z_root() . '/new_channel');
}
}
function get($update = 0, $load = false) {
$o = '';
if(x($_SESSION,'theme'))
if (x($_SESSION, 'theme'))
unset($_SESSION['theme']);
if(x($_SESSION,'mobile_theme'))
if (x($_SESSION, 'mobile_theme'))
unset($_SESSION['mobile_theme']);
$splash = ((argc() > 1 && argv(1) === 'splash') ? true : false);
call_hooks('home_content',$o);
if($o)
call_hooks('home_content', $o);
if ($o)
return $o;
$frontpage = get_config('system','frontpage');
if($frontpage) {
if(strpos($frontpage,'include:') !== false) {
$file = trim(str_replace('include:' , '', $frontpage));
if(file_exists($file)) {
\App::$page['template'] = 'full';
\App::$page['title'] = t('$Projectname');
$o .= file_get_contents($file);
$frontpage = get_config('system', 'frontpage');
if ($frontpage) {
if (strpos($frontpage, 'include:') !== false) {
$file = trim(str_replace('include:', '', $frontpage));
if (file_exists($file)) {
App::$page['template'] = 'full';
App::$page['title'] = t('$Projectname');
$o .= file_get_contents($file);
return $o;
}
}
if(strpos($frontpage,'http') !== 0)
if (strpos($frontpage, 'http') !== 0)
$frontpage = z_root() . '/' . $frontpage;
if(intval(get_config('system','mirror_frontpage'))) {
if (intval(get_config('system', 'mirror_frontpage'))) {
$o = '<html><head><title>' . t('$Projectname') . '</title></head><body style="margin: 0; padding: 0; border: none;" ><iframe src="' . $frontpage . '" width="100%" height="100%" style="margin: 0; padding: 0; border: none;" ></iframe></body></html>';
echo $o;
killme();
}
goaway($frontpage);
}
$sitename = get_config('system','sitename');
if($sitename)
$o .= '<h1 class="home-welcome">' . sprintf( t('Welcome to %s') ,$sitename) . '</h1>';
$loginbox = get_config('system','login_on_homepage');
if(intval($loginbox) || $loginbox === false)
$sitename = get_config('system', 'sitename');
if ($sitename)
$o .= '<h1 class="home-welcome">' . sprintf(t('Welcome to %s'), $sitename) . '</h1>';
$loginbox = get_config('system', 'login_on_homepage');
if (intval($loginbox) || $loginbox === false)
$o .= login(true);
return $o;
}
}

View File

@@ -38,9 +38,6 @@ class Hq extends \Zotlabs\Web\Controller {
if(!local_channel())
return;
if($load)
$_SESSION['loadtime'] = datetime_convert();
if(argc() > 1 && argv(1) !== 'load') {
$item_hash = argv(1);
}
@@ -87,15 +84,9 @@ class Hq extends \Zotlabs\Web\Controller {
goaway(z_root() . '/moderate/' . $target_item['id']);
}
$static = ((array_key_exists('static',$_REQUEST)) ? intval($_REQUEST['static']) : 0);
$simple_update = (($update) ? " AND item_unseen = 1 " : '');
$simple_update = '';
if($update && $_SESSION['loadtime'])
$simple_update = " AND (( item_unseen = 1 AND item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' ) OR item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' ) ";
if($static && $simple_update)
$simple_update .= " and item_thread_top = 0 and author_xchan = '" . protect_sprintf(get_observer_hash()) . "' ";
$sys = get_sys_channel();
$sql_extra = item_permissions_sql($sys['channel_id']);
@@ -148,8 +139,6 @@ class Hq extends \Zotlabs\Web\Controller {
nav_set_selected('HQ');
$static = ((local_channel()) ? channel_manual_conv_update(local_channel()) : 1);
if($target_item) {
// if the target item is not a post (eg a like) we want to address its thread parent
//$mid = ((($target_item['verb'] == ACTIVITY_LIKE) || ($target_item['verb'] == ACTIVITY_DISLIKE)) ? $target_item['thr_parent'] : $target_item['mid']);
@@ -182,8 +171,7 @@ class Hq extends \Zotlabs\Web\Controller {
'$dm' => '0',
'$nouveau' => '0',
'$wall' => '0',
'$static' => $static,
'$page' => 1,
'$page' => '1',
'$list' => ((x($_REQUEST,'list')) ? intval($_REQUEST['list']) : 0),
'$search' => '',
'$xchan' => '',
@@ -249,8 +237,6 @@ class Hq extends \Zotlabs\Web\Controller {
intval($sys['channel_id'])
);
}
$_SESSION['loadtime'] = datetime_convert();
}
else {
$r = [];
@@ -275,6 +261,8 @@ class Hq extends \Zotlabs\Web\Controller {
$o .= '<div id="content-complete"></div>';
$_SESSION['loadtime'] = datetime_convert();
return $o;
}

View File

@@ -8,6 +8,7 @@ require_once('include/import.php');
require_once('include/perm_upgrade.php');
require_once('library/urlify/URLify.php');
use Zotlabs\Lib\Crypto;
use Zotlabs\Lib\Libzot;
@@ -68,7 +69,7 @@ class Import extends \Zotlabs\Web\Controller {
notice( t('Nothing to import.') . EOL);
return;
} else if(strpos($old_address, '')) {
// if you copy the identity address from your profile page, make it work for convenience - WARNING: this is a utf-8 variant and NOT an ASCII ampersand. Please do not edit.
// if you copy the identity address from your profile page, make it work for convenience - WARNING: this is a utf-8 variant and NOT an ASCII ampersand. Please do not edit.
$old_address = str_replace('', '@', $old_address);
}
@@ -227,11 +228,12 @@ class Import extends \Zotlabs\Web\Controller {
'hubloc_network' => 'zot',
'hubloc_primary' => (($seize) ? 1 : 0),
'hubloc_url' => z_root(),
'hubloc_url_sig' => base64url_encode(rsa_sign(z_root(),$channel['channel_prvkey'])),
'hubloc_url_sig' => base64url_encode(Crypto::sign(z_root(),$channel['channel_prvkey'])),
'hubloc_host' => \App::get_hostname(),
'hubloc_callback' => z_root() . '/post',
'hubloc_sitekey' => get_config('system','pubkey'),
'hubloc_updated' => datetime_convert()
'hubloc_updated' => datetime_convert(),
'hubloc_id_url' => channel_url($channel)
]
);
@@ -255,7 +257,7 @@ class Import extends \Zotlabs\Web\Controller {
'hubloc_network' => 'zot6',
'hubloc_primary' => (($seize) ? 1 : 0),
'hubloc_url' => z_root(),
'hubloc_url_sig' => 'sha256.' . base64url_encode(rsa_sign(z_root(),$channel['channel_prvkey'])),
'hubloc_url_sig' => 'sha256.' . base64url_encode(Crypto::sign(z_root(),$channel['channel_prvkey'])),
'hubloc_host' => \App::get_hostname(),
'hubloc_callback' => z_root() . '/zot',
'hubloc_sitekey' => get_config('system','pubkey'),
@@ -442,7 +444,7 @@ class Import extends \Zotlabs\Web\Controller {
if(array_key_exists('abook_instance',$abook) && $abook['abook_instance'] && strpos($abook['abook_instance'],z_root()) === false) {
$abook['abook_not_here'] = 1;
}
}
if($abook['abook_self']) {
$role = get_pconfig($channel['channel_id'],'system','permissions_role');
@@ -584,11 +586,6 @@ class Import extends \Zotlabs\Web\Controller {
if(array_key_exists('item_id',$data) && $data['item_id'])
import_item_ids($channel,$data['item_id']);
// send out refresh requests
// notify old server that it may no longer be primary.
\Zotlabs\Daemon\Master::Summon(array('Notifier','location',$channel['channel_id']));
// This will indirectly perform a refresh_all *and* update the directory
\Zotlabs\Daemon\Master::Summon(array('Directory', $channel['channel_id']));

File diff suppressed because it is too large Load Diff

View File

@@ -1,40 +1,42 @@
<?php
namespace Zotlabs\Module;
use App;
use Zotlabs\Lib\Activity;
use Zotlabs\Lib\Libsync;
use Zotlabs\Web\Controller;
use Zotlabs\Daemon\Master;
require_once('include/security.php');
require_once('include/bbcode.php');
require_once('include/items.php');
require_once('include/conversation.php');
class Like extends \Zotlabs\Web\Controller {
class Like extends Controller {
private function reaction_to_activity($reaction) {
$acts = [
'like' => ACTIVITY_LIKE ,
'dislike' => ACTIVITY_DISLIKE ,
'agree' => ACTIVITY_AGREE ,
'disagree' => ACTIVITY_DISAGREE ,
'abstain' => ACTIVITY_ABSTAIN ,
'attendyes' => ACTIVITY_ATTEND ,
'attendno' => ACTIVITY_ATTENDNO ,
'attendmaybe' => ACTIVITY_ATTENDMAYBE
'like' => ACTIVITY_LIKE,
'dislike' => ACTIVITY_DISLIKE,
'agree' => ACTIVITY_AGREE,
'disagree' => ACTIVITY_DISAGREE,
'abstain' => ACTIVITY_ABSTAIN,
'attendyes' => ACTIVITY_ATTEND,
'attendno' => ACTIVITY_ATTENDNO,
'attendmaybe' => ACTIVITY_ATTENDMAYBE
];
// unlike (etc.) reactions are an undo of positive reactions, rather than a negative action.
// The activity is the same in undo actions and will have the same activity mapping
if(substr($reaction,0,2) === 'un') {
$reaction = substr($reaction,2);
if (substr($reaction, 0, 2) === 'un') {
$reaction = substr($reaction, 2);
}
if(array_key_exists($reaction,$acts)) {
if (array_key_exists($reaction, $acts)) {
return $acts[$reaction];
}
@@ -42,79 +44,126 @@ class Like extends \Zotlabs\Web\Controller {
}
private function like_response($arr) {
$page_mode = (($arr['item']['item_thread_top'] && $_REQUEST['page_mode']) ? $_REQUEST['page_mode'] : 'r_preview');
$conv_mode = (($_REQUEST['conv_mode']) ? $_REQUEST['conv_mode'] : 'network');
if ($conv_mode === 'channel') {
$parts = explode('@', $arr['owner_xchan']['xchan_addr']);
profile_load($parts[0]);
}
$item_normal = item_normal();
if ($page_mode === 'list') {
$items = q("SELECT item.*, item.id AS item_id FROM item
WHERE uid = %d $item_normal
AND parent = %d",
intval($arr['item']['uid']),
intval($arr['item']['parent'])
);
xchan_query($items, true);
$items = fetch_post_tags($items, true);
$items = conv_sort($items, 'commented');
}
else {
$activities = q("SELECT item.*, item.id AS item_id FROM item
WHERE uid = %d $item_normal
AND thr_parent = '%s'
AND verb IN ('%s', '%s', '%s', '%s', '%s')",
intval($arr['item']['uid']),
dbesc($arr['item']['mid']),
dbesc(ACTIVITY_LIKE),
dbesc(ACTIVITY_DISLIKE),
dbesc(ACTIVITY_ATTEND),
dbesc(ACTIVITY_ATTENDNO),
dbesc(ACTIVITY_ATTENDMAYBE)
);
xchan_query($activities, true);
$items = array_merge([$arr['item']], $activities);
$items = fetch_post_tags($items, true);
}
$ret = [
'success' => 1,
'orig_id' => $arr['orig_item_id'], //this is required for pubstream items where $item_id != $item['id']
'id' => $arr['item']['id'],
'html' => conversation($items, $conv_mode, true, $page_mode),
];
return $ret;
}
public function get() {
$o = EMPTY_STR;
$o = EMPTY_STR;
$sys_channel = get_sys_channel();
$sys_channel_id = (($sys_channel) ? $sys_channel['channel_id'] : 0);
$observer = \App::get_observer();
$observer = App::get_observer();
$interactive = $_REQUEST['interactive'];
if((! $observer) || ($interactive)) {
if ((!$observer) || ($interactive)) {
$o .= '<h1>' . t('Like/Dislike') . '</h1>';
$o .= EOL . EOL;
if(! $observer) {
$_SESSION['return_url'] = \App::$query_string;
if (!$observer) {
$_SESSION['return_url'] = App::$query_string;
$o .= t('This action is restricted to members.') . EOL;
$o .= t('Please <a href="rmagic">login with your $Projectname ID</a> or <a href="register">register as a new $Projectname member</a> to continue.') . EOL;
return $o;
}
}
$verb = notags(trim($_GET['verb']));
if(! $verb)
if (!$verb)
$verb = 'like';
$activity = $this->reaction_to_activity($verb);
if(! $activity) {
return EMPTY_STR;
if (!$activity) {
return EMPTY_STR;
}
$is_rsvp = false;
if (in_array($activity, [ ACTIVITY_ATTEND, ACTIVITY_ATTENDNO, ACTIVITY_ATTENDMAYBE ])) {
if (in_array($activity, [ACTIVITY_ATTEND, ACTIVITY_ATTENDNO, ACTIVITY_ATTENDMAYBE])) {
$is_rsvp = true;
}
$extended_like = false;
$object = $target = null;
$post_type = EMPTY_STR;
$objtype = EMPTY_STR;
if(argc() == 3) {
if(! $observer)
$object = $target = null;
$post_type = EMPTY_STR;
$objtype = EMPTY_STR;
if (argc() == 3) {
if (!$observer)
killme();
$extended_like = true;
$obj_type = argv(1);
$obj_id = argv(2);
$public = true;
if($obj_type == 'profile') {
$obj_type = argv(1);
$obj_id = argv(2);
$public = true;
if ($obj_type == 'profile') {
$r = q("select * from profile where profile_guid = '%s' limit 1",
dbesc(argv(2))
);
if(! $r)
killme();
if (!$r)
killme();
$owner_uid = $r[0]['uid'];
if($r[0]['is_default'])
if ($r[0]['is_default'])
$public = true;
if(! $public) {
if (!$public) {
$d = q("select abook_xchan from abook where abook_profile = '%s' and abook_channel = %d",
dbesc($r[0]['profile_guid']),
intval($owner_uid)
);
if(! $d) {
if (!$d) {
// forgery - illegal
if($interactive) {
notice( t('Invalid request.') . EOL);
if ($interactive) {
notice(t('Invalid request.') . EOL);
return $o;
}
killme();
@@ -122,122 +171,122 @@ class Like extends \Zotlabs\Web\Controller {
// $d now contains a list of those who can see this profile - only send the status notification
// to them.
$allow_cid = $allow_gid = $deny_cid = $deny_gid = '';
foreach($d as $dd) {
foreach ($d as $dd) {
$allow_cid .= '<' . $dd['abook_xchan'] . '>';
}
}
$post_type = t('channel');
$objtype = ACTIVITY_OBJ_PROFILE;
$objtype = ACTIVITY_OBJ_PROFILE;
$profile = $r[0];
}
elseif($obj_type == 'thing') {
elseif ($obj_type == 'thing') {
$r = q("select * from obj where obj_type = %d and obj_obj = '%s' limit 1",
intval(TERM_OBJ_THING),
dbesc(argv(2))
);
if(! $r) {
if($interactive) {
notice( t('Invalid request.') . EOL);
intval(TERM_OBJ_THING),
dbesc(argv(2))
);
if (!$r) {
if ($interactive) {
notice(t('Invalid request.') . EOL);
return $o;
}
killme();
killme();
}
$owner_uid = $r[0]['obj_channel'];
$allow_cid = $r[0]['allow_cid'];
$allow_gid = $r[0]['allow_gid'];
$deny_cid = $r[0]['deny_cid'];
$deny_gid = $r[0]['deny_gid'];
if($allow_cid || $allow_gid || $deny_cid || $deny_gid)
$deny_cid = $r[0]['deny_cid'];
$deny_gid = $r[0]['deny_gid'];
if ($allow_cid || $allow_gid || $deny_cid || $deny_gid)
$public = false;
$post_type = t('thing');
$objtype = ACTIVITY_OBJ_PROFILE;
$tgttype = ACTIVITY_OBJ_THING;
$objtype = ACTIVITY_OBJ_PROFILE;
$tgttype = ACTIVITY_OBJ_THING;
$links = array();
$links[] = array('rel' => 'alternate', 'type' => 'text/html',
'href' => z_root() . '/thing/' . $r[0]['obj_obj']);
if($r[0]['imgurl'])
$links[] = array('rel' => 'alternate', 'type' => 'text/html',
'href' => z_root() . '/thing/' . $r[0]['obj_obj']);
if ($r[0]['imgurl'])
$links[] = array('rel' => 'photo', 'href' => $r[0]['obj_imgurl']);
$target = json_encode(array(
'type' => $tgttype,
'title' => $r[0]['obj_term'],
'id' => z_root() . '/thing/' . $r[0]['obj_obj'],
'link' => $links
));
$plink = '[zrl=' . z_root() . '/thing/' . $r[0]['obj_obj'] . ']' . $r[0]['obj_term'] . '[/zrl]';
}
if(! ($owner_uid && $r)) {
if($interactive) {
notice( t('Invalid request.') . EOL);
if (!($owner_uid && $r)) {
if ($interactive) {
notice(t('Invalid request.') . EOL);
return $o;
}
killme();
}
// The resultant activity is going to be a wall-to-wall post, so make sure this is allowed
$perms = get_all_perms($owner_uid,$observer['xchan_hash']);
if(! ($perms['post_like'] && $perms['view_profile'])) {
if($interactive) {
notice( t('Permission denied.') . EOL);
$perms = get_all_perms($owner_uid, $observer['xchan_hash']);
if (!($perms['post_like'] && $perms['view_profile'])) {
if ($interactive) {
notice(t('Permission denied.') . EOL);
return $o;
}
killme();
}
$ch = q("select * from channel left join xchan on channel_hash = xchan_hash where channel_id = %d limit 1",
intval($owner_uid)
);
if(! $ch) {
if($interactive) {
notice( t('Channel unavailable.') . EOL);
if (!$ch) {
if ($interactive) {
notice(t('Channel unavailable.') . EOL);
return $o;
}
killme();
}
if(! $plink)
if (!$plink)
$plink = '[zrl=' . z_root() . '/profile/' . $ch[0]['channel_address'] . ']' . $post_type . '[/zrl]';
$object = json_encode(Activity::fetch_profile([ 'id' => channel_url($ch[0]) ]));
$object = json_encode(Activity::fetch_profile(['id' => channel_url($ch[0])]));
// second like of the same thing is "undo" for the first like
$z = q("select * from likes where channel_id = %d and liker = '%s' and verb = '%s' and target_type = '%s' and target_id = '%s' limit 1",
intval($ch[0]['channel_id']),
dbesc($observer['xchan_hash']),
dbesc($activity),
dbesc(($tgttype)?$tgttype:$objtype),
dbesc(($tgttype) ? $tgttype : $objtype),
dbesc($obj_id)
);
if($z) {
if ($z) {
$z[0]['deleted'] = 1;
Libsync::build_sync_packet($ch[0]['channel_id'],array('likes' => $z));
Libsync::build_sync_packet($ch[0]['channel_id'], array('likes' => $z));
q("delete from likes where id = %d",
intval($z[0]['id'])
);
if($z[0]['i_mid']) {
if ($z[0]['i_mid']) {
$r = q("select id from item where mid = '%s' and uid = %d limit 1",
dbesc($z[0]['i_mid']),
intval($ch[0]['channel_id'])
);
if($r)
drop_item($r[0]['id'],false);
if($interactive) {
notice( t('Previous action reversed.') . EOL);
if ($r)
drop_item($r[0]['id'], false);
if ($interactive) {
notice(t('Previous action reversed.') . EOL);
return $o;
}
}
@@ -246,19 +295,19 @@ class Like extends \Zotlabs\Web\Controller {
}
else {
if(! $observer)
if (!$observer)
killme();
// this is used to like an item or comment
$item_id = ((argc() == 2) ? notags(trim(argv(1))) : 0);
logger('like: verb ' . $verb . ' item ' . $item_id, LOGGER_DEBUG);
// get the item. Allow linked photos (which are normally hidden) to be liked
$r = q("SELECT * FROM item WHERE id = %d
and item_type in (0,6,7) and item_deleted = 0 and item_unpublished = 0
$r = q("SELECT * FROM item WHERE 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($item_id)
);
@@ -267,32 +316,30 @@ class Like extends \Zotlabs\Web\Controller {
// create a copy of the parent in your stream. If not the conversation
// parent, copy that as well.
if($r) {
if($r[0]['uid'] === $sys_channel['channel_id'] && local_channel()) {
$r = [ copy_of_pubitem(\App::get_channel(), $r[0]['mid']) ];
if ($r) {
if ($r[0]['uid'] === $sys_channel['channel_id'] && local_channel()) {
$r = [copy_of_pubitem(App::get_channel(), $r[0]['mid'])];
}
}
if(! $item_id || (! $r)) {
if (!$item_id || (!$r)) {
logger('like: no item ' . $item_id);
killme();
}
xchan_query($r,true);
$item = $r[0];
xchan_query($r, true);
$item = $r[0];
$owner_uid = $r[0]['uid'];
$owner_aid = $r[0]['aid'];
$can_comment = false;
if((array_key_exists('owner',$item)) && intval($item['owner']['abook_self']))
$can_comment = perm_is_allowed($item['uid'],$observer['xchan_hash'],'post_comments');
else
$can_comment = can_comment_on_post($observer['xchan_hash'],$item);
if ((array_key_exists('owner', $item)) && intval($item['owner']['abook_self']))
$can_comment = perm_is_allowed($item['uid'], $observer['xchan_hash'], 'post_comments');
else
$can_comment = can_comment_on_post($observer['xchan_hash'], $item);
if(! $can_comment) {
notice( t('Permission denied') . EOL);
if (!$can_comment) {
notice(t('Permission denied') . EOL);
killme();
}
@@ -300,222 +347,215 @@ class Like extends \Zotlabs\Web\Controller {
dbesc($item['owner_xchan'])
);
if($r)
if ($r)
$thread_owner = $r[0];
else
killme();
$r = q("select * from xchan where xchan_hash = '%s' limit 1",
dbesc($item['author_xchan'])
);
if($r)
if ($r)
$item_author = $r[0];
else
killme();
$verbs = " '".dbesc($activity)."' ";
$multi_undo = false;
$verbs = " '" . dbesc($activity) . "' ";
$multi_undo = false;
// event participation and consensus items are essentially radio toggles. If you make a subsequent choice,
// we need to eradicate your first choice.
if($activity === ACTIVITY_ATTEND || $activity === ACTIVITY_ATTENDNO || $activity === ACTIVITY_ATTENDMAYBE) {
$verbs = " '" . dbesc(ACTIVITY_ATTEND) . "','" . dbesc(ACTIVITY_ATTENDNO) . "','" . dbesc(ACTIVITY_ATTENDMAYBE) . "' ";
// we need to eradicate your first choice.
if ($activity === ACTIVITY_ATTEND || $activity === ACTIVITY_ATTENDNO || $activity === ACTIVITY_ATTENDMAYBE) {
$verbs = " '" . dbesc(ACTIVITY_ATTEND) . "','" . dbesc(ACTIVITY_ATTENDNO) . "','" . dbesc(ACTIVITY_ATTENDMAYBE) . "' ";
$multi_undo = 1;
}
if($activity === ACTIVITY_AGREE || $activity === ACTIVITY_DISAGREE || $activity === ACTIVITY_ABSTAIN) {
$verbs = " '" . dbesc(ACTIVITY_AGREE) . "','" . dbesc(ACTIVITY_DISAGREE) . "','" . dbesc(ACTIVITY_ABSTAIN) . "' ";
if ($activity === ACTIVITY_AGREE || $activity === ACTIVITY_DISAGREE || $activity === ACTIVITY_ABSTAIN) {
$verbs = " '" . dbesc(ACTIVITY_AGREE) . "','" . dbesc(ACTIVITY_DISAGREE) . "','" . dbesc(ACTIVITY_ABSTAIN) . "' ";
$multi_undo = true;
}
$item_normal = item_normal();
$r = q("SELECT id, parent, uid, verb FROM item WHERE verb in ( $verbs ) $item_normal
AND author_xchan = '%s' AND thr_parent = '%s' and uid = %d ",
dbesc($observer['xchan_hash']),
dbesc($item['mid']),
intval($owner_uid)
);
if($r) {
if ($r) {
// already liked it. Drop that item.
require_once('include/items.php');
foreach($r as $rr) {
drop_item($rr['id'],false,DROPITEM_PHASE1);
foreach ($r as $rr) {
drop_item($rr['id'], false, DROPITEM_PHASE1);
// set the changed timestamp on the parent so we'll see the update without a page reload
$z = q("update item set changed = '%s' where id = %d and uid = %d",
q("update item set changed = '%s' where id = %d and uid = %d",
dbesc(datetime_convert()),
intval($rr['parent']),
intval($rr['uid'])
);
// Prior activity was a duplicate of the one we're submitting, just undo it;
// Prior activity was a duplicate of the one we're submitting, just undo it;
// don't fall through and create another
if(activity_match($rr['verb'],$activity))
if (activity_match($rr['verb'], $activity))
$multi_undo = false;
// drop_item was not done interactively, so we need to invoke the notifier
// in order to push the changes to connections
\Zotlabs\Daemon\Master::Summon(array('Notifier','drop',$rr['id']));
Master::Summon(array('Notifier', 'drop', $rr['id']));
}
if($interactive)
if ($interactive)
return;
if(! $multi_undo)
killme();
if (!$multi_undo) {
$ret = self::like_response([
'item' => $item,
'orig_item_id' => $item_id,
'owner_xchan' => $thread_owner
]);
json_return_and_die($ret);
}
}
}
$uuid = item_message_id();
$arr = array();
$arr['uuid'] = $uuid;
$arr['mid'] = z_root() . (($is_rsvp) ? '/activity/' : '/item/') . $uuid;
if($extended_like) {
$uuid = item_message_id();
$arr = array();
$arr['uuid'] = $uuid;
$arr['mid'] = z_root() . (($is_rsvp) ? '/activity/' : '/item/') . $uuid;
if ($extended_like) {
$arr['item_thread_top'] = 1;
$arr['item_origin'] = 1;
$arr['item_wall'] = 1;
$arr['item_origin'] = 1;
$arr['item_wall'] = 1;
}
else {
$post_type = (($item['resource_type'] === 'photo') ? t('photo') : t('status'));
if($item['obj_type'] === ACTIVITY_OBJ_EVENT)
if ($item['obj_type'] === ACTIVITY_OBJ_EVENT)
$post_type = t('event');
$links = array(array('rel' => 'alternate','type' => 'text/html', 'href' => $item['plink']));
$objtype = (($item['resource_type'] === 'photo') ? ACTIVITY_OBJ_PHOTO : ACTIVITY_OBJ_NOTE );
if($objtype === ACTIVITY_OBJ_NOTE && (! intval($item['item_thread_top'])))
$objtype = (($item['resource_type'] === 'photo') ? ACTIVITY_OBJ_PHOTO : ACTIVITY_OBJ_NOTE);
if ($objtype === ACTIVITY_OBJ_NOTE && (!intval($item['item_thread_top'])))
$objtype = ACTIVITY_OBJ_COMMENT;
$body = $item['body'];
$object = json_encode(Activity::fetch_item( [ 'id' => $item['mid'] ]));
$object = json_encode(Activity::fetch_item(['id' => $item['mid']]));
if(! intval($item['item_thread_top']))
$post_type = 'comment';
$arr['item_origin'] = 1;
if (!intval($item['item_thread_top']))
$post_type = 'comment';
$arr['item_origin'] = 1;
$arr['item_notshown'] = 1;
$arr['item_type'] = $item['item_type'];
if(intval($item['item_wall']))
$arr['item_type'] = $item['item_type'];
if (intval($item['item_wall']))
$arr['item_wall'] = 1;
// if this was a linked photo and was hidden, unhide it.
if(intval($item['item_hidden'])) {
if (intval($item['item_hidden'])) {
$r = q("update item set item_hidden = 0 where id = %d",
intval($item['id'])
);
}
}
}
if($verb === 'like')
if ($verb === 'like')
$bodyverb = t('%1$s likes %2$s\'s %3$s');
if($verb === 'dislike')
if ($verb === 'dislike')
$bodyverb = t('%1$s doesn\'t like %2$s\'s %3$s');
if($verb === 'agree')
if ($verb === 'agree')
$bodyverb = t('%1$s agrees with %2$s\'s %3$s');
if($verb === 'disagree')
if ($verb === 'disagree')
$bodyverb = t('%1$s doesn\'t agree with %2$s\'s %3$s');
if($verb === 'abstain')
if ($verb === 'abstain')
$bodyverb = t('%1$s abstains from a decision on %2$s\'s %3$s');
if($verb === 'attendyes')
if ($verb === 'attendyes')
$bodyverb = t('%1$s is attending %2$s\'s %3$s');
if($verb === 'attendno')
if ($verb === 'attendno')
$bodyverb = t('%1$s is not attending %2$s\'s %3$s');
if($verb === 'attendmaybe')
if ($verb === 'attendmaybe')
$bodyverb = t('%1$s may attend %2$s\'s %3$s');
if(! isset($bodyverb))
killme();
if($extended_like) {
$ulink = '[zrl=' . $ch[0]['xchan_url'] . '][bdi]' . $ch[0]['xchan_name'] . '[/bdi][/zrl]';
$alink = '[zrl=' . $observer['xchan_url'] . '][bdi]' . $observer['xchan_name'] . '[/bdi][/zrl]';
if (!isset($bodyverb))
killme();
if ($extended_like) {
$ulink = '[zrl=' . $ch[0]['xchan_url'] . '][bdi]' . $ch[0]['xchan_name'] . '[/bdi][/zrl]';
$alink = '[zrl=' . $observer['xchan_url'] . '][bdi]' . $observer['xchan_name'] . '[/bdi][/zrl]';
$private = (($public) ? 0 : 1);
}
else {
$arr['parent'] = $item['id'];
$arr['thr_parent'] = $item['mid'];
$ulink = '[zrl=' . $item_author['xchan_url'] . '][bdi]' . $item_author['xchan_name'] . '[/bdi][/zrl]';
$alink = '[zrl=' . $observer['xchan_url'] . '][bdi]' . $observer['xchan_name'] . '[/bdi][/zrl]';
$plink = '[zrl=' . z_root() . '/display/' . gen_link_id($item['mid']) . ']' . $post_type . '[/zrl]';
$allow_cid = $item['allow_cid'];
$allow_gid = $item['allow_gid'];
$deny_cid = $item['deny_cid'];
$deny_gid = $item['deny_gid'];
$private = $item['private'];
$arr['parent'] = $item['id'];
$arr['thr_parent'] = $item['mid'];
$ulink = '[zrl=' . $item_author['xchan_url'] . '][bdi]' . $item_author['xchan_name'] . '[/bdi][/zrl]';
$alink = '[zrl=' . $observer['xchan_url'] . '][bdi]' . $observer['xchan_name'] . '[/bdi][/zrl]';
$plink = '[zrl=' . z_root() . '/display/' . gen_link_id($item['mid']) . ']' . $post_type . '[/zrl]';
$allow_cid = $item['allow_cid'];
$allow_gid = $item['allow_gid'];
$deny_cid = $item['deny_cid'];
$deny_gid = $item['deny_gid'];
$private = $item['private'];
}
$arr['aid'] = (($extended_like) ? $ch[0]['channel_account_id'] : $owner_aid);
$arr['uid'] = $owner_uid;
$arr['item_flags'] = $item_flags;
$arr['item_wall'] = $item_wall;
$arr['item_flags'] = $item['item_flags'];
$arr['item_wall'] = $item['item_wall'];
$arr['parent_mid'] = (($extended_like) ? $arr['mid'] : $item['mid']);
$arr['owner_xchan'] = (($extended_like) ? $ch[0]['xchan_hash'] : $thread_owner['xchan_hash']);
$arr['author_xchan'] = $observer['xchan_hash'];
$arr['body'] = sprintf( $bodyverb, $alink, $ulink, $plink );
if($obj_type === 'thing' && $r[0]['imgurl']) {
$arr['body'] = sprintf($bodyverb, $alink, $ulink, $plink);
if ($obj_type === 'thing' && $r[0]['imgurl']) {
$arr['body'] .= "\n\n[zmg=80x80]" . $r[0]['imgurl'] . '[/zmg]';
}
if($obj_type === 'profile') {
if($public) {
$arr['body'] .= "\n\n" . '[embed]' . z_root() . '/profile/' . $ch[0]['channel_address'] . '[/embed]';
}
if ($obj_type === 'profile') {
if ($public) {
$arr['body'] .= "\n\n" . '[embed]' . z_root() . '/profile/' . $ch[0]['channel_address'] . '[/embed]';
}
else
$arr['body'] .= "\n\n[zmg=80x80]" . $profile['thumb'] . '[/zmg]';
}
$arr['verb'] = $activity;
$arr['obj_type'] = $objtype;
$arr['obj'] = $object;
if($target) {
$arr['tgt_type'] = $tgttype;
$arr['target'] = $target;
}
$arr['allow_cid'] = $allow_cid;
$arr['allow_gid'] = $allow_gid;
$arr['deny_cid'] = $deny_cid;
$arr['deny_gid'] = $deny_gid;
$arr['item_private'] = $private;
call_hooks('post_local',$arr);
$post = item_store($arr);
$arr['verb'] = $activity;
$arr['obj_type'] = $objtype;
$arr['obj'] = $object;
if ($target) {
$arr['tgt_type'] = $tgttype;
$arr['target'] = $target;
}
$arr['allow_cid'] = $allow_cid;
$arr['allow_gid'] = $allow_gid;
$arr['deny_cid'] = $deny_cid;
$arr['deny_gid'] = $deny_gid;
$arr['item_private'] = $private;
call_hooks('post_local', $arr);
$post = item_store($arr);
$post_id = $post['item_id'];
// save the conversation from expiration
if(local_channel() && array_key_exists('item',$post) && (intval($post['item']['id']) != intval($post['item']['parent'])))
retain_item($post['item']['parent']);
if (local_channel() && array_key_exists('item', $post) && (intval($post['item']['id']) != intval($post['item']['parent'])))
retain_item($post['item']['parent']);
$arr['id'] = $post_id;
call_hooks('post_local_end', $arr);
if($extended_like) {
if ($extended_like) {
$r = q("insert into likes (channel_id,liker,likee,iid,i_mid,verb,target_type,target_id,target) values (%d,'%s','%s',%d,'%s','%s','%s','%s','%s')",
intval($ch[0]['channel_id']),
dbesc($observer['xchan_hash']),
@@ -523,35 +563,38 @@ class Like extends \Zotlabs\Web\Controller {
intval($post_id),
dbesc($arr['mid']),
dbesc($activity),
dbesc(($tgttype)? $tgttype : $objtype),
dbesc(($tgttype) ? $tgttype : $objtype),
dbesc($obj_id),
dbesc(($target) ? $target : $object)
dbesc(($target) ? $target : $object)
);
$r = q("select * from likes where liker = '%s' and likee = '%s' and i_mid = '%s' and verb = '%s' and target_type = '%s' and target_id = '%s' ",
dbesc($observer['xchan_hash']),
dbesc($ch[0]['channel_hash']),
dbesc($arr['mid']),
dbesc($activity),
dbesc(($tgttype)? $tgttype : $objtype),
dbesc(($tgttype) ? $tgttype : $objtype),
dbesc($obj_id)
);
if($r)
Libsync::build_sync_packet($ch[0]['channel_id'],array('likes' => $r));
if ($r)
Libsync::build_sync_packet($ch[0]['channel_id'], array('likes' => $r));
}
\Zotlabs\Daemon\Master::Summon(array('Notifier','like',$post_id));
if($interactive) {
notice( t('Action completed.') . EOL);
Master::Summon(array('Notifier', 'like', $post_id));
if ($interactive) {
notice(t('Action completed.') . EOL);
$o .= t('Thank you.');
return $o;
}
killme();
$ret = self::like_response([
'item' => $item,
'orig_item_id' => $item_id,
'owner_xchan' => $thread_owner
]);
json_return_and_die($ret);
}
}

View File

@@ -19,22 +19,22 @@ class Lockview extends \Zotlabs\Web\Controller {
}
}
}
$type = ((argc() > 1) ? argv(1) : 0);
if (is_numeric($type)) {
$item_id = intval($type);
$type='item';
}
}
else {
$item_id = ((argc() > 2) ? intval(argv(2)) : 0);
}
if(! $item_id)
killme();
if (! in_array($type, array('item', 'photo', 'attach', 'event', 'menu_item', 'chatroom')))
killme();
// we have different naming in in menu_item table and chatroom table
switch($type) {
case 'menu_item':
@@ -47,17 +47,17 @@ class Lockview extends \Zotlabs\Web\Controller {
$id = 'id';
break;
}
$r = q("SELECT * FROM %s WHERE $id = %d LIMIT 1",
dbesc($type),
intval($item_id)
);
if(! $r)
killme();
$item = $r[0];
//we have different naming in in menu_item table and chatroom table
switch($type) {
case 'menu_item':
@@ -70,37 +70,37 @@ class Lockview extends \Zotlabs\Web\Controller {
$uid = $item['uid'];
break;
}
if($uid != local_channel()) {
echo '<div class="dropdown-item">' . t('Remote privacy information not available.') . '</div>';
killme();
}
if(intval($item['item_private']) && (! strlen($item['allow_cid'])) && (! strlen($item['allow_gid']))
if(intval($item['item_private']) && (! strlen($item['allow_cid'])) && (! strlen($item['allow_gid']))
&& (! strlen($item['deny_cid'])) && (! strlen($item['deny_gid']))) {
// if the post is private, but public_policy is blank ("visible to the internet"), and there aren't any
// specific recipients, we're the recipient of a post with "bcc" or targeted recipients; so we'll just show it
// as unknown specific recipients. The sender will have the visibility list and will fall through to the
// next section.
echo '<div class="dropdown-item">' . translate_scope((! $item['public_policy']) ? 'specific' : $item['public_policy']) . '</div>';
killme();
}
$allowed_users = expand_acl($item['allow_cid']);
$allowed_groups = expand_acl($item['allow_gid']);
$deny_users = expand_acl($item['deny_cid']);
$deny_groups = expand_acl($item['deny_gid']);
$o = '<div class="dropdown-item">' . t('Visible to:') . '</div>';
$l = array();
stringify_array_elms($allowed_groups,true);
stringify_array_elms($allowed_users,true);
stringify_array_elms($deny_groups,true);
stringify_array_elms($deny_users,true);
$profile_groups = [];
if($allowed_groups) {
@@ -113,24 +113,24 @@ class Lockview extends \Zotlabs\Web\Controller {
if(count($profile_groups)) {
$r = q("SELECT profile_name FROM profile WHERE profile_guid IN ( " . implode(', ', $profile_groups) . " )");
if($r)
foreach($r as $rr)
foreach($r as $rr)
$l[] = '<div class="dropdown-item"><b>' . t('Profile','acl') . ' ' . $rr['profile_name'] . '</b></div>';
}
if(count($allowed_groups)) {
$r = q("SELECT gname FROM pgrp WHERE hash IN ( " . implode(', ', $allowed_groups) . " )");
if($r)
foreach($r as $rr)
foreach($r as $rr)
$l[] = '<div class="dropdown-item"><b>' . $rr['gname'] . '</b></div>';
}
if(count($allowed_users)) {
$r = q("SELECT xchan_name FROM xchan WHERE xchan_hash IN ( " . implode(', ',$allowed_users) . " )");
if($r)
foreach($r as $rr)
foreach($r as $rr)
$l[] = '<div class="dropdown-item">' . $rr['xchan_name'] . '</div>';
if($atokens) {
foreach($atokens as $at) {
if(in_array("'" . $at['xchan_hash'] . "'",$allowed_users)) {
if(in_array("'" . $at['xchan_hash'] . "'",$allowed_users)) {
$l[] = '<div class="dropdown-item">' . $at['xchan_name'] . '</div>';
}
}
@@ -149,7 +149,7 @@ class Lockview extends \Zotlabs\Web\Controller {
if(count($profile_groups)) {
$r = q("SELECT profile_name FROM profile WHERE profile_guid IN ( " . implode(', ', $profile_groups) . " )");
if($r)
foreach($r as $rr)
foreach($r as $rr)
$l[] = '<div class="dropdown-item"><b><strike>' . t('Profile','acl') . ' ' . $rr['profile_name'] . '</strike></b></div>';
}
@@ -158,18 +158,18 @@ class Lockview extends \Zotlabs\Web\Controller {
if(count($deny_groups)) {
$r = q("SELECT gname FROM pgrp WHERE hash IN ( " . implode(', ', $deny_groups) . " )");
if($r)
foreach($r as $rr)
foreach($r as $rr)
$l[] = '<div class="dropdown-item"><b><strike>' . $rr['gname'] . '</strike></b></div>';
}
if(count($deny_users)) {
$r = q("SELECT xchan_name FROM xchan WHERE xchan_hash IN ( " . implode(', ', $deny_users) . " )");
if($r)
foreach($r as $rr)
foreach($r as $rr)
$l[] = '<div class="dropdown-item"><strike>' . $rr['xchan_name'] . '</strike></div>';
if($atokens) {
foreach($atokens as $at) {
if(in_array("'" . $at['xchan_hash'] . "'",$deny_users)) {
if(in_array("'" . $at['xchan_hash'] . "'",$deny_users)) {
$l[] = '<div class="dropdown-item"><strike>' . $at['xchan_name'] . '</strike></div>';
}
}
@@ -177,11 +177,11 @@ class Lockview extends \Zotlabs\Web\Controller {
}
echo $o . implode($l);
killme();
}
}

View File

@@ -8,55 +8,65 @@ use Zotlabs\Daemon\Master;
class Locs extends Controller {
function post() {
if(! local_channel())
return;
$channel = App::get_channel();
if($_REQUEST['primary']) {
$hubloc_id = intval($_REQUEST['primary']);
if($hubloc_id) {
$r = q("select * from hubloc where hubloc_id = %d and hubloc_hash = '%s' limit 1",
intval($hubloc_id),
dbesc($channel['channel_hash'])
);
if(! $r) {
notice( t('Location not found.') . EOL);
return;
}
q("UPDATE hubloc SET hubloc_primary = 0 WHERE hubloc_primary = 1 AND (hubloc_hash = '%s' OR hubloc_hash = '%s')",
dbesc($channel['channel_hash']),
dbesc($channel['channel_portable_id'])
);
q("UPDATE hubloc SET hubloc_primary = 1 WHERE hubloc_id = %d AND hubloc_hash = '%s'",
intval($hubloc_id),
dbesc($channel['channel_hash'])
);
$x = q("select * from hubloc where hubloc_id = %d and hubloc_hash = '%s' ",
intval($hubloc_id),
dbesc($channel['channel_hash'])
);
if ($x) {
hubloc_change_primary($x[0]);
}
Master::Summon( [ 'Notifier', 'refresh_all', $channel['channel_id'] ] );
return;
}
}
}
if($_REQUEST['drop']) {
$hubloc_id = intval($_REQUEST['drop']);
if($hubloc_id) {
$r = q("select * from hubloc where hubloc_id = %d and hubloc_url != '%s' and hubloc_hash = '%s' limit 1",
intval($hubloc_id),
dbesc(z_root()),
dbesc($channel['channel_hash'])
);
if(! $r) {
notice( t('Location not found.') . EOL);
return;
}
if(intval($r[0]['hubloc_primary'])) {
$x = q("select hubloc_id from hubloc where hubloc_primary = 1 and hubloc_hash = '%s'",
dbesc($channel['channel_hash'])
@@ -70,7 +80,7 @@ class Locs extends Controller {
return;
}
}
q("UPDATE hubloc SET hubloc_deleted = 1 WHERE hubloc_id_url = '%s' AND (hubloc_hash = '%s' OR hubloc_hash = '%s')",
dbesc($r[0]['hubloc_id_url']),
dbesc($channel['channel_hash']),
@@ -78,44 +88,41 @@ class Locs extends Controller {
);
Master::Summon( [ 'Notifier', 'refresh_all', $channel['channel_id'] ] );
return;
}
}
}
}
function get() {
if(! local_channel()) {
notice( t('Permission denied.') . EOL);
return;
}
$channel = App::get_channel();
if($_REQUEST['sync']) {
Master::Summon( [ 'Notifier', 'refresh_all', $channel['channel_id'] ] );
info( t('Syncing locations') . EOL);
goaway(z_root() . '/locs');
}
$r = q("select * from hubloc where hubloc_hash = '%s'",
dbesc($channel['channel_hash'])
);
if(! $r) {
notice( t('No locations found.') . EOL);
return;
}
for($x = 0; $x < count($r); $x ++) {
$r[$x]['primary'] = (intval($r[$x]['hubloc_primary']) ? true : false);
$r[$x]['deleted'] = (intval($r[$x]['hubloc_deleted']) ? true : false);
}
$o = replace_macros(get_markup_template('locmanage.tpl'), array(
'$header' => t('Manage Channel Locations'),
'$loc' => t('Location'),
@@ -129,8 +136,8 @@ class Locs extends Controller {
'$last_resort' => t('Use this form to drop the location if the hub is no longer operating.'),
'$hubs' => $r
));
return $o;
}
}

View File

@@ -20,51 +20,46 @@ class Network extends \Zotlabs\Web\Controller {
return;
}
if(in_array(substr($_GET['search'],0,1),[ '@', '!', '?']))
goaway('search' . '?f=&search=' . $_GET['search']);
if(in_array(substr($_GET['search'],0,1),[ '@', '!', '?']) || strpos($_GET['search'], 'https://') === 0)
goaway(z_root() . '/search?f=&search=' . $_GET['search']);
if(count($_GET) < 2) {
$network_options = get_pconfig(local_channel(),'system','network_page_default');
if($network_options)
goaway('network' . '?f=&' . $network_options);
goaway(z_root() . '/network?f=&' . $network_options);
}
$channel = App::get_channel();
App::$profile_uid = local_channel();
head_set_icon($channel['xchan_photo_s']);
}
function get($update = 0, $load = false) {
if(! local_channel()) {
$_SESSION['return_url'] = App::$query_string;
return login(false);
}
$o = '';
if($load) {
$_SESSION['loadtime'] = datetime_convert();
}
$arr = array('query' => App::$query_string);
call_hooks('network_content_init', $arr);
$channel = App::get_channel();
$item_normal = item_normal();
$item_normal_update = item_normal_update();
$datequery = $datequery2 = '';
$group = 0;
$nouveau = false;
$datequery = ((x($_GET,'dend') && is_a_date_arg($_GET['dend'])) ? notags($_GET['dend']) : '');
$datequery2 = ((x($_GET,'dbegin') && is_a_date_arg($_GET['dbegin'])) ? notags($_GET['dbegin']) : '');
$static = ((x($_GET,'static')) ? intval($_GET['static']) : 0);
$gid = ((x($_GET,'gid')) ? intval($_GET['gid']) : 0);
$category = ((x($_REQUEST,'cat')) ? $_REQUEST['cat'] : '');
$hashtags = ((x($_REQUEST,'tag')) ? $_REQUEST['tag'] : '');
@@ -92,13 +87,13 @@ class Network extends \Zotlabs\Web\Controller {
$search = '';
}
}
if($datequery)
$order = 'post';
// filter by collection (e.g. group)
if($gid) {
$r = q("SELECT * FROM pgrp WHERE id = %d AND uid = %d LIMIT 1",
intval($gid),
@@ -111,12 +106,12 @@ class Network extends \Zotlabs\Web\Controller {
goaway(z_root() . '/network');
// NOTREACHED
}
$group = $gid;
$group_hash = $r[0]['hash'];
$def_acl = array('allow_gid' => '<' . $r[0]['hash'] . '>');
}
$default_cmin = ((Apps::system_app_installed(local_channel(),'Affinity Tool')) ? get_pconfig(local_channel(),'affinity','cmin',0) : (-1));
$default_cmax = ((Apps::system_app_installed(local_channel(),'Affinity Tool')) ? get_pconfig(local_channel(),'affinity','cmax',99) : (-1));
@@ -132,7 +127,7 @@ class Network extends \Zotlabs\Web\Controller {
$net = ((x($_GET,'net')) ? $_GET['net'] : '');
$pf = ((x($_GET,'pf')) ? $_GET['pf'] : '');
$unseen = ((x($_GET,'unseen')) ? $_GET['unseen'] : '');
if (Apps::system_app_installed(local_channel(),'Affinity Tool')) {
$affinity_locked = intval(get_pconfig(local_channel(),'affinity','lock',1));
if ($affinity_locked) {
@@ -160,16 +155,16 @@ class Network extends \Zotlabs\Web\Controller {
}
$def_acl = [ 'allow_cid' => '<' . $cid_r[0]['abook_xchan'] . '>', 'allow_gid' => '', 'deny_cid' => '', 'deny_gid' => '' ];
}
if(! $update) {
// search terms header
if($search || $hashtags) {
$o .= replace_macros(get_markup_template("section_title.tpl"),array(
'$title' => t('Search Results For:') . ' ' . (($search) ? htmlspecialchars($search, ENT_COMPAT,'UTF-8') : '#' . htmlspecialchars($hashtags, ENT_COMPAT,'UTF-8'))
));
}
nav_set_selected('Network');
$bang = '!';
@@ -184,14 +179,14 @@ class Network extends \Zotlabs\Web\Controller {
}
$channel_acl = array(
'allow_cid' => $channel['channel_allow_cid'],
'allow_gid' => $channel['channel_allow_gid'],
'deny_cid' => $channel['channel_deny_cid'],
'allow_cid' => $channel['channel_allow_cid'],
'allow_gid' => $channel['channel_allow_gid'],
'deny_cid' => $channel['channel_deny_cid'],
'deny_gid' => $channel['channel_deny_gid']
);
$private_editing = (($group || $cid) ? true : false);
$x = array(
'is_owner' => true,
'allow_location' => ((intval(get_pconfig($channel['channel_id'],'system','use_browser_location'))) ? '1' : ''),
@@ -209,30 +204,28 @@ class Network extends \Zotlabs\Web\Controller {
'jotnets' => true,
'reset' => t('Reset form')
);
$status_editor = status_editor($a,$x,false,'Network');
$o .= $status_editor;
$static = channel_manual_conv_update(local_channel());
}
// We don't have to deal with ACL's on this page. You're looking at everything
// that belongs to you, hence you can see all of it. We will filter by group if
// desired.
$sql_options = (($star)
? " and item_starred = 1 "
: '');
$sql_nets = '';
$item_thread_top = ' AND item_thread_top = 1 ';
$sql_extra = '';
if($group) {
$contact_str = '';
@@ -248,18 +241,18 @@ class Network extends \Zotlabs\Web\Controller {
}
$item_thread_top = '';
$sql_extra = " AND item.parent IN ( SELECT DISTINCT parent FROM item WHERE true $sql_options AND (( author_xchan IN ( $contact_str ) OR owner_xchan in ( $contact_str )) or allow_gid like '" . protect_sprintf('%<' . dbesc($group_hash) . '>%') . "' ) and id = parent $item_normal ) ";
$x = group_rec_byhash(local_channel(), $group_hash);
if($x) {
$title = replace_macros(get_markup_template("section_title.tpl"),array(
'$title' => t('Privacy group: ') . $x['gname']
));
}
$o = $title;
$o .= $status_editor;
}
elseif($cid_r) {
$item_thread_top = '';
@@ -331,76 +324,26 @@ class Network extends \Zotlabs\Web\Controller {
}
}
if(x($category)) {
$sql_extra .= protect_sprintf(term_query('item', $category, TERM_CATEGORY));
}
if(x($hashtags)) {
$sql_extra .= protect_sprintf(term_query('item', $hashtags, TERM_HASHTAG, TERM_COMMUNITYTAG));
}
if(! $update) {
// The special div is needed for liveUpdate to kick in for this page.
// We only launch liveUpdate if you aren't filtering in some incompatible
// way and also you aren't writing a comment (discovered in javascript).
$maxheight = get_pconfig(local_channel(),'system','network_divmore_height');
if(! $maxheight)
$maxheight = 400;
$o .= '<div id="live-network"></div>' . "\r\n";
$o .= "<script> var profile_uid = " . local_channel()
. "; var profile_page = " . App::$pager['page']
. "; divmore_height = " . intval($maxheight) . "; </script>\r\n";
App::$page['htmlhead'] .= replace_macros(get_markup_template("build_query.tpl"),array(
'$baseurl' => z_root(),
'$pgtype' => 'network',
'$uid' => ((local_channel()) ? local_channel() : '0'),
'$gid' => (($gid) ? $gid : '0'),
'$cid' => (($cid) ? $cid : '0'),
'$cmin' => (($cmin) ? $cmin : '(-1)'),
'$cmax' => (($cmax) ? $cmax : '(-1)'),
'$star' => (($star) ? $star : '0'),
'$liked' => (($liked) ? $liked : '0'),
'$conv' => (($conv) ? $conv : '0'),
'$spam' => (($spam) ? $spam : '0'),
'$fh' => '0',
'$dm' => (($dm) ? $dm : '0'),
'$nouveau' => (($nouveau) ? $nouveau : '0'),
'$wall' => '0',
'$static' => $static,
'$list' => ((x($_REQUEST,'list')) ? intval($_REQUEST['list']) : 0),
'$page' => ((App::$pager['page'] != 1) ? App::$pager['page'] : 1),
'$search' => (($search) ? urlencode($search) : ''),
'$xchan' => (($xchan) ? urlencode($xchan) : ''),
'$order' => $order,
'$file' => (($file) ? urlencode($file) : ''),
'$cats' => (($category) ? urlencode($category) : ''),
'$tags' => (($hashtags) ? urlencode($hashtags) : ''),
'$dend' => $datequery,
'$mid' => '',
'$verb' => (($verb) ? urlencode($verb) : ''),
'$net' => (($net) ? urlencode($net) : ''),
'$dbegin' => $datequery2,
'$pf' => (($pf) ? intval($pf) : 0),
'$unseen' => (($unseen) ? urlencode($unseen) : '')
));
}
$sql_extra3 = '';
if($datequery) {
$sql_extra3 .= protect_sprintf(sprintf(" AND item.created <= '%s' ", dbesc(datetime_convert(date_default_timezone_get(),'',$datequery))));
}
if($datequery2) {
$sql_extra3 .= protect_sprintf(sprintf(" AND item.created >= '%s' ", dbesc(datetime_convert(date_default_timezone_get(),'',$datequery2))));
}
$sql_extra2 = (($nouveau) ? '' : " AND item.parent = item.id ");
$sql_extra3 = (($nouveau) ? '' : $sql_extra3);
if(x($_GET,'search')) {
$search = escape_tags($_GET['search']);
if(strpos($search,'#') === 0) {
@@ -413,7 +356,7 @@ class Network extends \Zotlabs\Web\Controller {
);
}
}
if ($verb) {
// the presence of a leading dot in the verb determines
@@ -433,7 +376,7 @@ class Network extends \Zotlabs\Web\Controller {
);
}
}
if(strlen($file)) {
$sql_extra .= term_query('item',$file,TERM_FILE);
}
@@ -441,52 +384,52 @@ class Network extends \Zotlabs\Web\Controller {
if ($dm) {
$sql_extra .= " AND item_private = 2 ";
}
if($conv) {
$item_thread_top = '';
$sql_extra .= " AND ( author_xchan = '" . dbesc($channel['channel_hash']) . "' OR item_mentionsme = 1 ) ";
}
if($update && ! $load) {
// only setup pagination on initial page view
$pager_sql = '';
}
else {
$itemspage = get_pconfig(local_channel(),'system','itemspage');
App::set_pager_itemspage(((intval($itemspage)) ? $itemspage : 10));
$pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(App::$pager['itemspage']), intval(App::$pager['start']));
}
// cmin and cmax are both -1 when the affinity tool is disabled
if(($cmin != (-1)) || ($cmax != (-1))) {
// Not everybody who shows up in the network stream will be in your address book.
// By default those that aren't are assumed to have closeness = 99; but this isn't
// recorded anywhere. So if cmax is 99, we'll open the search up to anybody in
// the stream with a NULL address book entry.
$sql_nets .= " AND ";
if($cmax == 99)
$sql_nets .= " ( ";
$sql_nets .= "( abook.abook_closeness >= " . intval($cmin) . " ";
$sql_nets .= " AND abook.abook_closeness <= " . intval($cmax) . " ) ";
if($cmax == 99)
$sql_nets .= " OR abook.abook_closeness IS NULL ) ";
}
$net_query = (($net) ? " left join xchan on xchan_hash = author_xchan " : '');
$net_query = (($net) ? " left join xchan on xchan_hash = author_xchan " : '');
$net_query2 = (($net) ? " and xchan_network = '" . protect_sprintf(dbesc($net)) . "' " : '');
$abook_uids = " and abook.abook_channel = " . local_channel() . " ";
$uids = " and item.uid = " . local_channel() . " ";
if(feature_enabled(local_channel(), 'network_list_mode'))
$page_mode = 'list';
else
@@ -494,8 +437,6 @@ class Network extends \Zotlabs\Web\Controller {
$parents_str = '';
$simple_update = (($update) ? " and item_unseen = 1 " : '');
// This fixes a very subtle bug so I'd better explain it. You wake up in the morning or return after a day
// or three and look at your matrix page - after opening up your browser. The first page loads just as it
// should. All of a sudden a few seconds later, page 2 will get inserted at the beginning of the page
@@ -507,24 +448,18 @@ class Network extends \Zotlabs\Web\Controller {
// which "arrived as you were reading page 1". We're going to do this
// by storing in your session the current UTC time whenever you LOAD a network page, and only UPDATE items
// which are both ITEM_UNSEEN and have "changed" since that time. Cross fingers...
$simple_update = '';
if($update && $_SESSION['loadtime'])
$simple_update = " AND (( item_unseen = 1 AND item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' ) OR item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' ) ";
if($load)
$simple_update = '';
if($static && $simple_update)
$simple_update .= " and item_thread_top = 0 and author_xchan = '" . protect_sprintf(get_observer_hash()) . "' ";
if($nouveau && $load) {
// "New Item View" - show all items unthreaded in reverse created date order
$items = q("SELECT item.*, item.id AS item_id, created FROM item
$items = q("SELECT item.*, item.id AS item_id, created FROM item
left join abook on ( item.owner_xchan = abook.abook_xchan $abook_uids )
$net_query
WHERE true $uids $item_normal
and (abook.abook_blocked = 0 or abook.abook_flags is null)
$simple_update
$sql_extra $sql_options $sql_nets
$net_query2
ORDER BY item.created DESC $pager_sql "
@@ -533,23 +468,23 @@ class Network extends \Zotlabs\Web\Controller {
$parents_str = ids_to_querystr($items,'item_id');
require_once('include/items.php');
xchan_query($items);
$items = fetch_post_tags($items,true);
}
elseif($update) {
// Normal conversation view
if($order === 'post')
$ordering = "created";
else
$ordering = "commented";
if($load) {
// Fetch a page full of parent items for this page
$r = q("SELECT item.parent AS item_id FROM item
$r = q("SELECT item.parent AS item_id FROM item
left join abook on ( item.owner_xchan = abook.abook_xchan $abook_uids )
$net_query
WHERE true $uids $item_thread_top $item_normal
@@ -570,22 +505,21 @@ class Network extends \Zotlabs\Web\Controller {
and (abook.abook_blocked = 0 or abook.abook_flags is null)
$sql_extra3 $sql_extra $sql_options $sql_nets $net_query2"
);
$_SESSION['loadtime'] = datetime_convert();
}
// Then fetch all the children of the parents that are on this page
if($r) {
$parents_str = ids_to_querystr($r,'item_id');
$items = q("SELECT item.*, item.id AS item_id FROM item
WHERE true $uids $item_normal
AND item.parent IN ( %s )
$sql_extra ",
dbesc($parents_str)
);
xchan_query($items,true);
$items = fetch_post_tags($items,true);
$items = conv_sort($items,$ordering);
@@ -595,18 +529,70 @@ class Network extends \Zotlabs\Web\Controller {
}
}
$mode = (($nouveau) ? 'network-new' : 'network');
if($search)
$mode = 'search';
if(! $update) {
// The special div is needed for liveUpdate to kick in for this page.
// We only launch liveUpdate if you aren't filtering in some incompatible
// way and also you aren't writing a comment (discovered in javascript).
$maxheight = get_pconfig(local_channel(),'system','network_divmore_height');
if(! $maxheight)
$maxheight = 400;
$o .= '<div id="live-network"></div>' . "\r\n";
$o .= "<script> var profile_uid = " . local_channel()
. "; var profile_page = " . App::$pager['page']
. "; divmore_height = " . intval($maxheight) . "; </script>\r\n";
App::$page['htmlhead'] .= replace_macros(get_markup_template("build_query.tpl"),array(
'$baseurl' => z_root(),
'$pgtype' => 'network',
'$uid' => ((local_channel()) ? local_channel() : '0'),
'$gid' => (($gid) ? $gid : '0'),
'$cid' => (($cid) ? $cid : '0'),
'$cmin' => (($cmin) ? $cmin : '(-1)'),
'$cmax' => (($cmax) ? $cmax : '(-1)'),
'$star' => (($star) ? $star : '0'),
'$liked' => (($liked) ? $liked : '0'),
'$conv' => (($conv) ? $conv : '0'),
'$spam' => (($spam) ? $spam : '0'),
'$fh' => '0',
'$dm' => (($dm) ? $dm : '0'),
'$nouveau' => (($nouveau) ? $nouveau : '0'),
'$wall' => '0',
'$list' => ((x($_REQUEST,'list')) ? intval($_REQUEST['list']) : 0),
'$page' => ((App::$pager['page'] != 1) ? App::$pager['page'] : 1),
'$search' => (($search) ? urlencode($search) : ''),
'$xchan' => (($xchan) ? urlencode($xchan) : ''),
'$order' => $order,
'$file' => (($file) ? urlencode($file) : ''),
'$cats' => (($category) ? urlencode($category) : ''),
'$tags' => (($hashtags) ? urlencode($hashtags) : ''),
'$dend' => $datequery,
'$mid' => '',
'$verb' => (($verb) ? urlencode($verb) : ''),
'$net' => (($net) ? urlencode($net) : ''),
'$dbegin' => $datequery2,
'$pf' => (($pf) ? intval($pf) : 0),
'$unseen' => (($unseen) ? urlencode($unseen) : ''),
'$page_mode' => $page_mode
));
}
$o .= conversation($items,$mode,$update,$page_mode);
if(($items) && (! $update))
$o .= alt_pager(count($items));
$_SESSION['loadtime'] = datetime_convert();
return $o;
}
}

View File

@@ -19,7 +19,7 @@ class Notifications extends \Zotlabs\Web\Controller {
$r = q("select count(*) as total from notify where uid = %d and seen = 0",
intval(local_channel())
);
if($r && intval($t[0]['total']) > 49) {
if($r && intval($r[0]['total']) > 49) {
$r = q("select * from notify where uid = %d
and seen = 0 order by created desc limit 50",
intval(local_channel())
@@ -32,7 +32,7 @@ class Notifications extends \Zotlabs\Web\Controller {
$r2 = q("select * from notify where uid = %d
and seen = 1 order by created desc limit %d",
intval(local_channel()),
intval(50 - intval($t[0]['total']))
intval(50 - intval($r[0]['total']))
);
$r = array_merge($r1,$r2);
}
@@ -41,7 +41,7 @@ class Notifications extends \Zotlabs\Web\Controller {
$notifications_available = 1;
foreach ($r as $rr) {
$x = strip_tags(bbcode($rr['msg']));
$notif_content .= replace_macros(get_markup_template('notify.tpl'),array(
$notif_content = replace_macros(get_markup_template('notify.tpl'),array(
'$item_link' => z_root().'/notify/view/'. $rr['id'],
'$item_image' => $rr['photo'],
'$item_text' => $x,
@@ -52,7 +52,7 @@ class Notifications extends \Zotlabs\Web\Controller {
}
}
else {
$notif_content .= t('No more system notifications.');
$notif_content = t('No more system notifications.');
}
$o .= replace_macros(get_markup_template('notifications.tpl'),array(

View File

@@ -11,9 +11,9 @@ use Zotlabs\Web\Controller;
* See spec/OpenWebAuth/Home.md
* Requests to this endpoint should be signed using HTTP Signatures
* using the 'Authorization: Signature' authentication method
* If the signature verifies a token is returned.
* If the signature verifies a token is returned.
*
* This token may be exchanged for an authenticated cookie.
* This token may be exchanged for an authenticated cookie.
*/
class Owa extends Controller {
@@ -31,36 +31,34 @@ class Owa extends Controller {
if ($sigblock) {
$keyId = $sigblock['keyId'];
if ($keyId) {
$r = q("select * from hubloc left join xchan on hubloc_hash = xchan_hash
where ( hubloc_addr = '%s' or hubloc_id_url = '%s' ) ",
dbesc(str_replace('acct:','',$keyId)),
$r = q("SELECT * FROM hubloc LEFT JOIN xchan ON hubloc_hash = xchan_hash
WHERE hubloc_id_url = '%s'",
dbesc($keyId)
);
if (! $r) {
$found = discover_by_webbie(str_replace('acct:','',$keyId));
if ($found) {
$r = q("select * from hubloc left join xchan on hubloc_hash = xchan_hash
where ( hubloc_addr = '%s' or hubloc_id_url = '%s' ) ",
dbesc(str_replace('acct:','',$keyId)),
$r = q("SELECT * FROM hubloc LEFT JOIN xchan ON hubloc_hash = xchan_hash
WHERE hubloc_id_url = '%s'",
dbesc($keyId)
);
}
}
if ($r) {
foreach ($r as $hubloc) {
$verified = HTTPSig::verify(file_get_contents('php://input'));
$verified = HTTPSig::verify(file_get_contents('php://input'), $hubloc['xchan_pubkey']);
if ($verified && $verified['header_signed'] && $verified['header_valid'] && ($verified['content_valid'] || (! $verified['content_signed']))) {
logger('OWA header: ' . print_r($verified,true),LOGGER_DATA);
logger('OWA success: ' . $hubloc['hubloc_addr'],LOGGER_DATA);
logger('OWA success: ' . $hubloc['hubloc_id_url'],LOGGER_DATA);
$ret['success'] = true;
$token = random_string(32);
Verify::create('owt',0,$token,$hubloc['hubloc_addr']);
Verify::create('owt',0,$token,$hubloc['hubloc_id_url']);
$result = '';
openssl_public_encrypt($token,$result,$hubloc['xchan_pubkey']);
$ret['encrypted_token'] = base64url_encode($result);
break;
} else {
logger('OWA fail: ' . $hubloc['hubloc_id'] . ' ' . $hubloc['hubloc_addr']);
logger('OWA fail: ' . $hubloc['hubloc_id'] . ' ' . $hubloc['hubloc_id_url']);
}
}
}

View File

@@ -8,16 +8,16 @@ use Zotlabs\Lib\Libsync;
class Pconfig extends \Zotlabs\Web\Controller {
function post() {
if(! local_channel())
return;
if($_SESSION['delegate'])
return;
check_form_security_token_redirectOnErr('/pconfig', 'pconfig');
$cat = trim(escape_tags($_POST['cat']));
$k = trim(escape_tags($_POST['k']));
$v = trim($_POST['v']);
@@ -27,16 +27,16 @@ class Pconfig extends \Zotlabs\Web\Controller {
if (preg_match('|^a:[0-9]+:{.*}$|s',$v) || preg_match('|O:8:"stdClass":[0-9]+:{.*}$|s',$v)) {
return;
}
if(in_array(argv(2),$this->disallowed_pconfig())) {
notice( t('This setting requires special processing and editing has been blocked.') . EOL);
return;
}
if(strpos($k,'password') !== false) {
$v = z_obscure($v);
$v = obscurify($v);
}
set_pconfig(local_channel(),$cat,$k,$v);
Libsync::build_sync_packet();
@@ -46,24 +46,24 @@ class Pconfig extends \Zotlabs\Web\Controller {
goaway(z_root() . '/pconfig/' . $cat . '/' . $k);
}
function get() {
if(! local_channel()) {
return login();
}
$content = '<h3>' . t('Configuration Editor') . '</h3>';
$content .= '<div class="descriptive-paragraph">' . t('Warning: Changing some settings could render your channel inoperable. Please leave this page unless you are comfortable with and knowledgeable about how to correctly use this feature.') . '</div>' . EOL . EOL;
if(argc() == 3) {
$content .= '<a href="pconfig">pconfig[' . local_channel() . ']</a>' . EOL;
$content .= '<a href="pconfig/' . escape_tags(argv(1)) . '">pconfig[' . local_channel() . '][' . escape_tags(argv(1)) . ']</a>' . EOL . EOL;
$content .= '<a href="pconfig/' . escape_tags(argv(1)) . '/' . escape_tags(argv(2)) . '" >pconfig[' . local_channel() . '][' . escape_tags(argv(1)) . '][' . escape_tags(argv(2)) . ']</a> = ' . get_pconfig(local_channel(),escape_tags(argv(1)),escape_tags(argv(2))) . EOL;
if(in_array(argv(2),$this->disallowed_pconfig())) {
notice( t('This setting requires special processing and editing has been blocked.') . EOL);
return $content;
@@ -71,8 +71,8 @@ class Pconfig extends \Zotlabs\Web\Controller {
else
$content .= $this->pconfig_form(escape_tags(argv(1)),escape_tags(argv(2)));
}
if(argc() == 2) {
$content .= '<a href="pconfig">pconfig[' . local_channel() . ']</a>' . EOL;
load_pconfig(local_channel(),escape_tags(argv(1)));
@@ -80,9 +80,9 @@ class Pconfig extends \Zotlabs\Web\Controller {
$content .= '<a href="pconfig/' . escape_tags(argv(1)) . '/' . $k . '" >pconfig[' . local_channel() . '][' . escape_tags(argv(1)) . '][' . $k . ']</a> = ' . escape_tags($x) . EOL;
}
}
if(argc() == 1) {
$r = q("select * from pconfig where uid = " . local_channel());
if($r) {
foreach($r as $rr) {
@@ -91,33 +91,33 @@ class Pconfig extends \Zotlabs\Web\Controller {
}
}
return $content;
}
function pconfig_form($cat,$k) {
$o = '<form action="pconfig" method="post" >';
$o .= '<input type="hidden" name="form_security_token" value="' . get_form_security_token('pconfig') . '" />';
$v = get_pconfig(local_channel(),$cat,$k);
if(strpos($k,'password') !== false)
$v = z_unobscure($v);
if(strpos($k,'password') !== false)
$v = unobscurify($v);
$o .= '<input type="hidden" name="cat" value="' . $cat . '" />';
$o .= '<input type="hidden" name="k" value="' . $k . '" />';
if(strpos($v,"\n"))
$o .= '<textarea name="v" >' . escape_tags($v) . '</textarea>';
else
$o .= '<input type="text" name="v" value="' . escape_tags($v) . '" />';
$o .= EOL . EOL;
$o .= EOL . EOL;
$o .= '<input type="submit" name="submit" value="' . t('Submit') . '" />';
$o .= '</form>';
return $o;
}
@@ -127,5 +127,5 @@ class Pconfig extends \Zotlabs\Web\Controller {
'permissions_role'
);
}
}

View File

@@ -35,7 +35,7 @@ class Photo extends \Zotlabs\Web\Controller {
call_hooks('cache_mode_hook', $cache_mode);
$observer_xchan = get_observer_hash();
$cachecontrol = '';
$cachecontrol = ', no-cache';
if(isset($type)) {
@@ -81,18 +81,18 @@ class Photo extends \Zotlabs\Web\Controller {
else
$data = dbunescbin($r[0]['content']);
}
}
if(! $data) {
$d = [ 'imgscale' => $resolution, 'channel_id' => $uid, 'default' => $default, 'data' => '', 'mimetype' => '' ];
call_hooks('get_profile_photo',$d);
$resolution = $d['imgscale'];
$uid = $d['channel_id'];
$default = $d['default'];
$data = $d['data'];
$mimetype = $d['mimetype'];
$modified = 0;
if(! $data) {
$d = [ 'imgscale' => $resolution, 'channel_id' => $uid, 'default' => $default, 'data' => '', 'mimetype' => '' ];
call_hooks('get_profile_photo',$d);
$resolution = $d['imgscale'];
$uid = $d['channel_id'];
$default = $d['default'];
$data = $d['data'];
$mimetype = $d['mimetype'];
$modified = 0;
}
}
if(! $data) {
@@ -102,7 +102,7 @@ class Photo extends \Zotlabs\Web\Controller {
$modified = filemtime($default);
}
$cachecontrol = ', must-revalidate';
$cachecontrol .= ', must-revalidate';
}
else {
@@ -147,7 +147,7 @@ class Photo extends \Zotlabs\Web\Controller {
);
if($r) {
$allowed = (-1);
$filename = $r[0]['filename'];
$u = intval($r[0]['photo_usage']);
if($u) {
$allowed = 1;
@@ -169,6 +169,7 @@ class Photo extends \Zotlabs\Web\Controller {
$url = z_root() . '/sslify/' . $filename . '?f=&url=' . urlencode($url);
goaway($url);
}
$cachecontrol = '';
}
}
}
@@ -193,9 +194,9 @@ class Photo extends \Zotlabs\Web\Controller {
$mimetype = $e[0]['mimetype'];
$modified = strtotime($e[0]['edited'] . 'Z');
if(intval($e[0]['os_storage'])) {
if(intval($e[0]['os_storage']))
$streaming = $data;
}
if($e[0]['allow_cid'] != '' || $e[0]['allow_gid'] != '' || $e[0]['deny_gid'] != '' || $e[0]['deny_gid'] != '')
$prvcachecontrol = 'no-store, no-cache, must-revalidate';
}
@@ -271,7 +272,7 @@ class Photo extends \Zotlabs\Web\Controller {
// in the event that infrastructure caching is present.
$smaxage = intval($maxage/12);
header("Cache-Control: no-cache, s-maxage=" . $smaxage . ", max-age=" . $maxage . $cachecontrol);
header("Cache-Control: s-maxage=" . $smaxage . ", max-age=" . $maxage . $cachecontrol);
}
@@ -281,7 +282,7 @@ class Photo extends \Zotlabs\Web\Controller {
header("Content-Length: " . (isset($filesize) ? $filesize : strlen($data)));
// If it's a file resource, stream it.
if($streaming && $channel) {
if($streaming) {
if(strpos($streaming,'store') !== false)
$istream = fopen($streaming,'rb');
else

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