mirror of
https://framagit.org/hubzilla/core.git
synced 2026-06-22 01:17:41 -04:00
Compare commits
856 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1aeb05628b | ||
|
|
b464fae3bf | ||
|
|
a34ce0732d | ||
|
|
f457b6623d | ||
|
|
01ebd51fb2 | ||
|
|
cb25fc031b | ||
|
|
6c6fc82f43 | ||
|
|
990017b588 | ||
|
|
192ab22cda | ||
|
|
5e5a0d7c91 | ||
|
|
2dc1adf091 | ||
|
|
371b8440c3 | ||
|
|
49509e7347 | ||
|
|
66f5b34c07 | ||
|
|
6a3d372050 | ||
|
|
c95359024c | ||
|
|
edf898d7b7 | ||
|
|
ee0060619d | ||
|
|
4f8ede35bd | ||
|
|
9d9c102da8 | ||
|
|
3de8f5e7de | ||
|
|
a18e873d08 | ||
|
|
b3c260a145 | ||
|
|
1097bcdaf9 | ||
|
|
cfde1be097 | ||
|
|
6df4da5313 | ||
|
|
f910de849f | ||
|
|
d6eaeba239 | ||
|
|
5c2e10c01e | ||
|
|
8754f72e63 | ||
|
|
569f243ebd | ||
|
|
651a3f8380 | ||
|
|
40714ecdd0 | ||
|
|
d4b1bcd641 | ||
|
|
acc1834b0d | ||
|
|
e237cf226a | ||
|
|
7c5a0887cc | ||
|
|
0745d0616a | ||
|
|
9cbb9a4874 | ||
|
|
14f3b72c82 | ||
|
|
b05845f495 | ||
|
|
2114779037 | ||
|
|
937b6d360e | ||
|
|
0d30eed4a7 | ||
|
|
39d4f67417 | ||
|
|
68d989c79e | ||
|
|
9600789d6b | ||
|
|
ea7559c158 | ||
|
|
baa12b7497 | ||
|
|
ac4aa6a9ea | ||
|
|
732dbfd6f5 | ||
|
|
5860abf46f | ||
|
|
2874d3e1e1 | ||
|
|
42b0205ad0 | ||
|
|
36778850ee | ||
|
|
19c0e97658 | ||
|
|
fe018d646a | ||
|
|
24132e56d9 | ||
|
|
8fc0210428 | ||
|
|
64560cbca9 | ||
|
|
6e97c97920 | ||
|
|
916edcb45e | ||
|
|
8873c10364 | ||
|
|
77e1220cf9 | ||
|
|
f402baffd3 | ||
|
|
216f3755fc | ||
|
|
d846cefade | ||
|
|
f3efdbf230 | ||
|
|
826ef11247 | ||
|
|
b68ddc4cd3 | ||
|
|
41f909c415 | ||
|
|
0b4e086376 | ||
|
|
5af3c35778 | ||
|
|
dddcddc453 | ||
|
|
754d90a676 | ||
|
|
8b0dce56ad | ||
|
|
42696606e3 | ||
|
|
b645ede168 | ||
|
|
6e12b5ec08 | ||
|
|
fbf36992be | ||
|
|
e0de813700 | ||
|
|
39448a0871 | ||
|
|
4fb37ef6f3 | ||
|
|
a9d4adaf23 | ||
|
|
70dfce356b | ||
|
|
10fbfa06e9 | ||
|
|
6315757967 | ||
|
|
9ddd840897 | ||
|
|
6c5627ac0e | ||
|
|
c2d6d376a4 | ||
|
|
55532c7cb1 | ||
|
|
a93fed5ae2 | ||
|
|
ba1b48f177 | ||
|
|
898762dd95 | ||
|
|
81ce67df94 | ||
|
|
55097c47c5 | ||
|
|
97b82fc77b | ||
|
|
b7bda0b87d | ||
|
|
6bf61dfa6b | ||
|
|
0e59cfb839 | ||
|
|
328ce0a837 | ||
|
|
34e24ea5e9 | ||
|
|
907426af5e | ||
|
|
360713c689 | ||
|
|
ee8aba3221 | ||
|
|
ae657754b0 | ||
|
|
0a730935f5 | ||
|
|
d285da09fe | ||
|
|
b291f1bad3 | ||
|
|
e1b660bfa3 | ||
|
|
0036c0cde9 | ||
|
|
49c1833a46 | ||
|
|
46fa26502b | ||
|
|
ba1e705c61 | ||
|
|
043e2ff58b | ||
|
|
deba1863f5 | ||
|
|
0e27f010f9 | ||
|
|
45b1be8962 | ||
|
|
fe9ca30c5e | ||
|
|
9e8ba5f6e2 | ||
|
|
5207e1e774 | ||
|
|
c1228d6b6d | ||
|
|
6262d351b7 | ||
|
|
27e57ff7aa | ||
|
|
74fc7508f3 | ||
|
|
3eea4f475c | ||
|
|
37b22fe542 | ||
|
|
b5b8106e7a | ||
|
|
b77100ff6d | ||
|
|
5eb6572277 | ||
|
|
69bed9c889 | ||
|
|
3c88c5e66a | ||
|
|
d40d62ac4f | ||
|
|
d23ed6b11f | ||
|
|
1e2a4a57b6 | ||
|
|
7892eeb2d2 | ||
|
|
d7ceb977da | ||
|
|
36d0594b8e | ||
|
|
3f32a5239d | ||
|
|
15a7d2d4de | ||
|
|
80ed2ff89a | ||
|
|
37a0343163 | ||
|
|
8529e2f14e | ||
|
|
b73401bd7f | ||
|
|
af839a0589 | ||
|
|
4bbeb224f6 | ||
|
|
8435d9eb13 | ||
|
|
d97df1859f | ||
|
|
46f67eaa1e | ||
|
|
54451851bb | ||
|
|
5b7387459c | ||
|
|
5d64a9c90f | ||
|
|
ffaa985339 | ||
|
|
291e12574a | ||
|
|
fc5b5ba021 | ||
|
|
056c55a963 | ||
|
|
02a0af3eef | ||
|
|
96e8316633 | ||
|
|
37878bf0a3 | ||
|
|
b4f079c4b5 | ||
|
|
18abfb11ef | ||
|
|
25dbc8a9f6 | ||
|
|
c639704f3c | ||
|
|
3dd7394247 | ||
|
|
b860b730a9 | ||
|
|
17e2877c91 | ||
|
|
b7bc28c333 | ||
|
|
fb5a52cbde | ||
|
|
6d125d02d8 | ||
|
|
0b18b35f5f | ||
|
|
9859008271 | ||
|
|
423c36f67b | ||
|
|
1e0195e439 | ||
|
|
30271bb32f | ||
|
|
e2b1670d6c | ||
|
|
2bfdfbe3cc | ||
|
|
9a85421a0e | ||
|
|
1fa59df6f3 | ||
|
|
2c93294eea | ||
|
|
316829269a | ||
|
|
55236f86e0 | ||
|
|
060210e930 | ||
|
|
9291622885 | ||
|
|
07978a061e | ||
|
|
08b2356ed1 | ||
|
|
d17934ed80 | ||
|
|
94f17f0dae | ||
|
|
7ccb2a2615 | ||
|
|
067a66b927 | ||
|
|
096fad5e8c | ||
|
|
e21e4c7127 | ||
|
|
5754ea828d | ||
|
|
5fbc203367 | ||
|
|
08884c44fb | ||
|
|
bd04ca21a4 | ||
|
|
19ae8cfdfc | ||
|
|
86e953f495 | ||
|
|
4bc4f5b2a6 | ||
|
|
5f2e808497 | ||
|
|
4f69e02768 | ||
|
|
e6ce2885c0 | ||
|
|
ec19ee9d82 | ||
|
|
983f063d33 | ||
|
|
eb6a143fff | ||
|
|
1881029040 | ||
|
|
209651705d | ||
|
|
fab3c92a7c | ||
|
|
8ad7376865 | ||
|
|
c41831aff9 | ||
|
|
8515aa6966 | ||
|
|
691de5bf2e | ||
|
|
2e155892fe | ||
|
|
6680c2faf3 | ||
|
|
decc8f2162 | ||
|
|
7d7a0c160f | ||
|
|
e89563eb4c | ||
|
|
dd204ec34f | ||
|
|
b3a5dd8aa8 | ||
|
|
26ee56f39c | ||
|
|
300b0e27bd | ||
|
|
29489f62cf | ||
|
|
09465619e5 | ||
|
|
390af7722d | ||
|
|
e18157f818 | ||
|
|
5435d2881c | ||
|
|
2e8f3d1869 | ||
|
|
3ad1cab006 | ||
|
|
b806a3ccc2 | ||
|
|
5e780ba089 | ||
|
|
c0a7dfe2f6 | ||
|
|
fe50d78a0f | ||
|
|
e513950cb5 | ||
|
|
adc6390a22 | ||
|
|
9449e8bd61 | ||
|
|
f13af0f60b | ||
|
|
acdb773f89 | ||
|
|
651a288148 | ||
|
|
b0664f7349 | ||
|
|
51586037e1 | ||
|
|
f573c1772a | ||
|
|
f08e91e19d | ||
|
|
8cd9fff26a | ||
|
|
d489a2854e | ||
|
|
9cfd1c2318 | ||
|
|
2dd0677d23 | ||
|
|
00d403e729 | ||
|
|
d83e2daf36 | ||
|
|
8fe6aede03 | ||
|
|
fa4ab45692 | ||
|
|
f57fbaa5dd | ||
|
|
aba8002170 | ||
|
|
9cc85adf47 | ||
|
|
01ed001041 | ||
|
|
403539919a | ||
|
|
52ea2fa33e | ||
|
|
ecd4754f6d | ||
|
|
f71033b30d | ||
|
|
885068834f | ||
|
|
c4c4ab2f3d | ||
|
|
aec3247952 | ||
|
|
b05b756148 | ||
|
|
03819abb22 | ||
|
|
d074e2aba0 | ||
|
|
2bbecfe8dd | ||
|
|
e078e13325 | ||
|
|
9d3b852d38 | ||
|
|
fadb0a5bf2 | ||
|
|
fa7aa6cedb | ||
|
|
6df98f2fad | ||
|
|
c597017402 | ||
|
|
9cb95f6065 | ||
|
|
477b1535a2 | ||
|
|
1d652cfcbd | ||
|
|
28b604c7c7 | ||
|
|
8c11be07cd | ||
|
|
e8dd2c28ff | ||
|
|
0bdffc4a2d | ||
|
|
94b1fe4a8b | ||
|
|
11ed445319 | ||
|
|
400dfb4e6b | ||
|
|
6b951734ce | ||
|
|
000fcfd1ac | ||
|
|
051e2ed6cd | ||
|
|
aac406a245 | ||
|
|
ef2952b5fd | ||
|
|
ffdf54b097 | ||
|
|
58593d7da6 | ||
|
|
3d13f36ce2 | ||
|
|
8c843ec6d0 | ||
|
|
232c7f5301 | ||
|
|
16cd8caef3 | ||
|
|
43dabee53d | ||
|
|
f016760851 | ||
|
|
99b5166f21 | ||
|
|
4aa29db7aa | ||
|
|
f5b8b18c8e | ||
|
|
6e5566f9c8 | ||
|
|
ca216ae819 | ||
|
|
4713241444 | ||
|
|
4917170a0d | ||
|
|
87775ae37a | ||
|
|
eaa244a2a3 | ||
|
|
db91d66d1a | ||
|
|
4d64481564 | ||
|
|
0a31fc176c | ||
|
|
659a8c967c | ||
|
|
626887a792 | ||
|
|
256b66de41 | ||
|
|
5ee4f37b8d | ||
|
|
3dc122db84 | ||
|
|
99c5a4e2f8 | ||
|
|
f922a92ffa | ||
|
|
a36de8ba1a | ||
|
|
e3d30763da | ||
|
|
c73518d8ec | ||
|
|
ed0d2fed66 | ||
|
|
960bcb6b53 | ||
|
|
6252340804 | ||
|
|
517d67b2e0 | ||
|
|
e95b7ca3a0 | ||
|
|
c771d7c31a | ||
|
|
ce0e8d7497 | ||
|
|
852678e238 | ||
|
|
16e6eec3fb | ||
|
|
afe8552be6 | ||
|
|
cd0e50da24 | ||
|
|
85001c034b | ||
|
|
a56f6576e2 | ||
|
|
d3e5d05026 | ||
|
|
322b619a71 | ||
|
|
dff906ca69 | ||
|
|
515d1d5e63 | ||
|
|
bb6ed22594 | ||
|
|
d655e1d765 | ||
|
|
db70ed006d | ||
|
|
ce1dd5c632 | ||
|
|
9e2a253dda | ||
|
|
95c645865d | ||
|
|
ceb510bbf5 | ||
|
|
2590e3c99b | ||
|
|
f2f9cfaf28 | ||
|
|
62db8c3969 | ||
|
|
ae3db366e5 | ||
|
|
57570c144a | ||
|
|
c3a235242e | ||
|
|
b629eb5657 | ||
|
|
2e674cd0b3 | ||
|
|
3330e9a19a | ||
|
|
c5f6208396 | ||
|
|
c0d93bbcf4 | ||
|
|
db941e7007 | ||
|
|
4761857157 | ||
|
|
3aefe23184 | ||
|
|
6f852814fd | ||
|
|
b15e521b0e | ||
|
|
63c401e6d6 | ||
|
|
e59750e8de | ||
|
|
9c184ddfd0 | ||
|
|
9df6e821d8 | ||
|
|
9551dc5ecd | ||
|
|
d372daff60 | ||
|
|
f742e6e394 | ||
|
|
414b2b0e4c | ||
|
|
603c5692ae | ||
|
|
b35e994d1b | ||
|
|
abe2ab229a | ||
|
|
5ad9939bcf | ||
|
|
ce451128ba | ||
|
|
70470016cc | ||
|
|
2122ea77e1 | ||
|
|
69266cd6c6 | ||
|
|
062d61567e | ||
|
|
d6120fc908 | ||
|
|
91f8e7a07b | ||
|
|
f57d89245c | ||
|
|
c307a71f53 | ||
|
|
1e4e59bb57 | ||
|
|
f62d16d274 | ||
|
|
f175712d4b | ||
|
|
5f942d78e6 | ||
|
|
538c8885ad | ||
|
|
c8158c3d62 | ||
|
|
1f4762060f | ||
|
|
81c3682781 | ||
|
|
2e6e1fdd55 | ||
|
|
1a09cd560b | ||
|
|
8c9d2bc6f6 | ||
|
|
78ad5ca713 | ||
|
|
43c2e71b25 | ||
|
|
5b9f32fade | ||
|
|
76a1a6da34 | ||
|
|
a2b0abc90d | ||
|
|
0fd8e02a88 | ||
|
|
55c4bfb670 | ||
|
|
ea1030f8bf | ||
|
|
6dd285811a | ||
|
|
ee149ed1eb | ||
|
|
c3aa96d423 | ||
|
|
6e59d95da5 | ||
|
|
a396e74a79 | ||
|
|
80bdb39ae3 | ||
|
|
5cb1a9dcc6 | ||
|
|
1cfa81450c | ||
|
|
1f18fed3a2 | ||
|
|
33cb429e15 | ||
|
|
cfdbf02e6b | ||
|
|
f8c631a3f0 | ||
|
|
74911e9f6d | ||
|
|
0f453ae4cf | ||
|
|
febebc8d3d | ||
|
|
166c45f97f | ||
|
|
af58364fef | ||
|
|
eadf83d61b | ||
|
|
3c20231aad | ||
|
|
402bf395d1 | ||
|
|
9a45938fe6 | ||
|
|
d963e4a2c4 | ||
|
|
1063a67ae2 | ||
|
|
602ef883bb | ||
|
|
aad6042d42 | ||
|
|
85d8c1a97e | ||
|
|
547e6542ba | ||
|
|
f74044f9b0 | ||
|
|
42651707f8 | ||
|
|
95c13eaf5a | ||
|
|
c74068ae4d | ||
|
|
ca92dd0299 | ||
|
|
798f791b6b | ||
|
|
331622309f | ||
|
|
4f334525c2 | ||
|
|
82e704ec5b | ||
|
|
67aaa97904 | ||
|
|
4f55248a6c | ||
|
|
61b46f1a3e | ||
|
|
286104a988 | ||
|
|
8ea6ead08a | ||
|
|
bd9cc23681 | ||
|
|
f2d7298cf4 | ||
|
|
da636ca881 | ||
|
|
39bfa30185 | ||
|
|
d7c005a2f1 | ||
|
|
763b69bf5b | ||
|
|
2f2e353ece | ||
|
|
0092b7c0a4 | ||
|
|
9f48109640 | ||
|
|
b976adb8aa | ||
|
|
fe38c81e07 | ||
|
|
fed9bc7072 | ||
|
|
044e252d19 | ||
|
|
6920fb2793 | ||
|
|
3d1171de8d | ||
|
|
6e09754d06 | ||
|
|
32f2de17d4 | ||
|
|
600e8081a8 | ||
|
|
59fd7c3c9a | ||
|
|
7e70fe1126 | ||
|
|
5265c774ae | ||
|
|
d1421d720c | ||
|
|
2bd09d3b30 | ||
|
|
56e54ac820 | ||
|
|
08d85798ed | ||
|
|
38c2b36606 | ||
|
|
01b747287a | ||
|
|
c925e13e5a | ||
|
|
1ced89a869 | ||
|
|
a5e32dc3de | ||
|
|
150174c3bb | ||
|
|
601ee0b40b | ||
|
|
9627c3e7c8 | ||
|
|
d88c67eba3 | ||
|
|
bb38a90dda | ||
|
|
c36743f7ee | ||
|
|
860275f888 | ||
|
|
670228ff63 | ||
|
|
4338e4ef86 | ||
|
|
dbc712c53c | ||
|
|
bb6011ea73 | ||
|
|
1915f34de8 | ||
|
|
675f26fe90 | ||
|
|
491e309911 | ||
|
|
283d27c5b1 | ||
|
|
24d862c1bc | ||
|
|
3708c1ac8c | ||
|
|
df60be423a | ||
|
|
a1e583129f | ||
|
|
a06b28b693 | ||
|
|
198070700c | ||
|
|
3a01aa40d8 | ||
|
|
b628af2258 | ||
|
|
0cb5d0d63e | ||
|
|
526c85e2ca | ||
|
|
8a21c8e618 | ||
|
|
8d3d5747d2 | ||
|
|
f1f1406596 | ||
|
|
9e42be9884 | ||
|
|
75e75b93cf | ||
|
|
0e8ecbc9fc | ||
|
|
a88236b36f | ||
|
|
df06c54bd2 | ||
|
|
f2d88387c9 | ||
|
|
db4c6bbd3b | ||
|
|
c8e7f79f50 | ||
|
|
1157dc7dc8 | ||
|
|
c12833521f | ||
|
|
5d9346999e | ||
|
|
52c0631833 | ||
|
|
e16aefec2c | ||
|
|
053a247cc8 | ||
|
|
1426b7a6dc | ||
|
|
ec66949b35 | ||
|
|
bc9d8d1136 | ||
|
|
542a527d0d | ||
|
|
5e0c392287 | ||
|
|
05ff94941c | ||
|
|
a27d75d610 | ||
|
|
446e842904 | ||
|
|
ba153e2c18 | ||
|
|
3342ea6891 | ||
|
|
8c3d5fd295 | ||
|
|
5fc58fb10a | ||
|
|
4e2ae9cd4e | ||
|
|
4167ca2e5c | ||
|
|
9b3e9dcf02 | ||
|
|
f203fcc92e | ||
|
|
0b20069c20 | ||
|
|
bad7b778b3 | ||
|
|
f89ce93940 | ||
|
|
1ddbc8a26d | ||
|
|
0a3094fc9a | ||
|
|
816bbad28a | ||
|
|
ce4150cd06 | ||
|
|
be19b75031 | ||
|
|
3ddab5966b | ||
|
|
2d5c99f459 | ||
|
|
a5a1bbf5d7 | ||
|
|
c4af4e3297 | ||
|
|
1acfc05e2d | ||
|
|
b40c38f58c | ||
|
|
87c41cb9ac | ||
|
|
0ec715d7c9 | ||
|
|
e6a261a789 | ||
|
|
3bd2a91992 | ||
|
|
c721bc672c | ||
|
|
931b876b44 | ||
|
|
87b91e5023 | ||
|
|
4b1384be83 | ||
|
|
8da6e6a096 | ||
|
|
5181e575b4 | ||
|
|
ca994735be | ||
|
|
718c303086 | ||
|
|
7200c71673 | ||
|
|
14c97799c6 | ||
|
|
a06e8bfaee | ||
|
|
7dad60bbd5 | ||
|
|
a66b4626fb | ||
|
|
330add963d | ||
|
|
da1ccc620b | ||
|
|
c412c01a65 | ||
|
|
74d7fa61d9 | ||
|
|
ef6ea4484e | ||
|
|
ba2d775215 | ||
|
|
f866771854 | ||
|
|
70b8c57d22 | ||
|
|
b04e0d0fd4 | ||
|
|
3f9d5e11d1 | ||
|
|
09fe271b25 | ||
|
|
d5c1a49984 | ||
|
|
e80d3653c9 | ||
|
|
30b0d0a5cc | ||
|
|
9beceb9b02 | ||
|
|
6f13cabfba | ||
|
|
7bd2de9967 | ||
|
|
b0b0973e2d | ||
|
|
3d866e8975 | ||
|
|
63fb8d0392 | ||
|
|
384de0925e | ||
|
|
5b5c569c82 | ||
|
|
6f2371ee74 | ||
|
|
d6e7d90197 | ||
|
|
aa73db0fe6 | ||
|
|
d85088fc3d | ||
|
|
7e21aeedcd | ||
|
|
342460fa17 | ||
|
|
e57211fbd1 | ||
|
|
d31eb4c89c | ||
|
|
6753d260e4 | ||
|
|
a3092204a1 | ||
|
|
10b49af776 | ||
|
|
3497ced9f9 | ||
|
|
7a0f22b0a7 | ||
|
|
4f03272a5f | ||
|
|
7755936a2e | ||
|
|
9f6844ec30 | ||
|
|
c2952aa803 | ||
|
|
8f7383f5c2 | ||
|
|
750641ef19 | ||
|
|
fb48dfc082 | ||
|
|
1de5bce1c1 | ||
|
|
676603239d | ||
|
|
4c87f36a8c | ||
|
|
12b2137a04 | ||
|
|
762e1c9c2b | ||
|
|
cd26ead043 | ||
|
|
6a560cfec4 | ||
|
|
489ba72d5c | ||
|
|
5df9779669 | ||
|
|
e49d2f6b8f | ||
|
|
9550a7a954 | ||
|
|
d9f855b97e | ||
|
|
e275dae6e3 | ||
|
|
88ccc2a3b9 | ||
|
|
84487edc05 | ||
|
|
7177649969 | ||
|
|
18b7b3f125 | ||
|
|
89c7e1a8ee | ||
|
|
774a9b118e | ||
|
|
327841280b | ||
|
|
1e0a686561 | ||
|
|
96883100b4 | ||
|
|
1fcb05ed8c | ||
|
|
8c85516c57 | ||
|
|
6989a3eaad | ||
|
|
57796a2f96 | ||
|
|
59b217f7ea | ||
|
|
fb9a193c44 | ||
|
|
2739f1f3f0 | ||
|
|
0c2cb18578 | ||
|
|
db2c5aae84 | ||
|
|
aa2cec103b | ||
|
|
a532a70ac0 | ||
|
|
ec6cec8854 | ||
|
|
3fb22d27ab | ||
|
|
1cbaab5889 | ||
|
|
fef19b47c2 | ||
|
|
5126613825 | ||
|
|
07097d2fa3 | ||
|
|
8c9fb32ca0 | ||
|
|
68d921e918 | ||
|
|
330b36159d | ||
|
|
046152e798 | ||
|
|
11ca5bb7d5 | ||
|
|
e0838ff8ab | ||
|
|
11a2419c22 | ||
|
|
f3420c0adb | ||
|
|
bd84ff4838 | ||
|
|
87689df062 | ||
|
|
1bfbd57ee4 | ||
|
|
64d7585282 | ||
|
|
0ee03a565f | ||
|
|
1b0e268416 | ||
|
|
0e8d1afcaf | ||
|
|
48a33f08e2 | ||
|
|
f9ca956510 | ||
|
|
65a472c113 | ||
|
|
4b17ea04a7 | ||
|
|
423fdc0a96 | ||
|
|
396b124e84 | ||
|
|
6a27afa6ac | ||
|
|
b9812ba06a | ||
|
|
bc6aded074 | ||
|
|
904401617a | ||
|
|
02089f15c4 | ||
|
|
43a18a2569 | ||
|
|
4c2dc2bf16 | ||
|
|
e6eb2a8476 | ||
|
|
af5ae163f3 | ||
|
|
d00860430f | ||
|
|
af0b4a0fca | ||
|
|
404189f88c | ||
|
|
1a27fad9b9 | ||
|
|
c2cfe481df | ||
|
|
3a56fb6ec6 | ||
|
|
61950decb3 | ||
|
|
1a614ea023 | ||
|
|
a83b6a5e63 | ||
|
|
65d98af24c | ||
|
|
62d35627f3 | ||
|
|
84f1ed1587 | ||
|
|
31b4fb343d | ||
|
|
3c3f5c60da | ||
|
|
18914f2081 | ||
|
|
b50da2d8b7 | ||
|
|
5bdd699c9d | ||
|
|
29e8e6d95c | ||
|
|
049fc91615 | ||
|
|
b7c96f2cbd | ||
|
|
1e6408df13 | ||
|
|
7b90548c1d | ||
|
|
5d330e18ff | ||
|
|
07662ff076 | ||
|
|
9252ae1596 | ||
|
|
0155e9131d | ||
|
|
247cf40ace | ||
|
|
4a6b450c55 | ||
|
|
5b80d57a54 | ||
|
|
8ac4547e73 | ||
|
|
3658975b69 | ||
|
|
abc3545ef9 | ||
|
|
01f8cb698d | ||
|
|
5e4d0f45fc | ||
|
|
efd2f78274 | ||
|
|
690ff955fa | ||
|
|
3fb27bdc55 | ||
|
|
d8306fca6f | ||
|
|
380775540d | ||
|
|
65e3b0dafd | ||
|
|
4ae81d753c | ||
|
|
0f01aac823 | ||
|
|
ce0a96351e | ||
|
|
93dda6f1fd | ||
|
|
5e83db959e | ||
|
|
74436eb03e | ||
|
|
993178fc49 | ||
|
|
1c217cf446 | ||
|
|
0bf2be1f9d | ||
|
|
548589be4d | ||
|
|
697a1b1ed1 | ||
|
|
d893c7eb33 | ||
|
|
8957d24752 | ||
|
|
677e730235 | ||
|
|
4227d973b9 | ||
|
|
06c0af50c3 | ||
|
|
4d3a48d1c1 | ||
|
|
f6b66f4cad | ||
|
|
a56f9ab4e6 | ||
|
|
ca913e5077 | ||
|
|
b25ebe12c5 | ||
|
|
984980b170 | ||
|
|
be45005dbb | ||
|
|
b8c9f04989 | ||
|
|
bf2d41eb14 | ||
|
|
158f9afb37 | ||
|
|
f884e31d21 | ||
|
|
d3a5ff9d68 | ||
|
|
7185780d4e | ||
|
|
f995b2822f | ||
|
|
d7490ac738 | ||
|
|
383d0e17f2 | ||
|
|
7c1a3ab36e | ||
|
|
edc8d17031 | ||
|
|
f3f861234d | ||
|
|
93278c00b7 | ||
|
|
5bbe93d49f | ||
|
|
21cd8d31d7 | ||
|
|
d649b4df28 | ||
|
|
2bb9550343 | ||
|
|
ef0feff4a5 | ||
|
|
dfa43b4856 | ||
|
|
a24a1ca6d7 | ||
|
|
2d4b35fbc9 | ||
|
|
57e2910477 | ||
|
|
ffbaa7e4dc | ||
|
|
df42036100 | ||
|
|
ca9491d343 | ||
|
|
96ae569eaf | ||
|
|
fb295d53f1 | ||
|
|
95d07974f4 | ||
|
|
39d78064da | ||
|
|
a2bcbb90ed | ||
|
|
c31b37f570 | ||
|
|
2a1341b910 | ||
|
|
354e341d69 | ||
|
|
13946b2b76 | ||
|
|
29aa52df6a | ||
|
|
c3267a27d3 | ||
|
|
3543e6dd32 | ||
|
|
5412ba617d | ||
|
|
1f81a2cb1b | ||
|
|
5da58d42f6 | ||
|
|
299b6037c9 | ||
|
|
1ed8b9dd14 | ||
|
|
cf4912cb3d | ||
|
|
e6ec87f910 | ||
|
|
f72fb974a9 | ||
|
|
bdb25315b6 | ||
|
|
60f0739c3e | ||
|
|
0faab9277f | ||
|
|
51fce12cd7 | ||
|
|
d79290df75 | ||
|
|
0bf65bcad5 | ||
|
|
44dbf19e89 | ||
|
|
469a76f1f6 | ||
|
|
f851c272fa | ||
|
|
027a9fec61 | ||
|
|
09fde2f839 | ||
|
|
8a14e4261d | ||
|
|
6c9f1de265 | ||
|
|
3ad0179b62 | ||
|
|
81f33da499 | ||
|
|
80d70e64f5 | ||
|
|
eec4845cd0 | ||
|
|
b99a4ade1a | ||
|
|
84e25e8fd2 | ||
|
|
39e14eb95c | ||
|
|
f277d08244 | ||
|
|
d7c479fa6d | ||
|
|
44e5dc7d97 | ||
|
|
fdd54057a8 | ||
|
|
d43485141f | ||
|
|
2350561903 | ||
|
|
5674badccd | ||
|
|
a793f4414d | ||
|
|
e99957f99f | ||
|
|
ad5bbc463b | ||
|
|
81993cf2a3 | ||
|
|
5d40742ee6 | ||
|
|
1ce050d911 | ||
|
|
8e7393fc26 | ||
|
|
ad45205ddf | ||
|
|
409e9208ee | ||
|
|
d8811b499d | ||
|
|
dd1f9494f1 | ||
|
|
20f4538db4 | ||
|
|
d08c8e6edc | ||
|
|
f1667dbbe6 | ||
|
|
2bab7e2693 | ||
|
|
824497b97a | ||
|
|
0b7bece8e3 | ||
|
|
6ddf1a5786 | ||
|
|
b9827dfe02 | ||
|
|
64f30831ac | ||
|
|
bf5722cd25 | ||
|
|
ae074153c8 | ||
|
|
63d46dbdfb | ||
|
|
bdf1b23198 | ||
|
|
6f1c261f6b | ||
|
|
3233d5485f | ||
|
|
aa06400a50 | ||
|
|
30724bd7c4 | ||
|
|
0d3b389538 | ||
|
|
9f7dbe16fd | ||
|
|
432024123a | ||
|
|
261762448e | ||
|
|
7ce4175876 | ||
|
|
a57739c462 | ||
|
|
03bdbfa705 | ||
|
|
92246ce3a8 | ||
|
|
cdf74c2e41 | ||
|
|
4a72ea6666 | ||
|
|
f76d9b7908 | ||
|
|
dcfdf3a5d7 | ||
|
|
4873f61d6c | ||
|
|
1538107ae4 | ||
|
|
9b93dc5137 | ||
|
|
5ec721b978 | ||
|
|
24568c0e2f | ||
|
|
92a89ca258 | ||
|
|
ba71c53bc6 | ||
|
|
b3cfeb573a | ||
|
|
9083e99d2a | ||
|
|
70ca247c88 | ||
|
|
14fc0c735b | ||
|
|
70b3c8080e | ||
|
|
2c483c460a | ||
|
|
79405cf1d3 | ||
|
|
5c755fdd1c |
158
.debianinstall/README.md
Normal file
158
.debianinstall/README.md
Normal file
@@ -0,0 +1,158 @@
|
||||
|
||||
# How to use
|
||||
|
||||
## Disclaimers
|
||||
|
||||
- **This script does work with a fresh install of Debian 12 only**.
|
||||
- Do not use if you have already installed and configured a webserver or sql server that was not installed by this script.
|
||||
|
||||
### Keep it Simple and Stupid
|
||||
|
||||
The script keeps everything as simple as possible (KISS):
|
||||
|
||||
- Apache as webserver (there is no choice to use another webserver like nginx)
|
||||
- default PHP version of Debian
|
||||
- one single Hubzilla intance only
|
||||
- re-running the script does no harm
|
||||
|
||||
### When to use other Scripts
|
||||
|
||||
Use the scripts under [homeinstall](https://framagit.org/hubzilla/core/-/tree/master/.homeinstall)
|
||||
if you look for more choices. The main differences are:
|
||||
|
||||
- Apache or nginx as webserver
|
||||
- install multiple instances (domains) that run side by side on the server
|
||||
- adds apache vhosts (instead of using the standard doc root /var/www/html)
|
||||
- install PHP from https://packages.sury.org/php/ (instead of using the Debian repository)
|
||||
- graphical installer whiptail
|
||||
- The script stops (fails) if it finds results of a previous installation. (The [debian-setup.sh](https://framagit.org/ojrandom/core/-/tree/dev/.debianinstall) will just jump over it.)
|
||||
- If something fails the script tries to clean up everything that was installed up to the point of failure. (That might cause trouble if certbot registered a certificate already.)
|
||||
- The script under [homeinstall](https://framagit.org/hubzilla/core/-/tree/master/.homeinstall) seems to be an older version of the scripts used for Streams
|
||||
+ [autoinstall](https://codeberg.org/streams/streams/src/branch/dev/contrib/autoinstall)
|
||||
+ [easyinstall](https://codeberg.org/streams/streams/src/branch/dev/contrib/easyinstall)
|
||||
|
||||
## Preconditions
|
||||
|
||||
Hardware
|
||||
|
||||
+ internet connection and router at home
|
||||
+ computer connected to your router (a Raspberry 3 will do for very small Hubs)
|
||||
|
||||
Software
|
||||
|
||||
+ fresh installation of Debian 12 (bookworm)
|
||||
+ router with open ports 80 and 443 for your web server
|
||||
|
||||
You can of course run the script on a VPS or any distant server as long as the above sotfware requirements are satisfied.
|
||||
|
||||
## How to run the script
|
||||
|
||||
+ Register your own domain (for example at selfHOST) or a free subdomain (for example at freeDNS)
|
||||
+ Log on to your fresh Debian
|
||||
- apt-get install git
|
||||
- mkdir -p /var/www
|
||||
- cd /var/www
|
||||
- git clone https://framagit.org/hubzilla/core.git html
|
||||
- cd html/.debianinstall
|
||||
- cp config.txt.template config.txt
|
||||
- nano config.txt
|
||||
- read the comments carefully
|
||||
- enter your values: db pass, domain
|
||||
- (optionally) Enter your values for dyn DNS
|
||||
- ./debian-setup.sh as root
|
||||
- ... wait, wait, wait until the script is finished
|
||||
+ Open your domain with a browser and step throught the initial configuration of your hubzilla instance.
|
||||
- default database name = hubzilla
|
||||
- default dababase user = hubzilla
|
||||
|
||||
## Optional - Switch verification of email on/off
|
||||
|
||||
Do this just before you register the first user without email verification.
|
||||
|
||||
In a terminal
|
||||
|
||||
su -
|
||||
cd /var/www/html
|
||||
|
||||
Check the current setting
|
||||
|
||||
util/config system verify_email
|
||||
|
||||
Switch the verification off
|
||||
|
||||
util/config system verify_email 0
|
||||
|
||||
## What the script will do for you...
|
||||
|
||||
+ install everything required by your hubzilla instance, basically a web server (Apache), PHP, a database (MySQL), certbot,...
|
||||
+ create a database
|
||||
+ run certbot to have everything for a secure connection (httpS)
|
||||
+ create a script for daily maintenance
|
||||
- renew certfificate (letsencrypt)
|
||||
- update of your hubzilla instance for core and addons (git)
|
||||
- update of Debian
|
||||
- restart
|
||||
+ create cron jobs for
|
||||
- DynDNS (selfHOST.de or freedns.afraid.org) every 5 minutes
|
||||
- Master.php for your hubzilla instance every 10 minutes
|
||||
- daily maintenance script every day at 05:30
|
||||
|
||||
The script is known to work without adjustments with
|
||||
|
||||
+ Hardware
|
||||
- standard PC with Debian 12 (bookworm)
|
||||
- Raspberry 4 with Raspbian, Debian 12 (TODO: needs confirmation after swich to Debian12)
|
||||
- for tesing purposes: under localhost inside a virtual machine, [KVM](https://wiki.debian.org/KVM)
|
||||
+ DynDNS
|
||||
- selfHOST.de
|
||||
- freedns.afraid.org
|
||||
|
||||
# Step-by-Step - some Details
|
||||
|
||||
## Preparations
|
||||
|
||||
## Configure your Router
|
||||
|
||||
Your webserver has to be visible in the internet.
|
||||
|
||||
Open the ports 80 and 443 on your router for your Debian. Make sure your web server is marked as "exposed host".
|
||||
|
||||
## Preparations Dynamic IP Address
|
||||
|
||||
Follow the instructions in .debianinstall/config.txt.
|
||||
|
||||
In short...
|
||||
|
||||
Your Hubzilla server must be reachable by a domain that you can type in your browser
|
||||
|
||||
cooldomain.org
|
||||
|
||||
You can use subdomains as well
|
||||
|
||||
my.cooldomain.org
|
||||
|
||||
There are two ways to get a domain...
|
||||
|
||||
### Method 1: Buy a Domain
|
||||
|
||||
...for example buy at selfHOST.de
|
||||
|
||||
The cost is 1,50 € per month (2019).
|
||||
|
||||
### Method 2: Register a free subdomain
|
||||
|
||||
...for example register at freedns.afraid.org
|
||||
|
||||
## Note on Rasperry
|
||||
|
||||
It is recommended to run the Raspi without graphical frontend (X-Server). Use...
|
||||
|
||||
sudo raspi-config
|
||||
|
||||
to boot the Rapsi to the client console.
|
||||
|
||||
DO NOT FORGET TO CHANGE THE DEFAULT PASSWORD FOR USER PI!
|
||||
|
||||
## Reminder for Different Web Wervers
|
||||
|
||||
For those of you who feel adventurous enough to use a different web server (i.e. Lighttpd...), don't forget that this script will install Apache or Nginx and that you can only have one web server listening to ports 80 & 443. Also, don't forget to tweak your daily shell script in /var/www/ accordingly.
|
||||
111
.debianinstall/config.txt.template
Normal file
111
.debianinstall/config.txt.template
Normal file
@@ -0,0 +1,111 @@
|
||||
|
||||
###############################################
|
||||
### MANDATORY - database password #############
|
||||
#
|
||||
# Please give your database password
|
||||
# It is better to not use blanks inside the password.
|
||||
# Example: db_pass=pass_word_with_no_blanks_in_it
|
||||
db_pass=
|
||||
|
||||
###############################################
|
||||
### MANDATORY - let's encrypt #################
|
||||
#
|
||||
# Zot requires encrypted communication via secure HTTP (HTTPS).
|
||||
# This script automates installation of an SSL certificate from
|
||||
# Let's Encrypt (https://letsencrypt.org)
|
||||
#
|
||||
# Please give the domain name of your hub/instance
|
||||
#
|
||||
# Example: my.cooldomain.org
|
||||
# Example: cooldomain.org
|
||||
#
|
||||
# You might use "localhost" for a LOCAL TEST installation.
|
||||
# This is usefull if you want to debug the server inside a VM.
|
||||
#
|
||||
# Example: localhost
|
||||
#
|
||||
# Email is optional if you use "localhost".
|
||||
#
|
||||
#
|
||||
le_domain=
|
||||
le_email=
|
||||
|
||||
|
||||
###############################################
|
||||
### OPTIONAL - selfHOST - dynamic IP address ##
|
||||
#
|
||||
# 1. Register a domain at selfhost.de
|
||||
# - choose offer "DOMAIN dynamisch" 1,50€/mon at 04/2019
|
||||
# 2. Get your configuration for dynamic IP update
|
||||
# - Log in at selfhost.de
|
||||
# - go to "DynDNS Accounte"
|
||||
# - klick "Details" of your (freshly) registered domain
|
||||
# - You will find the configuration there
|
||||
# - Benutzername (user name) > use this for "selfhost_user="
|
||||
# - Passwort (pass word) > use this for "selfhost_pass="
|
||||
#
|
||||
#
|
||||
selfhost_user=
|
||||
selfhost_pass=
|
||||
|
||||
###############################################
|
||||
### OPTIONAL - FreeDNS - dynamic IP address ###
|
||||
#
|
||||
# Please give the alpha-numeric-key of freedns
|
||||
#
|
||||
# Get a free subdomain from freedns and use it for your dynamic ip address
|
||||
# Documentation under http://www.techjawab.com/2013/06/setup-dynamic-dns-dyndns-for-free-on.html
|
||||
#
|
||||
# - Register for a Free domain at http://freedns.afraid.org/signup/
|
||||
# - WATCH THIS: Make sure you choose a domain with as less subdomains as
|
||||
# possible. Why? Let's encrpyt issues a limited count of certificates each
|
||||
# day. Possible other users of this domain will try to issue a certificate
|
||||
# at the same day.
|
||||
# - Logon to FreeDNS (where you just registered)
|
||||
# - Goto http://freedns.afraid.org/dynamic/
|
||||
# - Right click on "Direct Link" and copy the URL and paste it somewhere.
|
||||
# - You should notice a large and unique alpha-numeric key in the URL
|
||||
#
|
||||
# http://freedns.afraid.org/dynamic/update.php?alpha-numeric-key
|
||||
#
|
||||
# Provided your url from freedns is
|
||||
#
|
||||
# http://freedns.afraid.org/dynamic/update.php?U1Z6aGt2R0NzMFNPNWRjbWxxZGpsd093OjE1Mzg5NDE5
|
||||
#
|
||||
# Then you have to provide
|
||||
#
|
||||
# freedns_key=U1Z6aGt2R0NzMFNPNWRjbWxxZGpsd093OjE1Mzg5NDE5
|
||||
#
|
||||
#
|
||||
freedns_key=
|
||||
|
||||
|
||||
###############################################
|
||||
### OPTIONAL - do not mess with things below ##
|
||||
# (...if you are not certain)
|
||||
#
|
||||
# Usually you are done here
|
||||
# Everything below is OPTIONAL
|
||||
#
|
||||
###############################################
|
||||
#
|
||||
# Database for your hub/instance
|
||||
# If left empty, both your database and user will be named after your zot instance (hubzilla, zap or misty)
|
||||
# Use custom name, at least fo the database, if you plan to run more than one hub/instance on the same server
|
||||
#
|
||||
zotserver_db_name=
|
||||
zotserver_db_user=
|
||||
zotserver_db_pass=$db_pass
|
||||
#
|
||||
#
|
||||
# Password for package mysql-server
|
||||
# Example: mysqlpass=aberhallo
|
||||
# Example: mysqlpass="aber hallo has blanks in it"
|
||||
#
|
||||
mysqlpass=$db_pass
|
||||
|
||||
# Password for package phpmyadmin
|
||||
# Example: phpmyadminpass=aberhallo
|
||||
# Example: phpmyadminpass="aber hallo has blanks in it"
|
||||
phpmyadminpass=$db_pass
|
||||
|
||||
527
.debianinstall/debian-setup.sh
Normal file
527
.debianinstall/debian-setup.sh
Normal file
@@ -0,0 +1,527 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# How to use
|
||||
# ----------
|
||||
#
|
||||
# This file automates the installation of hubzilla: https://framagit.org/hubzilla/core
|
||||
# under Debian Linux "bookworm"
|
||||
#
|
||||
# 1) Copy the file "config.txt.template" to "config.txt"
|
||||
# Follow the instuctions there
|
||||
#
|
||||
# 2) Switch to user "root" by typing "su -"
|
||||
#
|
||||
# 3) Run with "./debian-setup.sh"
|
||||
# If this fails check if you can execute the script.
|
||||
# - To make it executable type "chmod +x debian-setup.sh"
|
||||
# - or run "bash debian-setup.sh"
|
||||
#
|
||||
#
|
||||
# What does this script do basically?
|
||||
# -----------------------------------
|
||||
#
|
||||
# This file automates the installation of a Hubzilla instance under Debian Linux
|
||||
# - install
|
||||
# * apache webserver,
|
||||
# * php,
|
||||
# * mariadb,
|
||||
# * adminer,
|
||||
# * addons
|
||||
# - configure cron
|
||||
# * "Master.php" for regular background processes of your hubzilla instance
|
||||
# * "apt-get update" and "apt-get dist-upgrade" and "apt-get autoremove" to keep linux up-to-date
|
||||
# * run command to keep the IP up-to-date > DynDNS provided by selfHOST.de or freedns.afraid.org
|
||||
# - run letsencrypt to create, register and use a certifacte for https
|
||||
#
|
||||
#
|
||||
# Credits
|
||||
# -------
|
||||
#
|
||||
# The script is derived from the easyinstall script of the Streams repository, which is based on
|
||||
# - Tom Wiedenhöfts (OJ Random) script homeinstall (for Hubzilla, ZAP,...) that was based on
|
||||
# - Thomas Willinghams script "debian-setup.sh" which he used to install the red#matrix.
|
||||
|
||||
function check_sanity {
|
||||
# Do some sanity checking.
|
||||
print_info "Sanity check..."
|
||||
if [ $(/usr/bin/id -u) != "0" ]
|
||||
then
|
||||
die 'Must be run by root user'
|
||||
fi
|
||||
|
||||
if [ -f /etc/lsb-release ]
|
||||
then
|
||||
die "Distribution is not supported"
|
||||
fi
|
||||
if [ ! -f /etc/debian_version ]
|
||||
then
|
||||
die "Debian is supported only"
|
||||
fi
|
||||
if ! grep -q 'Linux 12' /etc/issue
|
||||
then
|
||||
die "Linux 12 (bookworm) is supported only"x
|
||||
fi
|
||||
}
|
||||
|
||||
function check_config {
|
||||
print_info "config check..."
|
||||
# Check for required parameters
|
||||
if [ -z "$db_pass" ]
|
||||
then
|
||||
die "db_pass not set in $configfile"
|
||||
fi
|
||||
if [ -z "$le_domain" ]
|
||||
then
|
||||
die "le_domain not set in $configfile"
|
||||
fi
|
||||
}
|
||||
|
||||
function die {
|
||||
echo "ERROR: $1" > /dev/null 1>&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
|
||||
function update_upgrade {
|
||||
print_info "updated and upgrade..."
|
||||
# Run through the apt-get update/upgrade first. This should be done before
|
||||
# we try to install any package
|
||||
apt-get -q -y update && apt-get -q -y dist-upgrade && apt-get -q -y autoremove
|
||||
print_info "updated and upgraded linux"
|
||||
}
|
||||
|
||||
function nocheck_install {
|
||||
# export DEBIAN_FRONTEND=noninteractive ... answers from the package configuration database
|
||||
# - q ... without progress information
|
||||
# - y ... answer interactive questions with "yes"
|
||||
# DEBIAN_FRONTEND=noninteractive apt-get --no-install-recommends -q -y install $2
|
||||
# DEBIAN_FRONTEND=noninteractive apt-get --install-suggests -q -y install $1
|
||||
DEBIAN_FRONTEND=noninteractive apt-get -q -y install $1
|
||||
print_info "installed $1"
|
||||
}
|
||||
|
||||
|
||||
function print_info {
|
||||
echo -n -e '\e[1;34m'
|
||||
echo -n $1
|
||||
echo -e '\e[0m'
|
||||
}
|
||||
|
||||
function print_warn {
|
||||
echo -n -e '\e[1;31m'
|
||||
echo -n $1
|
||||
echo -e '\e[0m'
|
||||
}
|
||||
|
||||
function stop_zotserver {
|
||||
print_info "stopping apache..."
|
||||
systemctl stop apache2
|
||||
print_info "stopping mysql db..."
|
||||
systemctl stop mariadb
|
||||
}
|
||||
|
||||
function install_apache {
|
||||
print_info "installing apache..."
|
||||
nocheck_install "apache2 apache2-utils"
|
||||
a2enmod rewrite
|
||||
systemctl restart apache2
|
||||
}
|
||||
|
||||
function install_imagemagick {
|
||||
print_info "installing imagemagick..."
|
||||
nocheck_install "imagemagick"
|
||||
}
|
||||
|
||||
function install_curl {
|
||||
print_info "installing curl..."
|
||||
nocheck_install "curl"
|
||||
}
|
||||
|
||||
function install_wget {
|
||||
print_info "installing wget..."
|
||||
nocheck_install "wget"
|
||||
}
|
||||
|
||||
function install_sendmail {
|
||||
print_info "installing sendmail..."
|
||||
nocheck_install "sendmail sendmail-bin"
|
||||
}
|
||||
|
||||
function install_php {
|
||||
# openssl and mbstring are included in libapache2-mod-php
|
||||
print_info "installing php..."
|
||||
nocheck_install "libapache2-mod-php php php-pear php-curl php-gd php-mbstring php-xml php-zip"
|
||||
phpversion=$(php -v|grep --only-matching --perl-regexp "(PHP )\d+\.\\d+\.\\d+"|cut -c 5-7)
|
||||
sed -i "s/^upload_max_filesize =.*/upload_max_filesize = 100M/g" /etc/php/$phpversion/apache2/php.ini
|
||||
sed -i "s/^post_max_size =.*/post_max_size = 100M/g" /etc/php/$phpversion/apache2/php.ini
|
||||
}
|
||||
|
||||
function install_composer {
|
||||
print_info "We check if Composer is already downloaded"
|
||||
if [ ! -f /usr/local/bin/composer ]
|
||||
then
|
||||
EXPECTED_CHECKSUM="$(php -r 'copy("https://composer.github.io/installer.sig", "php://stdout");')"
|
||||
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
|
||||
ACTUAL_CHECKSUM="$(php -r "echo hash_file('sha384', 'composer-setup.php');")"
|
||||
if [ "$EXPECTED_CHECKSUM" != "$ACTUAL_CHECKSUM" ]
|
||||
then
|
||||
>&2 echo 'ERROR: Invalid installer checksum'
|
||||
rm composer-setup.php
|
||||
die 'ERROR: Invalid installer checksum'
|
||||
fi
|
||||
php composer-setup.php --quiet
|
||||
RESULT=$?
|
||||
rm composer-setup.php
|
||||
# exit $RESULT
|
||||
# We install Composer globally
|
||||
mv composer.phar /usr/local/bin/composer
|
||||
print_info "Composer was successfully downloaded."
|
||||
else
|
||||
print_info "Composer is already downloaded on this system."
|
||||
fi
|
||||
cd $install_path
|
||||
export COMPOSER_ALLOW_SUPERUSER=1;
|
||||
/usr/local/bin/composer install --no-dev
|
||||
/usr/local/bin/composer show
|
||||
export COMPOSER_ALLOW_SUPERUSER=0;
|
||||
}
|
||||
|
||||
|
||||
function install_mysql {
|
||||
print_info "installing mysql..."
|
||||
if [ -z "$mysqlpass" ]
|
||||
then
|
||||
die "mysqlpass not set in $configfile"
|
||||
fi
|
||||
if type mysql ; then
|
||||
echo "Yes, mysql is installed"
|
||||
else
|
||||
echo "mariadb-server"
|
||||
nocheck_install "mariadb-server"
|
||||
systemctl status mariadb
|
||||
systemctl start mariadb
|
||||
mysql --user=root <<_EOF_
|
||||
UPDATE mysql.user SET Password=PASSWORD('${mysqlpass}') WHERE User='root';
|
||||
DELETE FROM mysql.user WHERE User='';
|
||||
DROP DATABASE IF EXISTS test;
|
||||
DELETE FROM mysql.db WHERE Db='test' OR Db='test\\_%';
|
||||
FLUSH PRIVILEGES;
|
||||
_EOF_
|
||||
fi
|
||||
}
|
||||
|
||||
function install_adminer {
|
||||
print_info "installing adminer..."
|
||||
nocheck_install "adminer"
|
||||
if [ ! -f /etc/adminer/adminer.conf ]
|
||||
then
|
||||
echo "Alias /adminer /usr/share/adminer/adminer" > /etc/adminer/adminer.conf
|
||||
ln -s /etc/adminer/adminer.conf /etc/apache2/conf-available/adminer.conf
|
||||
else
|
||||
print_info "file /etc/adminer/adminer.conf exists already"
|
||||
fi
|
||||
|
||||
a2enmod rewrite
|
||||
|
||||
if [ ! -f /etc/apache2/apache2.conf ]
|
||||
then
|
||||
die "could not find file /etc/apache2/apache2.conf"
|
||||
fi
|
||||
sed -i \
|
||||
"s/AllowOverride None/AllowOverride all/" \
|
||||
/etc/apache2/apache2.conf
|
||||
|
||||
a2enconf adminer
|
||||
systemctl restart mariadb
|
||||
systemctl reload apache2
|
||||
}
|
||||
|
||||
function create_zotserver_db {
|
||||
print_info "creating zotserver database..."
|
||||
if [ -z "$db_name" ]
|
||||
then
|
||||
die "db_name not set in $configfile"
|
||||
fi
|
||||
if [ -z "$db_user" ]
|
||||
then
|
||||
die "db_user not set in $configfile"
|
||||
fi
|
||||
if [ -z "$db_pass" ]
|
||||
then
|
||||
die "db_pass not set in $configfile"
|
||||
fi
|
||||
systemctl restart mariadb
|
||||
# Make sure we don't write over an already existing database if we install more than one Zot hub/instance
|
||||
if [ -z $(mysql -h localhost -u root -p$mysqlpass -e "SHOW DATABASES;" | grep $db_name) ]
|
||||
then
|
||||
Q1="CREATE DATABASE IF NOT EXISTS $db_name;"
|
||||
Q2="GRANT USAGE ON *.* TO $db_user@localhost IDENTIFIED BY '$db_pass';"
|
||||
Q3="GRANT ALL PRIVILEGES ON $name.* to $db_user@localhost identified by '$db_pass';"
|
||||
Q4="FLUSH PRIVILEGES;"
|
||||
SQL="${Q1}${Q2}${Q3}${Q4}"
|
||||
mysql -uroot -p$mysqlpass -e "$SQL"
|
||||
else
|
||||
echo "database $db_name does exist already"
|
||||
fi
|
||||
}
|
||||
|
||||
function run_freedns {
|
||||
print_info "run freedns (dynamic IP)..."
|
||||
if [ -z "$freedns_key" ]
|
||||
then
|
||||
print_info "freedns was not started because 'freedns_key' is empty in $configfile"
|
||||
else
|
||||
if [ -n "$selfhost_user" ]
|
||||
then
|
||||
die "You can not use freeDNS AND selfHOST for dynamic IP updates ('freedns_key' AND 'selfhost_user' set in $configfile)"
|
||||
fi
|
||||
wget --no-check-certificate -O - http://freedns.afraid.org/dynamic/update.php?$freedns_key
|
||||
fi
|
||||
}
|
||||
|
||||
function install_run_selfhost {
|
||||
print_info "install and start selfhost (dynamic IP)..."
|
||||
if [ -z "$selfhost_user" ]
|
||||
then
|
||||
print_info "selfHOST was not started because 'selfhost_user' is empty in $configfile"
|
||||
else
|
||||
if [ -n "$freedns_key" ]
|
||||
then
|
||||
die "You can not use freeDNS AND selfHOST for dynamic IP updates ('freedns_key' AND 'selfhost_user' set in $configfile)"
|
||||
fi
|
||||
if [ -z "$selfhost_pass" ]
|
||||
then
|
||||
die "selfHOST was not started because 'selfhost_pass' is empty in $configfile"
|
||||
fi
|
||||
if [ ! -d $selfhostdir ]
|
||||
then
|
||||
mkdir $selfhostdir
|
||||
fi
|
||||
# the old way
|
||||
# https://carol.selfhost.de/update?username=123456&password=supersafe
|
||||
#
|
||||
# the prefered way
|
||||
wget --output-document=$selfhostdir/$selfhostscript http://jonaspasche.de/selfhost-updater
|
||||
echo "router" > $selfhostdir/device
|
||||
echo "$selfhost_user" > $selfhostdir/user
|
||||
echo "$selfhost_pass" > $selfhostdir/pass
|
||||
bash $selfhostdir/$selfhostscript update
|
||||
fi
|
||||
}
|
||||
|
||||
function ping_domain {
|
||||
print_info "ping domain $domain..."
|
||||
# Is the domain resolved? Try to ping 6 times à 10 seconds
|
||||
COUNTER=0
|
||||
for i in {1..6}
|
||||
do
|
||||
print_info "loop $i for ping -c 1 $domain ..."
|
||||
if ping -c 4 -W 1 $le_domain
|
||||
then
|
||||
print_info "$le_domain resolved"
|
||||
break
|
||||
else
|
||||
if [ $i -gt 5 ]
|
||||
then
|
||||
die "Failed to: ping -c 1 $domain not resolved"
|
||||
fi
|
||||
fi
|
||||
sleep 10
|
||||
done
|
||||
sleep 5
|
||||
}
|
||||
|
||||
function configure_cron_freedns {
|
||||
print_info "configure cron for freedns..."
|
||||
if [ -z "$freedns_key" ]
|
||||
then
|
||||
print_info "freedns is not configured because freedns_key is empty in $configfile"
|
||||
else
|
||||
# Use cron for dynamich ip update
|
||||
# - at reboot
|
||||
# - every 30 minutes
|
||||
if [ -z "`grep 'freedns.afraid.org' /etc/crontab`" ]
|
||||
then
|
||||
echo "@reboot root http://freedns.afraid.org/dynamic/update.php?$freedns_key > /dev/null 2>&1" >> /etc/crontab
|
||||
echo "*/30 * * * * root wget --no-check-certificate -O - http://freedns.afraid.org/dynamic/update.php?$freedns_key > /dev/null 2>&1" >> /etc/crontab
|
||||
else
|
||||
print_info "cron for freedns was configured already"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
function configure_cron_selfhost {
|
||||
print_info "configure cron for selfhost..."
|
||||
if [ -z "$selfhost_user" ]
|
||||
then
|
||||
print_info "selfhost is not configured because selfhost_key is empty in $configfile"
|
||||
else
|
||||
# Use cron for dynamich ip update
|
||||
# - at reboot
|
||||
# - every 5 minutes
|
||||
if [ -z "`grep 'selfhost-updater.sh' /etc/crontab`" ]
|
||||
then
|
||||
echo "@reboot root bash /etc/selfhost/selfhost-updater.sh update > /dev/null 2>&1" >> /etc/crontab
|
||||
echo "*/5 * * * * root /bin/bash /etc/selfhost/selfhost-updater.sh update > /dev/null 2>&1" >> /etc/crontab
|
||||
else
|
||||
print_info "cron for selfhost was configured already"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
function install_letsencrypt {
|
||||
print_info "installing let's encrypt ..."
|
||||
# check if user gave domain
|
||||
if [ -z "$le_domain" ]
|
||||
then
|
||||
die "Failed to install let's encrypt: 'le_domain' is empty in $configfile"
|
||||
fi
|
||||
if [ -z "$le_email" ]
|
||||
then
|
||||
die "Failed to install let's encrypt: 'le_email' is empty in $configfile"
|
||||
fi
|
||||
nocheck_install "certbot python-certbot-apache"
|
||||
print_info "run certbot ..."
|
||||
certbot --apache -w $install_path -d $le_domain -m $le_email --agree-tos --non-interactive --redirect --hsts --uir
|
||||
service apache2 restart
|
||||
}
|
||||
|
||||
function check_https {
|
||||
print_info "checking httpS > testing ..."
|
||||
url_https=https://$le_domain
|
||||
wget_output=$(wget -nv --spider --max-redirect 0 $url_https)
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
print_warn "check not ok"
|
||||
else
|
||||
print_info "check ok"
|
||||
fi
|
||||
}
|
||||
|
||||
function install_zotserver {
|
||||
print_info "installing addons..."
|
||||
cd $install_path
|
||||
util/add_addon_repo https://framagit.org/hubzilla/addons hzaddons
|
||||
mkdir -p "store/[data]/smarty3"
|
||||
# chmod -R 777 store
|
||||
touch .htconfig.php
|
||||
# The next run of $cron_job (daily-update script) will correct the permissions of the next line
|
||||
chmod ou+w .htconfig.php
|
||||
cd /var/www/
|
||||
chown -R www-data:www-data $install_path
|
||||
chown root:www-data $install_path/
|
||||
chown root:www-data $install_path/.htaccess
|
||||
chmod 0644 $install_path/.htaccess
|
||||
print_info "installed addons"
|
||||
}
|
||||
|
||||
function configure_cron_daily {
|
||||
print_info "configuring cron..."
|
||||
# every 10 min for poller.php
|
||||
if [ -z "`grep 'php Zotlabs/Daemon/Master.php' /etc/crontab`" ]
|
||||
then
|
||||
echo "*/10 * * * * www-data cd $install_path; php Zotlabs/Daemon/Master.php Cron >> /dev/null 2>&1" >> /etc/crontab
|
||||
fi
|
||||
# Run external script daily at 05:30
|
||||
# - stop apache/nginx and mysql-server
|
||||
# - renew the certificate of letsencrypt
|
||||
# - update repository core and addon
|
||||
# - update and upgrade linux
|
||||
# - reboot is done by "shutdown -h now" because "reboot" hangs sometimes depending on the system
|
||||
echo "#!/bin/sh" > /var/www/$cron_job
|
||||
echo "#" >> /var/www/$cron_job
|
||||
echo "echo \" \"" >> /var/www/$cron_job
|
||||
echo "echo \"+++ \$(date) +++\"" >> /var/www/$cron_job
|
||||
echo "echo \" \"" >> /var/www/$cron_job
|
||||
echo "echo \"\$(date) - stopping apache and mysql...\"" >> /var/www/$cron_job
|
||||
echo "service apache2 stop" >> /var/www/$cron_job
|
||||
echo "/etc/init.d/mysql stop # to avoid inconsistencies" >> /var/www/$cron_job
|
||||
echo "#" >> /var/www/$cron_job
|
||||
echo "echo \"\$(date) - renew certificate...\"" >> /var/www/$cron_job
|
||||
echo "certbot renew --noninteractive" >> /var/www/$cron_job
|
||||
echo "#" >> /var/www/$cron_job
|
||||
echo "echo \"\$(date) - db size...\"" >> /var/www/$cron_job
|
||||
echo "du -h /var/lib/mysql/ | grep mysql/" >> /var/www/$cron_job
|
||||
echo "#" >> /var/www/$cron_job
|
||||
echo "# update of $le_domain Zot hub/instance" >> /var/www/$cron_job
|
||||
echo "echo \"\$(date) - updating core and addons...\"" >> /var/www/$cron_job
|
||||
echo "echo \"reaching git repository for $le_domain $zotserver hub/instance...\"" >> /var/www/$cron_job
|
||||
echo "(cd $install_path ; util/udall)" >> /var/www/$cron_job
|
||||
echo "chown -R www-data:www-data $install_path # make all accessible for the webserver" >> /var/www/$cron_job
|
||||
echo "chown root:www-data $install_path/.htaccess" >> /var/www/$cron_job
|
||||
echo "chmod 0644 $install_path/.htaccess # www-data can read but not write it" >> /var/www/$cron_job
|
||||
echo "echo \"\$(date) - updating linux...\"" >> /var/www/$cron_job
|
||||
echo "apt-get -q -y update && apt-get -q -y dist-upgrade && apt-get -q -y autoremove # update linux and upgrade" >> /var/www/$cron_job
|
||||
echo "echo \"\$(date) - Update finished. Rebooting...\"" >> /var/www/$cron_job
|
||||
echo "#" >> /var/www/$cron_job
|
||||
echo "shutdown -r now" >> /var/www/$cron_job
|
||||
|
||||
chmod a+x /var/www/$cron_job
|
||||
|
||||
# If global cron job does not exist we add it to /etc/crontab
|
||||
if grep -q $cron_job /etc/crontab
|
||||
then
|
||||
echo "cron job already in /etc/crontab"
|
||||
else
|
||||
echo "30 05 * * * root /bin/bash /var/www/$cron_job >> /var/www/daily-updates.log 2>&1" >> /etc/crontab
|
||||
echo "0 0 1 * * root rm /var/www/daily-updates.log" >> /etc/crontab
|
||||
fi
|
||||
|
||||
# This is active after either "reboot" or cron reload"
|
||||
systemctl restart cron
|
||||
print_info "configured cron for updates/upgrades"
|
||||
}
|
||||
|
||||
########################################################################
|
||||
# START OF PROGRAM
|
||||
########################################################################
|
||||
export PATH=/bin:/usr/bin:/sbin:/usr/sbin
|
||||
check_sanity
|
||||
|
||||
print_info "We're installing a $zotserver instance"
|
||||
install_path="$(dirname "$(pwd)")"
|
||||
|
||||
# Read config file edited by user
|
||||
configfile=config.txt
|
||||
source $configfile
|
||||
|
||||
selfhostdir=/etc/selfhost
|
||||
selfhostscript=selfhost-updater.sh
|
||||
cron_job="cron_job.sh"
|
||||
|
||||
#set -x # activate debugging from here
|
||||
|
||||
zotserver=hubzilla
|
||||
check_config
|
||||
stop_zotserver
|
||||
update_upgrade
|
||||
install_curl
|
||||
install_wget
|
||||
install_sendmail
|
||||
install_apache
|
||||
install_imagemagick
|
||||
install_php
|
||||
install_composer
|
||||
install_mysql
|
||||
install_adminer
|
||||
create_zotserver_db
|
||||
run_freedns
|
||||
install_run_selfhost
|
||||
ping_domain
|
||||
configure_cron_freedns
|
||||
configure_cron_selfhost
|
||||
|
||||
if [ "$le_domain" != "localhost" ]
|
||||
then
|
||||
install_letsencrypt
|
||||
check_https
|
||||
else
|
||||
print_info "is localhost - skipped installation of letsencrypt and configuration of apache for https"
|
||||
fi
|
||||
|
||||
install_zotserver
|
||||
|
||||
configure_cron_daily
|
||||
|
||||
|
||||
#set +x # stop debugging from here
|
||||
33
.gitignore
vendored
33
.gitignore
vendored
@@ -49,6 +49,8 @@ doc/html/
|
||||
# external repositories for themes/addons
|
||||
extend/
|
||||
# files generated by phpunit
|
||||
tests/.cache
|
||||
tests/.phpunit.result.cache
|
||||
tests/results/
|
||||
|
||||
## exclude IDE files
|
||||
@@ -78,5 +80,36 @@ composer.phar
|
||||
vendor/**/tests/
|
||||
vendor/**/Test/
|
||||
vendor/sabre/*/examples/
|
||||
|
||||
# Exclude dev dependencies
|
||||
vendor/bin/pdepend
|
||||
vendor/bin/php-parse
|
||||
vendor/bin/phpcbf
|
||||
vendor/bin/phpcs
|
||||
vendor/bin/phpmd
|
||||
vendor/bin/phpunit
|
||||
vendor/composer/pcre/
|
||||
vendor/composer/xdebug-handler/
|
||||
vendor/dms/
|
||||
vendor/doctrine/
|
||||
vendor/myclabs/
|
||||
vendor/nikic/
|
||||
vendor/pdepend/
|
||||
vendor/phar-io/
|
||||
vendor/php-mock/
|
||||
vendor/phpmd/
|
||||
vendor/phpunit/
|
||||
vendor/psr/container/
|
||||
vendor/sebastian/
|
||||
vendor/squizlabs/
|
||||
vendor/symfony/config/
|
||||
vendor/symfony/dependency-injection/
|
||||
vendor/symfony/deprecation-contracts/
|
||||
vendor/symfony/filesystem/
|
||||
vendor/symfony/polyfill-ctype/
|
||||
vendor/symfony/polyfill-mbstring/
|
||||
vendor/symfony/polyfill-php80/
|
||||
vendor/symfony/service-contracts/
|
||||
vendor/theseer/
|
||||
# /info is a directory containing site-specific HTML documents
|
||||
/info/
|
||||
|
||||
178
.gitlab-ci.yml
178
.gitlab-ci.yml
@@ -1,10 +1,3 @@
|
||||
# Select image from https://hub.docker.com/_/php/
|
||||
#image: php:7.3
|
||||
# Use a prepared Hubzilla image to optimise pipeline duration
|
||||
# image: registry.gitlab.com/dawnbreak/hubzilla/core:php7.3
|
||||
|
||||
image: php:8.1
|
||||
|
||||
stages:
|
||||
- test
|
||||
- deploy
|
||||
@@ -24,6 +17,7 @@ variables:
|
||||
# Ignore a Composer warning
|
||||
COMPOSER_ALLOW_SUPERUSER: 1
|
||||
# Configure MySQL/MariaDB service (https://hub.docker.com/_/mysql/, https://hub.docker.com/_/mariadb/)
|
||||
DB_HOST: mysql
|
||||
MYSQL_DATABASE: hello_world_test
|
||||
MYSQL_ROOT_PASSWORD: mysql
|
||||
# Configure PostgreSQL service (https://hub.docker.com/_/postgres/)
|
||||
@@ -33,59 +27,69 @@ variables:
|
||||
|
||||
|
||||
before_script:
|
||||
# pecl and composer do not work with PHP production restrictions (from Hubzilla Docker image)
|
||||
- if [ -f /usr/local/etc/php/conf.d/z_prod.ini ]; then mv /usr/local/etc/php/conf.d/z_prod.ini /usr/local/etc/php/conf.d/z_prod.ini.off; fi
|
||||
# Install & enable Xdebug for code coverage reports
|
||||
- pecl install xdebug
|
||||
- apt-get update
|
||||
- apt-get install zip unzip libjpeg-dev libpng-dev -yqq
|
||||
- docker-php-ext-enable xdebug
|
||||
- docker-php-ext-install gd
|
||||
|
||||
|
||||
# Install composer
|
||||
- curl -sS https://getcomposer.org/installer | php
|
||||
# Install dev libraries from composer
|
||||
- php ./composer.phar install --no-progress
|
||||
# php.ini settings
|
||||
- echo 'xdebug.mode=coverage' >> /usr/local/etc/php/php.ini
|
||||
|
||||
# hidden job definition with template for PHP
|
||||
.job_template_php: &job_definition_php
|
||||
stage: test
|
||||
script:
|
||||
- vendor/bin/phpunit --configuration tests/phpunit.xml --coverage-text
|
||||
# Install & enable Xdebug for code coverage reports
|
||||
- apt-get update
|
||||
- apt-get install -yqq libicu-dev libjpeg-dev libpng-dev libpq-dev libyaml-dev libzip-dev mariadb-client postgresql-client unzip zip
|
||||
- pecl install xdebug yaml
|
||||
- docker-php-ext-enable xdebug yaml
|
||||
- docker-php-ext-install gd bcmath intl pdo_mysql pdo_pgsql zip
|
||||
|
||||
# Install composer
|
||||
- curl -sS https://getcomposer.org/installer | php
|
||||
# Install dev libraries from composer
|
||||
- php ./composer.phar install --no-progress
|
||||
# php.ini settings
|
||||
- echo 'xdebug.mode=coverage' >> /usr/local/etc/php/php.ini
|
||||
|
||||
# hidden job definition with template for MySQL/MariaDB
|
||||
#.job_template_mysql: &job_definition_mysql
|
||||
# stage: test
|
||||
# script:
|
||||
# - echo "USE $MYSQL_DATABASE; $(cat ./install/schema_mysql.sql)" | mysql --user=root --password="$MYSQL_ROOT_PASSWORD" --host=mysql "$MYSQL_DATABASE"
|
||||
# - echo "SHOW DATABASES;" | mysql --user=root --password="$MYSQL_ROOT_PASSWORD" --host=mysql "$MYSQL_DATABASE"
|
||||
# - echo "USE $MYSQL_DATABASE; SHOW TABLES;" | mysql --user=root --password="$MYSQL_ROOT_PASSWORD" --host=mysql "$MYSQL_DATABASE"
|
||||
# - vendor/bin/phpunit --configuration tests/phpunit.xml --coverage-text
|
||||
.job_template_mysql: &job_definition_mysql
|
||||
stage: test
|
||||
variables:
|
||||
HZ_TEST_DB_HOST: $DB_HOST
|
||||
HZ_TEST_DB_TYPE: mysql
|
||||
HZ_TEST_DB_USER: root
|
||||
HZ_TEST_DB_PASS: $MYSQL_ROOT_PASSWORD
|
||||
HZ_TEST_DB_DATABASE: $MYSQL_DATABASE
|
||||
script:
|
||||
# Import hubzilla's DB schema
|
||||
- echo "USE $MYSQL_DATABASE; $(cat ./install/schema_mysql.sql)" | mysql --user=root --password="$MYSQL_ROOT_PASSWORD" --host="$DB_HOST" "$MYSQL_DATABASE"
|
||||
# Show databases and relations/tables of hubzilla's database
|
||||
- echo "SHOW DATABASES;" | mysql --user=root --password="$MYSQL_ROOT_PASSWORD" --host="$DB_HOST" "$MYSQL_DATABASE"
|
||||
- echo "USE $MYSQL_DATABASE; SHOW TABLES;" | mysql --user=root --password="$MYSQL_ROOT_PASSWORD" --host="$DB_HOST" "$MYSQL_DATABASE"
|
||||
# Run the actual tests
|
||||
- touch dbfail.out
|
||||
- vendor/bin/phpunit --configuration tests/phpunit.xml --verbose --stop-on-error --coverage-text --colors=never --log-junit tests/results/junit.xml || exit_code=$?
|
||||
- if [ $exit_code -ne 0 ]; then echo "Test barfed!"; cat dbfail.out; exit $exit_code; fi
|
||||
coverage: '/^\s*Lines:\s*\d+.\d+\%/'
|
||||
|
||||
|
||||
# hidden job definition with template for PostgreSQL
|
||||
#.job_template_postgres: &job_definition_postgres
|
||||
# stage: test
|
||||
# services:
|
||||
# - postgres:latest
|
||||
# script:
|
||||
# - export PGPASSWORD=$POSTGRES_PASSWORD
|
||||
# - psql --version
|
||||
# - psql -h "postgres" -U "$POSTGRES_USER" -d "$POSTGRES_DB" -c "SELECT VERSION();"
|
||||
# Import hubzilla's DB schema
|
||||
# - psql -h "postgres" -U "$POSTGRES_USER" -v ON_ERROR_STOP=1 --quiet "$POSTGRES_DB" < ./install/schema_postgres.sql
|
||||
# Show databases and relations/tables of hubzilla's database
|
||||
#- psql -h "postgres" -U "$POSTGRES_USER" -l
|
||||
#- psql -h "postgres" -U "$POSTGRES_USER" -d "$POSTGRES_DB" -c "\dt;"
|
||||
# Run the actual tests
|
||||
# - vendor/bin/phpunit --configuration tests/phpunit-pgsql.xml --testdox
|
||||
.job_template_postgres: &job_definition_postgres
|
||||
stage: test
|
||||
variables:
|
||||
HZ_TEST_DB_HOST: postgres
|
||||
HZ_TEST_DB_TYPE: postgres
|
||||
HZ_TEST_DB_USER: $POSTGRES_USER
|
||||
HZ_TEST_DB_PASS: $POSTGRES_PASSWORD
|
||||
HZ_TEST_DB_DATABASE: $POSTGRES_DB
|
||||
script:
|
||||
- export PGPASSWORD=$POSTGRES_PASSWORD
|
||||
- psql --version
|
||||
- psql -h "postgres" -U "$POSTGRES_USER" -d "$POSTGRES_DB" -c "SELECT VERSION();"
|
||||
# Import hubzilla's DB schema
|
||||
- psql -h "postgres" -U "$POSTGRES_USER" -v ON_ERROR_STOP=1 --quiet "$POSTGRES_DB" < ./install/schema_postgres.sql
|
||||
# Show databases and relations/tables of hubzilla's database
|
||||
- psql -h "postgres" -U "$POSTGRES_USER" -l
|
||||
- psql -h "postgres" -U "$POSTGRES_USER" -d "$POSTGRES_DB" -c "\dt;"
|
||||
# Run the actual tests
|
||||
- touch dbfail.out
|
||||
- vendor/bin/phpunit --configuration tests/phpunit.xml --verbose --stop-on-error --coverage-text --colors=never --log-junit tests/results/junit.xml || exit_code=$?
|
||||
- if [ $exit_code -ne 0 ]; then echo "Test barfed!"; cat dbfail.out; exit $exit_code; fi
|
||||
coverage: '/^\s*Lines:\s*\d+.\d+\%/'
|
||||
|
||||
# hidden job definition with artifacts config template
|
||||
.artifacts_template:
|
||||
artifacts: &artifacts_template
|
||||
.artifacts_template: &artifacts_template
|
||||
artifacts:
|
||||
expire_in: 1 week
|
||||
# Gitlab should show the results, but has problems parsing PHPUnit's junit file.
|
||||
reports:
|
||||
@@ -96,54 +100,30 @@ before_script:
|
||||
- tests/results/
|
||||
|
||||
|
||||
# PHP8.1
|
||||
php8.1:
|
||||
<<: *job_definition_php
|
||||
# PHP8.1 with MySQL 8.0
|
||||
php8.1_mysql8.0.22:
|
||||
image: php:8.1
|
||||
services:
|
||||
- mysql:8.0
|
||||
<<: *job_definition_mysql
|
||||
<<: *artifacts_template
|
||||
|
||||
# PHP8.0 with MySQL 5.7
|
||||
#php8.0_mysql5.7:
|
||||
# <<: *job_definition_mysql
|
||||
# services:
|
||||
# - mysql:5.7
|
||||
# PHP8.1 with MariaDB 10.6
|
||||
php8.1_mariadb10.6:
|
||||
image: php:8.1
|
||||
services:
|
||||
- name: mariadb:10.6
|
||||
alias: mysql
|
||||
<<: *job_definition_mysql
|
||||
<<: *artifacts_template
|
||||
|
||||
|
||||
# PHP8.0 with MySQL 8 (latest)
|
||||
#php8.0_mysql8:
|
||||
# <<: *job_definition_mysql
|
||||
# services:
|
||||
# - name: mysql:8
|
||||
# command: ["--default-authentication-plugin=mysql_native_password"]
|
||||
|
||||
|
||||
# PHP8.0 with MariaDB 10.2
|
||||
#php8.0_mariadb10.2:
|
||||
# <<: *job_definition_mysql
|
||||
# services:
|
||||
# - name: mariadb:10.2
|
||||
# alias: mysql
|
||||
|
||||
|
||||
# PHP8.0 with MariaDB 10.3 (latest)
|
||||
#php8.0_mariadb10.3:
|
||||
# <<: *job_definition_mysql
|
||||
# image: php:8.0
|
||||
#image: registry.gitlab.com/dawnbreak/hubzilla/core:php7.3
|
||||
# services:
|
||||
# - name: mariadb:10.3
|
||||
# alias: mysql
|
||||
|
||||
|
||||
# PHP7.3 with PostgreSQL latest (11)
|
||||
#php7.3_postgres11:
|
||||
# <<: *job_definition_postgres
|
||||
# artifacts: *artifacts_template
|
||||
|
||||
|
||||
# PHP7.3 with PostgreSQL latest (11)
|
||||
#php7.3_postgres11:
|
||||
# <<: *job_definition_postgres
|
||||
# image: registry.gitlab.com/dawnbreak/hubzilla/core:php7.3
|
||||
# artifacts: *artifacts_template
|
||||
# PHP8.1 with PostgreSQL 12
|
||||
php8.1_postgres12:
|
||||
image: php:8.1
|
||||
services:
|
||||
- postgres:12-alpine
|
||||
<<: *job_definition_postgres
|
||||
<<: *artifacts_template
|
||||
|
||||
|
||||
# Generate Doxygen API Documentation and deploy it as GitLab pages
|
||||
|
||||
@@ -25,10 +25,10 @@ AddType audio/ogg .oga
|
||||
# in CGI mode.
|
||||
|
||||
RewriteCond %{REQUEST_URI} ^/\.well\-known/.*
|
||||
RewriteRule ^(.*)$ index.php?q=$1 [E=REMOTE_USER:%{HTTP:Authorization},L,QSA]
|
||||
RewriteRule ^(.*)$ index.php?q=$1 "[E=REMOTE_USER:%{HTTP:Authorization},L,QSA,B= ?]"
|
||||
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
RewriteRule ^(.*)$ index.php?q=$1 [E=REMOTE_USER:%{HTTP:Authorization},L,QSA]
|
||||
RewriteRule ^(.*)$ index.php?q=$1 "[E=REMOTE_USER:%{HTTP:Authorization},L,QSA,B= ?]"
|
||||
</IfModule>
|
||||
|
||||
|
||||
334
CHANGELOG
334
CHANGELOG
@@ -1,3 +1,337 @@
|
||||
Hubzilla 9.0 (2024-03-22)
|
||||
- Refactor browser to browser encryption based on sodium plus library
|
||||
- Added developer docs for the refactored test system
|
||||
- Move escape_tags() to Lib/Text::escape_tags() and add test
|
||||
- Messages are now sent as articles instead of notes - this can be configured for activitypub
|
||||
- Implement support for custom emojis
|
||||
- Add test for Lib/Activity::get_textfield()
|
||||
- Refactor mod things to be AS2 compliant
|
||||
- Implement basic bbcode tests and minor refactor
|
||||
- Refactor profile activities to be AS2 complient
|
||||
- Removed poke and moods app
|
||||
- Cleanup deprecated/unused activity types
|
||||
- Update doxygen config for generating online API docs
|
||||
- Make DBA driver transaction aware
|
||||
- Deprecate internal usage of ActivityStreams1 in favor of ActivityStreams2
|
||||
- Introduce Lib/Activity::get_actor() force flag to omit cache
|
||||
- Refactor mod contactedit refresh
|
||||
- Require intl PHP extension
|
||||
- Improved checks in Web/HTTPSig::find_headers()
|
||||
- Implement custom sass bootstrap builds for channels and site
|
||||
- Mark items verified in zot delivery if either JSalmon, LDSignature or EddsaSignature verified
|
||||
- Added support for code blocks with language in markdown and html
|
||||
- Improved conversation item design
|
||||
- Start using uuid for internal reference instead of base64 encoded mid
|
||||
- Store seen mids in session instead of cache
|
||||
- Increase sess_data DB column to medium text
|
||||
- Introduce Lib/Activity::init_background_fetch()
|
||||
- Refactor zotconvo daemon
|
||||
- Implement short time object cache to reduce network calls (performance)
|
||||
- Refactor Lib/Activity::fetch_and_store_parents()
|
||||
- Introduce the fetchparents daemon
|
||||
- Refactor Libzot::process_delivery()
|
||||
- Start processing source xchan in xchan_query()
|
||||
- Added CI job for MariaDB 10.6
|
||||
- Store the original announce actor (the one that pushed the item into our stream first) in source_xchan instead of owner_xchan to preserve the original owner
|
||||
- Added optional circle person avatar
|
||||
- Added min supported DB backends to administrator docs: MySql v >= 8.0.22, MariaDB v >= 10.6, PostgreSql v >= 12
|
||||
- Added CI job for MySql 8.0
|
||||
- Improved validate_email()
|
||||
- Implement fep-8b32 - object integrity proofs
|
||||
- Implement native repeats
|
||||
- Updated spanish strings
|
||||
- Add tests for check_account_email()
|
||||
- Vastly improved unit tests including the database
|
||||
- Require sodium PHP extension
|
||||
- Require bcmath or gmp PHP extension
|
||||
- Deprecate simplepie idna_convert()
|
||||
- Update apache rewite rule to fix issue with recent apache versions - issue #1822
|
||||
- Display selected mid in an open state - issue #1425
|
||||
- Add bookmark and category to AP schema
|
||||
|
||||
Bugfixes
|
||||
- Fix cover photos not uploaded into folder due to missing source option
|
||||
- Fix regression where config returned default value in some cases
|
||||
- Fix attachments listed in reverse order
|
||||
- Fix unterminated entity reference error when dealing with domxpath and add a test
|
||||
- Fix obsolete system language selector in admin/site
|
||||
- Fix imagick readImageBlob() exception not handled
|
||||
- Fix content not moved to new location if folder was renamed via webdav
|
||||
- Fix bootstrap namespaces not up-to-date in htmlpurifier
|
||||
- Fix inReplyTo field in Lib/Activity not dealing with arrays
|
||||
- Fix round buttons not being round
|
||||
- Fix import from ical if timezone was not set in the source data
|
||||
- Fix hard linebreaks from markdown and html not preserved in bbcode conversion
|
||||
- Fix indentation from markdown and html not preserved in bbcode conversion
|
||||
- Fix images with alt text from markdown and not preserved in bbcode conversion
|
||||
- Fix custom emoji reactions arriving from pleroma
|
||||
- Fix issue where if an item is created and deleted again before the notifier has completed the queueworker will dismiss the delete because it looks like a duplicate entry
|
||||
- Fix handling HTML entities via mbstring is deprecated
|
||||
- Fix various PHP deprecation warnings
|
||||
- Fix apache rewite rule to fix issue with recent apache versions - issue #1822
|
||||
- Fix display selected mid in an open state - issue #1425
|
||||
|
||||
Addons
|
||||
- Removed smileybutton addon
|
||||
- Removed smiley_pack addon
|
||||
- Pubcrawl: refactor presentation of encrypted messages
|
||||
- Removed deprecated cryptojs addon
|
||||
- Removed emojione addon
|
||||
- New addon emoji which can provide different emoji sets via config.system.emoji_set variable - emojitwo (default), openmoji, mutant are currently supported
|
||||
- Removed addon moremoods
|
||||
- Removed addon morepokes
|
||||
- Pubcrawl: implement actor_refetch hook
|
||||
- Diaspora: implement actor_refetch hook
|
||||
- Navbanner_options: fix PHP warnings
|
||||
- Pubcrawl: add assertionMethod to encode_person()
|
||||
- Socialauth: cleanup unused files
|
||||
- Openstreetmap: adjust URLs
|
||||
|
||||
|
||||
Hubzilla 8.8.8 (2024-02-29)
|
||||
- Streams compatibility fixes
|
||||
|
||||
|
||||
Hubzilla 8.8.7 (2024-01-19)
|
||||
- Fix regression in Activity::actor_store()
|
||||
|
||||
|
||||
Hubzilla 8.8.6 (2024-01-11)
|
||||
- Provide more builtin jsonld files
|
||||
- Development branch compatibility in Libsync
|
||||
|
||||
|
||||
Hubzilla 8.8.5 (2024-01-01)
|
||||
- Fix possible loop if DB is not reachable (introduced in 8.8.3)
|
||||
- Fix some errors and deprecation warnings with PHP 8.2
|
||||
- Deprecate simplepie idna_convert in favor of PHP native function
|
||||
- Fix double processed quoted strings in get_tags()
|
||||
|
||||
|
||||
Hubzilla 8.8.4 (2023-12-20)
|
||||
- Fix regression introduced in version 8.8.3
|
||||
- Add test for Lib/Config
|
||||
- Add active addons and blocked sites to siteinfo
|
||||
|
||||
|
||||
Hubzilla 8.8.3 (2023-12-17)
|
||||
- Check return from Config::Load() and retry on failure
|
||||
- Libzot::import() do not prozess items where we could not fetch the author
|
||||
- Translation updates for Norwegian Bokmål (nb_NO)
|
||||
- Add the app terms before syncing, otherwise the terms will be reset at the other end
|
||||
- Addon statistics: deprecate nodeinfo 1.0 and implement nodeinfo 2.1
|
||||
- Addon cards: fix PHP error
|
||||
|
||||
|
||||
Hubzilla 8.8.2 (2023-12-06)
|
||||
- Fix missing includes - issue #1820
|
||||
- Addon logger_stats: improved performance reading big log files
|
||||
|
||||
|
||||
Hubzilla 8.8.1 (2023-11-27)
|
||||
- Fix error in cards addon
|
||||
- Fix error in articles addon
|
||||
- Fix double left and right template css
|
||||
|
||||
|
||||
Hubzilla 8.8 (2023-11-25)
|
||||
- Add additional observer and channel info for nav templates
|
||||
- Do not provide confidential channel info for templates
|
||||
- Add link to profile to vcard
|
||||
- Improved switch colors for better visibility
|
||||
- Raise cache.v column from text to mediumtext for MYSQL
|
||||
- Implement low level support for native repeats
|
||||
- Color mode related code moved to theme_init.php in redbasic
|
||||
- Do not overrule default list style when parsing bbcode
|
||||
- Introduce Activity::get_actor() which will check for the cache record in xconfig before fetching
|
||||
- Refactor Activity::actor_store()
|
||||
- Use new language detect library which supports many more languages
|
||||
- Use Activity::encode_person() instead of plain xchan_url to set attributedTo
|
||||
- Update composer libraries
|
||||
- Move right aside into bottom of left aside if screen width is < 1200px in redbasic
|
||||
- When parsing events, use event object in first place and use the body bbcode as backup
|
||||
- Make OWA compatible with mastodon style keyId
|
||||
- Add sourced item events to the channel calendar
|
||||
- Make activity filter widget portable to other modules
|
||||
- Deprecate remains of the unused $a variable which has been replaced by the App class ages ago
|
||||
- Return object instead of json string in the custom jsonld document loader
|
||||
- Only show theme switch icon if switching is supported by the theme
|
||||
- Store the actor cache date with the actor record so we can easily invalidate it after a period of time
|
||||
- Allow themes to manipulate app icons (photos) via hook
|
||||
- Also look for widgets in view/theme/themename/widget
|
||||
- Cache seen pubstream item mids so that they can be hidden from notifications
|
||||
- Theme fixes to make barebones bootstrap themes work slightly better
|
||||
- Update Norwegian Bokmål strings
|
||||
- Update Spanish strings
|
||||
- Transparent background for colorbox controls icons
|
||||
- Use body background color for colorboxes in redbasic
|
||||
|
||||
Bugfixes
|
||||
- Remove fragment from actor urls
|
||||
- HTTPsig case insensitive digest algorithm
|
||||
- Fix possible privacy mismatch when processing zot requests
|
||||
- Fix @someone in URL turned into mention in some situations - issue #1816
|
||||
- Fix fatal error in simplepie with PHP8.2
|
||||
- Fix tools visible allthough permission has been revoked for observer in files app
|
||||
- Fix updates entry not removed if a channel was removed
|
||||
- Fix form reset button not visible in mod rpost
|
||||
- Fix missing columns for updates table in install script
|
||||
- Fix for item widget not respecting ACL if added by title - issue #1799
|
||||
- Fix sabre/dav caldav php warnings
|
||||
- Fix public stream comments/reactions not allowed if item_fetched is set
|
||||
|
||||
Addons
|
||||
- Superblock: fix php warnings
|
||||
- Pubcrawl: restrict mod ap_probe to admin and add checkbox for signed requests
|
||||
- Wiki: fix wiki_list widget not registered
|
||||
- Deprecate remains of the unused $a variable which has been replaced by the App class ages ago
|
||||
- Pubcrawl: reflect core delivery changes for repeated items
|
||||
- Cart fix regression
|
||||
- Logger_stats: new addon for admins to track hub activities
|
||||
- Pubcrawl: check if we have the record in the short term cache before actually fetching it
|
||||
- Pubcrawl: reflect core changes to Activity::actor_store()
|
||||
- Gallery: update to photoswipe 5
|
||||
- Pubcrawl: some platforms are sending activities without an object - return error 400
|
||||
- HSSE: update sce-editor to latest version
|
||||
- SSE: sse: do not process items that are older than last login date or in case we are not logged in older than 10 minutes
|
||||
- Faces: new addon for face recognision in uploaded photos
|
||||
|
||||
|
||||
Hubzilla 8.6.3 (2023-09-16)
|
||||
- Fix regression in jsonld_document_loader()
|
||||
- Improve type checking for announce activities
|
||||
- Improve query in drop_item() to prevent possible memory exhaustion
|
||||
- Addon gallery: only add gallery code if the module is supported
|
||||
- Addon hsse: port to bootstrap 5 namespaces - core issue #1793
|
||||
|
||||
|
||||
Hubzilla 8.6.2 (2023-08-27)
|
||||
- Fix public stream comments/reactions fetching
|
||||
- Fix notification text for likes in cases where obj.actor is not set
|
||||
- Fix missing pdl file for mod cover_photo
|
||||
- Fix unable to create folders with name 0
|
||||
- Fix index name mixup in mysql schema file
|
||||
- Fix missing semicolon in mysql schema file
|
||||
- Removed unused variable
|
||||
- Fix typo in manifest
|
||||
- Fix cached jsonld files fetched via network
|
||||
- Page rendering performance improvements
|
||||
- Fix internal follow activity possibly creating notification items
|
||||
- Fix admin table highlight color for dark mode
|
||||
- Pubcrawl: do not handle not implemented listen activity
|
||||
- Diaspora: fix unshare not implemented
|
||||
|
||||
|
||||
Hubzilla 8.6.1 (2023-07-18)
|
||||
- Fix diaspora discovery
|
||||
|
||||
|
||||
Hubzilla 8.6 (2023-07-11)
|
||||
- Update fullcalendar library
|
||||
- Improve and unify selection of deliverable abook xchans
|
||||
- Remove unused pseudo_abook()
|
||||
- Implement optional moderation for unsolicited items
|
||||
- Hardened comment permission handling for unsolicited items
|
||||
- Remove unused templates
|
||||
- Deprecate ActivityStreams::fetch() and provide the possibility to fetch local items directly
|
||||
- Add simplified version of automated install script
|
||||
- Shuffle queue deliveries for more randomness
|
||||
- Update composer libraries
|
||||
- Add new 2-column templates
|
||||
- Implement optional OCAP for items to allow access to restricted media without OWA
|
||||
|
||||
Bugfixes
|
||||
- Fix content in nobb and noparse text linkified - issue #1776
|
||||
- Fix editing an event changes the set time - issue #1771
|
||||
- Fix person object with mixed up hubloc info - issue #1770
|
||||
- Fix $escape variable not passed on to stringify_array_elms()
|
||||
- Fix relaying and syncing in Activity::drop()
|
||||
- Fix allow code not sticking after channel sync - issue #1769
|
||||
- Fix channel oembed regressions
|
||||
|
||||
Addons
|
||||
- Diaspora: fix signature check for likes
|
||||
- Diaspora: fix relaying retractions
|
||||
- Diaspora: port to core unsolicited comments option
|
||||
- Gallery: add an exception for streams reshares
|
||||
- Pubcrawl: dismiss comments that are expected to arrive via owner relay
|
||||
- Pubcrawl: improved inbox handling
|
||||
- Pubcrawl: catch gup.pe updates to followers collection
|
||||
- Pubcrawl: fix follow allow hook
|
||||
- Diaspora: fix follow allow hook
|
||||
- Content_import: fix crash in post handler
|
||||
- Pubcrawl: store follow url when fetching webfinger
|
||||
- Diaspora: store follow url when fetching webfinger
|
||||
- Pubcrawl: move addressing to separate function
|
||||
|
||||
|
||||
Hubzilla 8.4.2 (2023-06-02)
|
||||
- Update bootstrap to stable version 5.3.0
|
||||
- Fix hubloc confusion in mod rmagic
|
||||
- Improved unseen forums notification
|
||||
- Add workaround for friendica accept header bug for nginx
|
||||
- Fix acl not set correctly in attach_store()
|
||||
- Fix attachment name parsing
|
||||
- Fix display issue in oembed video template
|
||||
- content_import: fix crash in post handler
|
||||
- pubcrawl: move addressing to separate function
|
||||
|
||||
|
||||
Hubzilla 8.4.1 (2023-05-20)
|
||||
- Fix issue where accepting AP contacts would reset send stream permission
|
||||
- Fix link to release page in upgrade info addon
|
||||
|
||||
|
||||
Hubzilla 8.4 (2023-05-17)
|
||||
- Slightly rewrite Activity::store() to save a query
|
||||
- Use act->objprop() in decode_note() to get activity values
|
||||
- Make sure to re-discover a channel upon connecting if we have just an xchan but no hubloc
|
||||
- Updated ES translations
|
||||
- Updated RU translations
|
||||
- Redesigned profile vcard to implement cover images
|
||||
- Slightly improved discovery of AP quoted messages
|
||||
- Updated bootstrap library
|
||||
- Changed hashtag encoding to match mastodons expectations (issue #1750)
|
||||
- Implement fedearted directory flags from trusted directory servers
|
||||
- Use Activity::get_actor_hublocs() in Libzot::fetch_conversation() instead of custom queries
|
||||
- Add the conversation endpoint
|
||||
- Implement paginated fetch for zot requests in mod item
|
||||
- Implement Zotconvo daemon to fetch conversations in the background
|
||||
- Expose deleted channels to webfinger (otherwise we can not mark them deleted locally)
|
||||
- Expire items in batches to prevent memory exhaustion
|
||||
- Remove legacy zot compatibility tweaks
|
||||
- Rewrite and simplify directory sync
|
||||
- Improve potentially long running sql query finding the thread parent
|
||||
- Implement option to override permissions for posts with mentions
|
||||
|
||||
Bugfixes
|
||||
- Fix parent_mid and thr_parent not set correctly for response activities
|
||||
- Fix query for postgres in attach_list_files()
|
||||
- Fix item_url_replace() failing on arrays
|
||||
- Fix OWA compatibility with friendica
|
||||
- Fix regression in decoding the object type
|
||||
- Fix xss vulnerability in justified gallery library
|
||||
- Fix permissions not initialized after accepted follow request from AP
|
||||
- Fix empty path passed to fopen()
|
||||
- Fix % value in format_poll() not rounded
|
||||
- Fix remove_all_xchan_resources() executed for local channels
|
||||
- Fix likes not synced via libsync between clones
|
||||
|
||||
Addons
|
||||
- Pubcrawl: fix xchan_url used as follow object instead of xchan_hash
|
||||
- Channelreputation: moved to unmaintained repo due to duplication issues when storing data in pconfig
|
||||
- Pubcrawl: add lemmy accept/reject follow quirks
|
||||
- Diaspora: handle 4xx return codes in queue management
|
||||
- Diaspora: fix fatal error in the case where parent_guid is set but empty
|
||||
- Pubcrawl: if shared inbox delivery fails deliver to contacts instead of everybody we know from that site
|
||||
- Articles: fix PHP error
|
||||
- Diaspora: rewrite synced (from a clone) item author to primary
|
||||
- Diaspora: improve reshare detection
|
||||
- Diaspora: fix contact role not sets
|
||||
- Pubcrawl: rewrite synced (from a clone) item author to primary
|
||||
- Pubcrawl: if we receive a public message to the shared inbox deliver to following *and* directly addressed
|
||||
|
||||
|
||||
Hubzilla 8.2 (2023-03-19)
|
||||
- Remove redundant untranslated htconfig templates
|
||||
- Implement workaround for friendica image/attachment construct
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace Zotlabs\Access;
|
||||
|
||||
|
||||
/**
|
||||
* @brief AccessList class which represents individual content ACLs.
|
||||
*
|
||||
@@ -17,29 +18,48 @@ class AccessList {
|
||||
* @brief Allow contacts
|
||||
* @var string
|
||||
*/
|
||||
private $allow_cid;
|
||||
private ?string $allow_cid;
|
||||
/**
|
||||
* @brief Allow groups
|
||||
* @var string
|
||||
*/
|
||||
private $allow_gid;
|
||||
private ?string $allow_gid;
|
||||
/**
|
||||
* @brief Deny contacts
|
||||
* @var string
|
||||
*/
|
||||
private $deny_cid;
|
||||
private ?string $deny_cid;
|
||||
/**
|
||||
* @brief Deny groups
|
||||
* @var string
|
||||
*/
|
||||
private $deny_gid;
|
||||
private ?string $deny_gid;
|
||||
/**
|
||||
* @brief Indicates if we are using the default constructor values or
|
||||
* values that have been set explicitly.
|
||||
* @var boolean
|
||||
*/
|
||||
private $explicit;
|
||||
private bool $explicit;
|
||||
|
||||
/**
|
||||
* @brief Keys required by the constructor if the channel array is given.
|
||||
*/
|
||||
private const REQUIRED_KEYS_CONSTRUCTOR = [
|
||||
'channel_allow_cid',
|
||||
'channel_allow_gid',
|
||||
'channel_deny_cid',
|
||||
'channel_deny_gid'
|
||||
];
|
||||
|
||||
/**
|
||||
* @brief Keys required by the set method.
|
||||
*/
|
||||
private const REQUIRED_KEYS_SET = [
|
||||
'allow_cid',
|
||||
'allow_gid',
|
||||
'deny_cid',
|
||||
'deny_gid'
|
||||
];
|
||||
|
||||
/**
|
||||
* @brief Constructor for AccessList class.
|
||||
@@ -53,8 +73,9 @@ class AccessList {
|
||||
* * \e string \b channel_deny_cid => string of denied cids
|
||||
* * \e string \b channel_deny_gid => string of denied gids
|
||||
*/
|
||||
function __construct($channel) {
|
||||
function __construct(array $channel) {
|
||||
if ($channel) {
|
||||
$this->validate_input_array($channel, self::REQUIRED_KEYS_CONSTRUCTOR);
|
||||
$this->allow_cid = $channel['channel_allow_cid'];
|
||||
$this->allow_gid = $channel['channel_allow_gid'];
|
||||
$this->deny_cid = $channel['channel_deny_cid'];
|
||||
@@ -70,13 +91,24 @@ class AccessList {
|
||||
$this->explicit = false;
|
||||
}
|
||||
|
||||
private function validate_input_array(array $arr, array $required_keys) : void {
|
||||
$missing_keys = array_diff($required_keys, array_keys($arr));
|
||||
|
||||
if (!empty($missing_keys)) {
|
||||
throw new \Exception(
|
||||
'Invalid AccessList object: Expected array with keys: '
|
||||
. implode(', ', $missing_keys)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get if we are using the default constructor values
|
||||
* or values that have been set explicitly.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
function get_explicit() {
|
||||
function get_explicit() : bool {
|
||||
return $this->explicit;
|
||||
}
|
||||
|
||||
@@ -94,7 +126,9 @@ class AccessList {
|
||||
* * \e string \b deny_gid => string of denied gids
|
||||
* @param boolean $explicit (optional) default true
|
||||
*/
|
||||
function set($arr, $explicit = true) {
|
||||
function set(array $arr, bool $explicit = true) : void {
|
||||
$this->validate_input_array($arr, self::REQUIRED_KEYS_SET);
|
||||
|
||||
$this->allow_cid = $arr['allow_cid'];
|
||||
$this->allow_gid = $arr['allow_gid'];
|
||||
$this->deny_cid = $arr['deny_cid'];
|
||||
@@ -112,7 +146,7 @@ class AccessList {
|
||||
* * \e string \b deny_cid => string of denied cids
|
||||
* * \e string \b deny_gid => string of denied gids
|
||||
*/
|
||||
function get() {
|
||||
function get() : array {
|
||||
return [
|
||||
'allow_cid' => $this->allow_cid,
|
||||
'allow_gid' => $this->allow_gid,
|
||||
@@ -138,7 +172,7 @@ class AccessList {
|
||||
* * \e array|string \b group_deny => array with gids or comma-seperated string
|
||||
* @param boolean $explicit (optional) default true
|
||||
*/
|
||||
function set_from_array($arr, $explicit = true) {
|
||||
function set_from_array(array $arr, bool $explicit = true) : void {
|
||||
$arr['contact_allow'] = $arr['contact_allow'] ?? [];
|
||||
$arr['group_allow'] = $arr['group_allow'] ?? [];
|
||||
$arr['contact_deny'] = $arr['contact_deny'] ?? [];
|
||||
@@ -161,7 +195,7 @@ class AccessList {
|
||||
*
|
||||
* @return boolean Return true if any of allow_* deny_* values is set.
|
||||
*/
|
||||
function is_private() {
|
||||
function is_private() : bool {
|
||||
return (($this->allow_cid || $this->allow_gid || $this->deny_cid || $this->deny_gid) ? true : false);
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace Zotlabs\Daemon;
|
||||
|
||||
use Zotlabs\Lib\Libsync;
|
||||
use Zotlabs\Lib\Libzotdir;
|
||||
|
||||
class Cron {
|
||||
|
||||
@@ -35,6 +36,17 @@ class Cron {
|
||||
|
||||
logger('cron: start');
|
||||
|
||||
// If this is a directory server, request a sync with an upstream
|
||||
// directory at least once a day, up to once every poll interval.
|
||||
// Pull remote changes and push local changes.
|
||||
// potential issue: how do we keep from creating an endless update loop?
|
||||
|
||||
$dirmode = get_config('system', 'directory_mode');
|
||||
|
||||
if ($dirmode == DIRECTORY_MODE_SECONDARY || $dirmode == DIRECTORY_MODE_PRIMARY) {
|
||||
Libzotdir::sync_directories($dirmode);
|
||||
}
|
||||
|
||||
// run queue delivery process in the background
|
||||
|
||||
Master::Summon(array('Queue'));
|
||||
@@ -112,13 +124,13 @@ class Cron {
|
||||
$r = q("SELECT DISTINCT xchan, content FROM photo WHERE photo_usage = %d AND expires < %s - INTERVAL %s",
|
||||
intval(PHOTO_CACHE),
|
||||
db_utcnow(),
|
||||
db_quoteinterval(get_config('system', 'active_expire_days', '30') . ' DAY')
|
||||
db_quoteinterval(get_config('system', 'cache_expire_days', 7) . ' DAY')
|
||||
);
|
||||
if ($r) {
|
||||
q("DELETE FROM photo WHERE photo_usage = %d AND expires < %s - INTERVAL %s",
|
||||
intval(PHOTO_CACHE),
|
||||
db_utcnow(),
|
||||
db_quoteinterval(get_config('system', 'active_expire_days', '30') . ' DAY')
|
||||
db_quoteinterval(get_config('system', 'cache_expire_days', 7) . ' DAY')
|
||||
);
|
||||
foreach ($r as $rr) {
|
||||
$file = dbunescbin($rr['content']);
|
||||
|
||||
@@ -65,10 +65,10 @@ class Cron_daily {
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up emdedded content cache
|
||||
// Clean up cache
|
||||
q("DELETE FROM cache WHERE updated < %s - INTERVAL %s",
|
||||
db_utcnow(),
|
||||
db_quoteinterval(get_config('system', 'active_expire_days', '30') . ' DAY')
|
||||
db_quoteinterval(get_config('system', 'cache_expire_days', 7) . ' DAY')
|
||||
);
|
||||
|
||||
//update statistics in config
|
||||
@@ -94,17 +94,6 @@ class Cron_daily {
|
||||
// expire any expired accounts
|
||||
downgrade_accounts();
|
||||
|
||||
// If this is a directory server, request a sync with an upstream
|
||||
// directory at least once a day, up to once every poll interval.
|
||||
// Pull remote changes and push local changes.
|
||||
// potential issue: how do we keep from creating an endless update loop?
|
||||
|
||||
$dirmode = get_config('system', 'directory_mode');
|
||||
|
||||
if ($dirmode == DIRECTORY_MODE_SECONDARY || $dirmode == DIRECTORY_MODE_PRIMARY) {
|
||||
Libzotdir::sync_directories($dirmode);
|
||||
}
|
||||
|
||||
Master::Summon(array('Expire'));
|
||||
Master::Summon(array('Cli_suggest'));
|
||||
|
||||
|
||||
@@ -32,7 +32,6 @@ class Expire {
|
||||
}
|
||||
|
||||
// physically remove anything that has been deleted for more than two months
|
||||
/** @FIXME - this is a wretchedly inefficient query */
|
||||
|
||||
q("delete from item where item_pending_remove = 1 and changed < %s - INTERVAL %s",
|
||||
db_utcnow(),
|
||||
@@ -44,8 +43,8 @@ class Expire {
|
||||
|
||||
logger('expire: start with pid ' . $pid, LOGGER_DEBUG);
|
||||
|
||||
$site_expire = intval(get_config('system', 'default_expire_days'));
|
||||
$commented_days = intval(get_config('system', 'active_expire_days'));
|
||||
$site_expire = intval(get_config('system', 'default_expire_days', 30));
|
||||
$commented_days = intval(get_config('system', 'active_expire_days', 7));
|
||||
|
||||
logger('site_expire: ' . $site_expire);
|
||||
|
||||
@@ -59,8 +58,8 @@ class Expire {
|
||||
continue;
|
||||
|
||||
// service class default (if non-zero) over-rides the site default
|
||||
|
||||
$service_class_expire = service_class_fetch($rr['channel_id'], 'expire_days');
|
||||
|
||||
if (intval($service_class_expire))
|
||||
$channel_expire = $service_class_expire;
|
||||
else
|
||||
@@ -85,7 +84,6 @@ class Expire {
|
||||
|
||||
// this should probably just fetch the channel_expire_days from the sys channel,
|
||||
// but there's no convenient way to set it.
|
||||
|
||||
$expire_days = get_config('system', 'sys_expire_days');
|
||||
if ($expire_days === false)
|
||||
$expire_days = 30;
|
||||
@@ -96,8 +94,9 @@ class Expire {
|
||||
|
||||
logger('Expire: sys interval: ' . $expire_days, LOGGER_DEBUG);
|
||||
|
||||
if ($expire_days)
|
||||
if ($expire_days) {
|
||||
item_expire($x['channel_id'], $expire_days, $commented_days);
|
||||
}
|
||||
|
||||
logger('Expire: sys: done', LOGGER_DEBUG);
|
||||
}
|
||||
|
||||
42
Zotlabs/Daemon/Fetchparents.php
Normal file
42
Zotlabs/Daemon/Fetchparents.php
Normal file
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Daemon;
|
||||
|
||||
use Zotlabs\Lib\Activity;
|
||||
|
||||
class Fetchparents {
|
||||
|
||||
static public function run($argc, $argv) {
|
||||
|
||||
logger('Fetchparents invoked: ' . print_r($argv, true));
|
||||
|
||||
if ($argc < 4) {
|
||||
return;
|
||||
}
|
||||
|
||||
$channels = explode(',', $argv[1]);
|
||||
if (!$channels) {
|
||||
return;
|
||||
}
|
||||
|
||||
$observer_hash = $argv[2];
|
||||
if (!$observer_hash) {
|
||||
return;
|
||||
}
|
||||
|
||||
$mid = $argv[3];
|
||||
if (!$mid) {
|
||||
return;
|
||||
}
|
||||
|
||||
$force = $argv[4] ?? false;
|
||||
|
||||
foreach ($channels as $channel_id) {
|
||||
$channel = channelx_by_n($channel_id);
|
||||
Activity::fetch_and_store_parents($channel, $observer_hash, $mid, null, $force);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,6 @@ namespace Zotlabs\Daemon;
|
||||
use Zotlabs\Lib\Libzot;
|
||||
use Zotlabs\Lib\Activity;
|
||||
use Zotlabs\Lib\Queue;
|
||||
use Zotlabs\Lib\LDSignatures;
|
||||
|
||||
require_once('include/html2plain.php');
|
||||
require_once('include/conversation.php');
|
||||
@@ -271,14 +270,13 @@ class Notifier {
|
||||
// Check for non published items, but allow an exclusion for transmitting hidden file activities
|
||||
|
||||
if (intval($target_item['item_unpublished']) || intval($target_item['item_delayed']) ||
|
||||
intval($target_item['item_blocked']) ||
|
||||
(intval($target_item['item_hidden']) && ($target_item['obj_type'] !== ACTIVITY_OBJ_FILE))) {
|
||||
intval($target_item['item_blocked']) || intval($target_item['item_hidden'])) {
|
||||
logger('notifier: target item not published, so not forwardable', LOGGER_DEBUG);
|
||||
return;
|
||||
}
|
||||
|
||||
// follow/unfollow is for internal use only
|
||||
if (in_array($target_item['verb'], [ACTIVITY_FOLLOW, ACTIVITY_UNFOLLOW])) {
|
||||
if (in_array($target_item['verb'], ['Follow', 'Ignore', ACTIVITY_FOLLOW, ACTIVITY_UNFOLLOW])) {
|
||||
logger('not fowarding follow/unfollow note activity');
|
||||
return;
|
||||
}
|
||||
@@ -300,6 +298,11 @@ class Notifier {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($target_item['verb'] === ACTIVITY_SHARE) {
|
||||
// Provide correct representation across the wire. Internally this is treated as a comment.
|
||||
$target_item['parent_mid'] = $target_item['thr_parent'] = $target_item['mid'];
|
||||
}
|
||||
|
||||
if ($target_item['mid'] === $target_item['parent_mid']) {
|
||||
$parent_item = $target_item;
|
||||
$top_level_post = true;
|
||||
@@ -337,14 +340,7 @@ class Notifier {
|
||||
self::$encoded_item = json_decode($m, true);
|
||||
}
|
||||
else {
|
||||
|
||||
self::$encoded_item = array_merge(['@context' => [
|
||||
ACTIVITYSTREAMS_JSONLD_REV,
|
||||
'https://w3id.org/security/v1',
|
||||
z_root() . ZOT_APSCHEMA_REV
|
||||
]], Activity::encode_activity($target_item)
|
||||
);
|
||||
self::$encoded_item['signature'] = LDSignatures::sign(self::$encoded_item, self::$channel);
|
||||
self::$encoded_item = Activity::build_packet(Activity::encode_activity($target_item), self::$channel, false);
|
||||
}
|
||||
|
||||
logger('target_item: ' . print_r($target_item, true), LOGGER_DEBUG);
|
||||
@@ -377,6 +373,7 @@ class Notifier {
|
||||
|
||||
if (($relay_to_owner || $uplink) && ($cmd !== 'relay')) {
|
||||
logger('notifier: followup relay', LOGGER_DEBUG);
|
||||
// If the Parent item is an Announce the real owner is the parent author
|
||||
$sendto = (($uplink) ? $parent_item['source_xchan'] : $parent_item['owner_xchan']);
|
||||
self::$recipients = [$sendto];
|
||||
self::$private = true;
|
||||
@@ -409,9 +406,7 @@ class Notifier {
|
||||
self::$private = false;
|
||||
self::$recipients = collect_recipients($parent_item, self::$private);
|
||||
|
||||
// FIXME add any additional recipients such as mentions, etc.
|
||||
|
||||
if ($top_level_post) {
|
||||
if ($top_level_post && intval($target_item['item_wall'])) {
|
||||
// remove clones who will receive the post via sync
|
||||
self::$recipients = array_values(array_diff(self::$recipients, [$target_item['owner_xchan']]));
|
||||
}
|
||||
|
||||
@@ -15,61 +15,45 @@ class Onedirsync {
|
||||
$update_id = intval($argv[1]);
|
||||
|
||||
if (!$update_id) {
|
||||
logger('onedirsync: no update');
|
||||
logger('onedirsync: no update id');
|
||||
return;
|
||||
}
|
||||
|
||||
$r = q("select * from updates where ud_id = %d limit 1",
|
||||
$r = q("select * from updates where ud_id = %d",
|
||||
intval($update_id)
|
||||
);
|
||||
|
||||
if (!$r)
|
||||
return;
|
||||
|
||||
if (($r[0]['ud_flags'] & UPDATE_FLAGS_UPDATED) || (!$r[0]['ud_addr']))
|
||||
return;
|
||||
|
||||
// Have we probed this channel more recently than the other directory server
|
||||
// (where we received this update from) ?
|
||||
// If we have, we don't need to do anything except mark any older entries updated
|
||||
|
||||
$x = q("select * from updates where ud_addr = '%s' and ud_date > '%s' and ( ud_flags & %d )>0 order by ud_date desc limit 1",
|
||||
dbesc($r[0]['ud_addr']),
|
||||
dbesc($r[0]['ud_date']),
|
||||
intval(UPDATE_FLAGS_UPDATED)
|
||||
);
|
||||
if ($x) {
|
||||
q("update updates set ud_flags = ( ud_flags | %d ) where ud_addr = '%s' and ( ud_flags & %d ) = 0 and ud_date != '%s'",
|
||||
intval(UPDATE_FLAGS_UPDATED),
|
||||
dbesc($r[0]['ud_addr']),
|
||||
intval(UPDATE_FLAGS_UPDATED),
|
||||
dbesc($x[0]['ud_date'])
|
||||
);
|
||||
if (!$r) {
|
||||
logger('onedirsync: update id not found');
|
||||
return;
|
||||
}
|
||||
|
||||
// ignore doing an update if this ud_addr refers to a known dead hubloc
|
||||
|
||||
$h = q("select * from hubloc where hubloc_addr = '%s'",
|
||||
$h = q("select * from hubloc where hubloc_id_url = '%s' order by hubloc_id desc",
|
||||
dbesc($r[0]['ud_addr']),
|
||||
);
|
||||
|
||||
$h = Libzot::zot_record_preferred($h);
|
||||
|
||||
if (($h) && (($h['hubloc_status'] & HUBLOC_OFFLINE) || $h['hubloc_deleted'] || $h['hubloc_error'])) {
|
||||
q("update updates set ud_flags = ( ud_flags | %d ) where ud_addr = '%s' and ( ud_flags & %d ) = 0 ",
|
||||
intval(UPDATE_FLAGS_DELETED),
|
||||
dbesc($r[0]['ud_addr']),
|
||||
intval(UPDATE_FLAGS_UPDATED)
|
||||
);
|
||||
return;
|
||||
|
||||
// 2023-04-12: Try to update anyway since the info is not always correct
|
||||
// This might change after all directory servers run the new code.
|
||||
|
||||
// q("update updates set ud_flags = 9 where ud_hash = '%s' and ud_flags != 9",
|
||||
// dbesc($r[0]['ud_hash'])
|
||||
//);
|
||||
|
||||
// return;
|
||||
}
|
||||
|
||||
// we might have to pull this out some day, but for now update_directory_entry()
|
||||
// runs zot_finger() and is kind of zot specific
|
||||
|
||||
if ($h && $h['hubloc_network'] !== 'zot6')
|
||||
if ($h && $h['hubloc_network'] !== 'zot6') {
|
||||
return;
|
||||
}
|
||||
|
||||
Libzotdir::update_directory_entry($r[0]);
|
||||
|
||||
|
||||
@@ -30,14 +30,10 @@ class Onepoll {
|
||||
$sql_extra = ' and abook_feed = 0 ';
|
||||
}
|
||||
|
||||
$contacts = q("SELECT abook.*, xchan.*, account.*
|
||||
FROM abook LEFT JOIN account on abook_account = account_id left join xchan on xchan_hash = abook_xchan
|
||||
where abook_id = %d $sql_extra
|
||||
and abook_pending = 0 and abook_archived = 0 and abook_blocked = 0 and abook_ignored = 0
|
||||
AND (( account_flags = %d ) OR ( account_flags = %d )) limit 1",
|
||||
intval($contact_id),
|
||||
intval(ACCOUNT_OK),
|
||||
intval(ACCOUNT_UNVERIFIED)
|
||||
$contacts = q("SELECT abook.*, xchan.* FROM abook
|
||||
LEFT JOIN xchan ON xchan_hash = abook_xchan
|
||||
WHERE abook_id = %d",
|
||||
intval($contact_id)
|
||||
);
|
||||
|
||||
if (!$contacts) {
|
||||
|
||||
@@ -19,24 +19,6 @@ class Poller {
|
||||
|
||||
$interval = get_config('queueworker', 'queue_interval', 500000);
|
||||
|
||||
/*
|
||||
if (!$interval) {
|
||||
$interval = ((get_config('system', 'delivery_interval') === false) ? 3 : intval(get_config('system', 'delivery_interval')));
|
||||
}
|
||||
|
||||
// Check for a lockfile. If it exists, but is over an hour old, it's stale. Ignore it.
|
||||
$lockfile = 'store/[data]/poller';
|
||||
if ((file_exists($lockfile)) && (filemtime($lockfile) > (time() - 3600))
|
||||
&& (!get_config('system', 'override_poll_lockfile'))) {
|
||||
logger("poller: Already running");
|
||||
return;
|
||||
}
|
||||
|
||||
// Create a lockfile. Needs two vars, but $x doesn't need to contain anything.
|
||||
$x = '';
|
||||
file_put_contents($lockfile, $x);
|
||||
*/
|
||||
|
||||
logger('poller: start');
|
||||
|
||||
$manual_id = 0;
|
||||
@@ -67,6 +49,11 @@ class Poller {
|
||||
: ''
|
||||
);
|
||||
|
||||
$allow_feeds = get_config('system', 'feed_contacts');
|
||||
if(!$allow_feeds) {
|
||||
$sql_extra .= ' and abook_feed = 0 ';
|
||||
}
|
||||
|
||||
$randfunc = db_getfunc('RAND');
|
||||
|
||||
$contacts = q("SELECT abook.abook_updated, abook.abook_connected, abook.abook_feed,
|
||||
@@ -76,7 +63,7 @@ class Poller {
|
||||
account.account_lastlog, account.account_flags
|
||||
FROM abook LEFT JOIN xchan on abook_xchan = xchan_hash
|
||||
LEFT JOIN account on abook_account = account_id
|
||||
where abook_self = 0
|
||||
where abook_self = 0 and abook_pending = 0 and abook_archived = 0 and abook_blocked = 0 and abook_ignored = 0
|
||||
$sql_extra
|
||||
AND (( account_flags = %d ) OR ( account_flags = %d )) $abandon_sql ORDER BY $randfunc",
|
||||
intval(ACCOUNT_OK),
|
||||
@@ -183,11 +170,12 @@ class Poller {
|
||||
$dirmode = intval(get_config('system', 'directory_mode'));
|
||||
|
||||
if ($dirmode == DIRECTORY_MODE_SECONDARY || $dirmode == DIRECTORY_MODE_PRIMARY) {
|
||||
$r = q("SELECT u.ud_addr, u.ud_id, u.ud_last FROM updates AS u INNER JOIN (SELECT ud_addr, max(ud_id) AS ud_id FROM updates WHERE ( ud_flags & %d ) = 0 AND ud_addr != '' AND ( ud_last <= '%s' OR ud_last > %s - INTERVAL %s ) GROUP BY ud_addr) AS s ON s.ud_id = u.ud_id ",
|
||||
intval(UPDATE_FLAGS_UPDATED),
|
||||
$r = q("SELECT * FROM updates WHERE ud_update = 1 AND (ud_last = '%s' OR ud_last > %s - INTERVAL %s)",
|
||||
dbesc(NULL_DATE),
|
||||
db_utcnow(), db_quoteinterval('7 DAY')
|
||||
db_utcnow(),
|
||||
db_quoteinterval('7 DAY')
|
||||
);
|
||||
|
||||
if ($r) {
|
||||
foreach ($r as $rr) {
|
||||
|
||||
@@ -209,10 +197,6 @@ class Poller {
|
||||
|
||||
set_config('system', 'lastpoll', datetime_convert());
|
||||
|
||||
//All done - clear the lockfile
|
||||
/*
|
||||
@unlink($lockfile);
|
||||
*/
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ class Queue {
|
||||
// delete all queue items more than 3 days old
|
||||
// but first mark these sites dead if we haven't heard from them in a month
|
||||
|
||||
$oldqItems = q("select outq_posturl from outq where outq_created < %s - INTERVAL %s",
|
||||
$oldqItems = q("select outq_posturl, outq_hash from outq where outq_created < %s - INTERVAL %s",
|
||||
db_utcnow(),
|
||||
db_quoteinterval('3 DAY')
|
||||
);
|
||||
@@ -29,13 +29,13 @@ class Queue {
|
||||
db_quoteinterval('1 MONTH')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
logger('Removing ' . count($oldqItems) . ' old queue entries');
|
||||
q("DELETE FROM outq WHERE outq_created < %s - INTERVAL %s",
|
||||
db_utcnow(),
|
||||
db_quoteinterval('3 DAY')
|
||||
);
|
||||
$old_hashes = ids_to_querystr($oldqItems, 'outq_hash', true);
|
||||
|
||||
logger('Removing ' . count($oldqItems) . ' old queue entries');
|
||||
dbq("DELETE FROM outq WHERE outq_hash IN ($old_hashes)");
|
||||
|
||||
}
|
||||
|
||||
$deliveries = [];
|
||||
|
||||
@@ -47,13 +47,16 @@ class Queue {
|
||||
LibQueue::deliver($qItems[0]);
|
||||
}
|
||||
else {
|
||||
$qItems = q("SELECT * FROM outq WHERE outq_delivered = 0 and outq_scheduled < %s ",
|
||||
$qItems = q("SELECT outq_hash FROM outq WHERE outq_scheduled < %s ",
|
||||
db_utcnow()
|
||||
);
|
||||
|
||||
if ($qItems) {
|
||||
foreach ($qItems as $qItem) {
|
||||
$deliveries[] = $qItem['outq_hash'];
|
||||
}
|
||||
|
||||
shuffle($deliveries);
|
||||
do_delivery($deliveries, true);
|
||||
}
|
||||
}
|
||||
|
||||
34
Zotlabs/Daemon/Xchan_photo.php
Normal file
34
Zotlabs/Daemon/Xchan_photo.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
/** @file */
|
||||
|
||||
namespace Zotlabs\Daemon;
|
||||
|
||||
class Xchan_photo {
|
||||
|
||||
static public function run($argc, $argv) {
|
||||
|
||||
if ($argc != 3) {
|
||||
return;
|
||||
}
|
||||
|
||||
$url = hex2bin($argv[1]);
|
||||
$xchan = hex2bin($argv[2]);
|
||||
|
||||
$photos = import_xchan_photo($url, $xchan);
|
||||
if ($photos) {
|
||||
$result = q("update xchan set xchan_photo_date = '%s', xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s' where xchan_hash = '%s'",
|
||||
dbescdate(datetime_convert()),
|
||||
dbesc($photos[0]),
|
||||
dbesc($photos[1]),
|
||||
dbesc($photos[2]),
|
||||
dbesc($photos[3]),
|
||||
dbesc($xchan)
|
||||
);
|
||||
|
||||
if (! $result) {
|
||||
logger("xchan update failed for $url");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
37
Zotlabs/Daemon/Zotconvo.php
Normal file
37
Zotlabs/Daemon/Zotconvo.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Daemon;
|
||||
|
||||
use Zotlabs\Lib\Libzot;
|
||||
|
||||
class Zotconvo {
|
||||
|
||||
static public function run($argc, $argv) {
|
||||
|
||||
logger('Zotconvo invoked: ' . print_r($argv, true));
|
||||
|
||||
if ($argc < 3) {
|
||||
return;
|
||||
}
|
||||
|
||||
$channels = explode(',', $argv[1]);
|
||||
if (!$channels) {
|
||||
return;
|
||||
}
|
||||
|
||||
$mid = $argv[2];
|
||||
if (!$mid) {
|
||||
return;
|
||||
}
|
||||
|
||||
$force = $argv[3] ?? false;
|
||||
|
||||
foreach ($channels as $channel_id) {
|
||||
$channel = channelx_by_n($channel_id);
|
||||
Libzot::fetch_conversation($channel, $mid, $force);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
}
|
||||
33
Zotlabs/Lib/ASCache.php
Normal file
33
Zotlabs/Lib/ASCache.php
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php /** @file */
|
||||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
/**
|
||||
* A wrapper for the cache api
|
||||
*/
|
||||
|
||||
class ASCache {
|
||||
public static function isEnabled() {
|
||||
return Config::Get('system', 'as_object_cache_enabled', true);
|
||||
}
|
||||
|
||||
public static function getAge() {
|
||||
return Config::Get('system', 'as_object_cache_time', '10 MINUTE');
|
||||
}
|
||||
|
||||
public static function Get($key) {
|
||||
if (!self::isEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
return Cache::get($key, self::getAge());
|
||||
}
|
||||
|
||||
public static function Set($key, $value) {
|
||||
if (!self::isEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Cache::set($key, $value);
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -14,6 +14,7 @@ class ActivityStreams {
|
||||
public $meta = null;
|
||||
public $valid = false;
|
||||
public $deleted = false;
|
||||
public $portable_id = null;
|
||||
public $id = '';
|
||||
public $parent_id = '';
|
||||
public $type = '';
|
||||
@@ -23,10 +24,11 @@ class ActivityStreams {
|
||||
public $origin = null;
|
||||
public $owner = null;
|
||||
public $signer = null;
|
||||
public $ldsig = null;
|
||||
public $sig = null;
|
||||
public $sigok = false;
|
||||
public $recips = null;
|
||||
public $raw_recips = null;
|
||||
public $saved_recips = null;
|
||||
|
||||
/**
|
||||
* @brief Constructor for ActivityStreams.
|
||||
@@ -35,12 +37,13 @@ class ActivityStreams {
|
||||
*
|
||||
* @param string $string
|
||||
*/
|
||||
function __construct($string) {
|
||||
function __construct($string, $portable_id = null) {
|
||||
|
||||
if(!$string)
|
||||
return;
|
||||
|
||||
$this->raw = $string;
|
||||
$this->portable_id = $portable_id;
|
||||
|
||||
if (is_array($string)) {
|
||||
$this->data = $string;
|
||||
@@ -86,7 +89,16 @@ class ActivityStreams {
|
||||
|
||||
// Attempt to assemble an Activity from what we were given.
|
||||
if ($this->is_valid()) {
|
||||
$this->id = $this->get_property_obj('id');
|
||||
$this->id = $this->get_property_obj('id');
|
||||
|
||||
if (!$this->id) {
|
||||
logger('Data with mmissing id: ' . print_r($this->data, true));
|
||||
return;
|
||||
}
|
||||
|
||||
// cache for future use
|
||||
ASCache::Set($this->id, 'json:' . $this->raw);
|
||||
|
||||
$this->type = $this->get_primary_type();
|
||||
$this->actor = $this->get_actor('actor', '', '');
|
||||
$this->obj = $this->get_compound_property('object');
|
||||
@@ -94,11 +106,19 @@ class ActivityStreams {
|
||||
$this->origin = $this->get_compound_property('origin');
|
||||
$this->recips = $this->collect_recips();
|
||||
|
||||
$this->ldsig = $this->get_compound_property('signature');
|
||||
if ($this->ldsig) {
|
||||
$this->signer = $this->get_actor('creator', $this->ldsig);
|
||||
if ($this->signer && is_array($this->signer) && array_key_exists('publicKey', $this->signer) && is_array($this->signer['publicKey']) && $this->signer['publicKey']['publicKeyPem']) {
|
||||
$this->sigok = LDSignatures::verify($this->data, $this->signer['publicKey']['publicKeyPem']);
|
||||
$this->sig = $this->get_compound_property('proof');
|
||||
if ($this->sig) {
|
||||
$this->checkEddsaSignature(); // will set signer and sigok if everything works out
|
||||
}
|
||||
|
||||
// Try LDSignatures if edsig failed
|
||||
if (!$this->sigok) {
|
||||
$this->sig = $this->get_compound_property('signature');
|
||||
if ($this->sig) {
|
||||
$this->signer = $this->get_actor('creator', $this->sig);
|
||||
if ($this->signer && is_array($this->signer) && array_key_exists('publicKey', $this->signer) && is_array($this->signer['publicKey']) && $this->signer['publicKey']['publicKeyPem']) {
|
||||
$this->sigok = LDSignatures::verify($this->data, $this->signer['publicKey']['publicKeyPem']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,25 +130,34 @@ class ActivityStreams {
|
||||
}
|
||||
}
|
||||
|
||||
// fetch recursive or embedded activities
|
||||
// Fetch recursive or embedded activities
|
||||
|
||||
if ($this->obj && is_array($this->obj) && array_key_exists('object', $this->obj)) {
|
||||
$this->obj['object'] = $this->get_compound_property('object', $this->obj);
|
||||
}
|
||||
|
||||
if ($this->obj && is_array($this->obj) && isset($this->obj['actor']))
|
||||
// Enumerate and store actors in referenced objects
|
||||
|
||||
if ($this->obj && is_array($this->obj) && isset($this->obj['actor'])) {
|
||||
$this->obj['actor'] = $this->get_actor('actor', $this->obj);
|
||||
if ($this->tgt && is_array($this->tgt) && isset($this->tgt['actor']))
|
||||
}
|
||||
|
||||
if ($this->tgt && is_array($this->tgt) && isset($this->tgt['actor'])) {
|
||||
$this->tgt['actor'] = $this->get_actor('actor', $this->tgt);
|
||||
}
|
||||
|
||||
// Determine if this is a followup or response activity
|
||||
|
||||
$this->parent_id = $this->get_property_obj('inReplyTo');
|
||||
|
||||
if ((!$this->parent_id) && is_array($this->obj) && isset($this->obj['inReplyTo'])) {
|
||||
$this->parent_id = $this->obj['inReplyTo'];
|
||||
if (!$this->parent_id && isset($this->obj['inReplyTo'])) {
|
||||
$this->parent_id = ((is_array($this->obj['inReplyTo'])) ? $this->obj['inReplyTo']['id'] : $this->obj['inReplyTo']);
|
||||
}
|
||||
if ((!$this->parent_id) && is_array($this->obj) && isset($this->obj['id'])) {
|
||||
|
||||
if (!$this->parent_id && isset($this->obj['id'])) {
|
||||
$this->parent_id = $this->obj['id'];
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,7 +183,7 @@ class ActivityStreams {
|
||||
* @return mixed
|
||||
*/
|
||||
public function objprop(string $property, mixed $default = false): mixed {
|
||||
$x = $this->get_property_obj($property,$this->obj);
|
||||
$x = $this->get_property_obj($property, $this->obj);
|
||||
return (isset($x)) ? $x : $default;
|
||||
}
|
||||
|
||||
@@ -301,12 +330,27 @@ class ActivityStreams {
|
||||
* @return NULL|mixed
|
||||
*/
|
||||
|
||||
function fetch_property($url) {
|
||||
return self::fetch($url);
|
||||
}
|
||||
function fetch_property($url, $channel = null) {
|
||||
$x = null;
|
||||
|
||||
static function fetch($url, $channel = null) {
|
||||
return Activity::fetch($url, $channel);
|
||||
if (str_starts_with($url, z_root() . '/item/')) {
|
||||
$x = Activity::fetch_local($url, $this->portable_id ?? '');
|
||||
logger('local: ' . print_r($x,true));
|
||||
}
|
||||
|
||||
if (!$x) {
|
||||
$x = Activity::fetch($url, $channel);
|
||||
if ($x === null && strpos($url, '/channel/')) {
|
||||
// look for other nomadic channels which might be alive
|
||||
$zf = Zotfinger::exec($url, $channel);
|
||||
if ($zf) {
|
||||
$url = $zf['signature']['signer'];
|
||||
$x = Activity::fetch($url, $channel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $x;
|
||||
}
|
||||
|
||||
static function is_an_actor($s) {
|
||||
@@ -317,7 +361,7 @@ class ActivityStreams {
|
||||
if (!$s) {
|
||||
return false;
|
||||
}
|
||||
return (in_array($s, ['Like', 'Dislike', 'Flag', 'Block', 'Accept', 'Reject', 'TentativeAccept', 'TentativeReject', 'emojiReaction', 'EmojiReaction', 'EmojiReact']));
|
||||
return (in_array($s, ['Announce', 'Like', 'Dislike', 'Flag', 'Block', 'Accept', 'Reject', 'TentativeAccept', 'TentativeReject', 'emojiReaction', 'EmojiReaction', 'EmojiReact']));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -333,7 +377,7 @@ class ActivityStreams {
|
||||
$x = $this->get_property_obj($property, $base, $namespace);
|
||||
|
||||
if ($this->is_url($x)) {
|
||||
$y = Activity::get_cached_actor($x);
|
||||
$y = Activity::get_actor($x);
|
||||
if ($y) {
|
||||
return $y;
|
||||
}
|
||||
@@ -366,12 +410,24 @@ class ActivityStreams {
|
||||
$x = $this->get_property_obj($property, $base, $namespace);
|
||||
|
||||
if ($this->is_url($x)) {
|
||||
$y = $this->fetch_property($x);
|
||||
$cached = ASCache::Get($x);
|
||||
if ($cached) {
|
||||
// logger('AS cached: ' . $x);
|
||||
$y = unserialise($cached);
|
||||
}
|
||||
else {
|
||||
// logger('AS fetching: ' . $x);
|
||||
$y = $this->fetch_property($x);
|
||||
if ($y) {
|
||||
ASCache::Set($x, serialise($y));
|
||||
}
|
||||
}
|
||||
if (is_array($y)) {
|
||||
$x = $y;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// verify and unpack JSalmon signature if present
|
||||
|
||||
if (is_array($x) && array_key_exists('signed', $x)) {
|
||||
@@ -471,4 +527,58 @@ class ActivityStreams {
|
||||
|
||||
}
|
||||
|
||||
public function checkEddsaSignature() {
|
||||
$signer = $this->get_property_obj('verificationMethod', $this->sig);
|
||||
|
||||
$parseUrl = parse_url($signer);
|
||||
|
||||
if (isset($parseUrl['fragment'])) {
|
||||
if (str_starts_with($parseUrl['fragment'], 'z6Mk')) {
|
||||
$publicKey = $parseUrl['fragment'];
|
||||
}
|
||||
unset($parseUrl['fragment']);
|
||||
}
|
||||
|
||||
if (isset($parseUrl['query'])) {
|
||||
unset($parseUrl['query']);
|
||||
}
|
||||
|
||||
$url = unparse_url($parseUrl);
|
||||
|
||||
$hublocs = Activity::get_actor_hublocs($url);
|
||||
|
||||
$hasStoredKey = false;
|
||||
if ($hublocs) {
|
||||
foreach ($hublocs as $hubloc) {
|
||||
if ($publicKey && $hubloc['xchan_epubkey'] === $publicKey) {
|
||||
$hasStoredKey = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!$hasStoredKey) {
|
||||
$this->signer = Activity::get_actor($url);
|
||||
|
||||
if (isset($this->signer['assertionMethod'])) {
|
||||
if (!isset($this->signer['assertionMethod'][0])) {
|
||||
$this->signer['assertionMethod'] = [$this->signer['assertionMethod']];
|
||||
}
|
||||
|
||||
foreach($this->signer['assertionMethod'] as $am) {
|
||||
if ($url === $am['controller'] &&
|
||||
$am['type'] === 'Multikey' &&
|
||||
str_starts_with($am['publicKeyMultibase'], 'z6Mk')
|
||||
) {
|
||||
$publicKey = $am['publicKeyMultibase'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($publicKey) {
|
||||
$this->sigok = (new JcsEddsa2022)->verify($this->data, $publicKey);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -352,8 +352,6 @@ class Apps {
|
||||
'Directory' => t('Directory'),
|
||||
'Help' => t('Help'),
|
||||
'Mail' => t('Mail'),
|
||||
'Mood' => t('Mood'),
|
||||
'Poke' => t('Poke'),
|
||||
'Chat' => t('Chat'),
|
||||
'Search' => t('Search'),
|
||||
'Probe' => t('Probe'),
|
||||
@@ -419,11 +417,28 @@ class Apps {
|
||||
static public function app_render($papp, $mode = 'view') {
|
||||
$installed = false;
|
||||
|
||||
if(! $papp)
|
||||
if(!$papp) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(! $papp['photo'])
|
||||
/**
|
||||
* @hooks app_render_before
|
||||
* Hook to manipulate the papp array before rendering
|
||||
*/
|
||||
|
||||
$hookinfo = [
|
||||
'name' => $papp['name'],
|
||||
'photo' => $papp['photo']
|
||||
];
|
||||
|
||||
call_hooks('app_render_manipulate_photo', $hookinfo);
|
||||
|
||||
// We will only allow to manipulate the photo
|
||||
$papp['photo'] = $hookinfo['photo'];
|
||||
|
||||
if(!$papp['photo']) {
|
||||
$papp['photo'] = 'icon:gear';
|
||||
}
|
||||
|
||||
self::translate_system_apps($papp);
|
||||
|
||||
|
||||
@@ -5,50 +5,52 @@ namespace Zotlabs\Lib;
|
||||
/**
|
||||
* cache api
|
||||
*/
|
||||
|
||||
|
||||
class Cache {
|
||||
|
||||
|
||||
/**
|
||||
* @brief Returns cached content
|
||||
*
|
||||
*
|
||||
* @param string $key
|
||||
* @param string $age in SQL format, default is '30 DAY'
|
||||
* @return string
|
||||
*/
|
||||
|
||||
public static function get($key, $age = '') {
|
||||
|
||||
$hash = hash('whirlpool',$key);
|
||||
public static function get($key, $age = '') {
|
||||
// $hash = hash('whirlpool',$key);
|
||||
$hash = uuid_from_url($key);
|
||||
|
||||
$r = q("SELECT v FROM cache WHERE k = '%s' AND updated > %s - INTERVAL %s LIMIT 1",
|
||||
dbesc($hash),
|
||||
db_utcnow(),
|
||||
db_quoteinterval(($age ? $age : get_config('system','object_cache_days', '30') . ' DAY'))
|
||||
);
|
||||
|
||||
|
||||
if ($r)
|
||||
return $r[0]['v'];
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public static function set($key,$value) {
|
||||
// $hash = hash('whirlpool',$key);
|
||||
$hash = uuid_from_url($key);
|
||||
|
||||
$hash = hash('whirlpool',$key);
|
||||
|
||||
$r = q("SELECT * FROM cache WHERE k = '%s' limit 1",
|
||||
$r = q("SELECT * FROM cache WHERE k = '%s' LIMIT 1",
|
||||
dbesc($hash)
|
||||
);
|
||||
if($r) {
|
||||
q("UPDATE cache SET v = '%s', updated = '%s' WHERE k = '%s'",
|
||||
dbesc($value),
|
||||
dbesc(datetime_convert()),
|
||||
dbesc($hash));
|
||||
dbesc($hash)
|
||||
);
|
||||
}
|
||||
else {
|
||||
q("INSERT INTO cache ( k, v, updated) VALUES ('%s','%s','%s')",
|
||||
q("INSERT INTO cache (k, v, updated) VALUES ('%s', '%s', '%s')",
|
||||
dbesc($hash),
|
||||
dbesc($value),
|
||||
dbesc(datetime_convert()));
|
||||
dbesc(datetime_convert())
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
use App;
|
||||
|
||||
class Config {
|
||||
|
||||
@@ -14,20 +15,41 @@ class Config {
|
||||
* @param string $family
|
||||
* The category of the configuration value
|
||||
*/
|
||||
static public function Load($family) {
|
||||
if(! array_key_exists($family, \App::$config))
|
||||
\App::$config[$family] = array();
|
||||
public static function Load($family, $recursionCounter = 0) {
|
||||
if (! array_key_exists($family, App::$config)) {
|
||||
App::$config[$family] = [];
|
||||
}
|
||||
|
||||
if(! array_key_exists('config_loaded', \App::$config[$family])) {
|
||||
// We typically continue when presented with minor DB issues,
|
||||
// but loading the site configuration is more important.
|
||||
|
||||
// Check for query returning false and give it approx 30 seconds
|
||||
// to recover if there's a problem. This is intended to fix a
|
||||
// rare issue on Galera where temporary sync issues were causing
|
||||
// the site encryption keys to be regenerated, which was causing
|
||||
// communication issues for members.
|
||||
|
||||
// This code probably belongs at the database layer, but we don't
|
||||
// necessarily want to shut the site down for problematic queries
|
||||
// caused by bad data. That could be used in a denial of service
|
||||
// attack. Those do need to be (and they are) logged.
|
||||
|
||||
if (! array_key_exists('config_loaded', App::$config[$family])) {
|
||||
$r = q("SELECT * FROM config WHERE cat = '%s'", dbesc($family));
|
||||
if($r !== false) {
|
||||
if($r) {
|
||||
foreach($r as $rr) {
|
||||
$k = $rr['k'];
|
||||
\App::$config[$family][$k] = $rr['v'];
|
||||
}
|
||||
if ($r === false && !App::$install) {
|
||||
sleep(3);
|
||||
$recursionCounter ++;
|
||||
if ($recursionCounter > 10) {
|
||||
system_unavailable();
|
||||
}
|
||||
\App::$config[$family]['config_loaded'] = true;
|
||||
self::Load($family, $recursionCounter);
|
||||
}
|
||||
elseif (is_array($r)) {
|
||||
foreach ($r as $rr) {
|
||||
$k = $rr['k'];
|
||||
App::$config[$family][$k] = $rr['v'];
|
||||
}
|
||||
App::$config[$family]['config_loaded'] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -46,19 +68,19 @@ class Config {
|
||||
* @return mixed
|
||||
* Return the set value, or false if the database update failed
|
||||
*/
|
||||
static public function Set($family, $key, $value) {
|
||||
public static function Set($family, $key, $value) {
|
||||
// manage array value
|
||||
$dbvalue = ((is_array($value)) ? serialize($value) : $value);
|
||||
$dbvalue = ((is_array($value)) ? 'json:' . json_encode($value) : $value);
|
||||
$dbvalue = ((is_bool($dbvalue)) ? intval($dbvalue) : $dbvalue);
|
||||
|
||||
if(self::Get($family, $key) === false || (! self::get_from_storage($family, $key))) {
|
||||
if (self::Get($family, $key) === false || (! self::get_from_storage($family, $key))) {
|
||||
$ret = q("INSERT INTO config ( cat, k, v ) VALUES ( '%s', '%s', '%s' ) ",
|
||||
dbesc($family),
|
||||
dbesc($key),
|
||||
dbesc($dbvalue)
|
||||
);
|
||||
if($ret) {
|
||||
\App::$config[$family][$key] = $value;
|
||||
if ($ret) {
|
||||
App::$config[$family][$key] = $value;
|
||||
$ret = $value;
|
||||
}
|
||||
return $ret;
|
||||
@@ -70,8 +92,8 @@ class Config {
|
||||
dbesc($key)
|
||||
);
|
||||
|
||||
if($ret) {
|
||||
\App::$config[$family][$key] = $value;
|
||||
if ($ret) {
|
||||
App::$config[$family][$key] = $value;
|
||||
$ret = $value;
|
||||
}
|
||||
|
||||
@@ -96,18 +118,34 @@ class Config {
|
||||
* @param string $default (optional) default false
|
||||
* @return mixed Return value or false on error or if not set
|
||||
*/
|
||||
static public function Get($family, $key, $default = false) {
|
||||
if((! array_key_exists($family, \App::$config)) || (! array_key_exists('config_loaded', \App::$config[$family])))
|
||||
self::Load($family);
|
||||
public static function Get($family, $key, $default = false) {
|
||||
|
||||
if(array_key_exists('config_loaded', \App::$config[$family])) {
|
||||
if(! array_key_exists($key, \App::$config[$family])) {
|
||||
if ((! array_key_exists($family, App::$config)) || (! array_key_exists('config_loaded', App::$config[$family]))) {
|
||||
self::Load($family);
|
||||
}
|
||||
|
||||
if (array_key_exists('config_loaded', App::$config[$family])) {
|
||||
if (! array_key_exists($key, App::$config[$family])) {
|
||||
return $default;
|
||||
}
|
||||
return ((! is_array(\App::$config[$family][$key])) && (preg_match('|^a:[0-9]+:{.*}$|s', \App::$config[$family][$key]))
|
||||
? unserialize(\App::$config[$family][$key])
|
||||
: \App::$config[$family][$key]
|
||||
);
|
||||
|
||||
$value = App::$config[$family][$key];
|
||||
|
||||
if (! is_array($value)) {
|
||||
if (substr($value, 0, 5) == 'json:') {
|
||||
return json_decode(substr($value, 5), true);
|
||||
} else if (preg_match('|^a:[0-9]+:{.*}$|s', $value)) {
|
||||
// Unserialize in inherently unsafe. Try to mitigate by not
|
||||
// allowing unserializing objects. Only kept for backwards
|
||||
// compatibility. JSON serialization should be prefered.
|
||||
return unserialize($value, array('allowed_classes' => false));
|
||||
} else {
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
|
||||
return $default;
|
||||
@@ -125,12 +163,13 @@ class Config {
|
||||
* The configuration key to delete
|
||||
* @return mixed
|
||||
*/
|
||||
static public function Delete($family, $key) {
|
||||
public static function Delete($family, $key) {
|
||||
|
||||
$ret = false;
|
||||
|
||||
if(array_key_exists($family, \App::$config) && array_key_exists($key, \App::$config[$family]))
|
||||
unset(\App::$config[$family][$key]);
|
||||
if (array_key_exists($family, App::$config) && array_key_exists($key, App::$config[$family])) {
|
||||
unset(App::$config[$family][$key]);
|
||||
}
|
||||
|
||||
$ret = q("DELETE FROM config WHERE cat = '%s' AND k = '%s'",
|
||||
dbesc($family),
|
||||
@@ -153,7 +192,7 @@ class Config {
|
||||
* The configuration key to query
|
||||
* @return mixed
|
||||
*/
|
||||
static private function get_from_storage($family,$key) {
|
||||
private static function get_from_storage($family, $key) {
|
||||
$ret = q("SELECT * FROM config WHERE cat = '%s' AND k = '%s' LIMIT 1",
|
||||
dbesc($family),
|
||||
dbesc($key)
|
||||
@@ -161,5 +200,4 @@ class Config {
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -69,7 +69,8 @@ class Connect {
|
||||
$xchan_hash = '';
|
||||
$sql_options = (($protocol) ? " and xchan_network = '" . dbesc($protocol) . "' " : '');
|
||||
|
||||
$r = q("SELECT * FROM xchan LEFT JOIN hubloc ON xchan_hash = hubloc_hash WHERE ( xchan_hash = '%s' or xchan_url = '%s' or xchan_addr = '%s') $sql_options ORDER BY hubloc_id DESC",
|
||||
// We need both, the xchan and the hubloc here hence use JOIN instead of LEFT JOIN
|
||||
$r = q("SELECT * FROM xchan JOIN hubloc ON xchan_hash = hubloc_hash WHERE ( xchan_hash = '%s' or xchan_url = '%s' or xchan_addr = '%s') $sql_options ORDER BY hubloc_id DESC",
|
||||
dbesc($url),
|
||||
dbesc($url),
|
||||
dbesc($url)
|
||||
|
||||
@@ -6,23 +6,26 @@ class DReport {
|
||||
private $location;
|
||||
private $sender;
|
||||
private $recipient;
|
||||
private $name;
|
||||
private $message_id;
|
||||
private $message_uuid;
|
||||
private $status;
|
||||
private $date;
|
||||
|
||||
function __construct($location,$sender,$recipient,$message_id,$status = 'deliver') {
|
||||
$this->location = $location;
|
||||
$this->sender = $sender;
|
||||
$this->recipient = $recipient;
|
||||
$this->name = EMPTY_STR;
|
||||
$this->message_id = $message_id;
|
||||
$this->status = $status;
|
||||
$this->date = datetime_convert();
|
||||
function __construct($location, $sender, $recipient, $message_id, $message_uuid = '', $status = 'deliver') {
|
||||
$this->location = $location;
|
||||
$this->sender = $sender;
|
||||
$this->recipient = $recipient;
|
||||
$this->name = EMPTY_STR;
|
||||
$this->message_id = $message_id;
|
||||
$this->message_uuid = $message_uuid;
|
||||
$this->status = $status;
|
||||
$this->date = datetime_convert();
|
||||
}
|
||||
|
||||
function update($status) {
|
||||
$this->status = $status;
|
||||
$this->date = datetime_convert();
|
||||
$this->status = $status;
|
||||
$this->date = datetime_convert();
|
||||
}
|
||||
|
||||
function set_name($name) {
|
||||
@@ -35,24 +38,26 @@ class DReport {
|
||||
|
||||
|
||||
function set($arr) {
|
||||
$this->location = $arr['location'];
|
||||
$this->sender = $arr['sender'];
|
||||
$this->recipient = $arr['recipient'];
|
||||
$this->name = $arr['name'];
|
||||
$this->message_id = $arr['message_id'];
|
||||
$this->status = $arr['status'];
|
||||
$this->date = $arr['date'];
|
||||
$this->location = $arr['location'];
|
||||
$this->sender = $arr['sender'];
|
||||
$this->recipient = $arr['recipient'];
|
||||
$this->name = $arr['name'];
|
||||
$this->message_id = $arr['message_id'];
|
||||
$this->message_uuid = $arr['message_uuid'] ?? '';
|
||||
$this->status = $arr['status'];
|
||||
$this->date = $arr['date'];
|
||||
}
|
||||
|
||||
function get() {
|
||||
return array(
|
||||
'location' => $this->location,
|
||||
'sender' => $this->sender,
|
||||
'recipient' => $this->recipient,
|
||||
'name' => $this->name,
|
||||
'message_id' => $this->message_id,
|
||||
'status' => $this->status,
|
||||
'date' => $this->date
|
||||
'location' => $this->location,
|
||||
'sender' => $this->sender,
|
||||
'recipient' => $this->recipient,
|
||||
'name' => $this->name,
|
||||
'message_id' => $this->message_id,
|
||||
'message_uuid' => $this->message_uuid,
|
||||
'status' => $this->status,
|
||||
'date' => $this->date
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -145,11 +145,11 @@ class Enotify {
|
||||
|
||||
$itemlink = $params['link'];
|
||||
|
||||
$action = t('commented on');
|
||||
$action = (($moderated) ? t('requested to comment on') : t('commented on'));
|
||||
|
||||
if(array_key_exists('item',$params)) {
|
||||
|
||||
if(in_array($params['item']['verb'], [ACTIVITY_LIKE, ACTIVITY_DISLIKE])) {
|
||||
if(in_array($params['item']['verb'], ['Like', 'Dislike', ACTIVITY_LIKE, ACTIVITY_DISLIKE, ACTIVITY_SHARE])) {
|
||||
|
||||
if(! $always_show_in_notices || !($vnotify & VNOTIFY_LIKE)) {
|
||||
logger('notification: not a visible activity. Ignoring.');
|
||||
@@ -157,11 +157,14 @@ class Enotify {
|
||||
return;
|
||||
}
|
||||
|
||||
if(activity_match($params['verb'], ACTIVITY_LIKE))
|
||||
$action = t('liked');
|
||||
if(activity_match($params['verb'], ['Like', ACTIVITY_LIKE]))
|
||||
$action = (($moderated) ? t('requested to like') : t('liked'));
|
||||
|
||||
if(activity_match($params['verb'], ACTIVITY_DISLIKE))
|
||||
$action = t('disliked');
|
||||
if(activity_match($params['verb'], ['Dislike', ACTIVITY_DISLIKE]))
|
||||
$action = (($moderated) ? t('requested to dislike') : t('disliked'));
|
||||
|
||||
if(activity_match($params['verb'], ACTIVITY_SHARE))
|
||||
$action = t('repeated');
|
||||
|
||||
}
|
||||
|
||||
@@ -259,7 +262,7 @@ class Enotify {
|
||||
|
||||
$itemlink = $params['link'];
|
||||
|
||||
if (array_key_exists('item',$params) && (activity_match($params['item']['verb'], ACTIVITY_LIKE) || activity_match($params['item']['verb'], ACTIVITY_DISLIKE))) {
|
||||
if (array_key_exists('item',$params) && (activity_match($params['item']['verb'], ['Like', 'Dislike', ACTIVITY_LIKE, ACTIVITY_DISLIKE]))) {
|
||||
if(! $always_show_in_notices || !($vnotify & VNOTIFY_LIKE) || !feature_enabled($recip['channel_id'], 'dislike')) {
|
||||
logger('notification: not a visible activity. Ignoring.');
|
||||
pop_lang();
|
||||
@@ -307,7 +310,14 @@ class Enotify {
|
||||
|
||||
$parent_item = $p[0];
|
||||
|
||||
$verb = ((activity_match($params['item']['verb'], ACTIVITY_DISLIKE)) ? t('disliked') : t('liked'));
|
||||
//$verb = ((activity_match($params['item']['verb'], ACTIVITY_DISLIKE)) ? t('disliked') : t('liked'));
|
||||
$moderated = (($params['item']['item_blocked'] == ITEM_MODERATED) ? true : false);
|
||||
|
||||
if(activity_match($params['item']['verb'], ['Like', ACTIVITY_LIKE]))
|
||||
$verb = (($moderated) ? t('requested to like') : t('liked'));
|
||||
|
||||
if(activity_match($params['item']['verb'], ['Dislike', ACTIVITY_DISLIKE]))
|
||||
$verb = (($moderated) ? t('requested to dislike') : t('disliked'));
|
||||
|
||||
// "your post"
|
||||
if($p[0]['owner']['xchan_name'] === $p[0]['author']['xchan_name'] && intval($p[0]['item_wall']))
|
||||
@@ -476,6 +486,8 @@ class Enotify {
|
||||
|
||||
require_once('include/html2bbcode.php');
|
||||
|
||||
/*
|
||||
|
||||
do {
|
||||
$dups = false;
|
||||
$hash = random_string();
|
||||
@@ -484,10 +496,12 @@ class Enotify {
|
||||
if ($r)
|
||||
$dups = true;
|
||||
} while ($dups === true);
|
||||
*/
|
||||
|
||||
|
||||
|
||||
$datarray = [];
|
||||
$datarray['hash'] = $hash;
|
||||
$datarray['hash'] = $params['item']['uuid'] ?? new_uuid();
|
||||
$datarray['sender_hash'] = $sender['xchan_hash'];
|
||||
$datarray['xname'] = $sender['xchan_name'];
|
||||
$datarray['url'] = $sender['xchan_url'];
|
||||
@@ -498,7 +512,7 @@ class Enotify {
|
||||
$datarray['link'] = $itemlink;
|
||||
$datarray['parent'] = $parent_mid;
|
||||
$datarray['parent_item'] = $parent_item;
|
||||
$datarray['ntype'] = $params['type'] ?? '';
|
||||
$datarray['ntype'] = $params['type'] ?? 0;
|
||||
$datarray['verb'] = $params['verb'] ?? '';
|
||||
$datarray['otype'] = $params['otype'] ?? '';
|
||||
$datarray['abort'] = false;
|
||||
@@ -546,8 +560,9 @@ class Enotify {
|
||||
dbesc($datarray['otype'])
|
||||
);
|
||||
|
||||
$r = q("select id from notify where hash = '%s' and uid = %d limit 1",
|
||||
dbesc($hash),
|
||||
$r = q("select id from notify where hash = '%s' and ntype = %d and uid = %d limit 1",
|
||||
dbesc($datarray['hash']),
|
||||
intval($datarray['ntype']),
|
||||
intval($recip['channel_id'])
|
||||
);
|
||||
if ($r) {
|
||||
@@ -828,18 +843,6 @@ class Enotify {
|
||||
: (($item['obj_type'] === 'Answer') ? sprintf( t('voted on %s\'s poll'), '[bdi]' . $item['owner']['xchan_name'] . '[/bdi]') : sprintf( t('commented on %s\'s post'), '[bdi]' . $item['owner']['xchan_name'] . '[/bdi]'))
|
||||
);
|
||||
|
||||
if($item['verb'] === ACTIVITY_SHARE && empty($item['owner']['xchan_pubforum'])) {
|
||||
$itemem_text = sprintf( t('repeated %s\'s post'), '[bdi]' . $item['author']['xchan_name'] . '[/bdi]');
|
||||
}
|
||||
|
||||
if($item['verb'] === ACTIVITY_LIKE) {
|
||||
$itemem_text = sprintf( t('liked %s\'s post'), '[bdi]' . $item['author']['xchan_name'] . '[/bdi]');
|
||||
}
|
||||
|
||||
if($item['verb'] === ACTIVITY_DISLIKE) {
|
||||
$itemem_text = sprintf( t('disliked %s\'s post'), '[bdi]' . $item['author']['xchan_name'] . '[/bdi]');
|
||||
}
|
||||
|
||||
if(in_array($item['obj_type'], ['Document', 'Video', 'Audio', 'Image'])) {
|
||||
$itemem_text = t('shared a file with you');
|
||||
}
|
||||
@@ -860,7 +863,6 @@ class Enotify {
|
||||
|
||||
// convert this logic into a json array just like the system notifications
|
||||
|
||||
$who = (($item['verb'] === ACTIVITY_SHARE && empty($item['owner']['xchan_pubforum'])) ? 'owner' : 'author');
|
||||
$body = html2plain(bbcode($item['body'], ['drop_media' => true, 'tryoembed' => false]), 75, true);
|
||||
if ($body) {
|
||||
$body = htmlentities($body, ENT_QUOTES, 'UTF-8', false);
|
||||
@@ -868,19 +870,20 @@ class Enotify {
|
||||
|
||||
$x = array(
|
||||
'notify_link' => $item['llink'],
|
||||
'name' => $item[$who]['xchan_name'],
|
||||
'addr' => $item[$who]['xchan_addr'] ? $item[$who]['xchan_addr'] : $item[$who]['xchan_url'],
|
||||
'url' => $item[$who]['xchan_url'],
|
||||
'photo' => $item[$who]['xchan_photo_s'],
|
||||
'name' => $item['author']['xchan_name'],
|
||||
'addr' => $item['author']['xchan_addr'] ? $item['author']['xchan_addr'] : $item['author']['xchan_url'],
|
||||
'url' => $item['author']['xchan_url'],
|
||||
'photo' => $item['author']['xchan_photo_s'],
|
||||
'when' => (($edit) ? datetime_convert('UTC', date_default_timezone_get(), $item['edited']) : datetime_convert('UTC', date_default_timezone_get(), $item['created'])),
|
||||
'class' => (intval($item['item_unseen']) ? 'notify-unseen' : 'notify-seen'),
|
||||
'b64mid' => (($item['mid']) ? gen_link_id($item['mid']) : ''),
|
||||
// 'b64mid' => (($item['mid']) ? gen_link_id($item['mid']) : ''),
|
||||
'b64mid' => (($item['uuid']) ? $item['uuid'] : ''),
|
||||
//'b64mid' => ((in_array($item['verb'], [ACTIVITY_LIKE, ACTIVITY_DISLIKE])) ? gen_link_id($item['thr_parent']) : gen_link_id($item['mid'])),
|
||||
'thread_top' => (($item['item_thread_top']) ? true : false),
|
||||
'message' => bbcode(escape_tags($itemem_text)),
|
||||
'body' => $body,
|
||||
// these are for the superblock addon
|
||||
'hash' => $item[$who]['xchan_hash'],
|
||||
'hash' => $item['author']['xchan_hash'],
|
||||
'uid' => $item['uid'],
|
||||
'display' => true
|
||||
);
|
||||
@@ -900,9 +903,6 @@ class Enotify {
|
||||
if(strpos($message, $tt['xname']) === 0)
|
||||
$message = substr($message, strlen($tt['xname']) + 1);
|
||||
|
||||
$mid = basename($tt['link']);
|
||||
|
||||
$b64mid = gen_link_id($mid);
|
||||
$x = [
|
||||
'notify_link' => (($tt['ntype'] === NOTIFY_MAIL) ? $tt['link'] : z_root() . '/notify/view/' . $tt['id']),
|
||||
'name' => $tt['xname'],
|
||||
@@ -910,7 +910,7 @@ class Enotify {
|
||||
'photo' => $tt['photo'],
|
||||
'when' => datetime_convert('UTC', date_default_timezone_get(), $tt['created']),
|
||||
'hclass' => (($tt['seen']) ? 'notify-seen' : 'notify-unseen'),
|
||||
'b64mid' => (($tt['otype'] == 'item') ? $b64mid : ''),
|
||||
'b64mid' => (($tt['otype'] == 'item') ? $tt['hash'] : ''),
|
||||
'notify_id' => (($tt['otype'] == 'item') ? $tt['id'] : ''),
|
||||
'message' => $message
|
||||
];
|
||||
|
||||
@@ -13,7 +13,7 @@ class IConfig {
|
||||
static public function Get(&$item, $family, $key, $default = false) {
|
||||
|
||||
$is_item = false;
|
||||
|
||||
|
||||
if(is_array($item)) {
|
||||
$is_item = true;
|
||||
if((! array_key_exists('iconfig',$item)) || (! is_array($item['iconfig'])))
|
||||
@@ -22,7 +22,7 @@ class IConfig {
|
||||
if(array_key_exists('item_id',$item))
|
||||
$iid = $item['item_id'];
|
||||
else
|
||||
$iid = $item['id'];
|
||||
$iid = $item['id'] ?? 0;
|
||||
}
|
||||
elseif(intval($item))
|
||||
$iid = $item;
|
||||
@@ -36,7 +36,7 @@ class IConfig {
|
||||
return $c['v'];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$r = q("select * from iconfig where iid = %d and cat = '%s' and k = '%s' limit 1",
|
||||
intval($iid),
|
||||
dbesc($family),
|
||||
@@ -63,11 +63,11 @@ class IConfig {
|
||||
* $value - value of meta variable
|
||||
* $sharing - boolean (default false); if true the meta information is propagated with the item
|
||||
* to other sites/channels, mostly useful when $item is an array and has not yet been stored/delivered.
|
||||
* If the meta information is added after delivery and you wish it to be shared, it may be necessary to
|
||||
* alter the item edited timestamp and invoke the delivery process on the updated item. The edited
|
||||
* If the meta information is added after delivery and you wish it to be shared, it may be necessary to
|
||||
* alter the item edited timestamp and invoke the delivery process on the updated item. The edited
|
||||
* timestamp needs to be altered in order to trigger an item_store_update() at the receiving end.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
static public function Set(&$item, $family, $key, $value, $sharing = false) {
|
||||
|
||||
@@ -162,4 +162,4 @@ class IConfig {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ class JSalmon {
|
||||
. base64url_encode($x['alg'],true);
|
||||
|
||||
$key = HTTPSig::get_key(EMPTY_STR,'zot6',base64url_decode($x['sigs']['key_id']));
|
||||
logger('key: ' . print_r($key,true));
|
||||
logger('key: ' . print_r($key,true), LOGGER_DATA);
|
||||
if($key['portable_id'] && $key['public_key']) {
|
||||
if(Crypto::verify($signed_data,base64url_decode($x['sigs']['value']),$key['public_key'])) {
|
||||
logger('verified');
|
||||
|
||||
92
Zotlabs/Lib/JcsEddsa2022.php
Normal file
92
Zotlabs/Lib/JcsEddsa2022.php
Normal file
@@ -0,0 +1,92 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
use Mmccook\JsonCanonicalizator\JsonCanonicalizatorFactory;
|
||||
use StephenHill\Base58;
|
||||
|
||||
class JcsEddsa2022 {
|
||||
|
||||
public function __construct() {
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function sign($data, $channel): array {
|
||||
$base58 = new Base58();
|
||||
$pubkey = (new Multibase())->publicKey($channel['channel_epubkey']);
|
||||
$options = [
|
||||
'type' => 'DataIntegrityProof',
|
||||
'cryptosuite' => 'eddsa-jcs-2022',
|
||||
'created' => datetime_convert('UTC', 'UTC', 'now', ATOM_TIME),
|
||||
'verificationMethod' => channel_url($channel) . '#' . $pubkey,
|
||||
'proofPurpose' => 'assertionMethod',
|
||||
];
|
||||
|
||||
$optionsHash = $this->hash($this->signableOptions($options), true);
|
||||
$dataHash = $this->hash($this->signableData($data), true);
|
||||
|
||||
$options['proofValue'] = 'z' . $base58->encode(sodium_crypto_sign_detached($optionsHash . $dataHash,
|
||||
sodium_base642bin($channel['channel_eprvkey'], SODIUM_BASE64_VARIANT_ORIGINAL_NO_PADDING)));
|
||||
|
||||
return $options;
|
||||
}
|
||||
|
||||
public function verify($data, $publicKey) {
|
||||
$base58 = new Base58();
|
||||
$encodedSignature = $data['proof']['proofValue'] ?? '';
|
||||
if (!str_starts_with($encodedSignature,'z')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$encodedSignature = substr($encodedSignature, 1);
|
||||
$optionsHash = $this->hash($this->signableOptions($data['proof']), true);
|
||||
$dataHash = $this->hash($this->signableData($data),true);
|
||||
|
||||
try {
|
||||
$result = sodium_crypto_sign_verify_detached($base58->decode($encodedSignature), $optionsHash . $dataHash,
|
||||
(new Multibase())->decode($publicKey, true));
|
||||
}
|
||||
catch (\Exception $e) {
|
||||
logger('verify exception:' . $e->getMessage());
|
||||
}
|
||||
|
||||
logger('SignatureVerify (eddsa-jcs-2022) ' . (($result) ? 'true' : 'false'));
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function signableData($data) {
|
||||
$signableData = [];
|
||||
if ($data) {
|
||||
foreach ($data as $k => $v) {
|
||||
if (!in_array($k, ['proof', 'signature'])) {
|
||||
$signableData[$k] = $v;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $signableData;
|
||||
}
|
||||
|
||||
public function signableOptions($options) {
|
||||
$signableOptions = [];
|
||||
|
||||
if ($options) {
|
||||
foreach ($options as $k => $v) {
|
||||
if ($k !== 'proofValue') {
|
||||
$signableOptions[$k] = $v;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $signableOptions;
|
||||
}
|
||||
|
||||
public function hash($obj, $binary = false) {
|
||||
return hash('sha256', $this->canonicalize($obj), $binary);
|
||||
}
|
||||
|
||||
public function canonicalize($data) {
|
||||
$canonicalization = JsonCanonicalizatorFactory::getInstance();
|
||||
return $canonicalization->canonicalize($data);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -141,7 +141,7 @@ class Libsync {
|
||||
|
||||
$total = count($synchubs);
|
||||
foreach ($synchubs as $hub) {
|
||||
$hash = random_string();
|
||||
$hash = new_uuid();
|
||||
$n = Libzot::build_packet($channel, 'sync', $env_recips, json_encode($info), 'hz', $hub['hubloc_sitekey'], $hub['site_crypto']);
|
||||
Queue::insert([
|
||||
'hash' => $hash,
|
||||
@@ -325,10 +325,7 @@ class Libsync {
|
||||
|
||||
if (array_key_exists('channel', $arr) && is_array($arr['channel']) && count($arr['channel'])) {
|
||||
|
||||
$remote_channel = $arr['channel'];
|
||||
$remote_channel['channel_id'] = $channel['channel_id'];
|
||||
|
||||
if (array_key_exists('channel_pageflags', $arr['channel']) && intval($arr['channel']['channel_pageflags'])) {
|
||||
if (array_key_exists('channel_pageflags', $arr['channel'])) {
|
||||
|
||||
// Several pageflags are site-specific and cannot be sync'd.
|
||||
// Only allow those bits which are shareable from the remote and then
|
||||
@@ -339,6 +336,8 @@ class Libsync {
|
||||
|
||||
}
|
||||
|
||||
$columns = db_columns('channel');
|
||||
|
||||
$disallowed = [
|
||||
'channel_id', 'channel_account_id', 'channel_primary', 'channel_prvkey',
|
||||
'channel_address', 'channel_notifyflags', 'channel_removed', 'channel_deleted',
|
||||
@@ -349,16 +348,21 @@ class Libsync {
|
||||
'channel_a_delegate'
|
||||
];
|
||||
|
||||
$clean = [];
|
||||
foreach ($arr['channel'] as $k => $v) {
|
||||
if (in_array($k, $disallowed))
|
||||
continue;
|
||||
$clean[$k] = $v;
|
||||
if (empty($channel['channel_epubkey']) && empty($channel['channel_eprvkey'])) {
|
||||
$eckey = sodium_crypto_sign_keypair();
|
||||
$channel['channel_epubkey'] = sodium_bin2base64(sodium_crypto_sign_publickey($eckey), SODIUM_BASE64_VARIANT_ORIGINAL_NO_PADDING);
|
||||
$channel['channel_eprvkey'] = sodium_bin2base64(sodium_crypto_sign_secretkey($eckey), SODIUM_BASE64_VARIANT_ORIGINAL_NO_PADDING);
|
||||
}
|
||||
if (count($clean)) {
|
||||
foreach ($clean as $k => $v) {
|
||||
dbq("UPDATE channel set " . dbesc($k) . " = '" . dbesc($v) . "' where channel_id = " . intval($channel['channel_id']));
|
||||
|
||||
foreach ($arr['channel'] as $k => $v) {
|
||||
if (in_array($k, $disallowed)) {
|
||||
continue;
|
||||
}
|
||||
if (!in_array($k, $columns)) {
|
||||
continue;
|
||||
}
|
||||
$r = dbq("UPDATE channel set " . dbesc($k) . " = '" . dbesc($v)
|
||||
. "' where channel_id = " . intval($channel['channel_id']));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -771,7 +775,12 @@ class Libsync {
|
||||
|
||||
static function sync_locations($sender, $arr) {
|
||||
|
||||
$ret = [];
|
||||
$ret = [
|
||||
'change_message' => '',
|
||||
'changed' => false,
|
||||
'message' => ''
|
||||
];
|
||||
|
||||
$what = '';
|
||||
$changed = false;
|
||||
|
||||
@@ -786,7 +795,7 @@ class Libsync {
|
||||
|
||||
if (isset($arr['locations']) && $arr['locations']) {
|
||||
|
||||
$xisting = q("select * from hubloc where hubloc_hash = '%s'",
|
||||
$xisting = q("select * from hubloc where hubloc_hash = '%s' and hubloc_deleted = 0",
|
||||
dbesc($sender['hash'])
|
||||
);
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -172,13 +172,12 @@ class Libzotdir {
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Checks the directory mode of this hub.
|
||||
* @brief fetches updates from known directories
|
||||
*
|
||||
* Checks the directory mode of this hub to see if it is some form of directory server. If it is,
|
||||
* get the directory realm of this hub. Fetch a list of all other directory servers in this realm and request
|
||||
* a directory sync packet. This will contain both directory updates and new ratings. Store these all in the DB.
|
||||
* In the case of updates, we will query each of them asynchronously from a poller task. Ratings are stored
|
||||
* directly if the rater's signature matches.
|
||||
* a directory sync packet. Store these all in the DB.
|
||||
* In the case of updates, we will query each of them asynchronously from a poller task.
|
||||
*
|
||||
* @param int $dirmode;
|
||||
*/
|
||||
@@ -233,6 +232,8 @@ class Libzotdir {
|
||||
if (! $r)
|
||||
return;
|
||||
|
||||
$dir_trusted_hosts = array_merge(get_directory_fallback_servers(), get_config('system', 'trusted_directory_servers', []));
|
||||
|
||||
foreach ($r as $rr) {
|
||||
if (! $rr['site_directory'])
|
||||
continue;
|
||||
@@ -264,31 +265,65 @@ class Libzotdir {
|
||||
|
||||
if (is_array($j['transactions']) && count($j['transactions'])) {
|
||||
foreach ($j['transactions'] as $t) {
|
||||
|
||||
if (empty($t['hash']) || empty($t['transaction_id']) || empty($t['address'])) {
|
||||
if (empty($t['hash']) || empty($t['host']) || empty($t['address'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$r = q("select * from updates where ud_guid = '%s' limit 1",
|
||||
dbesc($t['transaction_id'])
|
||||
$r = q("select * from updates where ud_hash = '%s' limit 1",
|
||||
dbesc($t['hash'])
|
||||
);
|
||||
if($r)
|
||||
continue;
|
||||
|
||||
$ud_flags = 0;
|
||||
if (is_array($t['flags']) && in_array('deleted',$t['flags']))
|
||||
$ud_flags |= UPDATE_FLAGS_DELETED;
|
||||
if (is_array($t['flags']) && in_array('forced',$t['flags']))
|
||||
$ud_flags |= UPDATE_FLAGS_FORCED;
|
||||
if ($r) {
|
||||
$update = 0;
|
||||
|
||||
$z = q("insert into updates ( ud_hash, ud_guid, ud_date, ud_flags, ud_addr )
|
||||
values ( '%s', '%s', '%s', %d, '%s' ) ",
|
||||
dbesc($t['hash']),
|
||||
dbesc($t['transaction_id']),
|
||||
dbesc($t['timestamp']),
|
||||
intval($ud_flags),
|
||||
dbesc($t['address'])
|
||||
);
|
||||
// no need to look at updates that originated from our own site
|
||||
if ($t['host'] === z_root()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// there is more recent xchan information
|
||||
if ($r[0]['ud_date'] <= $t['timestamp']) {
|
||||
$update = 1;
|
||||
}
|
||||
|
||||
// the host is trusted and flags have changed - update flags immediately
|
||||
if (in_array($t['host'], $dir_trusted_hosts) &&
|
||||
$rr['site_url'] === $t['host'] &&
|
||||
intval($r[0]['ud_flags']) !== intval($t['flags'])) {
|
||||
|
||||
q("UPDATE updates SET ud_update = %d, ud_flags = %d WHERE ud_id = %d",
|
||||
intval($update),
|
||||
intval($t['flags']),
|
||||
dbesc($r[0]['ud_id'])
|
||||
);
|
||||
|
||||
q("UPDATE xchan SET xchan_censored = %d WHERE xchan_hash = '%s'",
|
||||
intval($t['flags']),
|
||||
dbesc($r[0]['ud_hash'])
|
||||
);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!$update) {
|
||||
continue;
|
||||
}
|
||||
|
||||
q("UPDATE updates SET ud_update = %d WHERE ud_id = %d",
|
||||
intval($update),
|
||||
dbesc($r[0]['ud_id'])
|
||||
);
|
||||
}
|
||||
else {
|
||||
q("insert into updates ( ud_hash, ud_host, ud_date, ud_addr, ud_update, ud_flags )
|
||||
values ( '%s', '%s', '%s', '%s', 1, %d) ",
|
||||
dbesc($t['hash']),
|
||||
dbesc($t['host']),
|
||||
dbesc($t['timestamp']),
|
||||
dbesc($t['address']),
|
||||
dbesc(in_array($t['host'], $dir_trusted_hosts) ? $t['flags'] : 0)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -303,8 +338,9 @@ class Libzotdir {
|
||||
*
|
||||
* Ignore updating records marked as deleted.
|
||||
*
|
||||
* If successful, sets ud_last in the DB to the current datetime for this
|
||||
* If successful, sets ud_updated in the DB to the current datetime for this
|
||||
* reddress/webbie.
|
||||
* Else update ud_last so we can stop trying after 7 days (Daemon/Poller.php)
|
||||
*
|
||||
* @param array $ud Entry from update table
|
||||
*/
|
||||
@@ -313,32 +349,44 @@ class Libzotdir {
|
||||
|
||||
logger('update_directory_entry: ' . print_r($ud,true), LOGGER_DATA);
|
||||
|
||||
if ($ud['ud_addr'] && (! ($ud['ud_flags'] & UPDATE_FLAGS_DELETED))) {
|
||||
$success = false;
|
||||
$zf = [];
|
||||
// TODO: remove this check after all directory servers have version > 8.4
|
||||
// ud_addr will always be the channel url at that time
|
||||
$href = ((strpos($ud['ud_addr'], '://') === false) ? Webfinger::zot_url(punify($ud['ud_addr'])) : punify($ud['ud_addr']));
|
||||
if($href) {
|
||||
$zf = Zotfinger::exec($href);
|
||||
if($zf && array_path_exists('signature/signer',$zf) && $zf['signature']['signer'] === $href && intval($zf['signature']['header_valid'])) {
|
||||
$xc = Libzot::import_xchan($zf['data']);
|
||||
|
||||
// xchan_hash mismatch - this can happen after a site re-install at the same url
|
||||
if ($xc['success'] && $xc['hash'] !== $ud['ud_hash']) {
|
||||
self::delete_by_hash($ud['ud_hash']);
|
||||
}
|
||||
|
||||
// if the channel was deleted - delete the entry in updates
|
||||
if (!empty($zf['data']['deleted_locally'])) {
|
||||
self::delete_by_hash($ud['ud_hash']);
|
||||
}
|
||||
|
||||
$href = Webfinger::zot_url(punify($ud['ud_addr']));
|
||||
if($href) {
|
||||
$zf = Zotfinger::exec($href);
|
||||
}
|
||||
if(array_path_exists('signature/signer',$zf) && $zf['signature']['signer'] === $href && intval($zf['signature']['header_valid'])) {
|
||||
$xc = Libzot::import_xchan($zf['data'], 0, $ud);
|
||||
// This is a workaround for a missing xchan_updated column
|
||||
// TODO: implement xchan_updated in the xchan table and update this column instead
|
||||
if($zf['data']['primary_location']['address'] && $zf['data']['primary_location']['url']) {
|
||||
if(!empty($zf['data']['primary_location']['url'])) {
|
||||
q("UPDATE hubloc SET hubloc_updated = '%s' WHERE hubloc_id_url = '%s' AND hubloc_primary = 1",
|
||||
dbesc(datetime_convert()),
|
||||
dbesc($zf['data']['primary_location']['url'])
|
||||
);
|
||||
}
|
||||
}
|
||||
else {
|
||||
q("update updates set ud_last = '%s' where ud_addr = '%s'",
|
||||
dbesc(datetime_convert()),
|
||||
dbesc($ud['ud_addr'])
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
q("UPDATE updates SET ud_addr = '%s', ud_last = '%s' WHERE ud_hash = '%s'",
|
||||
dbesc($href ? $href : $ud['ud_addr']),
|
||||
dbesc(datetime_convert()),
|
||||
dbesc($ud['ud_hash'])
|
||||
);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -353,85 +401,78 @@ class Libzotdir {
|
||||
*/
|
||||
|
||||
static function local_dir_update($uid, $force) {
|
||||
logger('local_dir_update uid: ' . $uid, LOGGER_DEBUG);
|
||||
|
||||
|
||||
logger('local_dir_update: uid: ' . $uid, LOGGER_DEBUG);
|
||||
|
||||
$p = q("select channel.channel_hash, channel_address, channel_timezone, profile.* from profile left join channel on channel_id = uid where uid = %d and is_default = 1",
|
||||
$p = q("select channel.channel_hash, channel_address, channel_timezone, profile.*, xchan.xchan_hidden, xchan.xchan_url from profile left join channel on channel_id = uid left join xchan on channel_hash = xchan_hash where profile.uid = %d and profile.is_default = 1",
|
||||
intval($uid)
|
||||
);
|
||||
|
||||
$profile = array();
|
||||
$profile['encoding'] = 'zot';
|
||||
|
||||
if ($p) {
|
||||
$hash = $p[0]['channel_hash'];
|
||||
|
||||
$profile['description'] = $p[0]['pdesc'];
|
||||
$profile['birthday'] = $p[0]['dob'];
|
||||
if ($age = age($p[0]['dob'],$p[0]['channel_timezone'],''))
|
||||
$profile['age'] = $age;
|
||||
|
||||
$profile['gender'] = $p[0]['gender'];
|
||||
$profile['marital'] = $p[0]['marital'];
|
||||
$profile['sexual'] = $p[0]['sexual'];
|
||||
$profile['locale'] = $p[0]['locality'];
|
||||
$profile['region'] = $p[0]['region'];
|
||||
$profile['postcode'] = $p[0]['postal_code'];
|
||||
$profile['country'] = $p[0]['country_name'];
|
||||
$profile['about'] = $p[0]['about'];
|
||||
$profile['homepage'] = $p[0]['homepage'];
|
||||
$profile['hometown'] = $p[0]['hometown'];
|
||||
|
||||
if ($p[0]['keywords']) {
|
||||
$tags = array();
|
||||
$k = explode(' ', $p[0]['keywords']);
|
||||
if ($k)
|
||||
foreach ($k as $kk)
|
||||
if (trim($kk))
|
||||
$tags[] = trim($kk);
|
||||
|
||||
if ($tags)
|
||||
$profile['keywords'] = $tags;
|
||||
}
|
||||
|
||||
$hidden = (1 - intval($p[0]['publish']));
|
||||
|
||||
logger('hidden: ' . $hidden);
|
||||
|
||||
$r = q("select xchan_hidden from xchan where xchan_hash = '%s'",
|
||||
dbesc($p[0]['channel_hash'])
|
||||
);
|
||||
|
||||
if(intval($r[0]['xchan_hidden']) != $hidden) {
|
||||
$r = q("update xchan set xchan_hidden = %d where xchan_hash = '%s'",
|
||||
intval($hidden),
|
||||
dbesc($hash)
|
||||
);
|
||||
}
|
||||
|
||||
$arr = [ 'channel_id' => $uid, 'hash' => $hash, 'profile' => $profile ];
|
||||
call_hooks('local_dir_update', $arr);
|
||||
|
||||
$address = channel_reddress($p[0]);
|
||||
|
||||
if (perm_is_allowed($uid, '', 'view_profile')) {
|
||||
self::import_directory_profile($hash, $arr['profile'], $address, 0);
|
||||
}
|
||||
else {
|
||||
// they may have made it private
|
||||
q("delete from xprof where xprof_hash = '%s'",
|
||||
dbesc($hash)
|
||||
);
|
||||
q("delete from xtag where xtag_hash = '%s'",
|
||||
dbesc($hash)
|
||||
);
|
||||
}
|
||||
|
||||
if (!$p) {
|
||||
logger('profile not found');
|
||||
return;
|
||||
}
|
||||
|
||||
$ud_hash = random_string() . '@' . \App::get_hostname();
|
||||
self::update_modtime($hash, $ud_hash, channel_reddress($p[0]),(($force) ? UPDATE_FLAGS_FORCED : UPDATE_FLAGS_UPDATED));
|
||||
$profile = [];
|
||||
$profile['encoding'] = 'zot';
|
||||
|
||||
$hash = $p[0]['channel_hash'];
|
||||
|
||||
$profile['description'] = $p[0]['pdesc'];
|
||||
$profile['birthday'] = $p[0]['dob'];
|
||||
if ($age = age($p[0]['dob'],$p[0]['channel_timezone'],''))
|
||||
$profile['age'] = $age;
|
||||
|
||||
$profile['gender'] = $p[0]['gender'];
|
||||
$profile['marital'] = $p[0]['marital'];
|
||||
$profile['sexual'] = $p[0]['sexual'];
|
||||
$profile['locale'] = $p[0]['locality'];
|
||||
$profile['region'] = $p[0]['region'];
|
||||
$profile['postcode'] = $p[0]['postal_code'];
|
||||
$profile['country'] = $p[0]['country_name'];
|
||||
$profile['about'] = $p[0]['about'];
|
||||
$profile['homepage'] = $p[0]['homepage'];
|
||||
$profile['hometown'] = $p[0]['hometown'];
|
||||
|
||||
if ($p[0]['keywords']) {
|
||||
$tags = array();
|
||||
$k = explode(' ', $p[0]['keywords']);
|
||||
if ($k)
|
||||
foreach ($k as $kk)
|
||||
if (trim($kk))
|
||||
$tags[] = trim($kk);
|
||||
|
||||
if ($tags)
|
||||
$profile['keywords'] = $tags;
|
||||
}
|
||||
|
||||
$hidden = (1 - intval($p[0]['publish']));
|
||||
|
||||
logger('hidden: ' . $hidden);
|
||||
|
||||
if(intval($p[0]['xchan_hidden']) !== $hidden) {
|
||||
q("update xchan set xchan_hidden = %d where xchan_hash = '%s'",
|
||||
intval($hidden),
|
||||
dbesc($hash)
|
||||
);
|
||||
}
|
||||
|
||||
$arr = [ 'channel_id' => $uid, 'hash' => $hash, 'profile' => $profile ];
|
||||
call_hooks('local_dir_update', $arr);
|
||||
|
||||
if (perm_is_allowed($uid, '', 'view_profile')) {
|
||||
self::import_directory_profile($hash, $arr['profile']);
|
||||
}
|
||||
else {
|
||||
// they may have made it private
|
||||
q("delete from xprof where xprof_hash = '%s'",
|
||||
dbesc($hash)
|
||||
);
|
||||
q("delete from xtag where xtag_hash = '%s'",
|
||||
dbesc($hash)
|
||||
);
|
||||
}
|
||||
|
||||
self::update($hash, $p[0]['xchan_url']);
|
||||
}
|
||||
|
||||
|
||||
@@ -441,13 +482,10 @@ class Libzotdir {
|
||||
*
|
||||
* @param string $hash
|
||||
* @param array $profile
|
||||
* @param string $addr
|
||||
* @param number $ud_flags (optional) UPDATE_FLAGS_UPDATED
|
||||
* @param number $suppress_update (optional) default 0
|
||||
* @return boolean $updated if something changed
|
||||
*/
|
||||
|
||||
static function import_directory_profile($hash, $profile, $addr, $ud_flags = UPDATE_FLAGS_UPDATED, $suppress_update = 0) {
|
||||
static function import_directory_profile($hash, $profile) {
|
||||
|
||||
logger('import_directory_profile', LOGGER_DEBUG);
|
||||
if (! $hash)
|
||||
@@ -480,7 +518,12 @@ class Libzotdir {
|
||||
$clean = array();
|
||||
if (array_key_exists('keywords', $profile) and is_array($profile['keywords'])) {
|
||||
self::import_directory_keywords($hash,$profile['keywords']);
|
||||
|
||||
foreach ($profile['keywords'] as $kw) {
|
||||
if (in_array($kw, $clean)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$kw = trim(htmlspecialchars($kw,ENT_COMPAT, 'UTF-8', false));
|
||||
$kw = trim($kw, ',');
|
||||
$clean[] = $kw;
|
||||
@@ -587,9 +630,6 @@ class Libzotdir {
|
||||
*/
|
||||
call_hooks('import_directory_profile', $d);
|
||||
|
||||
if (($d['update']) && (! $suppress_update))
|
||||
self::update_modtime($arr['xprof_hash'],random_string() . '@' . \App::get_hostname(), $addr, $ud_flags);
|
||||
|
||||
return $d['update'];
|
||||
}
|
||||
|
||||
@@ -607,6 +647,10 @@ class Libzotdir {
|
||||
dbesc($hash)
|
||||
);
|
||||
|
||||
$xchan = q("select xchan_censored from xchan where xchan_hash = '%s'",
|
||||
dbesc($hash)
|
||||
);
|
||||
|
||||
if($r) {
|
||||
foreach($r as $rr)
|
||||
$existing[] = $rr['xtag_term'];
|
||||
@@ -614,6 +658,10 @@ class Libzotdir {
|
||||
|
||||
$clean = array();
|
||||
foreach($keywords as $kw) {
|
||||
if (in_array($kw, $clean)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$kw = trim(htmlspecialchars($kw,ENT_COMPAT, 'UTF-8', false));
|
||||
$kw = trim($kw, ',');
|
||||
$clean[] = $kw;
|
||||
@@ -628,9 +676,10 @@ class Libzotdir {
|
||||
}
|
||||
foreach($clean as $x) {
|
||||
if(! in_array($x, $existing)) {
|
||||
$r = q("insert into xtag ( xtag_hash, xtag_term, xtag_flags) values ( '%s' ,'%s', 0 )",
|
||||
$r = q("insert into xtag ( xtag_hash, xtag_term, xtag_flags) values ( '%s' ,'%s', %d )",
|
||||
dbesc($hash),
|
||||
dbesc($x)
|
||||
dbesc($x),
|
||||
intval($xchan[0]['xchan_censored'])
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -640,13 +689,12 @@ class Libzotdir {
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @param string $hash
|
||||
* @param string $guid
|
||||
* @param string $addr
|
||||
* @param int $flags (optional) default 0
|
||||
* @param string $hash the channel hash
|
||||
* @param string $addr the channel url
|
||||
* @param bool $bump_date (optional) default true
|
||||
*/
|
||||
|
||||
static function update_modtime($hash, $guid, $addr, $flags = 0) {
|
||||
static function update($hash, $addr, $bump_date = true, $flag = null) {
|
||||
|
||||
$dirmode = intval(get_config('system', 'directory_mode'));
|
||||
|
||||
@@ -654,26 +702,70 @@ class Libzotdir {
|
||||
return;
|
||||
}
|
||||
|
||||
if (empty($hash) || empty($guid) || empty($addr)) {
|
||||
if (empty($hash) || empty($addr)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if($flags) {
|
||||
q("insert into updates (ud_hash, ud_guid, ud_date, ud_flags, ud_addr ) values ( '%s', '%s', '%s', %d, '%s' )",
|
||||
dbesc($hash),
|
||||
dbesc($guid),
|
||||
dbesc(datetime_convert()),
|
||||
intval($flags),
|
||||
dbesc($addr)
|
||||
);
|
||||
$u = q("SELECT * FROM updates WHERE ud_hash = '%s' LIMIT 1",
|
||||
dbesc($hash)
|
||||
);
|
||||
|
||||
$date_sql = '';
|
||||
if ($bump_date) {
|
||||
$date_sql = "ud_date = '" . dbesc(datetime_convert()) . "',";
|
||||
}
|
||||
else {
|
||||
q("update updates set ud_flags = ( ud_flags | %d ) where ud_addr = '%s' and not (ud_flags & %d)>0 ",
|
||||
intval(UPDATE_FLAGS_UPDATED),
|
||||
|
||||
$flag_sql = '';
|
||||
if ($flag !== null) {
|
||||
$flag_sql = "ud_flags = '" . intval($flag) . "',";
|
||||
}
|
||||
|
||||
|
||||
if ($u) {
|
||||
$x = q("UPDATE updates SET $date_sql $flag_sql ud_last = '%s', ud_host = '%s', ud_addr = '%s', ud_update = 0 WHERE ud_id = %d",
|
||||
dbesc(NULL_DATE),
|
||||
dbesc(z_root()),
|
||||
dbesc($addr),
|
||||
intval(UPDATE_FLAGS_UPDATED)
|
||||
intval($u[0]['ud_id'])
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
q("INSERT INTO updates (ud_hash, ud_host, ud_date, ud_addr, ud_flags) VALUES ( '%s', '%s', '%s', '%s', %d )",
|
||||
dbesc($hash),
|
||||
dbesc(z_root()),
|
||||
dbesc(datetime_convert()),
|
||||
dbesc($addr),
|
||||
intval($flag)
|
||||
);
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief deletes a entry in updates by hash
|
||||
*
|
||||
* @param string $hash the channel hash
|
||||
* @return boolean
|
||||
*/
|
||||
|
||||
static function delete_by_hash($hash) {
|
||||
if (!$hash) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$x = q("DELETE FROM updates WHERE ud_hash = '%s'",
|
||||
dbesc($hash)
|
||||
);
|
||||
|
||||
if ($x) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
34
Zotlabs/Lib/Multibase.php
Normal file
34
Zotlabs/Lib/Multibase.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
use StephenHill\Base58;
|
||||
|
||||
class Multibase {
|
||||
|
||||
protected $key = null;
|
||||
|
||||
public function __construct() {
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function publicKey($key) {
|
||||
$base58 = new Base58();
|
||||
$raw = hex2bin('ed01') . sodium_base642bin($key, SODIUM_BASE64_VARIANT_ORIGINAL_NO_PADDING);
|
||||
return 'z' . $base58->encode($raw);
|
||||
}
|
||||
|
||||
public function secretKey($key) {
|
||||
$base58 = new Base58();
|
||||
$raw = hex2bin('8026') . sodium_base642bin($key, SODIUM_BASE64_VARIANT_ORIGINAL_NO_PADDING);
|
||||
return 'z' . $base58->encode($raw);
|
||||
}
|
||||
|
||||
public function decode($key, $binary = false) {
|
||||
$base58 = new Base58();
|
||||
$key = substr($key,1);
|
||||
$raw = $base58->decode($key);
|
||||
$binaryKey = substr($raw, 2);
|
||||
return $binary ? $binaryKey : sodium_bin2base64($binaryKey, SODIUM_BASE64_VARIANT_ORIGINAL_NO_PADDING);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -57,7 +57,6 @@ class Queue {
|
||||
outq_priority = outq_priority + %d,
|
||||
outq_scheduled = '%s'
|
||||
WHERE outq_hash = '%s'",
|
||||
|
||||
dbesc(datetime_convert()),
|
||||
intval($add_priority),
|
||||
dbesc($next),
|
||||
@@ -85,29 +84,16 @@ class Queue {
|
||||
// entries still exist for it. This fixes an issue where one immediate delivery left everything
|
||||
// else for that site undeliverable since all the other entries had been pushed far into the future.
|
||||
|
||||
$x = null;
|
||||
$sql_quirks = ((get_config('system', 'db_skip_locked_supported')) ? 'SKIP LOCKED' : 'NOWAIT');
|
||||
|
||||
q("START TRANSACTION");
|
||||
|
||||
$r = q("SELECT outq_hash FROM outq WHERE outq_posturl = '%s' LIMIT 1 FOR UPDATE $sql_quirks",
|
||||
$r = q("SELECT outq_hash, outq_posturl FROM outq WHERE outq_posturl = '%s' LIMIT 1",
|
||||
dbesc($record[0]['outq_posturl'])
|
||||
);
|
||||
|
||||
if ($r) {
|
||||
$x = q("UPDATE outq SET outq_scheduled = '%s' WHERE outq_hash = '%s'",
|
||||
dbesc(datetime_convert()),
|
||||
dbesc($r[0]['outq_hash'])
|
||||
$hashes = ids_to_querystr($r, 'outq_hash', true);
|
||||
$x = q("UPDATE outq SET outq_scheduled = '%s' WHERE outq_hash IN ($hashes)",
|
||||
dbesc(datetime_convert())
|
||||
);
|
||||
}
|
||||
|
||||
if ($x) {
|
||||
q("COMMIT");
|
||||
}
|
||||
else {
|
||||
q("ROLLBACK");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -260,7 +246,7 @@ class Queue {
|
||||
|
||||
if($result['success']) {
|
||||
logger('deliver: remote zot delivery succeeded to ' . $outq['outq_posturl']);
|
||||
Libzot::process_response($outq['outq_posturl'],$result, $outq);
|
||||
Libzot::process_response($outq['outq_posturl'], $result, $outq);
|
||||
}
|
||||
else {
|
||||
logger('deliver: remote zot delivery failed to ' . $outq['outq_posturl']);
|
||||
|
||||
@@ -24,7 +24,8 @@ class QueueWorker {
|
||||
// Exceptions for processtimeout ($workermaxage) value.
|
||||
// Currently the value is overriden with 3600 seconds (1h).
|
||||
public static $long_running_cmd = [
|
||||
'Queue'
|
||||
'Queue',
|
||||
'Expire'
|
||||
];
|
||||
|
||||
private static function qstart() {
|
||||
@@ -62,6 +63,8 @@ class QueueWorker {
|
||||
return;
|
||||
}
|
||||
|
||||
logger('queueworker_stats_summon: cmd:' . $argv[0] . ' ' . 'timestamp:' . time());
|
||||
|
||||
self::qstart();
|
||||
$r = q("INSERT INTO workerq (workerq_priority, workerq_data, workerq_uuid, workerq_cmd) VALUES (%d, '%s', '%s', '%s')",
|
||||
intval($priority),
|
||||
@@ -147,6 +150,10 @@ class QueueWorker {
|
||||
);
|
||||
|
||||
if ($r) {
|
||||
// TODO: some long running services store their pid in config.procid.daemon
|
||||
// we could possibly check if a pid exist and check if the process is still alive
|
||||
// prior to reseting workerq_reservationid
|
||||
|
||||
$ids = ids_to_querystr($r, 'workerq_id');
|
||||
$u = dbq("update workerq set workerq_reservationid = null where workerq_id in ($ids)");
|
||||
}
|
||||
@@ -159,7 +166,7 @@ class QueueWorker {
|
||||
|
||||
//usleep(self::$workersleep);
|
||||
|
||||
$workers = dbq("select count(distinct workerq_reservationid) as total from workerq where workerq_reservationid is not null");
|
||||
$workers = dbq("select count(*) as total from workerq where workerq_reservationid is not null");
|
||||
logger("WORKERCOUNT: " . $workers[0]['total'], LOGGER_DEBUG);
|
||||
|
||||
return intval($workers[0]['total']);
|
||||
@@ -172,7 +179,7 @@ class QueueWorker {
|
||||
|
||||
$wid = uniqid('', true);
|
||||
|
||||
usleep(mt_rand(300000, 1000000)); //Sleep .3 - 1 seconds before creating a new worker.
|
||||
//usleep(mt_rand(300000, 1000000)); //Sleep .3 - 1 seconds before creating a new worker.
|
||||
|
||||
$workers = self::GetWorkerCount();
|
||||
|
||||
@@ -197,7 +204,7 @@ class QueueWorker {
|
||||
$work = dbq("SELECT workerq_id, workerq_cmd FROM workerq WHERE workerq_reservationid IS NULL ORDER BY workerq_priority DESC, workerq_id ASC LIMIT 1 FOR UPDATE $sql_quirks");
|
||||
|
||||
if (!$work) {
|
||||
self::qcommit();
|
||||
self::qrollback();
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -294,12 +301,16 @@ class QueueWorker {
|
||||
$cls = '\\Zotlabs\\Daemon\\' . $argv[0];
|
||||
$argv = flatten_array_recursive($argv);
|
||||
$argc = count($argv);
|
||||
$rnd = random_string();
|
||||
$rnd = random_string(16);
|
||||
|
||||
logger('PROCESSING: ' . $rnd . ' ' . print_r($argv[0], true));
|
||||
|
||||
$start_timestamp = microtime(true);
|
||||
|
||||
$cls::run($argc, $argv);
|
||||
|
||||
logger('logger_stats_data cmd:' . $argv[0] . ' start:' . $start_timestamp . ' ' . 'end:' . microtime(true) . ' meta:' . $rnd);
|
||||
|
||||
logger('COMPLETED: ' . $rnd);
|
||||
|
||||
// @FIXME: Right now we assume that if we get a return, everything is OK.
|
||||
|
||||
@@ -112,7 +112,7 @@ class Share {
|
||||
if(! $this->item)
|
||||
return $bb;
|
||||
|
||||
$is_photo = (($this->item['obj_type'] === ACTIVITY_OBJ_PHOTO) ? true : false);
|
||||
$is_photo = ((in_array($this->item['obj_type'], ['Image', ACTIVITY_OBJ_PHOTO])) ? true : false);
|
||||
if($is_photo) {
|
||||
$object = json_decode($this->item['obj'],true);
|
||||
$photo_bb = $object['body'];
|
||||
|
||||
24
Zotlabs/Lib/Text.php
Normal file
24
Zotlabs/Lib/Text.php
Normal file
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
class Text {
|
||||
|
||||
/**
|
||||
* use this on "body" or "content" input where angle chars shouldn't be removed,
|
||||
* and allow them to be safely displayed.
|
||||
*
|
||||
* @param string $string
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
|
||||
public static function escape_tags(string $string): string {
|
||||
if (!$string) {
|
||||
return EMPTY_STR;
|
||||
}
|
||||
|
||||
return htmlspecialchars($string, ENT_COMPAT, 'UTF-8', false);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -19,7 +19,7 @@ class ThreadItem {
|
||||
private $comment_box_template = 'comment_item.tpl';
|
||||
private $commentable = false;
|
||||
// list of supported reaction emojis - a site can over-ride this via config system.reactions
|
||||
private $reactions = ['1f60a','1f44f','1f37e','1f48b','1f61e','2665','1f606','1f62e','1f634','1f61c','1f607','1f608'];
|
||||
private $reactions = ['slightly_smiling_face','clapping_hands','bottle_with_popping_cork','kiss_mark','disappointed_face','red_heart','grinning_face','astonished_face','sleeping_face','winking_face_with_tongue','smiling_face_with_halo','smiling_face_with_horns'];
|
||||
private $toplevel = false;
|
||||
private $children = array();
|
||||
private $parent = null;
|
||||
@@ -34,6 +34,7 @@ class ThreadItem {
|
||||
private $channel = null;
|
||||
private $display_mode = 'normal';
|
||||
private $reload = '';
|
||||
private $mid_uuid_map = [];
|
||||
|
||||
|
||||
public function __construct($data) {
|
||||
@@ -46,6 +47,7 @@ class ThreadItem {
|
||||
|
||||
// Prepare the children
|
||||
if(isset($data['children'])) {
|
||||
|
||||
foreach($data['children'] as $item) {
|
||||
|
||||
/*
|
||||
@@ -56,7 +58,6 @@ class ThreadItem {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
$child = new ThreadItem($item);
|
||||
$this->add_child($child);
|
||||
}
|
||||
@@ -65,6 +66,8 @@ class ThreadItem {
|
||||
unset($this->data['children']);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// allow a site to configure the order and content of the reaction emoji list
|
||||
if($this->toplevel) {
|
||||
$x = get_config('system','reactions');
|
||||
@@ -82,7 +85,7 @@ class ThreadItem {
|
||||
* _ false on failure
|
||||
*/
|
||||
|
||||
public function get_template_data($conv_responses, $thread_level=1, $conv_flags = []) {
|
||||
public function get_template_data($conv_responses, $mid_uuid_map, $thread_level=1, $conv_flags = []) {
|
||||
|
||||
$result = [];
|
||||
$item = $this->get_data();
|
||||
@@ -101,7 +104,7 @@ class ThreadItem {
|
||||
$conv = $this->get_conversation();
|
||||
$observer = $conv->get_observer();
|
||||
|
||||
$acl = new AccessList(false);
|
||||
$acl = new AccessList([]);
|
||||
$acl->set($item);
|
||||
|
||||
$lock = ((intval($item['item_private']) || ($item['uid'] == local_channel() && $acl->is_private()))
|
||||
@@ -121,12 +124,14 @@ class ThreadItem {
|
||||
$locktype = 0;
|
||||
}
|
||||
|
||||
$shareable = ((($conv->get_profile_owner() == local_channel() && local_channel()) && ($item['item_private'] != 1)) ? true : false);
|
||||
$shareable = ((($conv->get_profile_owner() == local_channel() && local_channel()) && (intval($item['item_private']) === 0)) ? true : false);
|
||||
|
||||
// allow an exemption for sharing stuff from your private feeds
|
||||
if($item['author']['xchan_network'] === 'rss')
|
||||
$shareable = true;
|
||||
|
||||
$repeatable = ((($conv->get_profile_owner() == local_channel() && local_channel()) && (intval($item['item_private']) === 0) && (in_array($item['author']['xchan_network'], ['zot6', 'activitypub']))) ? true : false);
|
||||
|
||||
// @fixme
|
||||
// Have recently added code to properly handle polls in group reshares by redirecting all of the poll responses to the group.
|
||||
// Sharing a poll using a regular embedded share is harder because the poll will need to fork. This is due to comment permissions.
|
||||
@@ -185,7 +190,7 @@ class ThreadItem {
|
||||
|
||||
$filer = ((($conv->get_profile_owner() == local_channel()) && (! array_key_exists('real_uid',$item))) ? t("Save to Folder") : false);
|
||||
|
||||
$profile_avatar = $item['author']['xchan_photo_m'];
|
||||
$profile_avatar = $item['author']['xchan_photo_s'];
|
||||
$profile_link = chanlink_hash($item['author_xchan']);
|
||||
$profile_name = $item['author']['xchan_name'];
|
||||
|
||||
@@ -194,10 +199,15 @@ class ThreadItem {
|
||||
$attend = null;
|
||||
|
||||
// process action responses - e.g. like/dislike/attend/agree/whatever
|
||||
$response_verbs = array('like');
|
||||
if(feature_enabled($conv->get_profile_owner(),'dislike'))
|
||||
$response_verbs[] = 'like';
|
||||
|
||||
if(feature_enabled($conv->get_profile_owner(),'dislike')) {
|
||||
$response_verbs[] = 'dislike';
|
||||
if($item['obj_type'] === ACTIVITY_OBJ_EVENT) {
|
||||
}
|
||||
|
||||
$response_verbs[] = 'announce';
|
||||
|
||||
if(in_array($item['obj_type'], ['Event', ACTIVITY_OBJ_EVENT])) {
|
||||
$response_verbs[] = 'attendyes';
|
||||
$response_verbs[] = 'attendno';
|
||||
$response_verbs[] = 'attendmaybe';
|
||||
@@ -222,6 +232,8 @@ class ThreadItem {
|
||||
$my_responses[$v] = ((isset($conv_responses[$v][$item['mid'] . '-m'])) ? 1 : 0);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
$like_count = ((x($conv_responses['like'],$item['mid'])) ? $conv_responses['like'][$item['mid']] : '');
|
||||
$like_list = ((x($conv_responses['like'],$item['mid'])) ? $conv_responses['like'][$item['mid'] . '-l'] : '');
|
||||
if (($like_list) && (count($like_list) > MAX_LIKERS)) {
|
||||
@@ -232,6 +244,16 @@ class ThreadItem {
|
||||
}
|
||||
$like_button_label = tt('Like','Likes',$like_count,'noun');
|
||||
|
||||
$repeat_count = ((x($conv_responses['announce'],$item['mid'])) ? $conv_responses['announce'][$item['mid']] : '');
|
||||
$repeat_list = ((x($conv_responses['announce'],$item['mid'])) ? $conv_responses['announce'][$item['mid'] . '-l'] : '');
|
||||
if (($repeat_list) && (count($repeat_list) > MAX_LIKERS)) {
|
||||
$repeat_list_part = array_slice($repeat_list, 0, MAX_LIKERS);
|
||||
array_push($repeat_list_part, '<a class="dropdown-item" href="#" data-toggle="modal" data-target="#repeatModal-' . $this->get_id() . '"><b>' . t('View all') . '</b></a>');
|
||||
} else {
|
||||
$repeat_list_part = '';
|
||||
}
|
||||
$repeat_button_label = tt('Repeat','Repeats',$repeat_count,'noun');
|
||||
|
||||
$showdislike = '';
|
||||
if (feature_enabled($conv->get_profile_owner(),'dislike')) {
|
||||
$dislike_count = ((x($conv_responses['dislike'],$item['mid'])) ? $conv_responses['dislike'][$item['mid']] : '');
|
||||
@@ -248,6 +270,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']) : '');
|
||||
*/
|
||||
|
||||
/*
|
||||
* We should avoid doing this all the time, but it depends on the conversation mode
|
||||
@@ -299,7 +322,7 @@ class ThreadItem {
|
||||
}
|
||||
|
||||
$has_event = false;
|
||||
if(($item['obj_type'] === ACTIVITY_OBJ_EVENT) && $conv->get_profile_owner() == local_channel())
|
||||
if((in_array($item['obj_type'], ['Event', ACTIVITY_OBJ_EVENT])) && $conv->get_profile_owner() == local_channel())
|
||||
$has_event = true;
|
||||
|
||||
$like = [];
|
||||
@@ -315,13 +338,11 @@ class ThreadItem {
|
||||
$share = [];
|
||||
$embed = [];
|
||||
if ($shareable) {
|
||||
// This actually turns out not to be possible in some protocol stacks without opening up hundreds of new issues.
|
||||
// Will allow it only for uri resolvable sources.
|
||||
if(strpos($item['mid'],'http') === 0) {
|
||||
//Not yet ready for primetime
|
||||
//$share = array( t('Repeat This'), t('repeat'));
|
||||
}
|
||||
$embed = [t('Share This'), t('share')];
|
||||
$embed = [t('Share'), t('share')];
|
||||
}
|
||||
|
||||
if ($repeatable) {
|
||||
$share = [t('Repeat'), t('repeat')];
|
||||
}
|
||||
|
||||
$dreport = '';
|
||||
@@ -333,7 +354,7 @@ class ThreadItem {
|
||||
$dreport_link = '';
|
||||
if((intval($item['item_type']) == ITEM_TYPE_POST) && (! get_config('system','disable_dreport')) && strcmp(datetime_convert('UTC','UTC',$item['created']),datetime_convert('UTC','UTC',"now - $keep_reports days")) > 0) {
|
||||
$dreport = t('Delivery Report');
|
||||
$dreport_link = gen_link_id($item['mid']);
|
||||
$dreport_link = '?mid=' . $item['mid'];
|
||||
}
|
||||
|
||||
$is_new = false;
|
||||
@@ -352,8 +373,8 @@ class ThreadItem {
|
||||
if($conv->get_mode() === 'channel')
|
||||
$viewthread = z_root() . '/channel/' . $owner_address . '?f=&mid=' . urlencode(gen_link_id($item['mid']));
|
||||
|
||||
$comment_count_txt = sprintf(tt('%d Comment', '%d Comments', $total_children), $total_children);
|
||||
$list_unseen_txt = (($unseen_comments) ? sprintf(t('%d unseen'), $unseen_comments) : '');
|
||||
$comment_count_txt = ['label' => sprintf(tt('%d comment', '%d comments', $total_children), $total_children), 'count' => $total_children];
|
||||
$list_unseen_txt = $unseen_comments ? ['label' => sprintf(t('%d unseen'), $unseen_comments), 'count' => $unseen_comments] : [];
|
||||
|
||||
$children = $this->get_children();
|
||||
|
||||
@@ -363,8 +384,8 @@ class ThreadItem {
|
||||
call_hooks('dropdown_extras',$dropdown_extras_arr);
|
||||
$dropdown_extras = $dropdown_extras_arr['dropdown_extras'];
|
||||
|
||||
$midb64 = gen_link_id($item['mid']);
|
||||
$mids = [ $midb64 ];
|
||||
$midb64 = $item['uuid'];
|
||||
$mids = [ $item['uuid'] ];
|
||||
$response_mids = [];
|
||||
foreach($response_verbs as $v) {
|
||||
if(isset($conv_responses[$v]['mids'][$item['mid']])) {
|
||||
@@ -480,31 +501,44 @@ class ThreadItem {
|
||||
'comment_count' => $total_children,
|
||||
'comment_count_txt' => $comment_count_txt,
|
||||
'list_unseen_txt' => $list_unseen_txt,
|
||||
'markseen' => t('Mark all seen'),
|
||||
'markseen' => t('Mark all comments seen'),
|
||||
'responses' => $responses,
|
||||
'my_responses' => $my_responses,
|
||||
/*
|
||||
'like_count' => $like_count,
|
||||
'like_list' => $like_list,
|
||||
'like_list_part' => $like_list_part,
|
||||
'like_button_label' => $like_button_label,
|
||||
'like_modal_title' => t('Likes','noun'),
|
||||
|
||||
'repeat_count' => $repeat_count,
|
||||
'repeat_list' => $repeat_list,
|
||||
'repeat_list_part' => $repeat_list_part,
|
||||
'repeat_button_label' => $repeat_button_label,
|
||||
'repeat_modal_title' => t('Repeats','noun'),
|
||||
|
||||
|
||||
'dislike_modal_title' => t('Dislikes','noun'),
|
||||
'dislike_count' => ((feature_enabled($conv->get_profile_owner(),'dislike')) ? $dislike_count : ''),
|
||||
'dislike_list' => ((feature_enabled($conv->get_profile_owner(),'dislike')) ? $dislike_list : ''),
|
||||
'dislike_list_part' => ((feature_enabled($conv->get_profile_owner(),'dislike')) ? $dislike_list_part : ''),
|
||||
'dislike_button_label' => ((feature_enabled($conv->get_profile_owner(),'dislike')) ? $dislike_button_label : ''),
|
||||
*/
|
||||
'modal_dismiss' => t('Close'),
|
||||
'showlike' => $showlike,
|
||||
'showdislike' => $showdislike,
|
||||
// 'showlike' => $showlike,
|
||||
// 'showdislike' => $showdislike,
|
||||
'comment' => ($item['item_delayed'] ? '' : $this->get_comment_box()),
|
||||
'previewing' => ($conv->is_preview() ? true : false ),
|
||||
'preview_lbl' => t('This is an unsaved preview'),
|
||||
'wait' => t('Please wait'),
|
||||
'thread_level' => $thread_level,
|
||||
'settings' => $settings,
|
||||
'thr_parent' => (($item['parent_mid'] != $item['thr_parent']) ? gen_link_id($item['thr_parent']) : ''),
|
||||
'contact_id' => (($contact) ? $contact['abook_id'] : '')
|
||||
|
||||
'thr_parent_uuid' => (($item['parent_mid'] != $item['thr_parent']) ? $mid_uuid_map[$item['thr_parent']] : ''),
|
||||
'contact_id' => (($contact) ? $contact['abook_id'] : ''),
|
||||
'moderate' => ($item['item_blocked'] == ITEM_MODERATED),
|
||||
'moderate_approve' => t('Approve'),
|
||||
'moderate_delete' => t('Delete'),
|
||||
'rtl' => in_array($item['lang'], rtl_languages()),
|
||||
);
|
||||
|
||||
$arr = array('item' => $item, 'output' => $tmp_item);
|
||||
@@ -527,12 +561,12 @@ class ThreadItem {
|
||||
|
||||
if(($this->get_display_mode() === 'normal') && ($nb_children > 0)) {
|
||||
foreach($children as $child) {
|
||||
$result['children'][] = $child->get_template_data($conv_responses, $thread_level + 1,$conv_flags);
|
||||
$result['children'][] = $child->get_template_data($conv_responses, $mid_uuid_map, $thread_level + 1,$conv_flags);
|
||||
}
|
||||
// Collapse
|
||||
if(($nb_children > $visible_comments) || ($thread_level > 1)) {
|
||||
$result['children'][0]['comment_firstcollapsed'] = true;
|
||||
$result['children'][0]['num_comments'] = $comment_count_txt;
|
||||
$result['children'][0]['num_comments'] = $comment_count_txt['label'];
|
||||
$result['children'][0]['hide_text'] = sprintf( t('%s show all'), '<i class="fa fa-chevron-down"></i>');
|
||||
if($thread_level > 1) {
|
||||
$result['children'][$nb_children - 1]['comment_lastcollapsed'] = true;
|
||||
@@ -609,7 +643,7 @@ class ThreadItem {
|
||||
* Only add what will be displayed
|
||||
*/
|
||||
|
||||
if(activity_match($item->get_data_value('verb'),ACTIVITY_LIKE) || activity_match($item->get_data_value('verb'),ACTIVITY_DISLIKE)) {
|
||||
if(activity_match($item->get_data_value('verb'), ['Like', 'Dislike', ACTIVITY_LIKE, ACTIVITY_DISLIKE])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -870,10 +904,16 @@ class ThreadItem {
|
||||
|
||||
if($this->is_toplevel() && ($this->get_data_value('author_xchan') != $this->get_data_value('owner_xchan'))) {
|
||||
$this->owner_url = chanlink_hash($this->data['owner']['xchan_hash']);
|
||||
$this->owner_photo = $this->data['owner']['xchan_photo_m'];
|
||||
$this->owner_photo = $this->data['owner']['xchan_photo_s'];
|
||||
$this->owner_name = $this->data['owner']['xchan_name'];
|
||||
$this->wall_to_wall = true;
|
||||
}
|
||||
elseif($this->is_toplevel() && $this->get_data_value('verb') === 'Announce' && isset($this->data['source'])) {
|
||||
$this->owner_url = chanlink_hash($this->data['source']['xchan_hash']);
|
||||
$this->owner_photo = $this->data['source']['xchan_photo_s'];
|
||||
$this->owner_name = $this->data['source']['xchan_name'];
|
||||
$this->wall_to_wall = true;
|
||||
}
|
||||
}
|
||||
|
||||
private function is_wall_to_wall() {
|
||||
|
||||
@@ -4,18 +4,30 @@ namespace Zotlabs\Lib;
|
||||
|
||||
class ThreadListener {
|
||||
|
||||
public static function isEnabled() {
|
||||
return Config::Get('system','enable_thread_listener');
|
||||
}
|
||||
|
||||
static public function store($target_id,$portable_id,$ltype = 0) {
|
||||
if (!self::isEnabled()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$x = self::fetch($target_id,$portable_id,$ltype = 0);
|
||||
if(! $x) {
|
||||
if(! $x) {
|
||||
$r = q("insert into listeners ( target_id, portable_id, ltype ) values ( '%s', '%s' , %d ) ",
|
||||
dbesc($target_id),
|
||||
dbesc($portable_id),
|
||||
intval($ltype)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static public function fetch($target_id,$portable_id,$ltype = 0) {
|
||||
if (!self::isEnabled()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$x = q("select * from listeners where target_id = '%s' and portable_id = '%s' and ltype = %d limit 1",
|
||||
dbesc($target_id),
|
||||
dbesc($portable_id),
|
||||
@@ -28,6 +40,10 @@ class ThreadListener {
|
||||
}
|
||||
|
||||
static public function fetch_by_target($target_id,$ltype = 0) {
|
||||
if (!self::isEnabled()) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$x = q("select * from listeners where target_id = '%s' and ltype = %d",
|
||||
dbesc($target_id),
|
||||
intval($ltype)
|
||||
|
||||
@@ -171,7 +171,7 @@ class ThreadStream {
|
||||
*/
|
||||
|
||||
|
||||
if(($item->get_data_value('id') != $item->get_data_value('parent')) && (activity_match($item->get_data_value('verb'),ACTIVITY_LIKE) || activity_match($item->get_data_value('verb'),ACTIVITY_DISLIKE))) {
|
||||
if($item->get_data_value('id') != $item->get_data_value('parent') && activity_match($item->get_data_value('verb'), ['Like', 'Dislike', ACTIVITY_LIKE, ACTIVITY_DISLIKE])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -211,7 +211,7 @@ class ThreadStream {
|
||||
* _ The data requested on success
|
||||
* _ false on failure
|
||||
*/
|
||||
public function get_template_data($conv_responses) {
|
||||
public function get_template_data($conv_responses, $mid_uuid_map) {
|
||||
$result = array();
|
||||
|
||||
foreach($this->threads as $item) {
|
||||
@@ -220,7 +220,7 @@ class ThreadStream {
|
||||
$item_data = $this->prepared_item;
|
||||
}
|
||||
else {
|
||||
$item_data = $item->get_template_data($conv_responses);
|
||||
$item_data = $item->get_template_data($conv_responses, $mid_uuid_map);
|
||||
}
|
||||
if(!$item_data) {
|
||||
logger('Failed to get item template data ('. $item->get_id() .').', LOGGER_DEBUG, LOG_ERR);
|
||||
|
||||
@@ -35,9 +35,13 @@ class Zotfinger {
|
||||
$result = [];
|
||||
|
||||
$redirects = 0;
|
||||
$x = z_post_url($resource,$data,$redirects, [ 'headers' => $h ] );
|
||||
|
||||
logger('fetch: ' . print_r($x,true));
|
||||
$start_timestamp = microtime(true);
|
||||
$x = z_post_url($resource,$data,$redirects, [ 'headers' => $h ] );
|
||||
logger('logger_stats_data cmd:Zotfinger' . ' start:' . $start_timestamp . ' ' . 'end:' . microtime(true) . ' meta:' . $resource . '#' . random_string(16));
|
||||
btlogger('Zotfinger');
|
||||
|
||||
logger('fetch: ' . print_r($x,true), LOGGER_DATA);
|
||||
|
||||
if (in_array(intval($x['return_code']), [ 404, 410 ]) && $recurse) {
|
||||
|
||||
@@ -74,7 +78,7 @@ class Zotfinger {
|
||||
$result['data'] = json_decode(Crypto::unencapsulate($result['data'],get_config('system','prvkey')),true);
|
||||
}
|
||||
|
||||
logger('decrypted: ' . print_r($result,true));
|
||||
logger('decrypted: ' . print_r($result,true), LOGGER_DATA);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ use Zotlabs\Web\Controller;
|
||||
use Zotlabs\Daemon\Master;
|
||||
use Zotlabs\Lib\Activity as ZlibActivity;
|
||||
use Zotlabs\Lib\ActivityStreams;
|
||||
use Zotlabs\Lib\LDSignatures;
|
||||
use Zotlabs\Web\HTTPSig;
|
||||
use Zotlabs\Lib\Libzot;
|
||||
use Zotlabs\Lib\ThreadListener;
|
||||
@@ -26,7 +25,7 @@ class Activity extends Controller {
|
||||
|
||||
$portable_id = EMPTY_STR;
|
||||
|
||||
$item_normal_extra = sprintf(" and not verb in ('%s', '%s') ",
|
||||
$item_normal_extra = sprintf(" and not verb in ('Follow', 'Ignore', '%s', '%s') ",
|
||||
dbesc(ACTIVITY_FOLLOW),
|
||||
dbesc(ACTIVITY_UNFOLLOW)
|
||||
);
|
||||
@@ -155,22 +154,7 @@ class Activity extends Controller {
|
||||
if(! $i)
|
||||
http_status_exit(404, 'Not found');
|
||||
|
||||
$x = array_merge(['@context' => [
|
||||
ACTIVITYSTREAMS_JSONLD_REV,
|
||||
'https://w3id.org/security/v1',
|
||||
z_root() . ZOT_APSCHEMA_REV
|
||||
]], $i);
|
||||
|
||||
$headers = [];
|
||||
$headers['Content-Type'] = 'application/x-zot+json' ;
|
||||
$x['signature'] = LDSignatures::sign($x,$chan);
|
||||
$ret = json_encode($x, JSON_UNESCAPED_SLASHES);
|
||||
$headers['Digest'] = HTTPSig::generate_digest_header($ret);
|
||||
$headers['(request-target)'] = strtolower($_SERVER['REQUEST_METHOD']) . ' ' . $_SERVER['REQUEST_URI'];
|
||||
$h = HTTPSig::create_sig($headers,$chan['channel_prvkey'],channel_url($chan));
|
||||
HTTPSig::set_headers($h);
|
||||
echo $ret;
|
||||
killme();
|
||||
as_return_and_die($i, $chan);
|
||||
|
||||
}
|
||||
|
||||
@@ -202,7 +186,7 @@ class Activity extends Controller {
|
||||
}
|
||||
}
|
||||
|
||||
$item_normal_extra = sprintf(" and not verb in ('%s', '%s') ",
|
||||
$item_normal_extra = sprintf(" and not verb in ('Follow', 'Ignore', '%s', '%s') ",
|
||||
dbesc(ACTIVITY_FOLLOW),
|
||||
dbesc(ACTIVITY_UNFOLLOW)
|
||||
);
|
||||
@@ -260,25 +244,7 @@ class Activity extends Controller {
|
||||
|
||||
$channel = channelx_by_n($items[0]['uid']);
|
||||
|
||||
$x = array_merge( ['@context' => [
|
||||
ACTIVITYSTREAMS_JSONLD_REV,
|
||||
'https://w3id.org/security/v1',
|
||||
z_root() . ZOT_APSCHEMA_REV
|
||||
]], ZlibActivity::encode_activity($items[0],true));
|
||||
|
||||
$headers = [];
|
||||
$headers['Content-Type'] = 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"' ;
|
||||
$x['signature'] = LDSignatures::sign($x,$channel);
|
||||
$ret = json_encode($x, JSON_UNESCAPED_SLASHES);
|
||||
$headers['Date'] = datetime_convert('UTC','UTC', 'now', 'D, d M Y H:i:s \\G\\M\\T');
|
||||
$headers['Digest'] = HTTPSig::generate_digest_header($ret);
|
||||
$headers['(request-target)'] = strtolower($_SERVER['REQUEST_METHOD']) . ' ' . $_SERVER['REQUEST_URI'];
|
||||
|
||||
$h = HTTPSig::create_sig($headers,$channel['channel_prvkey'],channel_url($channel));
|
||||
HTTPSig::set_headers($h);
|
||||
echo $ret;
|
||||
killme();
|
||||
|
||||
as_return_and_die(ZlibActivity::encode_activity($items[0]), $channel);
|
||||
}
|
||||
|
||||
goaway(z_root() . '/item/' . argv(1));
|
||||
|
||||
@@ -346,7 +346,7 @@ class Accounts {
|
||||
'$users' => $users,
|
||||
'$msg' => t('Message')
|
||||
));
|
||||
$o .= paginate($a);
|
||||
$o .= paginate();
|
||||
|
||||
return $o;
|
||||
}
|
||||
|
||||
@@ -168,7 +168,7 @@ class Channels {
|
||||
'$baseurl' => z_root(),
|
||||
'$channels' => $channels,
|
||||
));
|
||||
$o .= paginate($a);
|
||||
$o .= paginate();
|
||||
|
||||
return $o;
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ class Queueworker extends Controller {
|
||||
|
||||
$content .= "<H4>There are " . $r[0]['total'] . " queue items to be processed.</H4>";
|
||||
|
||||
$r = dbq("select count(distinct workerq_reservationid) as qworkers from workerq where workerq_reservationid is not null");
|
||||
$r = dbq("select count(*) as qworkers from workerq where workerq_reservationid is not null");
|
||||
|
||||
$content .= "<H4>Active workers: " . $r[0]['qworkers'] . "</H4>";
|
||||
|
||||
|
||||
@@ -7,12 +7,12 @@ class Security {
|
||||
|
||||
function post() {
|
||||
check_form_security_token_redirectOnErr('/admin/security', 'admin_security');
|
||||
|
||||
|
||||
$allowed_email = ((x($_POST,'allowed_email')) ? notags(trim($_POST['allowed_email'])) : '');
|
||||
$not_allowed_email = ((x($_POST,'not_allowed_email')) ? notags(trim($_POST['not_allowed_email'])) : '');
|
||||
|
||||
set_config('system','allowed_email', $allowed_email);
|
||||
set_config('system','not_allowed_email', $not_allowed_email);
|
||||
set_config('system','not_allowed_email', $not_allowed_email);
|
||||
|
||||
$block_public = ((x($_POST,'block_public')) ? True : False);
|
||||
set_config('system','block_public',$block_public);
|
||||
@@ -25,22 +25,22 @@ class Security {
|
||||
|
||||
$ws = $this->trim_array_elems(explode("\n",$_POST['whitelisted_sites']));
|
||||
set_config('system','whitelisted_sites',$ws);
|
||||
|
||||
|
||||
$bs = $this->trim_array_elems(explode("\n",$_POST['blacklisted_sites']));
|
||||
set_config('system','blacklisted_sites',$bs);
|
||||
|
||||
|
||||
$wc = $this->trim_array_elems(explode("\n",$_POST['whitelisted_channels']));
|
||||
set_config('system','whitelisted_channels',$wc);
|
||||
|
||||
|
||||
$bc = $this->trim_array_elems(explode("\n",$_POST['blacklisted_channels']));
|
||||
set_config('system','blacklisted_channels',$bc);
|
||||
|
||||
|
||||
$embed_sslonly = ((x($_POST,'embed_sslonly')) ? True : False);
|
||||
set_config('system','embed_sslonly',$embed_sslonly);
|
||||
|
||||
|
||||
$we = $this->trim_array_elems(explode("\n",$_POST['embed_allow']));
|
||||
set_config('system','embed_allow',$we);
|
||||
|
||||
|
||||
$be = $this->trim_array_elems(explode("\n",$_POST['embed_deny']));
|
||||
set_config('system','embed_deny',$be);
|
||||
|
||||
@@ -49,47 +49,54 @@ class Security {
|
||||
|
||||
$inline_pdf = ((x($_POST,'inline_pdf')) ? intval($_POST['inline_pdf']) : 0);
|
||||
set_config('system', 'inline_pdf' , $inline_pdf);
|
||||
|
||||
|
||||
$ts = ((x($_POST,'transport_security')) ? True : False);
|
||||
set_config('system','transport_security_header',$ts);
|
||||
|
||||
$cs = ((x($_POST,'content_security')) ? True : False);
|
||||
set_config('system','content_security_policy',$cs);
|
||||
|
||||
$trusted_directory_servers = $this->trim_array_elems(explode("\n", $_POST['trusted_directory_servers']));
|
||||
set_config('system', 'trusted_directory_servers', $trusted_directory_servers);
|
||||
|
||||
goaway(z_root() . '/admin/security');
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
function get() {
|
||||
|
||||
|
||||
$whitesites = get_config('system','whitelisted_sites');
|
||||
$whitesites_str = ((is_array($whitesites)) ? implode("\n",$whitesites) : '');
|
||||
|
||||
|
||||
$blacksites = get_config('system','blacklisted_sites');
|
||||
$blacksites_str = ((is_array($blacksites)) ? implode("\n",$blacksites) : '');
|
||||
|
||||
|
||||
|
||||
|
||||
$whitechannels = get_config('system','whitelisted_channels');
|
||||
$whitechannels_str = ((is_array($whitechannels)) ? implode("\n",$whitechannels) : '');
|
||||
|
||||
|
||||
$blackchannels = get_config('system','blacklisted_channels');
|
||||
$blackchannels_str = ((is_array($blackchannels)) ? implode("\n",$blackchannels) : '');
|
||||
|
||||
|
||||
|
||||
|
||||
$whiteembeds = get_config('system','embed_allow');
|
||||
$whiteembeds_str = ((is_array($whiteembeds)) ? implode("\n",$whiteembeds) : '');
|
||||
|
||||
|
||||
$blackembeds = get_config('system','embed_deny');
|
||||
$blackembeds_str = ((is_array($blackembeds)) ? implode("\n",$blackembeds) : '');
|
||||
|
||||
|
||||
$trusted_directory_servers = get_config('system', 'trusted_directory_servers');
|
||||
$trusted_directory_servers_str = ((is_array($trusted_directory_servers)) ? implode("\n", $trusted_directory_servers) : '');
|
||||
$is_dir = (intval(get_config('system', 'directory_mode', DIRECTORY_MODE_NORMAL)) !== DIRECTORY_MODE_NORMAL);
|
||||
|
||||
$embed_coop = intval(get_config('system','embed_coop'));
|
||||
|
||||
|
||||
if((! $whiteembeds) && (! $blackembeds)) {
|
||||
$embedhelp1 = t("By default, unfiltered HTML is allowed in embedded media. This is inherently insecure.");
|
||||
}
|
||||
|
||||
$embedhelp2 = t("The recommended setting is to only allow unfiltered HTML from the following sites:");
|
||||
$embedhelp2 = t("The recommended setting is to only allow unfiltered HTML from the following sites:");
|
||||
$embedhelp3 = t("https://youtube.com/<br />https://www.youtube.com/<br />https://youtu.be/<br />https://vimeo.com/<br />https://soundcloud.com/<br />");
|
||||
$embedhelp4 = t("All other embedded content will be filtered, <strong>unless</strong> embedded content from that site is explicitly blocked.");
|
||||
|
||||
@@ -99,7 +106,7 @@ class Security {
|
||||
'$page' => t('Security'),
|
||||
'$form_security_token' => get_form_security_token('admin_security'),
|
||||
'$block_public' => array('block_public', t("Block public"), get_config('system','block_public'), t("Check to block public access to all otherwise public personal pages on this site unless you are currently authenticated.")),
|
||||
'$cloud_noroot' => [ 'cloud_noroot', t('Provide a cloud root directory'), 1 - intval(get_config('system','cloud_disable_siteroot')), t('The cloud root directory lists all channel names which provide public files') ],
|
||||
'$cloud_noroot' => [ 'cloud_noroot', t('Provide a cloud root directory'), 1 - intval(get_config('system','cloud_disable_siteroot')), t('The cloud root directory lists all channel names which provide public files') ],
|
||||
'$cloud_disksize' => [ 'cloud_disksize', t('Show total disk space available to cloud uploads'), intval(get_config('system','cloud_report_disksize')), '' ],
|
||||
'$transport_security' => array('transport_security', t('Set "Transport Security" HTTP header'),intval(get_config('system','transport_security_header')),''),
|
||||
'$content_security' => array('content_security', t('Set "Content Security Policy" HTTP header'),intval(get_config('system','content_security_policy')),''),
|
||||
@@ -115,6 +122,8 @@ class Security {
|
||||
'$thumbnail_security' => [ 'thumbnail_security', t("Allow SVG thumbnails in file browser"), get_config('system','thumbnail_security',0), t("WARNING: SVG images may contain malicious code.") ],
|
||||
'$inline_pdf' => [ 'inline_pdf', t("Allow embedded (inline) PDF files"), get_config('system','inline_pdf',0), '' ],
|
||||
|
||||
'$trusted_directory_servers' => (($is_dir) ? ['trusted_directory_servers', t('Additional trusted directory server URLs'), $trusted_directory_servers_str, t('Accept directory flags (spam, nsfw) from those servers. One per line like https://example.tld')] : ''),
|
||||
|
||||
// '$embed_coop' => array('embed_coop', t('Cooperative embed security'), $embed_coop, t('Enable to share embed security with other compatible sites/hubs')),
|
||||
|
||||
'$submit' => t('Submit')
|
||||
@@ -124,7 +133,7 @@ class Security {
|
||||
|
||||
function trim_array_elems($arr) {
|
||||
$narr = array();
|
||||
|
||||
|
||||
if($arr && is_array($arr)) {
|
||||
for($x = 0; $x < count($arr); $x ++) {
|
||||
$y = trim($arr[$x]);
|
||||
@@ -134,6 +143,6 @@ class Security {
|
||||
}
|
||||
return $narr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -67,9 +67,8 @@ class Site {
|
||||
$open_pubstream = ((x($_POST,'open_pubstream')) ? True : False);
|
||||
$login_on_homepage = ((x($_POST,'login_on_homepage')) ? True : False);
|
||||
$enable_context_help = ((x($_POST,'enable_context_help')) ? True : False);
|
||||
$global_directory = ((x($_POST,'directory_submit_url')) ? notags(trim($_POST['directory_submit_url'])) : '');
|
||||
$no_community_page = !((x($_POST,'no_community_page')) ? True : False);
|
||||
$default_expire_days = ((array_key_exists('default_expire_days',$_POST)) ? intval($_POST['default_expire_days']) : 0);
|
||||
$default_expire_days = ((array_key_exists('default_expire_days',$_POST)) ? intval($_POST['default_expire_days']) : 30);
|
||||
$active_expire_days = ((array_key_exists('active_expire_days',$_POST)) ? intval($_POST['active_expire_days']) : 7);
|
||||
|
||||
$reply_address = ((array_key_exists('reply_address',$_POST) && trim($_POST['reply_address'])) ? trim($_POST['reply_address']) : 'noreply@' . \App::get_hostname());
|
||||
@@ -181,7 +180,7 @@ class Site {
|
||||
set_config('system', 'admininfo', $admininfo);
|
||||
}
|
||||
set_config('system','siteinfo',$siteinfo);
|
||||
set_config('system', 'language', $language);
|
||||
//set_config('system', 'language', $language);
|
||||
set_config('system', 'theme', $theme);
|
||||
// if ( $theme_mobile === '---' ) {
|
||||
// del_config('system', 'mobile_theme');
|
||||
@@ -206,11 +205,6 @@ class Site {
|
||||
set_config('system','site_firehose', $site_firehose);
|
||||
set_config('system','open_pubstream', $open_pubstream);
|
||||
//set_config('system','force_queue_threshold', $force_queue);
|
||||
if ($global_directory == '') {
|
||||
del_config('system', 'directory_submit_url');
|
||||
} else {
|
||||
set_config('system', 'directory_submit_url', $global_directory);
|
||||
}
|
||||
|
||||
set_config('system','no_community_page', $no_community_page);
|
||||
set_config('system','no_utf', $no_utf);
|
||||
@@ -233,20 +227,6 @@ class Site {
|
||||
*/
|
||||
function get() {
|
||||
|
||||
/* Installed langs */
|
||||
$lang_choices = array();
|
||||
$langs = glob('view/*/hstrings.php');
|
||||
|
||||
if(is_array($langs) && count($langs)) {
|
||||
if(! in_array('view/en/hstrings.php',$langs))
|
||||
$langs[] = 'view/en/';
|
||||
asort($langs);
|
||||
foreach($langs as $l) {
|
||||
$t = explode("/",$l);
|
||||
$lang_choices[$t[1]] = $t[1];
|
||||
}
|
||||
}
|
||||
|
||||
/* Installed themes */
|
||||
$theme_choices_mobile["---"] = t("Default");
|
||||
$theme_choices = array();
|
||||
@@ -283,7 +263,7 @@ class Site {
|
||||
}
|
||||
|
||||
$dir_choices = null;
|
||||
$dirmode = get_config('system','directory_mode');
|
||||
$dirmode = get_config('system', 'directory_mode', DIRECTORY_MODE_NORMAL);
|
||||
$realm = get_directory_realm();
|
||||
|
||||
// directory server should not be set or settable unless we are a directory client
|
||||
@@ -301,6 +281,12 @@ class Site {
|
||||
$dir_choices[$xx['site_url']] = $xx['site_url'];
|
||||
}
|
||||
}
|
||||
if ($realm === DIRECTORY_REALM) {
|
||||
$fallback_servers = get_directory_fallback_servers();
|
||||
foreach ($fallback_servers as $fallback_server) {
|
||||
$dir_choices[$fallback_server] = $fallback_server;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Banner */
|
||||
@@ -425,7 +411,6 @@ class Site {
|
||||
'$banner' => array('banner', t("Banner/Logo"), $banner, t('Unfiltered HTML/CSS/JS is allowed')),
|
||||
'$admininfo' => array('admininfo', t("Administrator Information"), $admininfo, t("Contact information for site administrators. Displayed on siteinfo page. BBCode can be used here")),
|
||||
'$siteinfo' => array('siteinfo', t('Site Information'), get_config('system','siteinfo'), t("Publicly visible description of this site. Displayed on siteinfo page. BBCode can be used here")),
|
||||
'$language' => array('language', t("System language"), get_config('system','language'), "", $lang_choices),
|
||||
'$theme' => array('theme', t("System theme"), get_config('system','theme'), t("Default system theme - may be over-ridden by user profiles - <a href='#' id='cnftheme'>change theme settings</a>"), $theme_choices),
|
||||
// '$theme_mobile' => array('theme_mobile', t("Mobile system theme"), get_config('system','mobile_theme'), t("Theme for mobile devices"), $theme_choices_mobile),
|
||||
// '$site_channel' => array('site_channel', t("Channel to use for this website's static pages"), get_config('system','site_channel'), t("Site Channel")),
|
||||
@@ -536,7 +521,7 @@ class Site {
|
||||
'$poll_interval' => array('poll_interval', t("Poll interval"), (x(get_config('system','poll_interval'))?get_config('system','poll_interval'):2), t("Delay background polling processes by this many seconds to reduce system load. If 0, use delivery interval.")),
|
||||
'$imagick_path' => array('imagick_path', t("Path to ImageMagick convert program"), get_config('system','imagick_convert_path'), t("If set, use this program to generate photo thumbnails for huge images ( > 4000 pixels in either dimension), otherwise memory exhaustion may occur. Example: /usr/bin/convert")),
|
||||
'$maxloadavg' => array('maxloadavg', t("Maximum Load Average"), ((intval(get_config('system','maxloadavg')) > 0)?get_config('system','maxloadavg'):50), t("Maximum system load before delivery and poll processes are deferred - default 50.")),
|
||||
'$default_expire_days' => array('default_expire_days', t('Expiration period in days for imported (grid/network) content'), intval(get_config('system','default_expire_days')), t('0 for no expiration of imported content')),
|
||||
'$default_expire_days' => array('default_expire_days', t('Expiration period in days for imported (grid/network) content'), intval(get_config('system','default_expire_days', 30)), t('0 for no expiration of imported content')),
|
||||
'$active_expire_days' => array('active_expire_days', t('Do not expire any posts which have comments less than this many days ago'), intval(get_config('system','active_expire_days',7)), ''),
|
||||
'$sellpage' => array('site_sellpage', t('Public servers: Optional landing (marketing) webpage for new registrants'), get_config('system','sellpage',''), sprintf( t('Create this page first. Default is %s/register'),z_root())),
|
||||
'$first_page' => array('first_page', t('Page to display after creating a new channel'), get_config('system','workflow_channel_next','profiles'), t('Default: profiles')),
|
||||
|
||||
@@ -80,10 +80,25 @@ class Themes {
|
||||
|
||||
$this->toggle_theme($themes, $theme, $result);
|
||||
$s = $this->rebuild_theme_table($themes);
|
||||
if($result)
|
||||
info( sprintf('Theme %s enabled.', $theme));
|
||||
else
|
||||
info( sprintf('Theme %s disabled.', $theme));
|
||||
|
||||
if($result) {
|
||||
if (is_file("view/theme/$theme/php/config.php")){
|
||||
require_once("view/theme/$theme/php/config.php");
|
||||
if (function_exists($theme . '_theme_admin_enable')){
|
||||
call_user_func($theme . '_theme_admin_enable');
|
||||
}
|
||||
}
|
||||
info(sprintf('Theme %s enabled.', $theme));
|
||||
}
|
||||
else {
|
||||
if (is_file("view/theme/$theme/php/config.php")){
|
||||
require_once("view/theme/$theme/php/config.php");
|
||||
if (function_exists($theme . '_theme_admin_disable')){
|
||||
call_user_func($theme . '_theme_admin_disable');
|
||||
}
|
||||
}
|
||||
info(sprintf('Theme %s disabled.', $theme));
|
||||
}
|
||||
|
||||
set_config('system', 'allowed_themes', $s);
|
||||
goaway(z_root() . '/admin/themes' );
|
||||
|
||||
@@ -24,42 +24,42 @@ class Api extends \Zotlabs\Web\Controller {
|
||||
notice( t('Permission denied.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
function get() {
|
||||
|
||||
if(\App::$cmd === 'api/oauth/authorize'){
|
||||
|
||||
/*
|
||||
|
||||
/*
|
||||
* api/oauth/authorize interact with the user. return a standard page
|
||||
*/
|
||||
|
||||
|
||||
\App::$page['template'] = 'minimal';
|
||||
|
||||
|
||||
// get consumer/client from request token
|
||||
try {
|
||||
$request = \OAuth1Request::from_request();
|
||||
}
|
||||
catch(\Exception $e) {
|
||||
logger('OAuth exception: ' . print_r($e,true));
|
||||
// echo "<pre>"; var_dump($e);
|
||||
// echo "<pre>"; var_dump($e);
|
||||
killme();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
if(x($_POST,'oauth_yes')){
|
||||
|
||||
|
||||
$app = $this->oauth_get_client($request);
|
||||
if (is_null($app))
|
||||
if (is_null($app))
|
||||
return "Invalid request. Unknown token.";
|
||||
|
||||
$consumer = new \OAuth1Consumer($app['client_id'], $app['pw'], $app['redirect_uri']);
|
||||
|
||||
|
||||
$verifier = md5($app['secret'] . local_channel());
|
||||
set_config('oauth', $verifier, local_channel());
|
||||
|
||||
|
||||
|
||||
|
||||
if($consumer->callback_url != null) {
|
||||
$params = $request->get_parameters();
|
||||
$glue = '?';
|
||||
@@ -68,28 +68,28 @@ class Api extends \Zotlabs\Web\Controller {
|
||||
goaway($consumer->callback_url . $glue . "oauth_token=" . \OAuth1Util::urlencode_rfc3986($params['oauth_token']) . "&oauth_verifier=" . \OAuth1Util::urlencode_rfc3986($verifier));
|
||||
killme();
|
||||
}
|
||||
|
||||
|
||||
$tpl = get_markup_template("oauth_authorize_done.tpl");
|
||||
$o = replace_macros($tpl, array(
|
||||
'$title' => t('Authorize application connection'),
|
||||
'$info' => t('Return to your app and insert this Security Code:'),
|
||||
'$code' => $verifier,
|
||||
));
|
||||
|
||||
|
||||
return $o;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
if(! local_channel()) {
|
||||
//TODO: we need login form to redirect to this page
|
||||
notice( t('Please login to continue.') . EOL );
|
||||
return login(false,'api-login',$request->get_parameters());
|
||||
}
|
||||
|
||||
|
||||
$app = $this->oauth_get_client($request);
|
||||
if (is_null($app))
|
||||
return "Invalid request. Unknown token.";
|
||||
|
||||
|
||||
$tpl = get_markup_template('oauth_authorize.tpl');
|
||||
$o = replace_macros($tpl, array(
|
||||
'$title' => t('Authorize application connection'),
|
||||
@@ -98,12 +98,12 @@ class Api extends \Zotlabs\Web\Controller {
|
||||
'$yes' => t('Yes'),
|
||||
'$no' => t('No'),
|
||||
));
|
||||
|
||||
|
||||
//echo "<pre>"; var_dump($app); killme();
|
||||
|
||||
|
||||
return $o;
|
||||
}
|
||||
|
||||
|
||||
echo api_call();
|
||||
killme();
|
||||
}
|
||||
@@ -112,8 +112,8 @@ class Api extends \Zotlabs\Web\Controller {
|
||||
|
||||
$params = $request->get_parameters();
|
||||
$token = $params['oauth_token'];
|
||||
|
||||
$r = q("SELECT clients.* FROM clients, tokens WHERE clients.client_id = tokens.client_id
|
||||
|
||||
$r = q("SELECT clients.* FROM clients, tokens WHERE clients.client_id = tokens.client_id
|
||||
AND tokens.id = '%s' AND tokens.auth_scope = 'request' ",
|
||||
dbesc($token)
|
||||
);
|
||||
@@ -121,7 +121,7 @@ class Api extends \Zotlabs\Web\Controller {
|
||||
return $r[0];
|
||||
|
||||
return null;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -110,6 +110,11 @@ class Appman extends \Zotlabs\Web\Controller {
|
||||
dbesc($papp['guid'])
|
||||
);
|
||||
|
||||
$sync[0]['term'] = q("select * from term where otype = %d and oid = %d",
|
||||
intval(TERM_OBJ_APP),
|
||||
intval($sync[0]['id'])
|
||||
);
|
||||
|
||||
if (intval($sync[0]['app_system'])) {
|
||||
Libsync::build_sync_packet(local_channel(), ['sysapp' => $sync]);
|
||||
}
|
||||
@@ -126,6 +131,11 @@ class Appman extends \Zotlabs\Web\Controller {
|
||||
dbesc($papp['guid'])
|
||||
);
|
||||
|
||||
$sync[0]['term'] = q("select * from term where otype = %d and oid = %d",
|
||||
intval(TERM_OBJ_APP),
|
||||
intval($sync[0]['id'])
|
||||
);
|
||||
|
||||
if (intval($sync[0]['app_system'])) {
|
||||
Libsync::build_sync_packet(local_channel(), ['sysapp' => $sync]);
|
||||
}
|
||||
|
||||
@@ -2,68 +2,13 @@
|
||||
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
use Zotlabs\Web\Controller;
|
||||
use Zotlabs\Lib\Activity;
|
||||
|
||||
class Apschema extends \Zotlabs\Web\Controller {
|
||||
|
||||
class Apschema extends Controller {
|
||||
function init() {
|
||||
|
||||
$base = z_root();
|
||||
|
||||
$arr = [
|
||||
'@context' => [
|
||||
'zot' => z_root() . '/apschema#',
|
||||
'id' => '@id',
|
||||
'type' => '@type',
|
||||
'commentPolicy' => 'zot:commentPolicy',
|
||||
'meData' => 'zot:meData',
|
||||
'meDataType' => 'zot:meDataType',
|
||||
'meEncoding' => 'zot:meEncoding',
|
||||
'meAlgorithm' => 'zot:meAlgorithm',
|
||||
'meCreator' => 'zot:meCreator',
|
||||
'meSignatureValue' => 'zot:meSignatureValue',
|
||||
'locationAddress' => 'zot:locationAddress',
|
||||
'locationPrimary' => 'zot:locationPrimary',
|
||||
'locationDeleted' => 'zot:locationDeleted',
|
||||
'nomadicLocation' => 'zot:nomadicLocation',
|
||||
'nomadicHubs' => 'zot:nomadicHubs',
|
||||
'emojiReaction' => 'zot:emojiReaction',
|
||||
'expires' => 'zot:expires',
|
||||
'directMessage' => 'zot:directMessage',
|
||||
'schema' => 'http://schema.org#',
|
||||
'PropertyValue' => 'schema:PropertyValue',
|
||||
'value' => 'schema:value',
|
||||
|
||||
'manuallyApprovesFollowers' => 'as:manuallyApprovesFollowers',
|
||||
|
||||
|
||||
'magicEnv' => [
|
||||
'@id' => 'zot:magicEnv',
|
||||
'@type' => '@id'
|
||||
],
|
||||
|
||||
'nomadicLocations' => [
|
||||
'@id' => 'zot:nomadicLocations',
|
||||
'@type' => '@id'
|
||||
],
|
||||
|
||||
'ostatus' => 'http://ostatus.org#',
|
||||
'conversation' => 'ostatus:conversation',
|
||||
|
||||
'diaspora' => 'https://diasporafoundation.org/ns/',
|
||||
'guid' => 'diaspora:guid',
|
||||
|
||||
'Hashtag' => 'as:Hashtag'
|
||||
|
||||
]
|
||||
];
|
||||
|
||||
header('Content-Type: application/ld+json');
|
||||
echo json_encode($arr,JSON_UNESCAPED_SLASHES);
|
||||
echo json_encode(Activity::ap_context(), JSON_UNESCAPED_SLASHES);
|
||||
killme();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -95,7 +95,7 @@ class Attach extends Controller {
|
||||
killme();
|
||||
}
|
||||
|
||||
$r = attach_by_hash(argv(1), get_observer_hash(), ((argc() > 2) ? intval(argv(2)) : 0));
|
||||
$r = attach_by_hash(argv(1), get_observer_hash(), ((argc() > 2) ? intval(argv(2)) : 0), $token);
|
||||
|
||||
if (!$r['success']) {
|
||||
notice($r['message'] . EOL);
|
||||
|
||||
@@ -107,7 +107,7 @@ class Blocks extends \Zotlabs\Web\Controller {
|
||||
$x['pagetitle'] = $_REQUEST['pagetitle'] ?? '';
|
||||
|
||||
$a = '';
|
||||
$editor = status_editor($a,$x,false,'Blocks');
|
||||
$editor = status_editor($x, false, 'Blocks');
|
||||
|
||||
|
||||
$r = q("select iconfig.iid, iconfig.k, iconfig.v, mid, title, body, mimetype, created, edited from iconfig
|
||||
|
||||
@@ -1087,7 +1087,11 @@ class Cdav extends Controller {
|
||||
|
||||
$filters['name'] = 'VCALENDAR';
|
||||
$filters['prop-filters'][0]['name'] = 'VEVENT';
|
||||
$filters['prop-filters'][0]['is-not-defined'] = null;
|
||||
$filters['prop-filters'][0]['param-filters'] = null;
|
||||
$filters['prop-filters'][0]['text-match'] = null;
|
||||
$filters['comp-filters'][0]['name'] = 'VEVENT';
|
||||
$filters['comp-filters'][0]['is-not-defined'] = null;
|
||||
$filters['comp-filters'][0]['time-range']['start'] = $start;
|
||||
$filters['comp-filters'][0]['time-range']['end'] = $end;
|
||||
|
||||
|
||||
@@ -101,16 +101,23 @@ class Channel extends Controller {
|
||||
App::$meta->set('robots', 'noindex, noarchive');
|
||||
}
|
||||
|
||||
$identifier = 'uuid';
|
||||
$mid = $_REQUEST['mid'] ?? '';
|
||||
|
||||
if (str_starts_with($mid, 'b64.')) {
|
||||
$mid = unpack_link_id($mid);
|
||||
$identifier = 'mid';
|
||||
}
|
||||
|
||||
if ($mid === false) {
|
||||
http_status_exit(404, 'Not found');
|
||||
}
|
||||
|
||||
if (ActivityStreams::is_as_request($channel)) {
|
||||
|
||||
// Somebody may attempt an ActivityStreams fetch on one of our message permalinks
|
||||
// Make it do the right thing.
|
||||
|
||||
$mid = ((x($_REQUEST, 'mid')) ? unpack_link_id($_REQUEST['mid']) : '');
|
||||
if ($mid === false) {
|
||||
http_status_exit(404, 'Not found');
|
||||
}
|
||||
|
||||
if ($mid) {
|
||||
$obj = null;
|
||||
if (strpos($mid, z_root() . '/item/') === 0) {
|
||||
@@ -127,6 +134,7 @@ class Channel extends Controller {
|
||||
$obj->init();
|
||||
}
|
||||
}
|
||||
|
||||
as_return_and_die(Activity::encode_person($channel, true), $channel);
|
||||
}
|
||||
|
||||
@@ -155,15 +163,9 @@ class Channel extends Controller {
|
||||
profile_load($which, $profile);
|
||||
|
||||
// Add Opengraph markup
|
||||
$mid = ((x($_REQUEST, 'mid')) ? unpack_link_id($_REQUEST['mid']) : '');
|
||||
|
||||
if ($mid === false) {
|
||||
notice(t('Malformed message id.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
if ($mid) {
|
||||
$r = q("SELECT * FROM item WHERE mid = '%s' AND uid = %d AND item_private = 0 LIMIT 1",
|
||||
$r = q("SELECT * FROM item WHERE $identifier = '%s' AND uid = %d AND item_private = 0 LIMIT 1",
|
||||
dbesc($mid),
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
@@ -178,7 +180,16 @@ class Channel extends Controller {
|
||||
|
||||
$category = $datequery = $datequery2 = '';
|
||||
|
||||
$mid = ((x($_REQUEST, 'mid')) ? unpack_link_id($_REQUEST['mid']) : '');
|
||||
$mid = $_REQUEST['mid'] ?? '';
|
||||
$identifier = 'uuid';
|
||||
$encoded_mid = null;
|
||||
|
||||
if (str_starts_with($mid, 'b64.')) {
|
||||
$encoded_mid = $mid;
|
||||
$mid = unpack_link_id($mid);
|
||||
$identifier = 'mid';
|
||||
}
|
||||
|
||||
if ($mid === false) {
|
||||
notice(t('Malformed message id.') . EOL);
|
||||
return;
|
||||
@@ -268,7 +279,7 @@ class Channel extends Controller {
|
||||
];
|
||||
|
||||
$a = '';
|
||||
$o .= status_editor($a, $x, false, 'Channel');
|
||||
$o .= status_editor($x, false, 'Channel');
|
||||
}
|
||||
|
||||
// Add pinned content
|
||||
@@ -284,13 +295,9 @@ class Channel extends Controller {
|
||||
* Get permissions SQL - if $remote_contact is true, our remote user has been pre-verified and we already have fetched his/her groups
|
||||
*/
|
||||
|
||||
$item_normal = " and item.item_hidden = 0 and item.item_type = 0 and item.item_deleted = 0
|
||||
and item.item_unpublished = 0 and item.item_pending_remove = 0
|
||||
and item.item_blocked = 0 ";
|
||||
if (!$is_owner)
|
||||
$item_normal .= "and item.item_delayed = 0 ";
|
||||
$item_normal = item_normal();
|
||||
$item_normal_update = item_normal_update();
|
||||
$sql_extra = item_permissions_sql(App::$profile['profile_uid']);
|
||||
$sql_extra = item_permissions_sql(App::$profile['profile_uid']);
|
||||
|
||||
if (feature_enabled(App::$profile['profile_uid'], 'channel_list_mode') && (!$mid))
|
||||
$page_mode = 'list';
|
||||
@@ -326,7 +333,7 @@ class Channel extends Controller {
|
||||
if (($update) && (!$load)) {
|
||||
|
||||
if ($mid) {
|
||||
$r = q("SELECT parent AS item_id from item where mid = '%s' and uid = %d $item_normal_update
|
||||
$r = q("SELECT parent AS item_id, uuid from item where $identifier = '%s' and uid = %d $item_normal_update
|
||||
AND item_wall = 1 $simple_update $sql_extra limit 1",
|
||||
dbesc($mid),
|
||||
intval(App::$profile['profile_uid'])
|
||||
@@ -374,7 +381,7 @@ class Channel extends Controller {
|
||||
|
||||
if ($noscript_content || $load) {
|
||||
if ($mid) {
|
||||
$r = q("SELECT parent AS item_id from item where mid = '%s' and uid = %d $item_normal
|
||||
$r = q("SELECT parent AS item_id, uuid from item where $identifier = '%s' and uid = %d $item_normal
|
||||
AND item_wall = 1 $sql_extra limit 1",
|
||||
dbesc($mid),
|
||||
intval(App::$profile['profile_uid'])
|
||||
@@ -400,7 +407,6 @@ class Channel extends Controller {
|
||||
}
|
||||
}
|
||||
if ($r) {
|
||||
|
||||
$parents_str = ids_to_querystr($r, 'item_id');
|
||||
|
||||
$r = q("SELECT item.*, item.id AS item_id
|
||||
@@ -431,13 +437,9 @@ class Channel extends Controller {
|
||||
|
||||
$mode = (($search) ? 'search' : 'channel');
|
||||
|
||||
|
||||
if ((!$update) && (!$load)) {
|
||||
|
||||
|
||||
|
||||
//if we got a decoded hash we must encode it again before handing to javascript
|
||||
$mid = gen_link_id($mid);
|
||||
|
||||
// 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.
|
||||
|
||||
@@ -474,7 +476,7 @@ class Channel extends Controller {
|
||||
'$file' => '',
|
||||
'$cats' => (($category) ? urlencode($category) : ''),
|
||||
'$tags' => (($hashtags) ? urlencode($hashtags) : ''),
|
||||
'$mid' => (($mid) ? urlencode($mid) : ''),
|
||||
'$mid' => $encoded_mid ?? $mid,
|
||||
'$verb' => '',
|
||||
'$net' => '',
|
||||
'$dend' => $datequery,
|
||||
|
||||
@@ -181,7 +181,7 @@ class Chat extends Controller {
|
||||
);
|
||||
|
||||
if($x) {
|
||||
$acl = new AccessList(false);
|
||||
$acl = new AccessList([]);
|
||||
$acl->set($x[0]);
|
||||
|
||||
$private = $acl->is_private();
|
||||
@@ -212,7 +212,7 @@ class Chat extends Controller {
|
||||
'$online' => t('I am online'),
|
||||
'$bookmark_link' => $bookmark_link,
|
||||
'$bookmark' => t('Bookmark this room'),
|
||||
'$feature_encrypt' => ((feature_enabled(local_channel(),'content_encrypt')) ? true : false),
|
||||
'$feature_encrypt' => ((feature_enabled(App::$profile['profile_uid'], 'content_encrypt')) ? true : false),
|
||||
'$cipher' => $cipher,
|
||||
'$linkurl' => t('Please enter a link URL:'),
|
||||
'$encrypt' => t('Encrypt text'),
|
||||
@@ -225,7 +225,7 @@ class Chat extends Controller {
|
||||
|
||||
$o = '';
|
||||
|
||||
$acl = new AccessList($channel);
|
||||
$acl = new AccessList($channel ?? []);
|
||||
$channel_acl = $acl->get();
|
||||
|
||||
$lockstate = (($channel_acl['allow_cid'] || $channel_acl['allow_gid'] || $channel_acl['deny_cid'] || $channel_acl['deny_gid']) ? 'lock' : 'unlock');
|
||||
|
||||
@@ -54,9 +54,9 @@ class Cloud extends Controller {
|
||||
if (local_channel()) {
|
||||
$channel = \App::get_channel();
|
||||
$auth->setCurrentUser($channel['channel_address']);
|
||||
$auth->channel_account_id = $channel['channel_account_id'];
|
||||
$auth->channel_id = $channel['channel_id'];
|
||||
$auth->channel_hash = $channel['channel_hash'];
|
||||
$auth->channel_account_id = $channel['channel_account_id'];
|
||||
if($channel['channel_timezone'])
|
||||
$auth->setTimezone($channel['channel_timezone']);
|
||||
}
|
||||
|
||||
@@ -409,7 +409,6 @@ class Connections extends \Zotlabs\Web\Controller {
|
||||
'$approve' => t('Approve'),
|
||||
'$cmd' => App::$cmd,
|
||||
'$contacts' => $contacts,
|
||||
'$paginate' => paginate($a),
|
||||
'$abook_usage_message' => $abook_usage_message,
|
||||
'$group_label' => t('This is a group/forum channel')
|
||||
]);
|
||||
|
||||
@@ -177,22 +177,8 @@ class Contactedit extends Controller {
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
if (($pr) && (!intval($contact['abook_hidden'])) && (intval(get_pconfig($channel['channel_id'], 'system', 'post_newfriend')))) {
|
||||
$xarr = [];
|
||||
|
||||
$xarr['item_wall'] = 1;
|
||||
$xarr['item_origin'] = 1;
|
||||
$xarr['item_thread_top'] = 1;
|
||||
$xarr['owner_xchan'] = $xarr['author_xchan'] = $channel['channel_hash'];
|
||||
$xarr['allow_cid'] = $channel['channel_allow_cid'];
|
||||
$xarr['allow_gid'] = $channel['channel_allow_gid'];
|
||||
$xarr['deny_cid'] = $channel['channel_deny_cid'];
|
||||
$xarr['deny_gid'] = $channel['channel_deny_gid'];
|
||||
$xarr['item_private'] = (($xarr['allow_cid'] || $xarr['allow_gid'] || $xarr['deny_cid'] || $xarr['deny_gid']) ? 1 : 0);
|
||||
|
||||
$xarr['body'] = '[zrl=' . $channel['xchan_url'] . ']' . $channel['xchan_name'] . '[/zrl]' . ' ' . t('is now connected to') . ' ' . '[zrl=' . $contact['xchan_url'] . ']' . $contact['xchan_name'] . '[/zrl]';
|
||||
|
||||
$xarr['body'] .= "\n\n\n" . '[zrl=' . $contact['xchan_url'] . '][zmg=80x80]' . $contact['xchan_photo_m'] . '[/zmg][/zrl]';
|
||||
|
||||
$xarr['body'] .= "\n\n\n" . '[zrl=' . $contact['xchan_url'] . '][zmg=' . $contact['xchan_photo_m'] . ']' . $contact['xchan_name'] . '[/zmg][/zrl]';
|
||||
post_activity_item($xarr);
|
||||
|
||||
}
|
||||
@@ -494,28 +480,32 @@ class Contactedit extends Controller {
|
||||
'message' => ''
|
||||
];
|
||||
|
||||
if ($cmd === 'resetphoto') {
|
||||
q("update xchan set xchan_photo_date = '2001-01-01 00:00:00' where xchan_hash = '%s'",
|
||||
if ($cmd === 'refresh') {
|
||||
q("update xchan set xchan_photo_date = '0001-01-01 00:00:00', xchan_name_date = '0001-01-01 00:00:00' where xchan_hash = '%s'",
|
||||
dbesc($contact['xchan_hash'])
|
||||
);
|
||||
$cmd = 'refresh';
|
||||
}
|
||||
|
||||
if ($cmd === 'refresh') {
|
||||
if ($contact['xchan_network'] === 'zot6') {
|
||||
if (Libzot::refresh($contact, App::get_channel())) {
|
||||
$ret['success'] = true;
|
||||
$ret['message'] = t('Refresh succeeded');
|
||||
}
|
||||
else {
|
||||
$ret['message'] = t('Refresh failed - channel is currently unavailable');
|
||||
$ret['message'] = t('Refresh failed');
|
||||
}
|
||||
}
|
||||
else {
|
||||
// if you are on a different network we'll force a refresh of the connection basic info
|
||||
Master::Summon(['Notifier', 'permission_update', $contact['abook_id']]);
|
||||
$ret['success'] = true;
|
||||
$ret['message'] = t('Refresh succeeded');
|
||||
$hookinfo = [
|
||||
'contact' => $contact,
|
||||
'success' => false,
|
||||
'message' => ''
|
||||
];
|
||||
|
||||
call_hooks('actor_refetch', $hookinfo);
|
||||
|
||||
$ret['success'] = $hookinfo['success'];
|
||||
$ret['message'] = $hookinfo['message'];
|
||||
}
|
||||
|
||||
return $ret;
|
||||
@@ -625,16 +615,10 @@ class Contactedit extends Controller {
|
||||
return [
|
||||
|
||||
'refresh' => [
|
||||
'label' => t('Refresh Permissions'),
|
||||
'title' => t('Fetch updated permissions'),
|
||||
'label' => t('Refresh'),
|
||||
'title' => t('Refetch contact info'),
|
||||
],
|
||||
|
||||
'rephoto' => [
|
||||
'label' => t('Refresh Photo'),
|
||||
'title' => t('Fetch updated photo'),
|
||||
],
|
||||
|
||||
|
||||
'block' => [
|
||||
'label' => (intval($contact['abook_blocked']) ? t('Unblock') : t('Block')),
|
||||
'sel' => (intval($contact['abook_blocked']) ? 'active' : ''),
|
||||
|
||||
188
Zotlabs/Module/Conversation.php
Normal file
188
Zotlabs/Module/Conversation.php
Normal file
@@ -0,0 +1,188 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
use Zotlabs\Web\Controller;
|
||||
use Zotlabs\Lib\ActivityStreams;
|
||||
use Zotlabs\Lib\Activity;
|
||||
use Zotlabs\Lib\Libzot;
|
||||
use Zotlabs\Web\HTTPSig;
|
||||
use Zotlabs\Lib\LDSignatures;
|
||||
use Zotlabs\Lib\ThreadListener;
|
||||
use Zotlabs\Lib\Config;
|
||||
use App;
|
||||
|
||||
class Conversation extends Controller {
|
||||
|
||||
public function init() {
|
||||
|
||||
if (ActivityStreams::is_as_request()) {
|
||||
$item_id = argv(1);
|
||||
|
||||
if (!$item_id) {
|
||||
http_status_exit(404, 'Not found');
|
||||
}
|
||||
|
||||
$portable_id = EMPTY_STR;
|
||||
|
||||
$item_normal_extra = sprintf(" and not verb in ('Follow', 'Ignore', '%s', '%s') ",
|
||||
dbesc(ACTIVITY_FOLLOW),
|
||||
dbesc(ACTIVITY_UNFOLLOW)
|
||||
);
|
||||
|
||||
$item_normal = " and item.item_hidden = 0 and item.item_type = 0 and item.item_unpublished = 0 and item.item_delayed = 0 and item.item_blocked = 0 $item_normal_extra ";
|
||||
|
||||
$i = null;
|
||||
|
||||
// do we have the item (at all)?
|
||||
|
||||
$r = q("select parent_mid from item where mid = '%s' or uuid = '%s' $item_normal order by item_wall desc limit 1",
|
||||
dbesc(z_root() . '/item/' . $item_id),
|
||||
dbesc($item_id)
|
||||
);
|
||||
|
||||
if (!$r) {
|
||||
http_status_exit(404, 'Not found');
|
||||
}
|
||||
|
||||
// process an authenticated fetch
|
||||
|
||||
$sigdata = HTTPSig::verify(EMPTY_STR);
|
||||
if ($sigdata['portable_id'] && $sigdata['header_valid']) {
|
||||
$portable_id = $sigdata['portable_id'];
|
||||
observer_auth($portable_id);
|
||||
|
||||
// first see if we have a copy of this item's parent owned by the current signer
|
||||
// include xchans for all zot-like networks - these will have the same guid and public key
|
||||
|
||||
$x = q(
|
||||
"select * from xchan where xchan_hash = '%s'",
|
||||
dbesc($sigdata['portable_id'])
|
||||
);
|
||||
|
||||
if ($x) {
|
||||
$xchans = q(
|
||||
"select xchan_hash from xchan where xchan_hash = '%s' OR ( xchan_guid = '%s' AND xchan_pubkey = '%s' ) ",
|
||||
dbesc($sigdata['portable_id']),
|
||||
dbesc($x[0]['xchan_guid']),
|
||||
dbesc($x[0]['xchan_pubkey'])
|
||||
);
|
||||
|
||||
if ($xchans) {
|
||||
$hashes = ids_to_querystr($xchans, 'xchan_hash', true);
|
||||
$i = q(
|
||||
"select id as item_id from item where mid = '%s' $item_normal and owner_xchan in ( " . protect_sprintf($hashes) . " ) limit 1",
|
||||
dbesc($r[0]['parent_mid'])
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
elseif (Config::get('system', 'require_authenticated_fetch', false)) {
|
||||
http_status_exit(403, 'Permission denied');
|
||||
}
|
||||
|
||||
// if we don't have a parent id belonging to the signer see if we can obtain one as a visitor that we have permission to access
|
||||
// with a bias towards those items owned by channels on this site (item_wall = 1)
|
||||
|
||||
$sql_extra = item_permissions_sql(0);
|
||||
|
||||
if (!$i) {
|
||||
$i = q("select id as item_id from item where mid = '%s' $item_normal $sql_extra order by item_wall desc limit 1",
|
||||
dbesc($r[0]['parent_mid'])
|
||||
);
|
||||
}
|
||||
|
||||
if (!$i) {
|
||||
http_status_exit(403, 'Forbidden');
|
||||
}
|
||||
|
||||
$parents_str = ids_to_querystr($i, 'item_id');
|
||||
$itemspage = 30;
|
||||
$page = $_REQUEST['page'] ?? 1;
|
||||
$offset = (intval($page) - 1) * $itemspage;
|
||||
|
||||
$items = dbq("SELECT item.*,
|
||||
item.id AS item_id,
|
||||
(SELECT count(*) FROM item WHERE item.parent IN ( $parents_str ) $item_normal) AS total
|
||||
FROM item WHERE item.parent IN ( $parents_str ) $item_normal order by item.id LIMIT $itemspage OFFSET $offset"
|
||||
);
|
||||
|
||||
if (!$items) {
|
||||
http_status_exit(404, 'Not found');
|
||||
}
|
||||
|
||||
xchan_query($items, true);
|
||||
$items = fetch_post_tags($items);
|
||||
|
||||
$observer = App::get_observer();
|
||||
$parent = $items[0];
|
||||
$recips = (($parent['owner']['xchan_network'] === 'activitypub') ? get_iconfig($parent['id'], 'activitypub', 'recips', []) : []);
|
||||
$to = (($recips && array_key_exists('to', $recips) && is_array($recips['to'])) ? $recips['to'] : null);
|
||||
$nitems = [];
|
||||
foreach ($items as $i) {
|
||||
$mids = [];
|
||||
|
||||
if (intval($i['item_private'])) {
|
||||
if (!$observer) {
|
||||
continue;
|
||||
}
|
||||
/*
|
||||
// ignore private reshare, possibly from hubzilla
|
||||
if ($i['verb'] === 'Announce') {
|
||||
if (!in_array($i['thr_parent'], $mids)) {
|
||||
$mids[] = $i['thr_parent'];
|
||||
}
|
||||
continue;
|
||||
}
|
||||
// also ignore any children of the private reshares
|
||||
if (in_array($i['thr_parent'], $mids)) {
|
||||
continue;
|
||||
}
|
||||
*/
|
||||
|
||||
if ((!$to) || (!in_array($observer['xchan_url'], $to))) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
$nitems[] = $i;
|
||||
}
|
||||
|
||||
if (!$nitems) {
|
||||
http_status_exit(404, 'Not found');
|
||||
}
|
||||
|
||||
App::set_pager_total($nitems[0]['total']);
|
||||
App::set_pager_itemspage($itemspage);
|
||||
|
||||
$channel = channelx_by_n($nitems[0]['uid']);
|
||||
|
||||
if (!$channel) {
|
||||
http_status_exit(404, 'Not found');
|
||||
}
|
||||
|
||||
if (!perm_is_allowed($channel['channel_id'], get_observer_hash(), 'view_stream')) {
|
||||
http_status_exit(403, 'Forbidden');
|
||||
}
|
||||
|
||||
$i = Activity::encode_item_collection($nitems, App::$query_string, 'OrderedCollection', $nitems[0]['total']);
|
||||
|
||||
if (!$i) {
|
||||
http_status_exit(404, 'Not found');
|
||||
}
|
||||
|
||||
if ($portable_id && (!intval($nitems[0]['item_private']))) {
|
||||
$c = q("select abook_id from abook where abook_channel = %d and abook_xchan = '%s'",
|
||||
intval($nitems[0]['uid']),
|
||||
dbesc($portable_id)
|
||||
);
|
||||
if (!$c) {
|
||||
ThreadListener::store(z_root() . '/item/' . $item_id, $portable_id);
|
||||
}
|
||||
}
|
||||
|
||||
as_return_and_die($i, $channel);
|
||||
}
|
||||
|
||||
goaway(z_root() . '/item/' . argv(1));
|
||||
}
|
||||
}
|
||||
@@ -93,8 +93,6 @@ class Cover_photo extends \Zotlabs\Web\Controller {
|
||||
$image_id = substr($image_id,0,-2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
$srcX = intval($_POST['xstart']);
|
||||
$srcY = intval($_POST['ystart']);
|
||||
$srcW = intval($_POST['xfinal']) - $srcX;
|
||||
@@ -228,7 +226,7 @@ class Cover_photo extends \Zotlabs\Web\Controller {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->send_cover_photo_activity($channel,$base_image,$profile);
|
||||
profile_activity([t('Cover Photo')], $base_image['resource_id']);
|
||||
|
||||
$sync = attach_export_data($channel,$base_image['resource_id']);
|
||||
if($sync)
|
||||
@@ -245,13 +243,12 @@ class Cover_photo extends \Zotlabs\Web\Controller {
|
||||
|
||||
}
|
||||
|
||||
|
||||
$hash = photo_new_resource();
|
||||
$smallest = 0;
|
||||
|
||||
require_once('include/attach.php');
|
||||
|
||||
$res = attach_store(\App::get_channel(), get_observer_hash(), '', array('album' => t('Cover Photos'), 'hash' => $hash, 'nosync' => true));
|
||||
$res = attach_store(\App::get_channel(), get_observer_hash(), '', ['album' => t('Cover Photos'), 'hash' => $hash, 'nosync' => true, 'source' => 'photos']);
|
||||
|
||||
logger('attach_store: ' . print_r($res,true));
|
||||
|
||||
@@ -287,45 +284,6 @@ class Cover_photo extends \Zotlabs\Web\Controller {
|
||||
|
||||
}
|
||||
|
||||
function send_cover_photo_activity($channel,$photo,$profile) {
|
||||
|
||||
$arr = array();
|
||||
$arr['item_thread_top'] = 1;
|
||||
$arr['item_origin'] = 1;
|
||||
$arr['item_wall'] = 1;
|
||||
|
||||
if($profile && stripos($profile['gender'],t('female')) !== false)
|
||||
$t = t('%1$s updated her %2$s');
|
||||
elseif($profile && stripos($profile['gender'],t('male')) !== false)
|
||||
$t = t('%1$s updated his %2$s');
|
||||
else
|
||||
$t = t('%1$s updated their %2$s');
|
||||
|
||||
$ptext = '[zrl=' . z_root() . '/photos/' . $channel['channel_address'] . '/image/' . $photo['resource_id'] . ']' . t('cover photo') . '[/zrl]';
|
||||
|
||||
$ltext = '[zrl=' . z_root() . '/profile/' . $channel['channel_address'] . ']' . '[zmg]' . z_root() . '/photo/' . $photo['resource_id'] . '-8[/zmg][/zrl]';
|
||||
|
||||
$arr['body'] = sprintf($t,$channel['channel_name'],$ptext) . "\n\n" . $ltext;
|
||||
|
||||
$acl = new \Zotlabs\Access\AccessList($channel);
|
||||
$x = $acl->get();
|
||||
$arr['allow_cid'] = $x['allow_cid'];
|
||||
|
||||
$arr['allow_gid'] = $x['allow_gid'];
|
||||
$arr['deny_cid'] = $x['deny_cid'];
|
||||
$arr['deny_gid'] = $x['deny_gid'];
|
||||
|
||||
$arr['uid'] = $channel['channel_id'];
|
||||
$arr['aid'] = $channel['channel_account_id'];
|
||||
|
||||
$arr['owner_xchan'] = $channel['channel_hash'];
|
||||
$arr['author_xchan'] = $channel['channel_hash'];
|
||||
|
||||
post_activity_item($arr);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Generate content of profile-photo view
|
||||
@@ -334,7 +292,6 @@ class Cover_photo extends \Zotlabs\Web\Controller {
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
function get() {
|
||||
|
||||
if(! local_channel()) {
|
||||
|
||||
@@ -4,6 +4,7 @@ namespace Zotlabs\Module;
|
||||
|
||||
use App;
|
||||
use Zotlabs\Web\Controller;
|
||||
use Zotlabs\Lib\Libzotdir;
|
||||
|
||||
|
||||
class Dircensor extends Controller {
|
||||
@@ -15,11 +16,12 @@ class Dircensor extends Controller {
|
||||
|
||||
$dirmode = intval(get_config('system','directory_mode'));
|
||||
|
||||
if (! ($dirmode == DIRECTORY_MODE_PRIMARY || $dirmode == DIRECTORY_MODE_STANDALONE)) {
|
||||
if(!in_array($dirmode, [DIRECTORY_MODE_PRIMARY, DIRECTORY_MODE_SECONDARY, DIRECTORY_MODE_STANDALONE])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$xchan = argv(1);
|
||||
|
||||
if(! $xchan) {
|
||||
return;
|
||||
}
|
||||
@@ -32,19 +34,43 @@ class Dircensor extends Controller {
|
||||
return;
|
||||
}
|
||||
|
||||
$val = (($r[0]['xchan_censored']) ? 0 : 1);
|
||||
$severity = intval($_REQUEST['severity'] ?? 0);
|
||||
$flag = DIRECTORY_FLAG_OK;
|
||||
|
||||
q("update xchan set xchan_censored = $val where xchan_hash = '%s'",
|
||||
if ($severity === 1) {
|
||||
$flag = DIRECTORY_FLAG_UNSAFE;
|
||||
}
|
||||
|
||||
if ($severity === 2) {
|
||||
$flag = DIRECTORY_FLAG_HIDDEN;
|
||||
}
|
||||
|
||||
Libzotdir::update($xchan, $r[0]['xchan_url'], true, $flag);
|
||||
|
||||
q("UPDATE xchan SET xchan_censored = %d WHERE xchan_hash = '%s'",
|
||||
intval($flag),
|
||||
dbesc($xchan)
|
||||
);
|
||||
|
||||
if($val) {
|
||||
q("UPDATE xtag SET xtag_flags = %d WHERE xtag_hash = '%s'",
|
||||
intval($flag),
|
||||
dbesc($xchan)
|
||||
);
|
||||
|
||||
if($flag) {
|
||||
info( t('Entry censored') . EOL);
|
||||
}
|
||||
else {
|
||||
info( t('Entry uncensored') . EOL);
|
||||
info( t('Entry OK') . EOL);
|
||||
}
|
||||
|
||||
|
||||
if (isset($_REQUEST['aj'])) {
|
||||
json_return_and_die([
|
||||
'success' => 1,
|
||||
'flag' => $flag
|
||||
]);
|
||||
}
|
||||
|
||||
goaway(z_root() . '/directory');
|
||||
|
||||
}
|
||||
|
||||
@@ -151,7 +151,7 @@ class Directory extends Controller {
|
||||
|
||||
$url = '';
|
||||
|
||||
if(($dirmode == DIRECTORY_MODE_PRIMARY) || ($dirmode == DIRECTORY_MODE_STANDALONE)) {
|
||||
if(in_array($dirmode, [DIRECTORY_MODE_PRIMARY, DIRECTORY_MODE_SECONDARY, DIRECTORY_MODE_STANDALONE])) {
|
||||
$url = z_root() . '/dirsearch';
|
||||
if (is_site_admin()) {
|
||||
$directory_admin = true;
|
||||
@@ -191,7 +191,10 @@ class Directory extends Controller {
|
||||
if(get_config('system','disable_directory_keywords'))
|
||||
$kw = 0;
|
||||
|
||||
$query = $url . '?f=&kw=' . $kw . (($safe_mode != 1) ? '&safe=' . $safe_mode : '');
|
||||
if (intval($safe_mode) === 0 && $directory_admin)
|
||||
$safe_mode = -1;
|
||||
|
||||
$query = $url . '?f=&kw=' . $kw . (($safe_mode < 1) ? '&safe=' . $safe_mode : '');
|
||||
|
||||
if($token)
|
||||
$query .= '&t=' . $token;
|
||||
@@ -296,10 +299,11 @@ class Directory extends Controller {
|
||||
$hometown = ((x($profile,'hometown') == 1) ? html2plain($profile['hometown']) : False);
|
||||
|
||||
$about = ((x($profile,'about') == 1) ? zidify_links(bbcode($profile['about'], ['tryoembed' => false])) : False);
|
||||
if ($about && $safe_mode) {
|
||||
$about = html2plain($about);
|
||||
if ($about && $safe_mode > 0) {
|
||||
$about = strip_tags($about, '<br>');
|
||||
}
|
||||
|
||||
|
||||
$keywords = ((x($profile,'keywords')) ? $profile['keywords'] : '');
|
||||
|
||||
|
||||
@@ -351,11 +355,15 @@ class Directory extends Controller {
|
||||
'gender' => $gender,
|
||||
'pdesc' => $pdesc,
|
||||
'pdesc_label' => t('Description:'),
|
||||
'censor' => (($directory_admin) ? 'dircensor/' . $rr['hash'] : ''),
|
||||
'censor_label' => (($rr['censored']) ? t('Uncensor') : t('Censor')),
|
||||
'censor' => (($directory_admin) ? 'dircensor/' . $rr['hash'] . '?severity=' . ((intval($rr['censored']) > 0) ? 0 : 1) : ''),
|
||||
'censor_label' => t('Unsafe'),
|
||||
'censor_class' => ((intval($rr['censored']) === 1) ? 'active' : ''),
|
||||
'censor_2' => (($directory_admin) ? 'dircensor/' . $rr['hash'] . '?severity=' . ((intval($rr['censored']) > 1) ? 0 : 2) : ''),
|
||||
'censor_2_label' => t('Spam'),
|
||||
'censor_2_class' => ((intval($rr['censored']) > 1) ? 'active' : ''),
|
||||
'marital' => $marital,
|
||||
'homepage' => $homepage,
|
||||
'homepageurl' => (($safe_mode) ? $homepageurl : linkify($homepageurl)),
|
||||
'homepageurl' => (($safe_mode > 0) ? $homepageurl : linkify($homepageurl)),
|
||||
'hometown' => $hometown,
|
||||
'hometown_label' => t('Hometown:'),
|
||||
'about' => $about,
|
||||
@@ -436,7 +444,8 @@ class Directory extends Controller {
|
||||
'$reverse' => t('Reverse Alphabetic'),
|
||||
'$date' => t('Newest to Oldest'),
|
||||
'$reversedate' => t('Oldest to Newest'),
|
||||
'$suggest' => $suggest ? '&suggest=1' : ''
|
||||
'$suggest' => $suggest ? '&suggest=1' : '',
|
||||
'$directory_admin' => $directory_admin
|
||||
));
|
||||
|
||||
|
||||
|
||||
@@ -15,8 +15,7 @@ class Dirsearch extends Controller {
|
||||
|
||||
$ret = array('success' => false);
|
||||
|
||||
// logger('request: ' . print_r($_REQUEST,true));
|
||||
|
||||
// logger('request: ' . print_r($_REQUEST,true));
|
||||
|
||||
$dirmode = intval(get_config('system','directory_mode'));
|
||||
|
||||
@@ -25,7 +24,6 @@ class Dirsearch extends Controller {
|
||||
json_return_and_die($ret);
|
||||
}
|
||||
|
||||
|
||||
$access_token = $_REQUEST['t'] ?? '';
|
||||
|
||||
$token = get_config('system','realm_token');
|
||||
@@ -41,7 +39,8 @@ class Dirsearch extends Controller {
|
||||
}
|
||||
|
||||
$sql_extra = '';
|
||||
|
||||
$keywords_query = '';
|
||||
$hub_query = '';
|
||||
|
||||
$tables = array('name','address','locale','region','postcode','country','gender','marital','sexual','keywords');
|
||||
|
||||
@@ -85,9 +84,7 @@ class Dirsearch extends Controller {
|
||||
|
||||
|
||||
// by default use a safe search
|
||||
$safe = ((x($_REQUEST,'safe'))); // ? intval($_REQUEST['safe']) : 1 );
|
||||
if ($safe === false)
|
||||
$safe = 1;
|
||||
$safe = $_REQUEST['safe'] ?? 1;
|
||||
|
||||
if(array_key_exists('sync',$_REQUEST)) {
|
||||
if($_REQUEST['sync'])
|
||||
@@ -102,10 +99,10 @@ class Dirsearch extends Controller {
|
||||
$hub = \App::get_hostname();
|
||||
}
|
||||
|
||||
if($hub)
|
||||
$hub_query = " and xchan_hash in (select hubloc_hash from hubloc where hubloc_host = '" . protect_sprintf(dbesc($hub)) . "') ";
|
||||
else
|
||||
$hub_query = '';
|
||||
if($hub) {
|
||||
$hub_query = " and xchan_hash in (select hubloc_hash from hubloc where hubloc_deleted = 0 and hubloc_host = '" . protect_sprintf(dbesc($hub)) . "') ";
|
||||
}
|
||||
|
||||
|
||||
$sort_order = ((x($_REQUEST,'order')) ? $_REQUEST['order'] : '');
|
||||
|
||||
@@ -131,9 +128,16 @@ class Dirsearch extends Controller {
|
||||
$sql_extra .= $this->dir_query_build($joiner,'xprof_marital',$marital);
|
||||
if($sexual)
|
||||
$sql_extra .= $this->dir_query_build($joiner,'xprof_sexual',$sexual);
|
||||
if($keywords)
|
||||
if($keywords && $name) {
|
||||
// this is a general search
|
||||
$sql_extra .= $this->dir_query_build($joiner,'xprof_keywords',$keywords);
|
||||
|
||||
}
|
||||
if($keywords && !$name) {
|
||||
// this is a search for keywords only
|
||||
$keywords_arr = explode(',', $keywords);
|
||||
stringify_array_elms($keywords_arr, true);
|
||||
$keywords_query = " AND xchan_hash IN (SELECT xtag_hash FROM xtag WHERE xtag_term IN (" . protect_sprintf(implode(',', $keywords_arr)) . ")) ";
|
||||
}
|
||||
|
||||
// we only support an age range currently. You must set both agege
|
||||
// (greater than or equal) and agele (less than or equal)
|
||||
@@ -177,9 +181,15 @@ class Dirsearch extends Controller {
|
||||
$sql_extra .= " and xchan_addr like '%%" . \App::get_hostname() . "' ";
|
||||
}
|
||||
|
||||
$safesql = (($safe > 0) ? " and xchan_censored = 0 and xchan_selfcensored = 0 " : '');
|
||||
$safesql = '';
|
||||
if($safe > 0)
|
||||
$safesql = " and xchan_censored = 0 and xchan_selfcensored = 0 ";
|
||||
|
||||
if($safe < 1)
|
||||
$safesql = " and xchan_censored < 2 and xchan_selfcensored < 2 ";
|
||||
|
||||
if($safe < 0)
|
||||
$safesql = " and ( xchan_censored = 1 OR xchan_selfcensored = 1 ) ";
|
||||
$safesql = " and xchan_censored < 3 and xchan_selfcensored < 2 ";
|
||||
|
||||
if($forums)
|
||||
$safesql .= " and xchan_pubforum = " . ((intval($forums)) ? '1 ' : '0 ');
|
||||
@@ -215,26 +225,25 @@ class Dirsearch extends Controller {
|
||||
|
||||
if($sync) {
|
||||
$spkt = array('transactions' => array());
|
||||
$r = q("select * from updates where ud_date >= '%s' and ud_guid != '' and ud_addr != '' order by ud_date desc",
|
||||
|
||||
$r = q("SELECT * FROM updates WHERE ud_update = 0 AND ud_last = '%s' AND ud_date >= '%s' ORDER BY ud_date DESC",
|
||||
dbesc(NULL_DATE),
|
||||
dbesc($sync)
|
||||
);
|
||||
|
||||
if($r) {
|
||||
foreach($r as $rr) {
|
||||
$flags = array();
|
||||
if($rr['ud_flags'] & UPDATE_FLAGS_DELETED)
|
||||
$flags[] = 'deleted';
|
||||
if($rr['ud_flags'] & UPDATE_FLAGS_FORCED)
|
||||
$flags[] = 'forced';
|
||||
|
||||
$spkt['transactions'][] = array(
|
||||
$spkt['transactions'][] = [
|
||||
'hash' => $rr['ud_hash'],
|
||||
'address' => $rr['ud_addr'],
|
||||
'transaction_id' => $rr['ud_guid'],
|
||||
'host' => $rr['ud_host'],
|
||||
'transaction_id' => $rr['ud_host'], // deprecated 2023-04-12 - can be removed after dir servers at version >= 8.4
|
||||
'timestamp' => $rr['ud_date'],
|
||||
'flags' => $flags
|
||||
);
|
||||
'flags' => $rr['ud_flags']
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
json_return_and_die($spkt);
|
||||
}
|
||||
else {
|
||||
@@ -264,7 +273,7 @@ class Dirsearch extends Controller {
|
||||
xprof.xprof_hometown as hometown,
|
||||
xprof.xprof_keywords as keywords
|
||||
from xchan left join xprof on xchan_hash = xprof_hash left join hubloc on (hubloc_id_url = xchan_url and hubloc_hash = xchan_hash)
|
||||
where hubloc_primary = 1 and hubloc_updated > %s - INTERVAL %s and ( $logic $sql_extra ) $hub_query and xchan_network = 'zot6' and xchan_system = 0 and xchan_hidden = 0 and xchan_orphan = 0 and xchan_deleted = 0
|
||||
where hubloc_primary = 1 and hubloc_updated > %s - INTERVAL %s and ( $logic $sql_extra ) $hub_query $keywords_query and xchan_network = 'zot6' and xchan_system = 0 and xchan_hidden = 0 and xchan_orphan = 0 and xchan_deleted = 0 and hubloc_deleted = 0
|
||||
$safesql $order $qlimit",
|
||||
db_utcnow(),
|
||||
db_quoteinterval('30 DAY')
|
||||
|
||||
@@ -2,15 +2,13 @@
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
use App;
|
||||
use Zotlabs\Web\Controller;
|
||||
|
||||
require_once("include/bbcode.php");
|
||||
require_once('include/security.php');
|
||||
require_once('include/conversation.php');
|
||||
require_once('include/acl_selectors.php');
|
||||
require_once('include/items.php');
|
||||
class Display extends Controller {
|
||||
|
||||
function init() {
|
||||
|
||||
class Display extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
|
||||
function get($update = 0, $load = false) {
|
||||
|
||||
@@ -40,7 +38,14 @@ class Display extends \Zotlabs\Web\Controller {
|
||||
$item_hash = $_REQUEST['mid'];
|
||||
}
|
||||
|
||||
$item_hash = unpack_link_id($item_hash);
|
||||
$identifier = 'uuid';
|
||||
$encoded_item_hash = null;
|
||||
|
||||
if (str_starts_with($item_hash, 'b64.')) {
|
||||
$encoded_item_hash = $item_hash;
|
||||
$item_hash = unpack_link_id($item_hash);
|
||||
$identifier = 'mid';
|
||||
}
|
||||
|
||||
if ($item_hash === false) {
|
||||
App::$error = 400;
|
||||
@@ -91,7 +96,7 @@ class Display extends \Zotlabs\Web\Controller {
|
||||
|
||||
$o .= '<div id="jot-popup">';
|
||||
$a = '';
|
||||
$o .= status_editor($a,$x,false,'Display');
|
||||
$o .= status_editor($x, false, 'Display');
|
||||
$o .= '</div>';
|
||||
}
|
||||
|
||||
@@ -106,7 +111,7 @@ class Display extends \Zotlabs\Web\Controller {
|
||||
|
||||
$target_item = null;
|
||||
|
||||
$r = q("select id, uid, mid, parent, parent_mid, thr_parent, verb, item_type, item_deleted, author_xchan, item_blocked from item where mid = '%s' limit 1",
|
||||
$r = q("select id, uid, mid, parent, parent_mid, thr_parent, verb, item_type, item_deleted, author_xchan, item_blocked from item where $identifier = '%s' limit 1",
|
||||
dbesc($item_hash)
|
||||
);
|
||||
|
||||
@@ -154,18 +159,11 @@ class Display extends \Zotlabs\Web\Controller {
|
||||
call_hooks('item_custom_display', $target_item);
|
||||
|
||||
$simple_update = '';
|
||||
if($update && $_SESSION['loadtime'])
|
||||
if($update && isset($_SESSION['loadtime']))
|
||||
$simple_update = " AND (( item_unseen = 1 AND item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' ) OR item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' ) ";
|
||||
|
||||
if((! $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']);
|
||||
|
||||
// if we got a decoded hash we must encode it again before handing to javascript
|
||||
$mid = gen_link_id($target_item['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";
|
||||
@@ -198,7 +196,7 @@ class Display extends \Zotlabs\Web\Controller {
|
||||
'$dbegin' => '',
|
||||
'$verb' => '',
|
||||
'$net' => '',
|
||||
'$mid' => (($mid) ? urlencode($mid) : '')
|
||||
'$mid' => $encoded_item_hash ?? $item_hash
|
||||
));
|
||||
|
||||
head_add_link([
|
||||
|
||||
@@ -13,11 +13,10 @@ class Dreport extends \Zotlabs\Web\Controller {
|
||||
|
||||
$table = 'item';
|
||||
$channel = \App::get_channel();
|
||||
$mid = ((argc() > 1) ? unpack_link_id(argv(1)) : '');
|
||||
$mid = $_REQUEST['mid'] ?? '';
|
||||
|
||||
if($mid === 'push') {
|
||||
if(argv(1) === 'push') {
|
||||
$table = 'push';
|
||||
$mid = ((argc() > 2) ? unpack_link_id(argv(2)) : '');
|
||||
|
||||
if($mid) {
|
||||
$i = q("select id from item where mid = '%s' and uid = %d and ( author_xchan = '%s' or ( owner_xchan = '%s' and item_wall = 1 )) ",
|
||||
@@ -31,7 +30,7 @@ class Dreport extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
}
|
||||
sleep(3);
|
||||
goaway(z_root() . '/dreport/' . gen_link_id($mid));
|
||||
goaway(z_root() . '/dreport?mid=' . $mid);
|
||||
}
|
||||
|
||||
if(! $mid) {
|
||||
@@ -114,7 +113,7 @@ class Dreport extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
}
|
||||
|
||||
usort($r,'self::dreport_gravity_sort');
|
||||
usort($r, [self::class, 'dreport_gravity_sort']);
|
||||
|
||||
$entries = array();
|
||||
foreach($r as $rr) {
|
||||
|
||||
@@ -132,7 +132,7 @@ class Editblock extends \Zotlabs\Web\Controller {
|
||||
'bbcode' => (($mimetype == 'text/bbcode') ? true : false)
|
||||
);
|
||||
|
||||
$editor = status_editor($a, $x, false, 'Editblock');
|
||||
$editor = status_editor($x, false, 'Editblock');
|
||||
|
||||
$o .= replace_macros(get_markup_template('edpost_head.tpl'), array(
|
||||
'$title' => t('Edit Block'),
|
||||
|
||||
@@ -131,7 +131,7 @@ class Editlayout extends \Zotlabs\Web\Controller {
|
||||
'profile_uid' => intval($owner),
|
||||
);
|
||||
|
||||
$editor = status_editor($a, $x, false, 'Editlayout');
|
||||
$editor = status_editor($x, false, 'Editlayout');
|
||||
|
||||
$o .= replace_macros(get_markup_template('edpost_head.tpl'), array(
|
||||
'$title' => t('Edit Layout'),
|
||||
|
||||
@@ -107,7 +107,7 @@ class Editpost extends \Zotlabs\Web\Controller {
|
||||
);
|
||||
|
||||
$a = '';
|
||||
$editor = status_editor($a, $x, false, 'Editpost');
|
||||
$editor = status_editor($x, false, 'Editpost');
|
||||
|
||||
$o .= replace_macros(get_markup_template('edpost_head.tpl'), array(
|
||||
'$title' => t('Edit post'),
|
||||
|
||||
@@ -75,7 +75,7 @@ class Editwebpage extends \Zotlabs\Web\Controller {
|
||||
|
||||
// Figure out which post we're editing
|
||||
$post_id = ((argc() > 2) ? intval(argv(2)) : 0);
|
||||
|
||||
|
||||
if(! $post_id) {
|
||||
notice( t('Item not found') . EOL);
|
||||
return;
|
||||
@@ -90,7 +90,7 @@ class Editwebpage extends \Zotlabs\Web\Controller {
|
||||
return;
|
||||
}
|
||||
|
||||
// We've already figured out which item we want and whose copy we need,
|
||||
// We've already figured out which item we want and whose copy we need,
|
||||
// so we don't need anything fancy here
|
||||
|
||||
$sql_extra = item_permissions_sql($owner);
|
||||
@@ -122,13 +122,13 @@ class Editwebpage extends \Zotlabs\Web\Controller {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$layout = $itm[0]['layout_mid'];
|
||||
|
||||
$content = $itm[0]['body'];
|
||||
if($itm[0]['mimetype'] === 'text/markdown')
|
||||
$content = \Zotlabs\Lib\MarkdownSoap::unescape($itm[0]['body']);
|
||||
|
||||
|
||||
$rp = 'webpages/' . $which;
|
||||
|
||||
$x = array(
|
||||
@@ -160,7 +160,7 @@ class Editwebpage extends \Zotlabs\Web\Controller {
|
||||
'bbcode' => (($mimetype == 'text/bbcode') ? true : false)
|
||||
);
|
||||
|
||||
$editor = status_editor($a, $x, false, 'Editwebpage');
|
||||
$editor = status_editor($x, false, 'Editwebpage');
|
||||
|
||||
$o .= replace_macros(get_markup_template('edpost_head.tpl'), array(
|
||||
'$title' => t('Edit Webpage'),
|
||||
|
||||
57
Zotlabs/Module/Emoji.php
Normal file
57
Zotlabs/Module/Emoji.php
Normal file
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
use Zotlabs\Web\Controller;
|
||||
use Zotlabs\Daemon\Master;
|
||||
use Zotlabs\Lib\ActivityStreams;
|
||||
use App;
|
||||
|
||||
|
||||
class Emoji extends Controller {
|
||||
|
||||
function init() {
|
||||
|
||||
$shortname = argv(1);
|
||||
|
||||
if (!$shortname) {
|
||||
killme();
|
||||
}
|
||||
|
||||
$emojis = get_emojis();
|
||||
|
||||
if (!isset($emojis[$shortname])) {
|
||||
killme();
|
||||
}
|
||||
|
||||
$emoji = $emojis[$shortname];
|
||||
|
||||
if (!file_exists($emoji['filepath'])) {
|
||||
killme();
|
||||
}
|
||||
|
||||
$image = getimagesize($emoji['filepath']);
|
||||
|
||||
if(ActivityStreams::is_as_request()) {
|
||||
$last_modified = date(ATOM_TIME, filemtime($emoji['filepath']));
|
||||
|
||||
$obj = [
|
||||
'id' => z_root() . '/emoji/' . $shortname,
|
||||
'type' => 'Emoji',
|
||||
'name' => $emoji['shortname'],
|
||||
'updated' => $last_modified,
|
||||
'icon' => [
|
||||
'type' => 'Image',
|
||||
'mediaType' => $image['mime'],
|
||||
'url' => z_root() . '/' . $emoji['filepath']
|
||||
]
|
||||
];
|
||||
|
||||
as_return_and_die($obj);
|
||||
}
|
||||
|
||||
header('Content-Type: ' . $image['mime']);
|
||||
echo file_get_contents($emoji['filepath']);
|
||||
killme();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,7 +4,6 @@ namespace Zotlabs\Module;
|
||||
use Zotlabs\Web\Controller;
|
||||
use Zotlabs\Lib\ActivityStreams;
|
||||
use Zotlabs\Lib\Activity;
|
||||
use Zotlabs\Lib\LDSignatures;
|
||||
use Zotlabs\Web\HTTPSig;
|
||||
|
||||
class Event extends Controller {
|
||||
@@ -17,7 +16,7 @@ class Event extends Controller {
|
||||
if(! $item_id)
|
||||
return;
|
||||
|
||||
$item_normal = " and item.item_hidden = 0 and item.item_type = 0 and item.item_unpublished = 0
|
||||
$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 ";
|
||||
|
||||
$sql_extra = item_permissions_sql(0);
|
||||
@@ -49,28 +48,9 @@ class Event extends Controller {
|
||||
$obj = $items[0]['obj'];
|
||||
}
|
||||
|
||||
$x = array_merge(['@context' => [
|
||||
ACTIVITYSTREAMS_JSONLD_REV,
|
||||
'https://w3id.org/security/v1',
|
||||
z_root() . ZOT_APSCHEMA_REV
|
||||
]], $obj );
|
||||
|
||||
$headers = [];
|
||||
$headers['Content-Type'] = 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"' ;
|
||||
$x['signature'] = LDSignatures::sign($x,$channel);
|
||||
$ret = json_encode($x, JSON_UNESCAPED_SLASHES);
|
||||
$headers['Date'] = datetime_convert('UTC','UTC', 'now', 'D, d M Y H:i:s \\G\\M\\T');
|
||||
$headers['Digest'] = HTTPSig::generate_digest_header($ret);
|
||||
$headers['(request-target)'] = strtolower($_SERVER['REQUEST_METHOD']) . ' ' . $_SERVER['REQUEST_URI'];
|
||||
|
||||
$h = HTTPSig::create_sig($headers,$channel['channel_prvkey'],channel_url($channel));
|
||||
HTTPSig::set_headers($h);
|
||||
|
||||
echo $ret;
|
||||
killme();
|
||||
|
||||
as_return_and_die($obj, $channel);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ class File_upload extends \Zotlabs\Web\Controller {
|
||||
$_REQUEST['deny_cid'] = ((isset($_REQUEST['contact_deny'])) ? perms2str($_REQUEST['contact_deny']) : '');
|
||||
$_REQUEST['deny_gid'] = ((isset($_REQUEST['group_deny'])) ? perms2str($_REQUEST['group_deny']) : '');
|
||||
|
||||
if(isset($_REQUEST['filename']) && $_REQUEST['filename']) {
|
||||
if(isset($_REQUEST['filename']) && strlen($_REQUEST['filename'])) {
|
||||
$r = attach_mkdir($channel, get_observer_hash(), $_REQUEST);
|
||||
if($r['success']) {
|
||||
$hash = $r['data']['hash'];
|
||||
|
||||
@@ -7,7 +7,6 @@ use Zotlabs\Lib\Libsync;
|
||||
use Zotlabs\Lib\ActivityStreams;
|
||||
use Zotlabs\Lib\Activity;
|
||||
use Zotlabs\Web\HTTPSig;
|
||||
use Zotlabs\Lib\LDSignatures;
|
||||
use Zotlabs\Lib\Connect;
|
||||
use Zotlabs\Daemon\Master;
|
||||
|
||||
@@ -39,30 +38,14 @@ class Follow extends Controller {
|
||||
http_status_exit(404, 'Not found');
|
||||
}
|
||||
|
||||
$x = array_merge(['@context' => [
|
||||
ACTIVITYSTREAMS_JSONLD_REV,
|
||||
'https://w3id.org/security/v1',
|
||||
z_root() . ZOT_APSCHEMA_REV
|
||||
]],
|
||||
[
|
||||
$obj = [
|
||||
'id' => z_root() . '/follow/' . $r[0]['abook_id'],
|
||||
'type' => 'Follow',
|
||||
'actor' => $actor,
|
||||
'object' => $r[0]['xchan_url']
|
||||
]);
|
||||
|
||||
$headers = [];
|
||||
$headers['Content-Type'] = 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"' ;
|
||||
$x['signature'] = LDSignatures::sign($x,$chan);
|
||||
$ret = json_encode($x, JSON_UNESCAPED_SLASHES);
|
||||
$headers['Date'] = datetime_convert('UTC','UTC', 'now', 'D, d M Y H:i:s \\G\\M\\T');
|
||||
$headers['Digest'] = HTTPSig::generate_digest_header($ret);
|
||||
$headers['(request-target)'] = strtolower($_SERVER['REQUEST_METHOD']) . ' ' . $_SERVER['REQUEST_URI'];
|
||||
$h = HTTPSig::create_sig($headers,$chan['channel_prvkey'],channel_url($chan));
|
||||
HTTPSig::set_headers($h);
|
||||
echo $ret;
|
||||
killme();
|
||||
];
|
||||
|
||||
as_return_and_die($obj, $chan);
|
||||
}
|
||||
|
||||
if (! local_channel()) {
|
||||
|
||||
@@ -17,8 +17,6 @@ class Hq extends \Zotlabs\Web\Controller {
|
||||
function init() {
|
||||
if(! local_channel())
|
||||
return;
|
||||
|
||||
App::$profile_uid = local_channel();
|
||||
}
|
||||
|
||||
function get($update = 0, $load = false) {
|
||||
@@ -27,19 +25,25 @@ class Hq extends \Zotlabs\Web\Controller {
|
||||
return;
|
||||
}
|
||||
|
||||
App::$profile_uid = local_channel();
|
||||
|
||||
$item_hash = '';
|
||||
|
||||
if(argc() > 1 && argv(1) !== 'load') {
|
||||
$item_hash = unpack_link_id(argv(1));
|
||||
$item_hash = argv(1);
|
||||
}
|
||||
|
||||
if(isset($_REQUEST['mid'])) {
|
||||
$item_hash = unpack_link_id($_REQUEST['mid']);
|
||||
$item_hash = $_REQUEST['mid'];
|
||||
}
|
||||
|
||||
if($item_hash === false) {
|
||||
notice(t('Malformed message id.') . EOL);
|
||||
return;
|
||||
$identifier = 'uuid';
|
||||
$encoded_item_hash = null;
|
||||
|
||||
if (str_starts_with($item_hash, 'b64.')) {
|
||||
$encoded_item_hash = $item_hash;
|
||||
$item_hash = unpack_link_id($item_hash);
|
||||
$identifier = 'mid';
|
||||
}
|
||||
|
||||
$item_normal = item_normal();
|
||||
@@ -54,7 +58,7 @@ class Hq extends \Zotlabs\Web\Controller {
|
||||
// select the target item with a bias to our own item
|
||||
$sql_order = ((local_channel() > $sys['channel_id']) ? 'DESC' : 'ASC');
|
||||
|
||||
$r = q("select id, uid, mid, parent_mid, thr_parent, verb, item_type, item_deleted, item_blocked from item where uid in (%d, %d) and mid = '%s' order by uid $sql_order limit 2",
|
||||
$r = q("select id, uid, mid, parent_mid, thr_parent, verb, item_type, item_deleted, item_blocked from item where uid in (%d, %d) and $identifier = '%s' order by uid $sql_order limit 2",
|
||||
intval(local_channel()),
|
||||
intval($sys['channel_id']),
|
||||
dbesc($item_hash)
|
||||
@@ -67,11 +71,6 @@ class Hq extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
}
|
||||
|
||||
//if the item is to be moderated redirect to /moderate
|
||||
if($target_item['item_blocked'] == ITEM_MODERATED) {
|
||||
goaway(z_root() . '/moderate/' . $target_item['id']);
|
||||
}
|
||||
|
||||
$simple_update = '';
|
||||
if($update && $_SESSION['loadtime'])
|
||||
$simple_update = " AND (( item_unseen = 1 AND item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' ) OR item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' ) ";
|
||||
@@ -90,6 +89,7 @@ class Hq extends \Zotlabs\Web\Controller {
|
||||
|
||||
$x = [
|
||||
'is_owner' => true,
|
||||
'profile_uid' => $channel['channel_id'],
|
||||
'allow_location' => ((intval(get_pconfig($channel['channel_id'],'system','use_browser_location'))) ? '1' : ''),
|
||||
'default_location' => $channel['channel_location'],
|
||||
'nickname' => $channel['channel_address'],
|
||||
@@ -109,7 +109,7 @@ class Hq extends \Zotlabs\Web\Controller {
|
||||
];
|
||||
|
||||
$a = '';
|
||||
$o .= status_editor($a, $x, true);
|
||||
$o .= status_editor($x, true, 'Hq');
|
||||
|
||||
}
|
||||
|
||||
@@ -122,7 +122,7 @@ class Hq extends \Zotlabs\Web\Controller {
|
||||
//$mid = ((($target_item['verb'] == ACTIVITY_LIKE) || ($target_item['verb'] == ACTIVITY_DISLIKE)) ? $target_item['thr_parent'] : $target_item['mid']);
|
||||
|
||||
// if we got a decoded hash we must encode it again before handing to javascript
|
||||
$mid = gen_link_id($target_item['mid']);
|
||||
// $mid = gen_link_id($target_item['mid']);
|
||||
}
|
||||
else {
|
||||
$mid = '';
|
||||
@@ -160,7 +160,7 @@ class Hq extends \Zotlabs\Web\Controller {
|
||||
'$dbegin' => '',
|
||||
'$verb' => '',
|
||||
'$net' => '',
|
||||
'$mid' => (($mid) ? urlencode($mid) : '')
|
||||
'$mid' => $encoded_item_hash ?? $item_hash
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ class Item extends Controller {
|
||||
|
||||
$portable_id = EMPTY_STR;
|
||||
|
||||
$item_normal_extra = sprintf(" and not verb in ('%s', '%s') ",
|
||||
$item_normal_extra = sprintf(" and not verb in ('Follow', 'Ignore', '%s', '%s') ",
|
||||
dbesc(ACTIVITY_FOLLOW),
|
||||
dbesc(ACTIVITY_UNFOLLOW)
|
||||
);
|
||||
@@ -63,8 +63,8 @@ class Item extends Controller {
|
||||
|
||||
// do we have the item (at all)?
|
||||
|
||||
$r = q("select * from item where mid = '%s' $item_normal limit 1",
|
||||
dbesc(z_root() . '/item/' . $item_id)
|
||||
$r = q("select parent_mid from item where uuid = '%s' $item_normal limit 1",
|
||||
dbesc($item_id)
|
||||
);
|
||||
|
||||
if (!$r) {
|
||||
@@ -84,7 +84,7 @@ class Item extends Controller {
|
||||
}
|
||||
observer_auth($portable_id);
|
||||
|
||||
$i = q("select id as item_id from item where mid = '%s' $item_normal and owner_xchan = '%s' limit 1",
|
||||
$i = q("select id as item_id, uid from item where mid = '%s' $item_normal and owner_xchan = '%s' limit 1",
|
||||
dbesc($r[0]['parent_mid']),
|
||||
dbesc($portable_id)
|
||||
);
|
||||
@@ -99,7 +99,7 @@ class Item extends Controller {
|
||||
$sql_extra = item_permissions_sql(0);
|
||||
|
||||
if (!$i) {
|
||||
$i = q("select id as item_id from item where mid = '%s' $item_normal $sql_extra order by item_wall desc limit 1",
|
||||
$i = q("select id as item_id, uid, item_private from item where mid = '%s' $item_normal $sql_extra order by item_wall desc limit 1",
|
||||
dbesc($r[0]['parent_mid'])
|
||||
);
|
||||
}
|
||||
@@ -108,57 +108,56 @@ class Item extends Controller {
|
||||
http_status_exit(403, 'Forbidden');
|
||||
}
|
||||
|
||||
$chan = channelx_by_n($i[0]['uid']);
|
||||
|
||||
if (!$chan) {
|
||||
http_status_exit(404, 'Not found');
|
||||
}
|
||||
|
||||
if (!perm_is_allowed($chan['channel_id'], get_observer_hash(), 'view_stream')) {
|
||||
http_status_exit(403, 'Forbidden');
|
||||
}
|
||||
|
||||
$parents_str = ids_to_querystr($i, 'item_id');
|
||||
|
||||
$items = q("SELECT item.*, item.id AS item_id FROM item WHERE item.parent IN ( %s ) $item_normal order by item.id asc",
|
||||
dbesc($parents_str)
|
||||
// We won't need to check for privacy mismatches if the verified observer is also owner
|
||||
$parent_item_private = ((isset($i[0]['item_private'])) ? " and item_private = " . intval($i[0]['item_private']) . " " : '');
|
||||
|
||||
$total = q("SELECT count(*) AS count FROM item WHERE parent = %d $parent_item_private $item_normal ",
|
||||
intval($parents_str)
|
||||
);
|
||||
|
||||
if (!$items) {
|
||||
http_status_exit(404, 'Not found');
|
||||
App::set_pager_total($total[0]['count']);
|
||||
App::set_pager_itemspage(30);
|
||||
|
||||
if (App::$pager['total'] > App::$pager['itemspage']) {
|
||||
// let mod conversation handle this request
|
||||
App::$query_string = str_replace('item', 'conversation', App::$query_string);
|
||||
$i = Activity::paged_collection_init(App::$pager['total'], App::$query_string);
|
||||
as_return_and_die($i ,$chan);
|
||||
}
|
||||
else {
|
||||
$items = q("SELECT item.*, item.id AS item_id FROM item WHERE item.parent = %d $parent_item_private $item_normal ORDER BY item.id",
|
||||
intval($parents_str)
|
||||
);
|
||||
|
||||
xchan_query($items, true);
|
||||
$items = fetch_post_tags($items, true);
|
||||
xchan_query($items, true);
|
||||
$items = fetch_post_tags($items, true);
|
||||
|
||||
if (!$items)
|
||||
http_status_exit(404, 'Not found');
|
||||
|
||||
$chan = channelx_by_n($items[0]['uid']);
|
||||
|
||||
if (!$chan)
|
||||
http_status_exit(404, 'Not found');
|
||||
|
||||
if (!perm_is_allowed($chan['channel_id'], get_observer_hash(), 'view_stream'))
|
||||
http_status_exit(403, 'Forbidden');
|
||||
|
||||
|
||||
$i = Activity::encode_item_collection($items, 'conversation/' . $item_id, 'OrderedCollection');
|
||||
|
||||
if (!$i)
|
||||
http_status_exit(404, 'Not found');
|
||||
$i = Activity::encode_item_collection($items, App::$query_string, 'OrderedCollection', App::$pager['total']);
|
||||
}
|
||||
|
||||
if ($portable_id && (!intval($items[0]['item_private']))) {
|
||||
ThreadListener::store(z_root() . '/item/' . $item_id, $portable_id);
|
||||
$c = q("select abook_id from abook where abook_channel = %d and abook_xchan = '%s'",
|
||||
intval($items[0]['uid']),
|
||||
dbesc($portable_id)
|
||||
);
|
||||
if (!$c) {
|
||||
ThreadListener::store(z_root() . '/item/' . $item_id, $portable_id);
|
||||
}
|
||||
}
|
||||
|
||||
$x = array_merge(['@context' => [
|
||||
ACTIVITYSTREAMS_JSONLD_REV,
|
||||
'https://w3id.org/security/v1',
|
||||
z_root() . ZOT_APSCHEMA_REV
|
||||
]], $i);
|
||||
|
||||
$headers = [];
|
||||
$headers['Content-Type'] = 'application/x-zot+json';
|
||||
$x['signature'] = LDSignatures::sign($x, $chan);
|
||||
$ret = json_encode($x, JSON_UNESCAPED_SLASHES);
|
||||
$headers['Digest'] = HTTPSig::generate_digest_header($ret);
|
||||
$headers['(request-target)'] = strtolower($_SERVER['REQUEST_METHOD']) . ' ' . $_SERVER['REQUEST_URI'];
|
||||
$h = HTTPSig::create_sig($headers, $chan['channel_prvkey'], channel_url($chan));
|
||||
HTTPSig::set_headers($h);
|
||||
echo $ret;
|
||||
killme();
|
||||
|
||||
as_return_and_die($i ,$chan);
|
||||
}
|
||||
|
||||
if (ActivityStreams::is_as_request()) {
|
||||
@@ -169,7 +168,7 @@ class Item extends Controller {
|
||||
|
||||
$portable_id = EMPTY_STR;
|
||||
|
||||
$item_normal_extra = sprintf(" and not verb in ('%s', '%s') ",
|
||||
$item_normal_extra = sprintf(" and not verb in ('Follow', 'Ignore', '%s', '%s') ",
|
||||
dbesc(ACTIVITY_FOLLOW),
|
||||
dbesc(ACTIVITY_UNFOLLOW)
|
||||
);
|
||||
@@ -181,8 +180,7 @@ class Item extends Controller {
|
||||
// do we have the item (at all)?
|
||||
// add preferential bias to item owners (item_wall = 1)
|
||||
|
||||
$r = q("select * from item where mid = '%s' or uuid = '%s' $item_normal order by item_wall desc limit 1",
|
||||
dbesc(z_root() . '/item/' . $item_id),
|
||||
$r = q("select * from item where uuid = '%s' $item_normal order by item_wall desc limit 1",
|
||||
dbesc($item_id)
|
||||
);
|
||||
|
||||
@@ -223,6 +221,22 @@ class Item extends Controller {
|
||||
);
|
||||
}
|
||||
|
||||
$bear = Activity::token_from_request();
|
||||
if ($bear) {
|
||||
logger('bear: ' . $bear, LOGGER_DEBUG);
|
||||
if (!$i) {
|
||||
$t = q("select * from iconfig where cat = 'ocap' and k = 'relay' and v = '%s'",
|
||||
dbesc($bear)
|
||||
);
|
||||
if ($t) {
|
||||
$i = q("select id as item_id from item where uuid = '%s' and id = %d $item_normal limit 1",
|
||||
dbesc($item_id),
|
||||
intval($t[0]['iid'])
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!$i) {
|
||||
http_status_exit(403, 'Forbidden');
|
||||
}
|
||||
@@ -255,29 +269,13 @@ class Item extends Controller {
|
||||
}
|
||||
}
|
||||
|
||||
$x = array_merge(['@context' => [
|
||||
ACTIVITYSTREAMS_JSONLD_REV,
|
||||
'https://w3id.org/security/v1',
|
||||
z_root() . ZOT_APSCHEMA_REV
|
||||
]], $i);
|
||||
|
||||
$headers = [];
|
||||
$headers['Content-Type'] = 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"';
|
||||
$x['signature'] = LDSignatures::sign($x, $chan);
|
||||
$ret = json_encode($x, JSON_UNESCAPED_SLASHES);
|
||||
$headers['Date'] = datetime_convert('UTC', 'UTC', 'now', 'D, d M Y H:i:s \\G\\M\\T');
|
||||
$headers['Digest'] = HTTPSig::generate_digest_header($ret);
|
||||
$headers['(request-target)'] = strtolower($_SERVER['REQUEST_METHOD']) . ' ' . $_SERVER['REQUEST_URI'];
|
||||
$h = HTTPSig::create_sig($headers, $chan['channel_prvkey'], channel_url($chan));
|
||||
HTTPSig::set_headers($h);
|
||||
echo $ret;
|
||||
killme();
|
||||
as_return_and_die($i ,$chan);
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (argc() > 1 && argv(1) !== 'drop') {
|
||||
$x = q("select uid, item_wall, llink, mid from item where mid = '%s' or mid = '%s' or uuid = '%s'",
|
||||
$x = q("select uid, item_wall, llink, mid, uuid from item where mid = '%s' or mid = '%s' or uuid = '%s'",
|
||||
dbesc(z_root() . '/item/' . argv(1)),
|
||||
dbesc(z_root() . '/activity/' . argv(1)),
|
||||
dbesc(argv(1))
|
||||
@@ -287,7 +285,7 @@ class Item extends Controller {
|
||||
if (intval($xv['item_wall'])) {
|
||||
$c = channelx_by_n($xv['uid']);
|
||||
if ($c) {
|
||||
goaway(z_root() . '/channel/' . $c['channel_address'] . '?mid=' . gen_link_id($xv['mid']));
|
||||
goaway(z_root() . '/channel/' . $c['channel_address'] . '?mid=' . $xv['uuid']);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -300,14 +298,15 @@ class Item extends Controller {
|
||||
|
||||
|
||||
function post() {
|
||||
|
||||
// This will change. Figure out who the observer is and whether or not
|
||||
// they have permission to post here. Else ignore the post.
|
||||
|
||||
if ((!local_channel()) && (!remote_channel()) && (!x($_REQUEST, 'anonname')))
|
||||
return;
|
||||
|
||||
$uid = local_channel();
|
||||
$uid = local_channel();
|
||||
$token = '';
|
||||
|
||||
$channel = null;
|
||||
$observer = null;
|
||||
$datarray = [];
|
||||
@@ -405,7 +404,7 @@ class Item extends Controller {
|
||||
$pagetitle = ((x($_REQUEST, 'pagetitle')) ? escape_tags($_REQUEST['pagetitle']) : '');
|
||||
$layout_mid = ((x($_REQUEST, 'layout_mid')) ? escape_tags($_REQUEST['layout_mid']) : '');
|
||||
$plink = ((x($_REQUEST, 'permalink')) ? escape_tags($_REQUEST['permalink']) : '');
|
||||
$obj_type = ((x($_REQUEST, 'obj_type')) ? escape_tags($_REQUEST['obj_type']) : ACTIVITY_OBJ_NOTE);
|
||||
$obj_type = ((x($_REQUEST, 'obj_type')) ? escape_tags($_REQUEST['obj_type']) : 'Article');
|
||||
|
||||
// allow API to bulk load a bunch of imported items with sending out a bunch of posts.
|
||||
$nopush = ((x($_REQUEST, 'nopush')) ? intval($_REQUEST['nopush']) : 0);
|
||||
@@ -444,9 +443,6 @@ class Item extends Controller {
|
||||
if (!x($_REQUEST, 'type'))
|
||||
$_REQUEST['type'] = 'net-comment';
|
||||
|
||||
if ($obj_type == ACTIVITY_OBJ_NOTE)
|
||||
$obj_type = ACTIVITY_OBJ_COMMENT;
|
||||
|
||||
if ($parent) {
|
||||
$r = q("SELECT * FROM item WHERE id = %d LIMIT 1",
|
||||
intval($parent)
|
||||
@@ -679,7 +675,7 @@ class Item extends Controller {
|
||||
$verb = $orig_post['verb'];
|
||||
$app = $orig_post['app'];
|
||||
$title = escape_tags(trim($_REQUEST['title']));
|
||||
$summary = trim($_REQUEST['summary']);
|
||||
$summary = escape_tags(trim($_REQUEST['summary']));
|
||||
$body = trim($_REQUEST['body']);
|
||||
$item_flags = $orig_post['item_flags'];
|
||||
$item_origin = $orig_post['item_origin'];
|
||||
@@ -740,7 +736,7 @@ class Item extends Controller {
|
||||
$coord = ((isset($_REQUEST['coord'])) ? notags(trim($_REQUEST['coord'])) : '');
|
||||
$verb = ((isset($_REQUEST['verb'])) ? notags(trim($_REQUEST['verb'])) : '');
|
||||
$title = ((isset($_REQUEST['title'])) ? escape_tags(trim($_REQUEST['title'])) : '');
|
||||
$summary = ((isset($_REQUEST['summary'])) ? trim($_REQUEST['summary']) : '');
|
||||
$summary = ((isset($_REQUEST['summary'])) ? escape_tags(trim($_REQUEST['summary'])) : '');
|
||||
$body = ((isset($_REQUEST['body'])) ? trim($_REQUEST['body']) : '');
|
||||
$body .= ((isset($_REQUEST['attachment'])) ? trim($_REQUEST['attachment']) : '');
|
||||
$postopts = '';
|
||||
@@ -793,7 +789,6 @@ class Item extends Controller {
|
||||
&& ($channel['channel_pageflags'] & PAGE_ALLOWCODE)) ? true : false);
|
||||
|
||||
if ($preview) {
|
||||
$summary = z_input_filter($summary, $mimetype, $execflag);
|
||||
$body = z_input_filter($body, $mimetype, $execflag);
|
||||
}
|
||||
|
||||
@@ -830,7 +825,6 @@ class Item extends Controller {
|
||||
|
||||
require_once('include/text.php');
|
||||
|
||||
|
||||
// BBCODE alert: the following functions assume bbcode input
|
||||
// and will require alternatives for alternative content-types (text/html, text/markdown, text/plain, etc.)
|
||||
// we may need virtual or template classes to implement the possible alternatives
|
||||
@@ -866,6 +860,21 @@ class Item extends Controller {
|
||||
$private = 2;
|
||||
}
|
||||
|
||||
if ($private && get_pconfig($profile_uid, 'system', 'ocap_enabled')) {
|
||||
// for edited posts, re-use any existing OCAP token (if found).
|
||||
// Otherwise generate a new one.
|
||||
|
||||
if ($iconfig) {
|
||||
foreach ($iconfig as $cfg) {
|
||||
if ($cfg['cat'] === 'ocap' && $cfg['k'] === 'relay') {
|
||||
$token = $cfg['v'];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!$token) {
|
||||
$token = new_token();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -887,9 +896,9 @@ class Item extends Controller {
|
||||
*/
|
||||
|
||||
if (!$preview) {
|
||||
fix_attached_photo_permissions($profile_uid, $owner_xchan['xchan_hash'], ((strpos($body, '[/crypt]')) ? $_POST['media_str'] : $body), $str_contact_allow, $str_group_allow, $str_contact_deny, $str_group_deny);
|
||||
fix_attached_photo_permissions($profile_uid, $owner_xchan['xchan_hash'], ((strpos($summary, '[/crypt]')) ? $_POST['media_str'] : $summary), $str_contact_allow, $str_group_allow, $str_contact_deny, $str_group_deny);
|
||||
fix_attached_file_permissions($channel, $observer['xchan_hash'], ((strpos($body, '[/crypt]')) ? $_POST['media_str'] : $body), $str_contact_allow, $str_group_allow, $str_contact_deny, $str_group_deny);
|
||||
fix_attached_permissions($profile_uid, ((strpos($body, '[/crypt]')) ? $_POST['media_str'] : $body), $str_contact_allow, $str_group_allow, $str_contact_deny, $str_group_deny, $token);
|
||||
//fix_attached_photo_permissions($profile_uid, $owner_xchan['xchan_hash'], ((strpos($body, '[/crypt]')) ? $_POST['media_str'] : $body), $str_contact_allow, $str_group_allow, $str_contact_deny, $str_group_deny, $token);
|
||||
//fix_attached_file_permissions($channel, $observer['xchan_hash'], ((strpos($body, '[/crypt]')) ? $_POST['media_str'] : $body), $str_contact_allow, $str_group_allow, $str_contact_deny, $str_group_deny, $token);
|
||||
}
|
||||
|
||||
$attachments = '';
|
||||
@@ -929,6 +938,30 @@ class Item extends Controller {
|
||||
}
|
||||
}
|
||||
|
||||
if (preg_match_all('/(\:(\w|\+|\-)+\:)(?=|[\!\.\?]|$)/', $body, $match)) {
|
||||
// emoji shortcodes
|
||||
$emojis = get_emojis();
|
||||
foreach ($match[0] as $mtch) {
|
||||
$shortname = trim($mtch, ':');
|
||||
|
||||
if (!isset($emojis[$shortname])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$emoji = $emojis[$shortname];
|
||||
|
||||
$post_tags[] = [
|
||||
'uid' => $profile_uid,
|
||||
'ttype' => TERM_EMOJI,
|
||||
'otype' => TERM_OBJ_POST,
|
||||
'term' => trim($mtch),
|
||||
'url' => z_root() . '/emoji/' . $shortname,
|
||||
'imgurl' => z_root() . '/' . $emoji['filepath']
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// BBCODE end alert
|
||||
}
|
||||
|
||||
@@ -949,6 +982,10 @@ class Item extends Controller {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if ($orig_post) {
|
||||
// preserve original tags
|
||||
$t = q("select * from term where oid = %d and otype = %d and uid = %d and ttype in ( %d, %d, %d )",
|
||||
@@ -972,14 +1009,12 @@ class Item extends Controller {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$item_unseen = ((local_channel() != $profile_uid) ? 1 : 0);
|
||||
$item_wall = ((isset($_REQUEST['type']) && ($_REQUEST['type'] === 'wall' || $_REQUEST['type'] === 'wall-comment')) ? 1 : 0);
|
||||
$item_origin = (($origin) ? 1 : 0);
|
||||
$item_consensus = (($consensus) ? 1 : 0);
|
||||
$item_nocomment = (($nocomment) ? 1 : 0);
|
||||
|
||||
|
||||
// determine if this is a wall post
|
||||
|
||||
if ($parent) {
|
||||
@@ -997,7 +1032,7 @@ class Item extends Controller {
|
||||
|
||||
|
||||
if (!strlen($verb))
|
||||
$verb = ACTIVITY_POST;
|
||||
$verb = 'Create';
|
||||
|
||||
$notify_type = (($parent) ? 'comment-new' : 'wall-new');
|
||||
|
||||
@@ -1128,8 +1163,13 @@ class Item extends Controller {
|
||||
if (!empty_acl($datarray))
|
||||
$datarray['public_policy'] = '';
|
||||
|
||||
if ($iconfig)
|
||||
if ($iconfig) {
|
||||
$datarray['iconfig'] = $iconfig;
|
||||
}
|
||||
|
||||
if ($token) {
|
||||
IConfig::set($datarray, 'ocap', 'relay', $token);
|
||||
}
|
||||
|
||||
// preview mode - prepare the body for display and send it via json
|
||||
|
||||
@@ -1194,23 +1234,14 @@ class Item extends Controller {
|
||||
(($remote_id) ? $remote_id : basename($datarray['mid'])), true);
|
||||
}
|
||||
|
||||
|
||||
if ($orig_post) {
|
||||
$datarray['id'] = $post_id;
|
||||
|
||||
$x = item_store_update($datarray, $execflag);
|
||||
|
||||
// We only need edit activities for other federated protocols
|
||||
// which do not support edits natively. While this does federate
|
||||
// edits, it presents a number of issues locally - such as #757 and #758.
|
||||
// The SQL check for an edit activity would not perform that well so to fix these issues
|
||||
// requires an additional item flag (perhaps 'item_edit_activity') that we can add to the
|
||||
// query for searches and notifications.
|
||||
|
||||
// For now we'll just forget about trying to make edits work on network protocols that
|
||||
// don't support them.
|
||||
|
||||
// item_create_edit_activity($x);
|
||||
if ($x['success']) {
|
||||
$this->add_listeners($datarray);
|
||||
}
|
||||
|
||||
if (!$parent) {
|
||||
$r = q("select * from item where id = %d",
|
||||
@@ -1238,6 +1269,10 @@ class Item extends Controller {
|
||||
|
||||
$post = item_store($datarray, $execflag);
|
||||
|
||||
if ($post['success']) {
|
||||
$this->add_listeners($datarray);
|
||||
}
|
||||
|
||||
$post_id = $post['item_id'];
|
||||
|
||||
$datarray = $post['item'];
|
||||
@@ -1261,8 +1296,8 @@ class Item extends Controller {
|
||||
'from_xchan' => $datarray['author_xchan'],
|
||||
'to_xchan' => $datarray['owner_xchan'],
|
||||
'item' => $datarray,
|
||||
'link' => z_root() . '/display/' . gen_link_id($datarray['mid']),
|
||||
'verb' => ACTIVITY_POST,
|
||||
'link' => z_root() . '/display/' . $datarray['uuid'],
|
||||
'verb' => 'Create',
|
||||
'otype' => 'item',
|
||||
'parent' => $parent,
|
||||
'parent_mid' => $parent_item['mid']
|
||||
@@ -1279,8 +1314,8 @@ class Item extends Controller {
|
||||
'from_xchan' => $datarray['author_xchan'],
|
||||
'to_xchan' => $datarray['owner_xchan'],
|
||||
'item' => $datarray,
|
||||
'link' => z_root() . '/display/' . gen_link_id($datarray['mid']),
|
||||
'verb' => ACTIVITY_POST,
|
||||
'link' => z_root() . '/display/' . $datarray['uuid'],
|
||||
'verb' => 'Create',
|
||||
'otype' => 'item'
|
||||
]);
|
||||
}
|
||||
@@ -1325,7 +1360,7 @@ class Item extends Controller {
|
||||
}
|
||||
|
||||
$datarray['id'] = $post_id;
|
||||
$datarray['llink'] = z_root() . '/display/' . gen_link_id($datarray['mid']);
|
||||
$datarray['llink'] = z_root() . '/display/' . $datarray['uuid'];
|
||||
|
||||
call_hooks('post_local_end', $datarray);
|
||||
|
||||
@@ -1349,7 +1384,7 @@ class Item extends Controller {
|
||||
|
||||
if ($return_path) {
|
||||
if ($return_path === 'hq') {
|
||||
goaway(z_root() . '/hq/' . gen_link_id($datarray['mid']));
|
||||
goaway(z_root() . '/hq/' . $datarray['uuid']);
|
||||
}
|
||||
|
||||
goaway(z_root() . "/" . $return_path);
|
||||
@@ -1603,4 +1638,33 @@ class Item extends Controller {
|
||||
}
|
||||
|
||||
|
||||
function add_listeners($item) {
|
||||
// ONLY public items!
|
||||
if ($item['item_thread_top'] && !$item['item_private'] && !empty($item['term'])) {
|
||||
foreach($item['term'] as $t) {
|
||||
if (empty($t['url']) || $t['ttype'] != TERM_MENTION || $t['otype'] != TERM_OBJ_POST) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$listener = q("select hubloc_hash, hubloc_network from hubloc where hubloc_id_url = '%s' and hubloc_deleted = 0 order by hubloc_id desc",
|
||||
dbesc($t['url'])
|
||||
);
|
||||
|
||||
if ($listener) {
|
||||
$listener = Libzot::zot_record_preferred($listener);
|
||||
|
||||
$c = q("select abook_id from abook where abook_channel = %d and abook_xchan = '%s'",
|
||||
intval($profile_uid),
|
||||
dbesc($listener['hubloc_hash'])
|
||||
);
|
||||
|
||||
if (!$c) {
|
||||
ThreadListener::store($item['mid'], $listener['hubloc_hash']);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -139,7 +139,7 @@ class Layouts extends \Zotlabs\Web\Controller {
|
||||
$x['pagetitle'] = $_REQUEST['pagetitle'] ?? '';
|
||||
|
||||
$a = '';
|
||||
$editor = status_editor($a,$x,false,'Layouts');
|
||||
$editor = status_editor($x, false, 'Layouts');
|
||||
|
||||
$r = q("select iconfig.iid, iconfig.v, mid, title, body, mimetype, created, edited, item_type from iconfig
|
||||
left join item on iconfig.iid = item.id
|
||||
|
||||
@@ -19,14 +19,12 @@ 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' => 'Like',
|
||||
'dislike' => 'Dislike',
|
||||
'announce' => ACTIVITY_SHARE,
|
||||
'attendyes' => 'Accept',
|
||||
'attendno' => 'Reject',
|
||||
'attendmaybe' => 'TentativeAccept'
|
||||
];
|
||||
|
||||
// unlike (etc.) reactions are an undo of positive reactions, rather than a negative action.
|
||||
@@ -71,11 +69,12 @@ class Like extends Controller {
|
||||
$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')",
|
||||
AND verb IN ('%s', '%s', '%s', '%s', '%s', '%s', 'Accept', 'Reject', 'TentativeAccept')",
|
||||
intval($arr['item']['uid']),
|
||||
dbesc($arr['item']['mid']),
|
||||
dbesc(ACTIVITY_LIKE),
|
||||
dbesc(ACTIVITY_DISLIKE),
|
||||
dbesc('Like'),
|
||||
dbesc('Dislike'),
|
||||
dbesc(ACTIVITY_SHARE),
|
||||
dbesc(ACTIVITY_ATTEND),
|
||||
dbesc(ACTIVITY_ATTENDNO),
|
||||
dbesc(ACTIVITY_ATTENDMAYBE)
|
||||
@@ -133,7 +132,7 @@ class Like extends Controller {
|
||||
}
|
||||
|
||||
$is_rsvp = false;
|
||||
if (in_array($activity, [ACTIVITY_ATTEND, ACTIVITY_ATTENDNO, ACTIVITY_ATTENDMAYBE])) {
|
||||
if (in_array($activity, ['Accept', 'Reject', 'TentativeAccept', ACTIVITY_ATTEND, ACTIVITY_ATTENDNO, ACTIVITY_ATTENDMAYBE])) {
|
||||
$is_rsvp = true;
|
||||
}
|
||||
|
||||
@@ -182,7 +181,7 @@ class Like extends Controller {
|
||||
}
|
||||
}
|
||||
$post_type = t('channel');
|
||||
$obj_type = ACTIVITY_OBJ_PROFILE;
|
||||
$obj_type = 'Profile';
|
||||
|
||||
$profile = $r[0];
|
||||
}
|
||||
@@ -211,8 +210,8 @@ class Like extends Controller {
|
||||
$public = false;
|
||||
|
||||
$post_type = t('thing');
|
||||
$obj_type = ACTIVITY_OBJ_PROFILE;
|
||||
$tgttype = ACTIVITY_OBJ_THING;
|
||||
$obj_type = 'Profile';
|
||||
$tgttype = 'Page';
|
||||
|
||||
$links = array();
|
||||
$links[] = array('rel' => 'alternate', 'type' => 'text/html',
|
||||
@@ -220,12 +219,7 @@ class Like extends Controller {
|
||||
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
|
||||
));
|
||||
$target = Activity::fetch_thing(['id' => $r[0]['obj_obj']]);
|
||||
|
||||
$plink = '[zrl=' . z_root() . '/thing/' . $r[0]['obj_obj'] . ']' . $r[0]['obj_term'] . '[/zrl]';
|
||||
|
||||
@@ -323,6 +317,8 @@ class Like extends Controller {
|
||||
// parent, copy that as well.
|
||||
|
||||
if ($r) {
|
||||
$obj_type = $r[0]['obj_type'];
|
||||
|
||||
if ($r[0]['uid'] === $sys_channel['channel_id'] && local_channel()) {
|
||||
$r = [copy_of_pubitem(App::get_channel(), $r[0]['mid'])];
|
||||
}
|
||||
@@ -370,15 +366,11 @@ class Like extends Controller {
|
||||
|
||||
$multi_undo = false;
|
||||
|
||||
// event participation and consensus items are essentially radio toggles. If you make a subsequent choice,
|
||||
// event participation 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) . "' ";
|
||||
$multi_undo = 1;
|
||||
}
|
||||
if ($activity === ACTIVITY_AGREE || $activity === ACTIVITY_DISAGREE || $activity === ACTIVITY_ABSTAIN) {
|
||||
$verbs = " '" . dbesc(ACTIVITY_AGREE) . "','" . dbesc(ACTIVITY_DISAGREE) . "','" . dbesc(ACTIVITY_ABSTAIN) . "' ";
|
||||
if (in_array($activity, ['Accept', 'Reject', 'TentativeAccept', ACTIVITY_ATTEND, ACTIVITY_ATTENDNO, ACTIVITY_ATTENDMAYBE])) {
|
||||
$verbs = "'Accept','Reject','TentativeAccept','" . dbesc(ACTIVITY_ATTEND) . "','" . dbesc(ACTIVITY_ATTENDNO) . "','" . dbesc(ACTIVITY_ATTENDMAYBE) . "' ";
|
||||
$multi_undo = true;
|
||||
}
|
||||
|
||||
@@ -407,12 +399,20 @@ class Like extends Controller {
|
||||
if (activity_match($rr['verb'], $activity))
|
||||
$multi_undo = false;
|
||||
|
||||
$d = q("select * from item where id = %d",
|
||||
intval($rr['id'])
|
||||
);
|
||||
if ($d) {
|
||||
xchan_query($d);
|
||||
$sync_item = fetch_post_tags($d);
|
||||
Libsync::build_sync_packet($profile_uid, ['item' => [encode_item($sync_item[0], true)]]);
|
||||
}
|
||||
|
||||
// drop_item was not done interactively, so we need to invoke the notifier
|
||||
// in order to push the changes to connections
|
||||
|
||||
Master::Summon(array('Notifier', 'drop', $rr['id']));
|
||||
|
||||
|
||||
}
|
||||
|
||||
if ($interactive)
|
||||
@@ -429,7 +429,7 @@ class Like extends Controller {
|
||||
}
|
||||
}
|
||||
|
||||
$uuid = item_message_id();
|
||||
$uuid = new_uuid();
|
||||
|
||||
$arr = array();
|
||||
|
||||
@@ -442,14 +442,20 @@ class Like extends Controller {
|
||||
$arr['item_wall'] = 1;
|
||||
}
|
||||
else {
|
||||
$post_type = (($item['resource_type'] === 'photo') ? t('photo') : t('status'));
|
||||
if ($item['obj_type'] === ACTIVITY_OBJ_EVENT)
|
||||
$post_type = t('event');
|
||||
|
||||
$obj_type = (($item['resource_type'] === 'photo') ? ACTIVITY_OBJ_PHOTO : ACTIVITY_OBJ_NOTE);
|
||||
|
||||
if ($obj_type === ACTIVITY_OBJ_NOTE && (!intval($item['item_thread_top'])))
|
||||
$obj_type = ACTIVITY_OBJ_COMMENT;
|
||||
switch ($item['object_type']) {
|
||||
case 'Image':
|
||||
$post_type = t('image');
|
||||
break;
|
||||
case 'Invite':
|
||||
$post_type = t('event');
|
||||
break;
|
||||
case 'Profile':
|
||||
$post_type = t('profile');
|
||||
break;
|
||||
default:
|
||||
$post_type = t('status');
|
||||
break;
|
||||
}
|
||||
|
||||
$object = json_encode(Activity::fetch_item(['id' => $item['mid']]));
|
||||
|
||||
@@ -477,12 +483,6 @@ class Like extends Controller {
|
||||
$bodyverb = t('%1$s likes %2$s\'s %3$s');
|
||||
if ($verb === 'dislike')
|
||||
$bodyverb = t('%1$s doesn\'t like %2$s\'s %3$s');
|
||||
if ($verb === 'agree')
|
||||
$bodyverb = t('%1$s agrees with %2$s\'s %3$s');
|
||||
if ($verb === 'disagree')
|
||||
$bodyverb = t('%1$s doesn\'t agree with %2$s\'s %3$s');
|
||||
if ($verb === 'abstain')
|
||||
$bodyverb = t('%1$s abstains from a decision on %2$s\'s %3$s');
|
||||
if ($verb === 'attendyes')
|
||||
$bodyverb = t('%1$s is attending %2$s\'s %3$s');
|
||||
if ($verb === 'attendno')
|
||||
@@ -499,11 +499,11 @@ class Like extends Controller {
|
||||
$private = (($public) ? 0 : 1);
|
||||
}
|
||||
else {
|
||||
$arr['parent'] = $item['id'];
|
||||
$arr['parent'] = $item['parent'];
|
||||
$arr['thr_parent'] = $item['mid'];
|
||||
$ulink = '[zrl=' . $item_author['xchan_url'] . '][bdi]' . $item_author['xchan_name'] . '[/bdi][/zrl]';
|
||||
$alink = '[zrl=' . $observer['xchan_url'] . '][bdi]' . $observer['xchan_name'] . '[/bdi][/zrl]';
|
||||
$plink = '[zrl=' . z_root() . '/display/' . gen_link_id($item['mid']) . ']' . $post_type . '[/zrl]';
|
||||
$plink = '[zrl=' . z_root() . '/display/' . $item['uuid'] . ']' . $post_type . '[/zrl]';
|
||||
$allow_cid = $item['allow_cid'];
|
||||
$allow_gid = $item['allow_gid'];
|
||||
$deny_cid = $item['deny_cid'];
|
||||
@@ -516,7 +516,7 @@ class Like extends Controller {
|
||||
$arr['uid'] = $owner_uid;
|
||||
$arr['item_flags'] = $item['item_flags'];
|
||||
$arr['item_wall'] = $item['item_wall'];
|
||||
$arr['parent_mid'] = (($extended_like) ? $arr['mid'] : $item['mid']);
|
||||
$arr['parent_mid'] = (($extended_like) ? $arr['mid'] : $item['parent_mid']);
|
||||
$arr['owner_xchan'] = (($extended_like) ? $ch[0]['xchan_hash'] : $thread_owner['xchan_hash']);
|
||||
$arr['author_xchan'] = $observer['xchan_hash'];
|
||||
$arr['body'] = sprintf($bodyverb, $alink, $ulink, $plink);
|
||||
@@ -524,7 +524,7 @@ class Like extends Controller {
|
||||
if ($obj_type === 'thing' && $r[0]['imgurl']) {
|
||||
$arr['body'] .= "\n\n[zmg=80x80]" . $r[0]['imgurl'] . '[/zmg]';
|
||||
}
|
||||
if ($obj_type === 'profile') {
|
||||
if ($obj_type === 'Profile') {
|
||||
if ($public) {
|
||||
$arr['body'] .= "\n\n" . '[embed]' . z_root() . '/profile/' . $ch[0]['channel_address'] . '[/embed]';
|
||||
}
|
||||
@@ -546,7 +546,14 @@ class Like extends Controller {
|
||||
$arr['deny_cid'] = $deny_cid;
|
||||
$arr['deny_gid'] = $deny_gid;
|
||||
$arr['item_private'] = $private;
|
||||
$arr['created'] = datetime_convert();
|
||||
|
||||
$created = datetime_convert();
|
||||
|
||||
$arr['created'] = $created;
|
||||
$arr['edited'] = $created;
|
||||
$arr['commented'] = $created;
|
||||
$arr['received'] = $created;
|
||||
$arr['changed'] = $created;
|
||||
|
||||
call_hooks('post_local', $arr);
|
||||
|
||||
@@ -562,6 +569,16 @@ class Like extends Controller {
|
||||
|
||||
call_hooks('post_local_end', $arr);
|
||||
|
||||
$r = q("select * from item where id = %d",
|
||||
intval($post_id)
|
||||
);
|
||||
if ($r) {
|
||||
xchan_query($r);
|
||||
$sync_item = fetch_post_tags($r);
|
||||
Libsync::build_sync_packet($profile_uid, ['item' => [encode_item($sync_item[0], true)]]);
|
||||
}
|
||||
|
||||
|
||||
if ($extended_like) {
|
||||
$r = q("insert into likes (channel_id,liker,likee,iid,i_mid,verb,target_type,target_id,target) values (%d,'%s','%s',%d,'%s','%s','%s','%s','%s')",
|
||||
intval($ch[0]['channel_id']),
|
||||
|
||||
@@ -291,11 +291,15 @@ class Linkinfo extends \Zotlabs\Web\Controller {
|
||||
|
||||
// Check codepage in HTTP headers or HTML if not exist
|
||||
$cp = (preg_match('/Content-Type: text\/html; charset=(.+)\r\n/i', $header, $o) ? $o[1] : '');
|
||||
if(empty($cp))
|
||||
$cp = (preg_match('/meta.+content=["\']text\/html; charset=([^"\']+)/i', $body, $o) ? $o[1] : 'AUTO');
|
||||
if(empty($cp)) {
|
||||
$cp = (preg_match('/meta.+content=["\']text\/html; charset=([^"\']+)/i', $body, $o) ? $o[1] : 'AUTO');
|
||||
}
|
||||
|
||||
$body = mb_convert_encoding($body, 'UTF-8', $cp);
|
||||
$body = mb_convert_encoding($body, 'HTML-ENTITIES', "UTF-8");
|
||||
$body = mb_convert_encoding($body, 'UTF-8', $cp);
|
||||
|
||||
// Handling HTML entities via mbstring is deprecated
|
||||
//$body = mb_convert_encoding($body, 'HTML-ENTITIES', "UTF-8");
|
||||
$body = mb_encode_numericentity($body, [0x80, 0x10FFFF, 0, ~0], 'UTF-8');
|
||||
|
||||
$doc = new \DOMDocument();
|
||||
@$doc->loadHTML($body);
|
||||
|
||||
@@ -15,6 +15,7 @@ class Lockview extends Controller {
|
||||
$atoken_xchans = [];
|
||||
$access_list = [];
|
||||
$guest_access_list = [];
|
||||
$ocap_access_list = [];
|
||||
|
||||
if (local_channel()) {
|
||||
$at = q("select * from atoken where atoken_uid = %d",
|
||||
@@ -166,6 +167,24 @@ class Lockview extends Controller {
|
||||
}
|
||||
}
|
||||
}
|
||||
$ocap_tokens = [];
|
||||
foreach ($allowed_users as $allowed_user) {
|
||||
$allowed_user = trim($allowed_user, '\'');
|
||||
if (str_starts_with($allowed_user, 'token:')) {
|
||||
$ocap_tokens[] = str_replace('token:', '', $allowed_user);
|
||||
}
|
||||
}
|
||||
|
||||
if ($ocap_tokens) {
|
||||
stringify_array_elms($ocap_tokens, true);
|
||||
$ocap_mids = dbq("select id, mid from item where id in (select iid from iconfig where cat = 'ocap' and k = 'relay' and v in (" . implode(', ', $ocap_tokens) . "))");
|
||||
|
||||
foreach ($ocap_mids as $ocap) {
|
||||
$ocap_access_list[] = '<a href="' . $ocap['mid'] . '" class="dropdown-item-text" target="_blank">' . t('Item') . ' ' . $ocap['id'] . '</a>';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$profile_groups = [];
|
||||
@@ -205,9 +224,6 @@ class Lockview extends Controller {
|
||||
}
|
||||
|
||||
if ($atokens && $allowed_xchans && $url) {
|
||||
|
||||
$guest_access_list = [];
|
||||
|
||||
$allowed_xchans = array_unique($allowed_xchans);
|
||||
foreach ($atokens as $atoken) {
|
||||
if (in_array($atoken['xchan_hash'], $allowed_xchans)) {
|
||||
@@ -216,22 +232,25 @@ class Lockview extends Controller {
|
||||
}
|
||||
}
|
||||
|
||||
$access_list_header = '';
|
||||
$access_list_header = '<div class="dropdown-header text-uppercase h6">' . t('Access') . '</div>';
|
||||
$guest_access_list_header = '<div class="dropdown-header text-uppercase h6">' . t('Guest access') . '</div>';
|
||||
$ocap_access_list_header = '<div class="dropdown-header text-uppercase h6">' . t('OCAP access') . '</div>';
|
||||
$divider = '<div class="dropdown-divider"></div>';
|
||||
$str = '';
|
||||
|
||||
if ($access_list) {
|
||||
$access_list_header = '<div class="dropdown-header text-uppercase h6">' . t('Access') . '</div>';
|
||||
$str .= $access_list_header . implode($access_list);
|
||||
}
|
||||
|
||||
$guest_access_list_header = '';
|
||||
if ($guest_access_list) {
|
||||
$guest_access_list_header = '<div class="dropdown-header text-uppercase h6">' . t('Guest access') . '</div>';
|
||||
$str .= $divider . $guest_access_list_header . implode($guest_access_list);
|
||||
}
|
||||
|
||||
$divider = '';
|
||||
if ($access_list && $guest_access_list) {
|
||||
$divider = '<div class="dropdown-divider"></div>';
|
||||
if ($ocap_access_list) {
|
||||
$str .= $divider . $ocap_access_list_header . implode($ocap_access_list);
|
||||
}
|
||||
|
||||
echo $access_list_header . implode($access_list) . $divider . $guest_access_list_header . implode($guest_access_list);
|
||||
echo $str;
|
||||
killme();
|
||||
|
||||
}
|
||||
|
||||
@@ -105,13 +105,13 @@ class Magic extends Controller {
|
||||
$headers['Accept'] = 'application/x-zot+json' ;
|
||||
$headers['Content-Type'] = 'application/x-zot+json' ;
|
||||
$headers['X-Open-Web-Auth'] = random_string();
|
||||
$headers['Digest'] = HTTPSig::generate_digest_header($data);
|
||||
$headers['Host'] = $parsed['host'];
|
||||
$headers['(request-target)'] = 'post ' . '/owa';
|
||||
$headers['(request-target)'] = 'get ' . '/owa';
|
||||
|
||||
$headers = HTTPSig::create_sig($headers,$channel['channel_prvkey'], channel_url($channel),true,'sha512');
|
||||
$redirects = 0;
|
||||
$x = z_post_url($owapath,$data,$redirects,[ 'headers' => $headers ]);
|
||||
$x = z_fetch_url($owapath, false, $redirects, ['headers' => $headers]);
|
||||
|
||||
logger('owa fetch returned: ' . print_r($x,true),LOGGER_DATA);
|
||||
if ($x['success']) {
|
||||
$j = json_decode($x['body'],true);
|
||||
|
||||
@@ -23,7 +23,7 @@ class Manifest extends Controller {
|
||||
[ 'src' => '/images/app/hz-144.png', 'sizes' => '144x144', 'type' => 'image/png' ],
|
||||
[ 'src' => '/images/app/hz-152.png', 'sizes' => '152x152', 'type' => 'image/png' ],
|
||||
[ 'src' => '/images/app/hz-192.png', 'sizes' => '192x192', 'type' => 'image/png', 'purpose' => 'any maskable' ],
|
||||
[ 'src' => '/images/app/hz-348.png', 'sizes' => '384x384', 'type' => 'image/png' ],
|
||||
[ 'src' => '/images/app/hz-384.png', 'sizes' => '384x384', 'type' => 'image/png' ],
|
||||
[ 'src' => '/images/app/hz-512.png', 'sizes' => '512x512', 'type' => 'image/png' ],
|
||||
[ 'src' => '/images/app/hz.svg', 'sizes' => '64x64', 'type' => 'image/xml+svg' ]
|
||||
],
|
||||
|
||||
@@ -17,7 +17,7 @@ class Moderate extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
|
||||
\App::set_pager_itemspage(30);
|
||||
$pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(\App::$pager['itemspage']), intval(\App::$pager['start']));
|
||||
$pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(\App::$pager['itemspage']), intval(\App::$pager['start']));
|
||||
|
||||
//show all items
|
||||
if(argc() == 1) {
|
||||
@@ -40,8 +40,13 @@ class Moderate extends \Zotlabs\Web\Controller {
|
||||
|
||||
if(argc() > 2) {
|
||||
$post_id = intval(argv(1));
|
||||
if(! $post_id)
|
||||
if(! $post_id) {
|
||||
if (is_ajax()) {
|
||||
killme();
|
||||
}
|
||||
|
||||
goaway(z_root() . '/moderate');
|
||||
}
|
||||
|
||||
$action = argv(2);
|
||||
|
||||
@@ -61,18 +66,20 @@ class Moderate extends \Zotlabs\Web\Controller {
|
||||
);
|
||||
|
||||
$item['item_blocked'] = 0;
|
||||
|
||||
item_update_parent_commented($item);
|
||||
|
||||
notice( t('Comment approved') . EOL);
|
||||
notice( t('Item approved') . EOL);
|
||||
}
|
||||
elseif($action === 'drop') {
|
||||
// TODO: not implemented
|
||||
// let the sender know we received their comment but we don't permit spam here.
|
||||
// Activity::send_rejection_activity(App::get_channel(), $item['author_xchan'], $item);
|
||||
|
||||
drop_item($post_id,false);
|
||||
notice( t('Comment deleted') . EOL);
|
||||
}
|
||||
notice( t('Item deleted') . EOL);
|
||||
}
|
||||
|
||||
// refetch the item after changes have been made
|
||||
|
||||
|
||||
$r = q("select * from item where id = %d",
|
||||
intval($post_id)
|
||||
);
|
||||
@@ -84,6 +91,11 @@ class Moderate extends \Zotlabs\Web\Controller {
|
||||
if($action === 'approve') {
|
||||
\Zotlabs\Daemon\Master::Summon(array('Notifier', 'comment-new', $post_id));
|
||||
}
|
||||
|
||||
if (is_ajax()) {
|
||||
killme();
|
||||
}
|
||||
|
||||
goaway(z_root() . '/moderate');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,163 +0,0 @@
|
||||
<?php
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
use App;
|
||||
use Zotlabs\Lib\Apps;
|
||||
use Zotlabs\Web\Controller;
|
||||
|
||||
require_once('include/security.php');
|
||||
require_once('include/bbcode.php');
|
||||
require_once('include/items.php');
|
||||
|
||||
|
||||
|
||||
class Mood extends Controller {
|
||||
|
||||
function init() {
|
||||
|
||||
if(! local_channel())
|
||||
return;
|
||||
|
||||
if(! Apps::system_app_installed(local_channel(), 'Mood')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$uid = local_channel();
|
||||
$channel = App::get_channel();
|
||||
$verb = ((isset($_GET['verb'])) ? notags(trim($_GET['verb'])) : '');
|
||||
|
||||
if(! $verb)
|
||||
return;
|
||||
|
||||
$verbs = get_mood_verbs();
|
||||
|
||||
if(! array_key_exists($verb,$verbs))
|
||||
return;
|
||||
|
||||
$activity = ACTIVITY_MOOD . '#' . urlencode($verb);
|
||||
|
||||
$parent = ((x($_GET,'parent')) ? intval($_GET['parent']) : 0);
|
||||
|
||||
|
||||
logger('mood: verb ' . $verb, LOGGER_DEBUG);
|
||||
|
||||
|
||||
if($parent) {
|
||||
$r = q("select mid, owner_xchan, private, allow_cid, allow_gid, deny_cid, deny_gid
|
||||
from item where id = %d and parent = %d and uid = %d limit 1",
|
||||
intval($parent),
|
||||
intval($parent),
|
||||
intval($uid)
|
||||
);
|
||||
if(count($r)) {
|
||||
$parent_mid = $r[0]['mid'];
|
||||
$private = $r[0]['item_private'];
|
||||
$allow_cid = $r[0]['allow_cid'];
|
||||
$allow_gid = $r[0]['allow_gid'];
|
||||
$deny_cid = $r[0]['deny_cid'];
|
||||
$deny_gid = $r[0]['deny_gid'];
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
$private = 0;
|
||||
|
||||
$allow_cid = $channel['channel_allow_cid'];
|
||||
$allow_gid = $channel['channel_allow_gid'];
|
||||
$deny_cid = $channel['channel_deny_cid'];
|
||||
$deny_gid = $channel['channel_deny_gid'];
|
||||
}
|
||||
|
||||
$poster = App::get_observer();
|
||||
|
||||
$uuid = item_message_id();
|
||||
$mid = z_root() . '/item/' . $uuid;
|
||||
|
||||
$action = sprintf( t('%1$s is %2$s','mood'), '[zrl=' . $poster['xchan_url'] . ']' . $poster['xchan_name'] . '[/zrl]' , $verbs[$verb]);
|
||||
|
||||
$arr = array();
|
||||
|
||||
$arr['aid'] = get_account_id();
|
||||
$arr['uid'] = $uid;
|
||||
$arr['uuid'] = $uuid;
|
||||
$arr['mid'] = $mid;
|
||||
$arr['parent_mid'] = (($parent_mid) ? $parent_mid : $mid);
|
||||
$arr['author_xchan'] = $poster['xchan_hash'];
|
||||
$arr['owner_xchan'] = (($parent_mid) ? $r[0]['owner_xchan'] : $poster['xchan_hash']);
|
||||
$arr['title'] = '';
|
||||
$arr['allow_cid'] = $allow_cid;
|
||||
$arr['allow_gid'] = $allow_gid;
|
||||
$arr['deny_cid'] = $deny_cid;
|
||||
$arr['deny_gid'] = $deny_gid;
|
||||
$arr['item_private'] = $private;
|
||||
$arr['verb'] = $activity;
|
||||
$arr['body'] = $action;
|
||||
$arr['item_origin'] = 1;
|
||||
$arr['item_wall'] = 1;
|
||||
$arr['item_unseen'] = 1;
|
||||
if(! $parent_mid)
|
||||
$item['item_thread_top'] = 1;
|
||||
|
||||
if ((! $arr['plink']) && intval($arr['item_thread_top'])) {
|
||||
$arr['plink'] = z_root() . '/channel/' . $channel['channel_address'] . '/?f=&mid=' . urlencode($arr['mid']);
|
||||
}
|
||||
|
||||
|
||||
$post = item_store($arr);
|
||||
$item_id = $post['item_id'];
|
||||
|
||||
if($item_id) {
|
||||
\Zotlabs\Daemon\Master::Summon(array('Notifier','activity', $item_id));
|
||||
}
|
||||
|
||||
call_hooks('post_local_end', $arr);
|
||||
|
||||
if($_SESSION['return_url'])
|
||||
goaway(z_root() . '/' . $_SESSION['return_url']);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
function get() {
|
||||
|
||||
if(! local_channel()) {
|
||||
notice( t('Permission denied.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
if(! Apps::system_app_installed(local_channel(), 'Mood')) {
|
||||
//Do not display any associated widgets at this point
|
||||
App::$pdl = '';
|
||||
$papp = Apps::get_papp('Mood');
|
||||
return Apps::app_render($papp, 'module');
|
||||
}
|
||||
|
||||
nav_set_selected('Mood');
|
||||
|
||||
$parent = ((x($_GET,'parent')) ? intval($_GET['parent']) : '0');
|
||||
|
||||
$verbs = get_mood_verbs();
|
||||
|
||||
$shortlist = array();
|
||||
foreach($verbs as $k => $v)
|
||||
if($v !== 'NOTRANSLATION')
|
||||
$shortlist[] = array($k,$v);
|
||||
|
||||
|
||||
$tpl = get_markup_template('mood_content.tpl');
|
||||
|
||||
$o = replace_macros($tpl,array(
|
||||
'$title' => t('Mood'),
|
||||
'$desc' => t('Set your current mood and tell your friends'),
|
||||
'$verbs' => $shortlist,
|
||||
'$parent' => $parent,
|
||||
'$submit' => t('Submit'),
|
||||
));
|
||||
|
||||
return $o;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -43,6 +43,8 @@ class Network extends \Zotlabs\Web\Controller {
|
||||
return login(false);
|
||||
}
|
||||
|
||||
App::$profile_uid = local_channel();
|
||||
|
||||
$o = '';
|
||||
|
||||
$arr = array('query' => App::$query_string);
|
||||
@@ -212,7 +214,7 @@ class Network extends \Zotlabs\Web\Controller {
|
||||
);
|
||||
|
||||
$a = '';
|
||||
$status_editor = status_editor($a, $x, false, 'Network');
|
||||
$status_editor = status_editor($x, false, 'Network');
|
||||
$o .= $status_editor;
|
||||
|
||||
}
|
||||
@@ -273,7 +275,7 @@ class Network extends \Zotlabs\Web\Controller {
|
||||
|
||||
$vnotify = get_pconfig(local_channel(), 'system', 'vnotify');
|
||||
if(! ($vnotify & VNOTIFY_LIKE))
|
||||
$likes_sql = " AND verb NOT IN ('" . dbesc(ACTIVITY_LIKE) . "', '" . dbesc(ACTIVITY_DISLIKE) . "') ";
|
||||
$likes_sql = " AND verb NOT IN ('Like', 'Dislike', '" . dbesc(ACTIVITY_LIKE) . "', '" . dbesc(ACTIVITY_DISLIKE) . "') ";
|
||||
|
||||
// This is for nouveau view public forum cid queries (if a forum notification is clicked)
|
||||
//$p = q("SELECT oid AS parent FROM term WHERE uid = %d AND ttype = %d AND term = '%s'",
|
||||
|
||||
@@ -28,7 +28,6 @@ class Oep extends \Zotlabs\Web\Controller {
|
||||
$format = $_REQUEST['format'] ?? '';
|
||||
if($format && $format !== 'json')
|
||||
http_status_exit(501, 'Not implemented');
|
||||
|
||||
if(fnmatch('*/photos/*/album/*',$url))
|
||||
$arr = $this->oep_album_reply($_REQUEST);
|
||||
elseif(fnmatch('*/photos/*/image/*',$url))
|
||||
@@ -95,12 +94,12 @@ class Oep extends \Zotlabs\Web\Controller {
|
||||
|
||||
$c = channelx_by_n($p[0]['uid']);
|
||||
|
||||
|
||||
if(! ($c && $res))
|
||||
return;
|
||||
|
||||
if(! perm_is_allowed($c[0]['channel_id'],get_observer_hash(),'view_stream'))
|
||||
if(! perm_is_allowed($c['channel_id'], get_observer_hash(), 'view_stream')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$sql_extra = item_permissions_sql($c['channel_id']);
|
||||
|
||||
@@ -336,32 +335,51 @@ class Oep extends \Zotlabs\Web\Controller {
|
||||
$maxwidth = ((isset($args['maxwidth'])) ? $args['maxwidth'] : 0);
|
||||
$maxheight = ((isset($args['maxheight'])) ? $args['maxheight'] : 0);
|
||||
|
||||
if(preg_match('#//(.*?)/(.*?)/(.*?)/(.*?)mid\=(.*?)(&|$)#',$url,$matches)) {
|
||||
$chn = $matches[3];
|
||||
$res = $matches[5];
|
||||
$parsed = parse_url($url);
|
||||
if (empty($parsed['path'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(! ($chn && $res))
|
||||
$nick = basename($parsed['path']);
|
||||
if (!$nick) {
|
||||
return;
|
||||
}
|
||||
|
||||
$c = q("select * from channel where channel_address = '%s' limit 1",
|
||||
dbesc($chn)
|
||||
if (empty($parsed['query'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
parse_str($parsed['query'], $query);
|
||||
|
||||
if (empty($query['mid'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$mid = unpack_link_id($query['mid']);
|
||||
if (!$mid) {
|
||||
return;
|
||||
}
|
||||
|
||||
$c = channelx_by_nick($nick);
|
||||
if(! $c) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(! perm_is_allowed($c['channel_id'], get_observer_hash(), 'view_stream')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$sql_extra = item_permissions_sql($c['channel_id']);
|
||||
$item_normal = item_normal();
|
||||
|
||||
$p = q("select * from item where mid = '%s' and uid = %d $sql_extra $item_normal limit 1",
|
||||
dbesc($mid),
|
||||
intval($c['channel_id'])
|
||||
);
|
||||
|
||||
if(! $c)
|
||||
return;
|
||||
|
||||
if(! perm_is_allowed($c[0]['channel_id'],get_observer_hash(),'view_stream'))
|
||||
return;
|
||||
|
||||
$sql_extra = item_permissions_sql($c[0]['channel_id']);
|
||||
|
||||
$p = q("select * from item where mid = '%s' and uid = %d $sql_extra limit 1",
|
||||
dbesc($res),
|
||||
intval($c[0]['channel_id'])
|
||||
);
|
||||
if(! $p)
|
||||
if(! $p) {
|
||||
return;
|
||||
}
|
||||
|
||||
xchan_query($p,true);
|
||||
$p = fetch_post_tags($p,true);
|
||||
|
||||
@@ -30,20 +30,37 @@ class Owa extends Controller {
|
||||
$sigblock = HTTPSig::parse_sigheader($_SERVER['HTTP_AUTHORIZATION']);
|
||||
if ($sigblock) {
|
||||
$keyId = $sigblock['keyId'];
|
||||
$parsed = parse_url($keyId);
|
||||
if (str_starts_with($parsed['scheme'],'http')) {
|
||||
unset($parsed['fragment']);
|
||||
unset($parsed['query']);
|
||||
$keyId = unparse_url($parsed);
|
||||
}
|
||||
else {
|
||||
$keyId = str_replace('acct:', '', $keyId);
|
||||
}
|
||||
if ($keyId) {
|
||||
$r = q("SELECT * FROM hubloc LEFT JOIN xchan ON hubloc_hash = xchan_hash
|
||||
WHERE hubloc_id_url = '%s' AND hubloc_deleted = 0 AND xchan_pubkey != '' ORDER BY hubloc_id DESC",
|
||||
WHERE (hubloc_addr = '%s' OR hubloc_id_url = '%s' OR xchan_hash = '%s')
|
||||
AND hubloc_deleted = 0 AND xchan_pubkey != ''
|
||||
ORDER BY hubloc_id DESC",
|
||||
dbesc($keyId),
|
||||
dbesc($keyId),
|
||||
dbesc($keyId)
|
||||
);
|
||||
if (! $r) {
|
||||
$found = discover_by_webbie($keyId);
|
||||
logger('found = ' . print_r($found, true));
|
||||
if ($found) {
|
||||
$r = q("SELECT * FROM hubloc LEFT JOIN xchan ON hubloc_hash = xchan_hash
|
||||
WHERE hubloc_id_url = '%s' AND hubloc_deleted = 0 AND xchan_pubkey != '' ORDER BY hubloc_id DESC ",
|
||||
WHERE (hubloc_addr = '%s' OR hubloc_id_url = '%s' OR xchan_hash = '%s') AND hubloc_deleted = 0 AND xchan_pubkey != '' ORDER BY hubloc_id DESC ",
|
||||
dbesc($keyId),
|
||||
dbesc($keyId),
|
||||
dbesc($keyId)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if ($r) {
|
||||
foreach ($r as $hubloc) {
|
||||
$verified = HTTPSig::verify(file_get_contents('php://input'), $hubloc['xchan_pubkey']);
|
||||
@@ -72,7 +89,8 @@ class Owa extends Controller {
|
||||
|
||||
if ($found) {
|
||||
$r = q("SELECT * FROM hubloc LEFT JOIN xchan ON hubloc_hash = xchan_hash
|
||||
WHERE hubloc_id_url = '%s' AND hubloc_deleted = 0 ORDER BY hubloc_id DESC LIMIT 1",
|
||||
WHERE (hubloc_addr = '%s' OR hubloc_id_url = '%s') AND hubloc_deleted = 0 ORDER BY hubloc_id DESC LIMIT 1",
|
||||
dbesc(str_replace('acct:', '', $keyId)),
|
||||
dbesc($keyId)
|
||||
);
|
||||
|
||||
|
||||
@@ -268,7 +268,8 @@ class Pdledit_gui extends Controller {
|
||||
|
||||
|
||||
$checkpaths = [
|
||||
'Zotlabs/Widget/*.php'
|
||||
'Zotlabs/Widget/*.php',
|
||||
'view/theme/' . lcfirst(App::$theme_info['name']) . '/widget/*.php'
|
||||
];
|
||||
|
||||
$addons = plugins_installed_list();
|
||||
|
||||
@@ -46,7 +46,7 @@ class Photo extends \Zotlabs\Web\Controller {
|
||||
dbesc(argv(1))
|
||||
);
|
||||
if ($r) {
|
||||
$allowed = attach_can_view($r[0]['uid'],$observer_xchan,argv(1)/*,$bear*/);
|
||||
$allowed = attach_can_view($r[0]['uid'], $observer_xchan, argv(1), $bear);
|
||||
}
|
||||
if (! $allowed) {
|
||||
http_status_exit(404,'Permission denied.');
|
||||
@@ -154,6 +154,11 @@ class Photo extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
else {
|
||||
|
||||
$bear = Activity::token_from_request();
|
||||
if ($bear) {
|
||||
logger('bear: ' . $bear, LOGGER_DEBUG);
|
||||
}
|
||||
|
||||
/**
|
||||
* Other photos
|
||||
*/
|
||||
@@ -223,7 +228,7 @@ class Photo extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
|
||||
if($allowed === (-1))
|
||||
$allowed = attach_can_view($r[0]['uid'],$observer_xchan,$photo);
|
||||
$allowed = attach_can_view($r[0]['uid'], $observer_xchan, $photo, $bear);
|
||||
|
||||
$channel = channelx_by_n($r[0]['uid']);
|
||||
|
||||
@@ -262,16 +267,15 @@ class Photo extends \Zotlabs\Web\Controller {
|
||||
http_status_exit(404,'not found');
|
||||
}
|
||||
|
||||
if(! $data)
|
||||
killme();
|
||||
if(! $data)
|
||||
killme();
|
||||
|
||||
$etag = '"' . md5($data . $modified) . '"';
|
||||
$etag = '"' . md5($data . $modified) . '"';
|
||||
|
||||
if($modified == 0)
|
||||
$modified = time();
|
||||
if($modified == 0)
|
||||
$modified = time();
|
||||
|
||||
header_remove('Pragma');
|
||||
|
||||
if((isset($_SERVER['HTTP_IF_NONE_MATCH']) && $_SERVER['HTTP_IF_NONE_MATCH'] === $etag) || (!isset($_SERVER['HTTP_IF_NONE_MATCH']) && isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && $_SERVER['HTTP_IF_MODIFIED_SINCE'] === gmdate("D, d M Y H:i:s", $modified) . " GMT")) {
|
||||
header_remove('Expires');
|
||||
header_remove('Cache-Control');
|
||||
@@ -307,6 +311,8 @@ class Photo extends \Zotlabs\Web\Controller {
|
||||
// This has performance considerations but we highly recommend you
|
||||
// leave it alone.
|
||||
|
||||
|
||||
|
||||
$maxage = $cache_mode['age'];
|
||||
|
||||
if($cache_mode['exp'] || (! isset($expires)) || (isset($expires) && $expires - 60 < time()))
|
||||
|
||||
@@ -851,6 +851,10 @@ class Photos extends \Zotlabs\Web\Controller {
|
||||
dbesc($datum)
|
||||
);
|
||||
|
||||
$tags = [];
|
||||
$likebuttons = [];
|
||||
$comments = '';
|
||||
|
||||
if(! ($ph && $x)) {
|
||||
|
||||
/* Check again - this time without specifying permissions */
|
||||
@@ -981,7 +985,6 @@ class Photos extends \Zotlabs\Web\Controller {
|
||||
$r = conv_sort($r,'commented');
|
||||
}
|
||||
|
||||
$tags = array();
|
||||
if(x($link_item, 'term')) {
|
||||
$cnt = 0;
|
||||
foreach($link_item['term'] as $t) {
|
||||
@@ -1075,7 +1078,6 @@ class Photos extends \Zotlabs\Web\Controller {
|
||||
];
|
||||
}
|
||||
|
||||
$comments = '';
|
||||
if(! $r) {
|
||||
if($observer && ($can_post || $can_comment)) {
|
||||
$commentbox = replace_macros($cmnt_tpl,array(
|
||||
@@ -1106,7 +1108,6 @@ class Photos extends \Zotlabs\Web\Controller {
|
||||
|
||||
$conv_responses = array(
|
||||
'like' => array('title' => t('Likes','title')),'dislike' => array('title' => t('Dislikes','title')),
|
||||
'agree' => array('title' => t('Agree','title')),'disagree' => array('title' => t('Disagree','title')), 'abstain' => array('title' => t('Abstain','title')),
|
||||
'attendyes' => array('title' => t('Attending','title')), 'attendno' => array('title' => t('Not attending','title')), 'attendmaybe' => array('title' => t('Might attend','title'))
|
||||
);
|
||||
|
||||
@@ -1150,8 +1151,9 @@ class Photos extends \Zotlabs\Web\Controller {
|
||||
$template = $tpl;
|
||||
$sparkle = '';
|
||||
|
||||
if(((activity_match($item['verb'],ACTIVITY_LIKE)) || (activity_match($item['verb'],ACTIVITY_DISLIKE))) && ($item['id'] != $item['parent']))
|
||||
if(activity_match($item['verb'], ['Like', 'Dislike', ACTIVITY_LIKE, ACTIVITY_DISLIKE]) && $item['id'] != $item['parent']) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$redirect_url = z_root() . '/redir/' . $item['cid'] ;
|
||||
|
||||
@@ -1209,13 +1211,12 @@ class Photos extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
|
||||
}
|
||||
$paginate = paginate($a);
|
||||
}
|
||||
|
||||
$album_e = array($album_link,$ph[0]['album']);
|
||||
$like_e = $like;
|
||||
$dislike_e = $dislike;
|
||||
|
||||
$paginate = paginate();
|
||||
|
||||
$response_verbs = array('like');
|
||||
if(feature_enabled($owner_uid,'dislike'))
|
||||
|
||||
@@ -37,7 +37,7 @@ class Pin extends \Zotlabs\Web\Controller {
|
||||
http_status_exit(404, 'Not found');
|
||||
}
|
||||
|
||||
$midb64 = gen_link_id($r[0]['mid']);
|
||||
$midb64 = $r[0]['uuid'];
|
||||
$pinned = (in_array($midb64, get_pconfig($r[0]['uid'], 'pinned', $r[0]['item_type'], [])) ? true : false);
|
||||
|
||||
switch(argv(1)) {
|
||||
|
||||
@@ -1,207 +0,0 @@
|
||||
<?php
|
||||
namespace Zotlabs\Module; /** @file */
|
||||
|
||||
use App;
|
||||
use Zotlabs\Lib\Apps;
|
||||
use Zotlabs\Lib\Activity;
|
||||
use Zotlabs\Web\Controller;
|
||||
|
||||
/**
|
||||
*
|
||||
* Poke, prod, finger, or otherwise do unspeakable things to somebody - who must be a connection in your address book
|
||||
* This function can be invoked with the required arguments (verb and cid and private and possibly parent) silently via ajax or
|
||||
* other web request. You must be logged in and connected to a channel.
|
||||
* If the required arguments aren't present, we'll display a simple form to choose a recipient and a verb.
|
||||
* parent is a special argument which let's you attach this activity as a comment to an existing conversation, which
|
||||
* may have started with somebody else poking (etc.) somebody, but this isn't necessary. This can be used in the adult
|
||||
* plugin version to have entire conversations where Alice poked Bob, Bob fingered Alice, Alice hugged Bob, etc.
|
||||
*
|
||||
* private creates a private conversation with the recipient. Otherwise your channel's default post privacy is used.
|
||||
*
|
||||
*/
|
||||
|
||||
require_once('include/items.php');
|
||||
|
||||
|
||||
class Poke extends Controller {
|
||||
|
||||
function init() {
|
||||
|
||||
if(! local_channel())
|
||||
return;
|
||||
|
||||
if(! Apps::system_app_installed(local_channel(), 'Poke')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$uid = local_channel();
|
||||
$channel = App::get_channel();
|
||||
|
||||
$verb = ((isset($_GET['verb'])) ? notags(trim($_GET['verb'])) : '');
|
||||
|
||||
if(! $verb)
|
||||
return;
|
||||
|
||||
$verbs = get_poke_verbs();
|
||||
|
||||
if(! array_key_exists($verb,$verbs))
|
||||
return;
|
||||
|
||||
$activity = ACTIVITY_POKE . '#' . urlencode($verbs[$verb][0]);
|
||||
|
||||
$contact_id = intval($_REQUEST['cid']);
|
||||
|
||||
$xchan = trim($_REQUEST['xchan']);
|
||||
|
||||
if(! ($contact_id || $xchan))
|
||||
return;
|
||||
|
||||
$parent = ((x($_REQUEST,'parent')) ? intval($_REQUEST['parent']) : 0);
|
||||
|
||||
logger('poke: verb ' . $verb . ' contact ' . $contact_id, LOGGER_DEBUG);
|
||||
|
||||
|
||||
if($contact_id) {
|
||||
$r = q("SELECT * FROM abook left join xchan on xchan_hash = abook_xchan where abook_id = %d and abook_channel = %d LIMIT 1",
|
||||
intval($contact_id),
|
||||
intval($uid)
|
||||
);
|
||||
}
|
||||
if($xchan) {
|
||||
$r = q("SELECT * FROM xchan where xchan_hash like ( '%s' ) LIMIT 1",
|
||||
dbesc($xchan . '%')
|
||||
);
|
||||
}
|
||||
|
||||
if(! $r) {
|
||||
logger('poke: no target.');
|
||||
return;
|
||||
}
|
||||
|
||||
$target = $r[0];
|
||||
$parent_item = null;
|
||||
|
||||
if($parent) {
|
||||
$r = q("select mid, item_private, owner_xchan, allow_cid, allow_gid, deny_cid, deny_gid
|
||||
from item where id = %d and parent = %d and uid = %d limit 1",
|
||||
intval($parent),
|
||||
intval($parent),
|
||||
intval($uid)
|
||||
);
|
||||
if($r) {
|
||||
$parent_item = $r[0];
|
||||
$parent_mid = $r[0]['mid'];
|
||||
$item_private = $r[0]['item_private'];
|
||||
$allow_cid = $r[0]['allow_cid'];
|
||||
$allow_gid = $r[0]['allow_gid'];
|
||||
$deny_cid = $r[0]['deny_cid'];
|
||||
$deny_gid = $r[0]['deny_gid'];
|
||||
}
|
||||
}
|
||||
elseif($contact_id) {
|
||||
|
||||
$item_private = ((x($_GET,'private')) ? intval($_GET['private']) : 0);
|
||||
|
||||
$allow_cid = (($item_private) ? '<' . $target['abook_xchan']. '>' : $channel['channel_allow_cid']);
|
||||
$allow_gid = (($item_private) ? '' : $channel['channel_allow_gid']);
|
||||
$deny_cid = (($item_private) ? '' : $channel['channel_deny_cid']);
|
||||
$deny_gid = (($item_private) ? '' : $channel['channel_deny_gid']);
|
||||
}
|
||||
|
||||
$arr['item_wall'] = 1;
|
||||
$arr['owner_xchan'] = (($parent_item) ? $parent_item['owner_xchan'] : $channel['channel_hash']);
|
||||
$arr['parent_mid'] = (($parent_mid) ? $parent_mid : '');
|
||||
$arr['title'] = '';
|
||||
$arr['allow_cid'] = $allow_cid;
|
||||
$arr['allow_gid'] = $allow_gid;
|
||||
$arr['deny_cid'] = $deny_cid;
|
||||
$arr['deny_gid'] = $deny_gid;
|
||||
$arr['verb'] = $activity;
|
||||
$arr['item_private'] = $item_private;
|
||||
$arr['obj_type'] = ACTIVITY_OBJ_NOTE;
|
||||
$arr['body'] = '[zrl=' . $channel['xchan_url'] . ']' . $channel['xchan_name'] . '[/zrl]' . ' ' . t($verbs[$verb][0]) . ' ' . '[zrl=' . $target['xchan_url'] . ']' . $target['xchan_name'] . '[/zrl]';
|
||||
$arr['item_origin'] = 1;
|
||||
$arr['item_unseen'] = 1;
|
||||
if(! $parent_item)
|
||||
$arr['item_thread_top'] = 1;
|
||||
|
||||
$arr['obj'] = Activity::encode_item($arr);
|
||||
|
||||
|
||||
post_activity_item($arr);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
function get() {
|
||||
|
||||
if(! local_channel()) {
|
||||
notice( t('Permission denied.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
if(! Apps::system_app_installed(local_channel(), 'Poke')) {
|
||||
//Do not display any associated widgets at this point
|
||||
App::$pdl = '';
|
||||
$papp = Apps::get_papp('Poke');
|
||||
return Apps::app_render($papp, 'module');
|
||||
}
|
||||
|
||||
nav_set_selected('Poke');
|
||||
|
||||
$name = '';
|
||||
$id = '';
|
||||
|
||||
if(isset($_REQUEST['c']) && intval($_REQUEST['c'])) {
|
||||
$r = q("select abook_id, xchan_name from abook left join xchan on abook_xchan = xchan_hash
|
||||
where abook_id = %d and abook_channel = %d limit 1",
|
||||
intval($_REQUEST['c']),
|
||||
intval(local_channel())
|
||||
);
|
||||
if($r) {
|
||||
$name = $r[0]['xchan_name'];
|
||||
$id = $r[0]['abook_id'];
|
||||
}
|
||||
}
|
||||
|
||||
$parent = ((x($_REQUEST,'parent')) ? intval($_REQUEST['parent']) : '0');
|
||||
|
||||
$verbs = get_poke_verbs();
|
||||
|
||||
$shortlist = array();
|
||||
foreach($verbs as $k => $v)
|
||||
if($v[1] !== 'NOTRANSLATION')
|
||||
$shortlist[] = array($k,$v[1]);
|
||||
|
||||
|
||||
$poke_basic = get_config('system','poke_basic');
|
||||
if($poke_basic) {
|
||||
$title = t('Poke');
|
||||
$desc = t('Poke somebody');
|
||||
}
|
||||
else {
|
||||
$title = t('Poke');
|
||||
$desc = t('Poke or ping somebody');
|
||||
}
|
||||
|
||||
$o = replace_macros(get_markup_template('poke_content.tpl'),array(
|
||||
'$title' => $title,
|
||||
'$poke_basic' => $poke_basic,
|
||||
'$desc' => $desc,
|
||||
'$clabel' => t('Recipient'),
|
||||
'$choice' => t('Choose action'),
|
||||
'$verbs' => $shortlist,
|
||||
'$parent' => $parent,
|
||||
'$prv_desc' => t('Make this post private'),
|
||||
'$private' => array('private', t('Make this post private'), false, ''),
|
||||
'$submit' => t('Submit'),
|
||||
'$name' => $name,
|
||||
'$id' => $id
|
||||
));
|
||||
|
||||
return $o;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -223,7 +223,7 @@ class Profile_photo extends Controller {
|
||||
intval(local_channel())
|
||||
);
|
||||
|
||||
send_profile_photo_activity($channel, $base_image, $profile);
|
||||
profile_activity([t('Profile Photo')], $base_image['resource_id']);
|
||||
}
|
||||
else {
|
||||
q("update profile set photo = '%s', thumb = '%s' where id = %d and uid = %d",
|
||||
@@ -269,7 +269,6 @@ class Profile_photo extends Controller {
|
||||
|
||||
// Update directory in background
|
||||
Master::Summon(['Directory', $channel['channel_id']]);
|
||||
|
||||
}
|
||||
else
|
||||
notice(t('Unable to process image') . EOL);
|
||||
|
||||
@@ -3,10 +3,6 @@ namespace Zotlabs\Module;
|
||||
|
||||
use Zotlabs\Lib\Libsync;
|
||||
|
||||
require_once('include/channel.php');
|
||||
require_once('include/selectors.php');
|
||||
|
||||
|
||||
class Profiles extends \Zotlabs\Web\Controller {
|
||||
|
||||
function init() {
|
||||
@@ -217,7 +213,6 @@ class Profiles extends \Zotlabs\Web\Controller {
|
||||
|
||||
check_form_security_token_redirectOnErr('/profiles', 'profile_edit');
|
||||
|
||||
|
||||
$is_default = (($orig[0]['is_default']) ? 1 : 0);
|
||||
|
||||
$profile_name = notags(trim($_POST['profile_name']));
|
||||
@@ -493,7 +488,7 @@ class Profiles extends \Zotlabs\Web\Controller {
|
||||
|
||||
$publish = ((x($_POST, 'profile_in_directory') && (intval($_POST['profile_in_directory']) == 1)) ? 1 : 0);
|
||||
|
||||
profile_activity($changes,$value);
|
||||
profile_activity($changes, $value);
|
||||
|
||||
}
|
||||
|
||||
@@ -579,12 +574,12 @@ class Profiles extends \Zotlabs\Web\Controller {
|
||||
$channel = \App::get_channel();
|
||||
|
||||
if($namechanged && $is_default) {
|
||||
// change name on all associated xchans by matching the url
|
||||
q("UPDATE xchan SET xchan_name = '%s', xchan_name_date = '%s' WHERE xchan_url = '%s'",
|
||||
q("UPDATE xchan SET xchan_name = '%s', xchan_name_date = '%s' WHERE xchan_hash = '%s'",
|
||||
dbesc($name),
|
||||
dbesc(datetime_convert()),
|
||||
dbesc(z_root() . '/channel/' . $channel['channel_address'])
|
||||
dbesc($channel['xchan_hash'])
|
||||
);
|
||||
|
||||
q("UPDATE channel SET channel_name = '%s' WHERE channel_hash = '%s'",
|
||||
dbesc($name),
|
||||
dbesc($channel['xchan_hash'])
|
||||
|
||||
@@ -40,7 +40,15 @@ class Pubstream extends \Zotlabs\Web\Controller {
|
||||
|
||||
$site_firehose = ((intval(get_config('system','site_firehose',0))) ? true : false);
|
||||
|
||||
$mid = (($_REQUEST['mid']) ? unpack_link_id($_REQUEST['mid']) : '');
|
||||
$mid = $_REQUEST['mid'] ?? '';
|
||||
$identifier = 'uuid';
|
||||
$encoded_mid = null;
|
||||
|
||||
if (str_starts_with($mid, 'b64.')) {
|
||||
$encoded_mid = $mid;
|
||||
$mid = unpack_link_id($mid);
|
||||
$identifier = 'mid';
|
||||
}
|
||||
|
||||
if ($mid === false) {
|
||||
notice(t('Malformed message id.') . EOL);
|
||||
@@ -91,7 +99,7 @@ class Pubstream extends \Zotlabs\Web\Controller {
|
||||
|
||||
$o .= '<div id="jot-popup">';
|
||||
$a = '';
|
||||
$o .= status_editor($a,$x,false,'Pubstream');
|
||||
$o .= status_editor($x, false, 'Pubstream');
|
||||
$o .= '</div>';
|
||||
}
|
||||
|
||||
@@ -99,9 +107,6 @@ class Pubstream extends \Zotlabs\Web\Controller {
|
||||
|
||||
nav_set_selected(t('Public Stream'));
|
||||
|
||||
if(!$mid)
|
||||
$_SESSION['static_loadtime'] = datetime_convert();
|
||||
|
||||
$maxheight = get_config('system','home_divmore_height');
|
||||
if(! $maxheight)
|
||||
$maxheight = 400;
|
||||
@@ -111,9 +116,6 @@ class Pubstream extends \Zotlabs\Web\Controller {
|
||||
. "; var profile_page = " . \App::$pager['page']
|
||||
. "; divmore_height = " . intval($maxheight) . "; </script>\r\n";
|
||||
|
||||
//if we got a decoded hash we must encode it again before handing to javascript
|
||||
$mid = gen_link_id($mid);
|
||||
|
||||
\App::$page['htmlhead'] .= replace_macros(get_markup_template("build_query.tpl"),array(
|
||||
'$baseurl' => z_root(),
|
||||
'$pgtype' => 'pubstream',
|
||||
@@ -139,7 +141,7 @@ class Pubstream extends \Zotlabs\Web\Controller {
|
||||
'$cats' => '',
|
||||
'$tags' => (($hashtags) ? urlencode($hashtags) : ''),
|
||||
'$dend' => '',
|
||||
'$mid' => (($mid) ? urlencode($mid) : ''),
|
||||
'$mid' => $encoded_mid ?? $mid,
|
||||
'$verb' => '',
|
||||
'$net' => (($net) ? urlencode($net) : ''),
|
||||
'$dbegin' => ''
|
||||
@@ -201,7 +203,7 @@ class Pubstream extends \Zotlabs\Web\Controller {
|
||||
$r = q("SELECT parent AS item_id FROM item
|
||||
left join abook on item.author_xchan = abook.abook_xchan
|
||||
$net_query
|
||||
WHERE item.mid = '%s' and item.item_private = 0
|
||||
WHERE item.$identifier = '%s' and item.item_private = 0
|
||||
$uids $site_firehose_sql
|
||||
$item_normal
|
||||
and (abook.abook_blocked = 0 or abook.abook_flags is null)
|
||||
@@ -228,7 +230,7 @@ class Pubstream extends \Zotlabs\Web\Controller {
|
||||
$r = q("SELECT parent AS item_id FROM item
|
||||
left join abook on item.author_xchan = abook.abook_xchan
|
||||
$net_query
|
||||
WHERE item.mid = '%s' and item.item_private = 0
|
||||
WHERE item.$identifier = '%s' and item.item_private = 0
|
||||
$uids $site_firehose_sql $item_normal_update $simple_update
|
||||
and (abook.abook_blocked = 0 or abook.abook_flags is null)
|
||||
$sql_extra $net_query2",
|
||||
|
||||
@@ -2,82 +2,96 @@
|
||||
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
use App;
|
||||
use Zotlabs\Web\Controller;
|
||||
use Zotlabs\Lib\Activity;
|
||||
use Zotlabs\Daemon\Master;
|
||||
|
||||
class React extends \Zotlabs\Web\Controller {
|
||||
class React extends Controller {
|
||||
|
||||
function get() {
|
||||
|
||||
if(! local_channel())
|
||||
if (!local_channel()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$sys = get_sys_channel();
|
||||
$channel = \App::get_channel();
|
||||
$channel = App::get_channel();
|
||||
|
||||
$postid = $_REQUEST['postid'];
|
||||
|
||||
if(! $postid)
|
||||
if (!$postid) {
|
||||
return;
|
||||
|
||||
$emoji = $_REQUEST['emoji'];
|
||||
|
||||
|
||||
if($_REQUEST['emoji']) {
|
||||
|
||||
$i = q("select * from item where id = %d and uid = %d",
|
||||
intval($postid),
|
||||
intval(local_channel())
|
||||
);
|
||||
|
||||
if(! $i) {
|
||||
$i = q("select * from item where id = %d and uid = %d",
|
||||
intval($postid),
|
||||
intval($sys['channel_id'])
|
||||
);
|
||||
|
||||
if($i) {
|
||||
$i = [ copy_of_pubitem($channel, $i[0]['mid']) ];
|
||||
$postid = (($i) ? $i[0]['id'] : 0);
|
||||
}
|
||||
}
|
||||
|
||||
if(! $i) {
|
||||
return;
|
||||
}
|
||||
|
||||
$uuid = item_message_id();
|
||||
|
||||
$n = array();
|
||||
$n['aid'] = $channel['channel_account_id'];
|
||||
$n['uid'] = $channel['channel_id'];
|
||||
$n['item_origin'] = true;
|
||||
$n['item_type'] = $i[0]['item_type'];
|
||||
$n['parent'] = $postid;
|
||||
$n['parent_mid'] = $i[0]['mid'];
|
||||
$n['uuid'] = $uuid;
|
||||
$n['mid'] = z_root() . '/item/' . $uuid;
|
||||
$n['verb'] = ACTIVITY_REACT . '#' . $emoji;
|
||||
$n['body'] = "\n\n[zmg=32x32]" . z_root() . '/images/emoji/' . $emoji . '.png[/zmg]' . "\n\n";
|
||||
$n['author_xchan'] = $channel['channel_hash'];
|
||||
|
||||
$n['tgt_type'] = 'Image';
|
||||
$n['target'] = [
|
||||
'type' => 'Image',
|
||||
'name' => $emoji,
|
||||
'url' => z_root() . '/images/emoji/' . $emoji . '.png'
|
||||
];
|
||||
|
||||
|
||||
$x = item_store($n);
|
||||
|
||||
retain_item($postid);
|
||||
|
||||
if($x['success']) {
|
||||
$nid = $x['item_id'];
|
||||
\Zotlabs\Daemon\Master::Summon(array('Notifier','like',$nid));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$shortname = $_REQUEST['emoji'];
|
||||
|
||||
$emojis = get_emojis();
|
||||
|
||||
if (!isset($emojis[$shortname])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$emoji = $emojis[$shortname];
|
||||
|
||||
if (!$emoji) {
|
||||
return;
|
||||
}
|
||||
|
||||
$i = q("select * from item where id = %d and uid = %d",
|
||||
intval($postid),
|
||||
intval(local_channel())
|
||||
);
|
||||
|
||||
if (!$i) {
|
||||
$i = q("select * from item where id = %d and uid = %d",
|
||||
intval($postid),
|
||||
intval($sys['channel_id'])
|
||||
);
|
||||
|
||||
if ($i) {
|
||||
$i = [ copy_of_pubitem($channel, $i[0]['mid']) ];
|
||||
$postid = (($i) ? $i[0]['id'] : 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (!$i) {
|
||||
return;
|
||||
}
|
||||
|
||||
$uuid = item_message_id();
|
||||
|
||||
$n['aid'] = $channel['channel_account_id'];
|
||||
$n['uid'] = $channel['channel_id'];
|
||||
$n['item_origin'] = true;
|
||||
$n['item_type'] = $i[0]['item_type'];
|
||||
$n['parent'] = $postid;
|
||||
$n['parent_mid'] = $i[0]['mid'];
|
||||
$n['uuid'] = $uuid;
|
||||
$n['mid'] = z_root() . '/item/' . $uuid;
|
||||
$n['verb'] = 'Create';
|
||||
$n['body'] = $emoji['shortname']; //'[img class="emoji single-emoji"]' . z_root() . '/' . $emoji['filepath'] . '[/img]';
|
||||
$n['author_xchan'] = $channel['channel_hash'];
|
||||
// $n['obj'] = Activity::fetch_item(['id' => $i[0]['mid']]);
|
||||
// $n['obj_type'] = ((array_path_exists('obj/type', $n)) ? $n['obj']['type'] : EMPTY_STR);
|
||||
|
||||
$n['term'][] = [
|
||||
'uid' => $channel['channel_id'],
|
||||
'ttype' => TERM_EMOJI,
|
||||
'otype' => TERM_OBJ_POST,
|
||||
'term' => $emoji['shortname'],
|
||||
'url' => z_root() . '/emoji/' . $shortname,
|
||||
'imgurl' => z_root() . '/' . $emoji['filepath']
|
||||
];
|
||||
|
||||
$x = item_store($n);
|
||||
|
||||
retain_item($postid);
|
||||
|
||||
if ($x['success']) {
|
||||
$nid = $x['item_id'];
|
||||
Master::Summon(['Notifier', 'like', $nid]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,13 +12,13 @@ class Rmagic extends \Zotlabs\Web\Controller {
|
||||
|
||||
$me = get_my_address();
|
||||
if($me) {
|
||||
$r = q("select hubloc_url, hubloc_network from hubloc where hubloc_addr = '%s' and hubloc_deleted = 0",
|
||||
$r = q("select hubloc_url, hubloc_network from hubloc where hubloc_addr = '%s' and hubloc_deleted = 0 order by hubloc_id desc",
|
||||
dbesc($me)
|
||||
);
|
||||
if(! $r) {
|
||||
$w = discover_by_webbie($me);
|
||||
if($w) {
|
||||
$r = q("select hubloc_url, hubloc_network from hubloc where hubloc_addr = '%s' and hubloc_deleted = 0",
|
||||
$r = q("select hubloc_url, hubloc_network from hubloc where hubloc_addr = '%s' and hubloc_deleted = 0 order by hubloc_id desc",
|
||||
dbesc($me)
|
||||
);
|
||||
}
|
||||
@@ -57,13 +57,13 @@ class Rmagic extends \Zotlabs\Web\Controller {
|
||||
|
||||
$r = null;
|
||||
if($address) {
|
||||
$r = q("select hubloc_url, hubloc_network from hubloc where hubloc_addr = '%s' and hubloc_deleted = 0",
|
||||
$r = q("select hubloc_url, hubloc_network from hubloc where hubloc_addr = '%s' and hubloc_deleted = 0 order by hubloc_id desc",
|
||||
dbesc($address)
|
||||
);
|
||||
if(! $r) {
|
||||
$w = discover_by_webbie($address);
|
||||
if($w) {
|
||||
$r = q("select hubloc_url, hubloc_network from hubloc where hubloc_addr = '%s' and hubloc_deleted = 0",
|
||||
$r = q("select hubloc_url, hubloc_network from hubloc where hubloc_addr = '%s' and hubloc_deleted = 0 order by hubloc_id desc",
|
||||
dbesc($address)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
<?php
|
||||
namespace Zotlabs\Module; /** @file */
|
||||
|
||||
use App;
|
||||
use Zotlabs\Lib\Libzot;
|
||||
use Zotlabs\Access\AccessList;
|
||||
|
||||
require_once('include/acl_selectors.php');
|
||||
require_once('include/crypto.php');
|
||||
@@ -43,9 +45,9 @@ class Rpost extends \Zotlabs\Web\Controller {
|
||||
// by the wretched beast called 'suhosin'. All the browsers now allow long GET requests, but suhosin
|
||||
// blocks them.
|
||||
|
||||
$url = Libzot::get_rpost_path(\App::get_observer());
|
||||
$url = Libzot::get_rpost_path(App::get_observer());
|
||||
// make sure we're not looping to our own hub
|
||||
if(($url) && (! stristr($url, \App::get_hostname()))) {
|
||||
if(($url) && (! stristr($url, App::get_hostname()))) {
|
||||
foreach($_GET as $key => $arg) {
|
||||
if($key === 'q')
|
||||
continue;
|
||||
@@ -80,7 +82,10 @@ class Rpost extends \Zotlabs\Web\Controller {
|
||||
'album' => $def_album,
|
||||
'directory' => $def_attach,
|
||||
'flags' => 1, // indicates temporary permissions are created
|
||||
'allow_cid' => '<' . $channel['channel_hash'] . '>'
|
||||
'allow_cid' => '<' . $channel['channel_hash'] . '>',
|
||||
'allow_gid' => '',
|
||||
'deny_cid' => '',
|
||||
'deny_gid' => ''
|
||||
]);
|
||||
|
||||
if (! $r['success']) {
|
||||
@@ -167,18 +172,10 @@ class Rpost extends \Zotlabs\Web\Controller {
|
||||
$_REQUEST['body'] = html2bbcode($_REQUEST['body']);
|
||||
}
|
||||
|
||||
$channel = \App::get_channel();
|
||||
|
||||
if(isset($_REQUEST['acl']) && $_REQUEST['acl']) {
|
||||
$acl = new \Zotlabs\Access\AccessList([]);
|
||||
$acl->set($_REQUEST['acl']);
|
||||
$channel_acl = $acl->get();
|
||||
}
|
||||
else {
|
||||
$acl = new \Zotlabs\Access\AccessList($channel);
|
||||
$channel_acl = $acl->get();
|
||||
}
|
||||
$channel = App::get_channel();
|
||||
|
||||
$acl = new AccessList($channel);
|
||||
$channel_acl = $acl->get();
|
||||
|
||||
if(isset($_REQUEST['url']) && $_REQUEST['url']) {
|
||||
$x = z_fetch_url(z_root() . '/linkinfo?f=&url=' . urlencode($_REQUEST['url']));
|
||||
@@ -209,11 +206,12 @@ class Rpost extends \Zotlabs\Web\Controller {
|
||||
'bbco_autocomplete' => 'bbcode',
|
||||
'editor_autocomplete' => true,
|
||||
'bbcode' => true,
|
||||
'jotnets' => true
|
||||
'jotnets' => true,
|
||||
'reset' => t('Reset form')
|
||||
);
|
||||
|
||||
$a = '';
|
||||
$editor = status_editor($a,$x,false,'Rpost');
|
||||
$editor = status_editor($x, false, 'Rpost');
|
||||
|
||||
$o .= replace_macros(get_markup_template('edpost_head.tpl'), array(
|
||||
'$title' => t('Edit post'),
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user