mirror of
https://framagit.org/hubzilla/core.git
synced 2026-06-21 09:01:15 -04:00
Compare commits
1049 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d95573741d | ||
|
|
faf4bcdd62 | ||
|
|
f699442bec | ||
|
|
8720931a53 | ||
|
|
d60c53cd12 | ||
|
|
6b0fe6e0a0 | ||
|
|
28f1f4cbdc | ||
|
|
508b3ce730 | ||
|
|
87ecc61fb4 | ||
|
|
0f6166da00 | ||
|
|
07e5b8295e | ||
|
|
9afdf86961 | ||
|
|
f4f1974be0 | ||
|
|
6f6399ca0f | ||
|
|
5018c0fbb8 | ||
|
|
188975ccbd | ||
|
|
5e1addc75e | ||
|
|
138beeac41 | ||
|
|
187364d94a | ||
|
|
6e74e76fcd | ||
|
|
615424d272 | ||
|
|
d40a7a609e | ||
|
|
0ec40f00a9 | ||
|
|
de054026f2 | ||
|
|
175b45d1ed | ||
|
|
e236b77817 | ||
|
|
21cd4a1b48 | ||
|
|
e9a50371f5 | ||
|
|
71f8a08e5f | ||
|
|
4419c93d80 | ||
|
|
fcc13ce02c | ||
|
|
941db04260 | ||
|
|
87d7a3053a | ||
|
|
ae11b2c281 | ||
|
|
f43577ec27 | ||
|
|
c648c38fb0 | ||
|
|
34d54fd309 | ||
|
|
891b1428cc | ||
|
|
453dd38e51 | ||
|
|
f59aefd3d9 | ||
|
|
451468d129 | ||
|
|
c0adf31da9 | ||
|
|
bb43c57b07 | ||
|
|
6c94bbc93f | ||
|
|
50422c608f | ||
|
|
7639157a49 | ||
|
|
f74cfaec5f | ||
|
|
d559b4a201 | ||
|
|
2d4064aca4 | ||
|
|
337d8ea78c | ||
|
|
4c0a26dbf9 | ||
|
|
885edd6261 | ||
|
|
011de75706 | ||
|
|
852e456d44 | ||
|
|
18136788e4 | ||
|
|
f1101808b7 | ||
|
|
791d5098a0 | ||
|
|
f2fd12fbe5 | ||
|
|
b5ab77908e | ||
|
|
25620081a1 | ||
|
|
5750e6cada | ||
|
|
394aa76a8f | ||
|
|
35c4deb884 | ||
|
|
0daccead12 | ||
|
|
e7c83a81c7 | ||
|
|
dcf8830752 | ||
|
|
3d519f478a | ||
|
|
3f0fc40ef8 | ||
|
|
820494c7a6 | ||
|
|
60b82d3690 | ||
|
|
57d9b1b332 | ||
|
|
67f8b78a7d | ||
|
|
aada997601 | ||
|
|
e5dd108bd7 | ||
|
|
ad91ab68ce | ||
|
|
66c3c32154 | ||
|
|
c9ce562369 | ||
|
|
a1f01529a7 | ||
|
|
38985dc4e2 | ||
|
|
e74c52094f | ||
|
|
e05f1f95cf | ||
|
|
b63c5f2785 | ||
|
|
685c569eaf | ||
|
|
b6e3469519 | ||
|
|
16071f300e | ||
|
|
a8de999b7c | ||
|
|
0dcbcf93c2 | ||
|
|
06273e980e | ||
|
|
c879e5de44 | ||
|
|
890290fff0 | ||
|
|
cddae14352 | ||
|
|
b3e6a3c1e2 | ||
|
|
255b6a14a8 | ||
|
|
bafbf04164 | ||
|
|
fdefa101d8 | ||
|
|
7e40eeb52a | ||
|
|
e98804693d | ||
|
|
953c294778 | ||
|
|
20d2811cd5 | ||
|
|
207df132e6 | ||
|
|
40e0fe1d25 | ||
|
|
fe3f42ce10 | ||
|
|
b4ca5c133c | ||
|
|
8f1a579597 | ||
|
|
aa69b43e0e | ||
|
|
cadd6fdfff | ||
|
|
85b97014c9 | ||
|
|
50ca95735d | ||
|
|
b55c7f794b | ||
|
|
205279f7f8 | ||
|
|
934721a98d | ||
|
|
d02a8d733e | ||
|
|
d59b81f11d | ||
|
|
b11d2c376b | ||
|
|
6d83b5b68d | ||
|
|
0ad7c8f69e | ||
|
|
e24c769f8e | ||
|
|
7cf9b85a97 | ||
|
|
dd3d65cb1c | ||
|
|
5e19632f2d | ||
|
|
cc543d1ad2 | ||
|
|
35299ed7c3 | ||
|
|
7008cf3269 | ||
|
|
6979ea44f4 | ||
|
|
81775eebe2 | ||
|
|
e70802c6ad | ||
|
|
7112bcd134 | ||
|
|
d3d5ddfb43 | ||
|
|
5580fc1954 | ||
|
|
d0e85f05af | ||
|
|
c136741db6 | ||
|
|
5724be1f8e | ||
|
|
29e89d1152 | ||
|
|
95dfde99c6 | ||
|
|
59fd3861a7 | ||
|
|
69d627a58b | ||
|
|
2772c33563 | ||
|
|
78f655f877 | ||
|
|
75a73be60c | ||
|
|
690874fc6e | ||
|
|
96de38a1f0 | ||
|
|
cef0c2ebb2 | ||
|
|
5e0f5460f2 | ||
|
|
ff8c9cfd14 | ||
|
|
b5b033fe22 | ||
|
|
5dc2f43d1d | ||
|
|
f0acb9f01e | ||
|
|
b6ca9b6020 | ||
|
|
9c6446edbe | ||
|
|
d84f0030be | ||
|
|
61f554e0d7 | ||
|
|
3b252d98b8 | ||
|
|
f5315ed6a2 | ||
|
|
c1f36802a1 | ||
|
|
ba0f24bf70 | ||
|
|
522b92128f | ||
|
|
ea77043aaf | ||
|
|
91dd877c2d | ||
|
|
e2e160b8e8 | ||
|
|
89c74868aa | ||
|
|
45a5a04189 | ||
|
|
1f41b1837f | ||
|
|
c01e1b6c33 | ||
|
|
08e7c7b249 | ||
|
|
b103993ad1 | ||
|
|
e12f375624 | ||
|
|
8cd67a5d4a | ||
|
|
31e030af69 | ||
|
|
375986437a | ||
|
|
5f93157d5a | ||
|
|
8d3c201830 | ||
|
|
612ef90523 | ||
|
|
e64856e957 | ||
|
|
8595835aa0 | ||
|
|
4d2507263d | ||
|
|
4a671fe634 | ||
|
|
ed845d93bc | ||
|
|
595f3d99b4 | ||
|
|
1e2d5b0c77 | ||
|
|
1215618589 | ||
|
|
67533ee478 | ||
|
|
3acd5dcc07 | ||
|
|
c387902a44 | ||
|
|
ad51be7dd9 | ||
|
|
3514f805ea | ||
|
|
2690159f09 | ||
|
|
902151918c | ||
|
|
5dd1ea21af | ||
|
|
b37c8bf928 | ||
|
|
923ae14c47 | ||
|
|
7ec6550734 | ||
|
|
e622802c24 | ||
|
|
244c8edfca | ||
|
|
245c0c22cd | ||
|
|
93b90ab23a | ||
|
|
765f9ffcf0 | ||
|
|
bdfdd515d8 | ||
|
|
72c6d3e7ba | ||
|
|
869ce64f87 | ||
|
|
86117c8859 | ||
|
|
96c4c72ee3 | ||
|
|
4b0d32eb14 | ||
|
|
1d705b9805 | ||
|
|
8605aee533 | ||
|
|
e4de9ef903 | ||
|
|
e529635952 | ||
|
|
21b71401d3 | ||
|
|
80bdcbb3e6 | ||
|
|
b878b69028 | ||
|
|
48440e368c | ||
|
|
a7bf07b864 | ||
|
|
a80e59812b | ||
|
|
3f784a974a | ||
|
|
5ce3565109 | ||
|
|
b25054e891 | ||
|
|
2c316c788e | ||
|
|
2fe2cc5e65 | ||
|
|
5d6a7922c1 | ||
|
|
d23e830955 | ||
|
|
762de94900 | ||
|
|
d938c79385 | ||
|
|
987a369fec | ||
|
|
586e2ef2df | ||
|
|
5edec37d57 | ||
|
|
42ef6208c1 | ||
|
|
6f508b81d6 | ||
|
|
81e2f73c98 | ||
|
|
be43d3e0fd | ||
|
|
60fd27eca4 | ||
|
|
ca4a3c3cc0 | ||
|
|
dfad87f674 | ||
|
|
743e575701 | ||
|
|
be627c3f3a | ||
|
|
80fdf53cc3 | ||
|
|
759f297aae | ||
|
|
1a41c44c2f | ||
|
|
88b014e9a7 | ||
|
|
bd0b8d768e | ||
|
|
f422362747 | ||
|
|
34217f5f90 | ||
|
|
56e503149d | ||
|
|
04af502e3a | ||
|
|
f2c1fd2a48 | ||
|
|
a86fd554a3 | ||
|
|
ef0a8bcde0 | ||
|
|
c38fc0b906 | ||
|
|
2758d3c3eb | ||
|
|
521a5074c9 | ||
|
|
430c48e828 | ||
|
|
2e747bec6f | ||
|
|
d945789e1b | ||
|
|
de306cd7b8 | ||
|
|
aedde6600e | ||
|
|
9c8d732081 | ||
|
|
5d1e10522f | ||
|
|
ba0410dd24 | ||
|
|
da44cef9a3 | ||
|
|
e9227b0ffe | ||
|
|
9299aff2af | ||
|
|
a9377d6a3f | ||
|
|
b223b71d0d | ||
|
|
02cf85fa34 | ||
|
|
76a6e0b6fc | ||
|
|
2a2f032f17 | ||
|
|
e7ddd1a481 | ||
|
|
813ab2c5ed | ||
|
|
4acdf9e817 | ||
|
|
465da3a942 | ||
|
|
fb601cc280 | ||
|
|
25b9776bf6 | ||
|
|
5271232aa5 | ||
|
|
7fa70108c4 | ||
|
|
ff09b2131e | ||
|
|
df758f40ef | ||
|
|
1d8dd949dc | ||
|
|
9dd333a2f4 | ||
|
|
d53b3b242d | ||
|
|
8e0e4b7b92 | ||
|
|
adee24af6f | ||
|
|
1b161b0ee4 | ||
|
|
5aaa8f44a2 | ||
|
|
1fbc6fa431 | ||
|
|
6177ec9134 | ||
|
|
bd4867ef39 | ||
|
|
0189d06375 | ||
|
|
aafdeb9000 | ||
|
|
e9a264cb43 | ||
|
|
b996d82c5f | ||
|
|
c53794a8a2 | ||
|
|
170b2e4465 | ||
|
|
4e0fc81e5d | ||
|
|
3b865d432f | ||
|
|
646dce7765 | ||
|
|
88a68f96da | ||
|
|
32bdf42913 | ||
|
|
53a010d1d4 | ||
|
|
a9e19cb89e | ||
|
|
4878611987 | ||
|
|
2c777acb25 | ||
|
|
49df57df45 | ||
|
|
374c30999a | ||
|
|
2ab480188a | ||
|
|
c4c47f7777 | ||
|
|
c36b2ca915 | ||
|
|
e55a1a6aa8 | ||
|
|
21e5b05b14 | ||
|
|
ea845aeacd | ||
|
|
ee3b077f26 | ||
|
|
393cee6619 | ||
|
|
d9196bb82a | ||
|
|
5ecbbfc7df | ||
|
|
9244ee8094 | ||
|
|
0b7ca61958 | ||
|
|
c56b140387 | ||
|
|
3e7d3a20af | ||
|
|
2d2cab0aba | ||
|
|
364346b07c | ||
|
|
be15a395d8 | ||
|
|
845f7e9382 | ||
|
|
976d6baf6a | ||
|
|
f9271bb0bd | ||
|
|
06f03eb13a | ||
|
|
1a1c0ca72c | ||
|
|
73f2db09ae | ||
|
|
be533679dd | ||
|
|
e31903cbc9 | ||
|
|
33d417955d | ||
|
|
9f0f794a0a | ||
|
|
33e4d7c0d8 | ||
|
|
ad30834123 | ||
|
|
fba64e9451 | ||
|
|
9b5e270379 | ||
|
|
ea5131db88 | ||
|
|
7ae86d29d2 | ||
|
|
13ff9a897d | ||
|
|
4db38ec64a | ||
|
|
29c5a65e8f | ||
|
|
dd2ffae8bf | ||
|
|
ca969cd0ed | ||
|
|
4f95b44ff2 | ||
|
|
cb7aec0da5 | ||
|
|
62eebc86f6 | ||
|
|
5ea7196e78 | ||
|
|
fcc47e69e4 | ||
|
|
d2f1c37431 | ||
|
|
817fe8d485 | ||
|
|
1dbd85322d | ||
|
|
fe90096ace | ||
|
|
ad60309187 | ||
|
|
634a515ec1 | ||
|
|
01abb82c37 | ||
|
|
1c88a8d4a0 | ||
|
|
ce77f82966 | ||
|
|
573af9e366 | ||
|
|
774cc852d4 | ||
|
|
c0735a5ca2 | ||
|
|
fa752b0ac1 | ||
|
|
3f69fc70f1 | ||
|
|
137f56f994 | ||
|
|
e2cbcf7039 | ||
|
|
64f8df0a0d | ||
|
|
274d556ec1 | ||
|
|
f28c3b441e | ||
|
|
4eaa893e0b | ||
|
|
36e969fd79 | ||
|
|
d8f16960c8 | ||
|
|
101a7648ee | ||
|
|
70a104f24f | ||
|
|
0f27db6271 | ||
|
|
56ec55110a | ||
|
|
570497071d | ||
|
|
49dee6312f | ||
|
|
63a6b4a162 | ||
|
|
ec4dea0920 | ||
|
|
7270da6a28 | ||
|
|
8cd66145bd | ||
|
|
92ee27349c | ||
|
|
a88233a045 | ||
|
|
0259130cf3 | ||
|
|
d0a1f0b8f9 | ||
|
|
97dd350c61 | ||
|
|
dc3b09c8f3 | ||
|
|
c8c4513af9 | ||
|
|
3201a4bec5 | ||
|
|
9da8e30c37 | ||
|
|
6bfac1a907 | ||
|
|
d0c7c99d5e | ||
|
|
934bcf5336 | ||
|
|
5b88873530 | ||
|
|
b161b02c51 | ||
|
|
ddc544e00a | ||
|
|
97d5ffe056 | ||
|
|
13319985fd | ||
|
|
e3aaa39f9e | ||
|
|
b6efb02ed2 | ||
|
|
c358d8326e | ||
|
|
f40fedcad6 | ||
|
|
b4973ede44 | ||
|
|
81338e8086 | ||
|
|
4270e17bc4 | ||
|
|
1329662edc | ||
|
|
249427365b | ||
|
|
326644104c | ||
|
|
1520a26e0f | ||
|
|
6ffdc1b642 | ||
|
|
22d8523e76 | ||
|
|
2d3740b912 | ||
|
|
c8ab5db768 | ||
|
|
c656478230 | ||
|
|
3d02758fee | ||
|
|
f473b5abfb | ||
|
|
22d68ddf08 | ||
|
|
2cba88f1eb | ||
|
|
f132436af3 | ||
|
|
fae70bf0a7 | ||
|
|
ffd2faf8a0 | ||
|
|
64a8913385 | ||
|
|
266dcd44bb | ||
|
|
8851921d6d | ||
|
|
c76ff4249e | ||
|
|
dbfe748d27 | ||
|
|
4ee809bed6 | ||
|
|
4ebf6cda5d | ||
|
|
a04b6d178b | ||
|
|
c8b45c3449 | ||
|
|
1bb74a5a01 | ||
|
|
ef94072cee | ||
|
|
ff3ff2478d | ||
|
|
2757822cd8 | ||
|
|
2cb0cade7b | ||
|
|
191e01e3ec | ||
|
|
8c65e9cb4a | ||
|
|
79968ea07a | ||
|
|
7a0d9a4494 | ||
|
|
06d1cf83d2 | ||
|
|
de058901c2 | ||
|
|
a40b882d72 | ||
|
|
46242aeaae | ||
|
|
ad040a0b11 | ||
|
|
4eaba326ce | ||
|
|
fd48f9d173 | ||
|
|
104c45f6e6 | ||
|
|
f4a71db42d | ||
|
|
1ac2b93fd8 | ||
|
|
03c1419ad0 | ||
|
|
18938280f5 | ||
|
|
01334d761a | ||
|
|
446204f7d8 | ||
|
|
328900cf3b | ||
|
|
837dbb7a14 | ||
|
|
c9794439bc | ||
|
|
079c13e633 | ||
|
|
7b8c85cf3f | ||
|
|
c229f058b4 | ||
|
|
e2b10f52e0 | ||
|
|
2b8afd5580 | ||
|
|
7e89d816d7 | ||
|
|
77c87bcccf | ||
|
|
b7a655917e | ||
|
|
d8bfa5dd96 | ||
|
|
88eb19165b | ||
|
|
2828b8cf5c | ||
|
|
b1b9dbe55f | ||
|
|
579adb4897 | ||
|
|
a9d52cd296 | ||
|
|
c71422e909 | ||
|
|
03506bd6cf | ||
|
|
244936b0fd | ||
|
|
f430a24fa3 | ||
|
|
ecb1c78173 | ||
|
|
42631b5943 | ||
|
|
109f9eed61 | ||
|
|
c7fdc53795 | ||
|
|
602ca91700 | ||
|
|
4cfc0b1a64 | ||
|
|
3d5fdd086b | ||
|
|
223c4c7b9a | ||
|
|
f7e925beaa | ||
|
|
e588ea8a8b | ||
|
|
91cad21d33 | ||
|
|
d6b9c8b93d | ||
|
|
a7273668d8 | ||
|
|
b1f74f4ef4 | ||
|
|
c640d1c599 | ||
|
|
9d0f71bfcb | ||
|
|
bbca6be0f9 | ||
|
|
31e1e9cbfb | ||
|
|
6de823b532 | ||
|
|
69878ed628 | ||
|
|
27ae9c9d34 | ||
|
|
52e698cae6 | ||
|
|
6a0ac591d1 | ||
|
|
328685d2fb | ||
|
|
806c738923 | ||
|
|
9c2d48bcd4 | ||
|
|
d8802e4fc8 | ||
|
|
2c8a243ece | ||
|
|
3372fb0761 | ||
|
|
af7a31cd14 | ||
|
|
cb2996a40c | ||
|
|
ea237a97a1 | ||
|
|
530b1d038f | ||
|
|
a31981966e | ||
|
|
84183d9f7e | ||
|
|
805f8bf983 | ||
|
|
67c9b5d049 | ||
|
|
44b935f875 | ||
|
|
cade25a112 | ||
|
|
a4831b0f7c | ||
|
|
ec9418b262 | ||
|
|
cec2e92fe3 | ||
|
|
625438ff64 | ||
|
|
6cfaa5cba3 | ||
|
|
31fea1014e | ||
|
|
898fea1e0e | ||
|
|
4b3979df04 | ||
|
|
ac52bebb88 | ||
|
|
c568f7b8d1 | ||
|
|
d925ec6759 | ||
|
|
c136c142b8 | ||
|
|
38be2386dd | ||
|
|
643b2f9205 | ||
|
|
ffe429be65 | ||
|
|
4a56b77f64 | ||
|
|
9773ab7aab | ||
|
|
6c02fa40f1 | ||
|
|
632996f53e | ||
|
|
710448e73f | ||
|
|
084177a20c | ||
|
|
5a2c62466e | ||
|
|
b739f91caa | ||
|
|
b1590ad645 | ||
|
|
f49010bb12 | ||
|
|
6e1c3b6d48 | ||
|
|
bcdd75b817 | ||
|
|
0271f2a1ae | ||
|
|
0c1c386a0a | ||
|
|
a3acec9674 | ||
|
|
4eaddd1279 | ||
|
|
eb3dbcce7b | ||
|
|
3ecf1cab5e | ||
|
|
c536526196 | ||
|
|
b2de12442d | ||
|
|
8f5cb0c45a | ||
|
|
3b4503c971 | ||
|
|
c358aa2806 | ||
|
|
938d26ba3e | ||
|
|
b23751128b | ||
|
|
d54ff4fae5 | ||
|
|
720d3dcedc | ||
|
|
ce4fc30439 | ||
|
|
b39474456f | ||
|
|
25cd9b4983 | ||
|
|
2d65ce542c | ||
|
|
c2b691fd01 | ||
|
|
ae691bdc7c | ||
|
|
ba566fd64b | ||
|
|
85c07d57fe | ||
|
|
16fd618380 | ||
|
|
06f2979e04 | ||
|
|
1ff9d1afdd | ||
|
|
a776f69a59 | ||
|
|
a574290235 | ||
|
|
84c9ae04fc | ||
|
|
c74c41c3b8 | ||
|
|
7cf73e0533 | ||
|
|
03e9ed71b4 | ||
|
|
e7e79f7423 | ||
|
|
589af1f9ee | ||
|
|
e7f25b8466 | ||
|
|
2100441b54 | ||
|
|
082826ee44 | ||
|
|
93ad3eb6f1 | ||
|
|
177209b5e9 | ||
|
|
47d80df81c | ||
|
|
3d6fa049da | ||
|
|
16738dfe7f | ||
|
|
c28ba4be37 | ||
|
|
8bcdc24fcb | ||
|
|
b36eb9a91c | ||
|
|
989fbe70cd | ||
|
|
85cf25a2a8 | ||
|
|
7bb94f9993 | ||
|
|
1297c8d2ae | ||
|
|
ed28ef185e | ||
|
|
9d97cc2a1d | ||
|
|
23acf02d58 | ||
|
|
60311eb04b | ||
|
|
b9a8b9e47b | ||
|
|
b7bac45427 | ||
|
|
7d05b8e5fd | ||
|
|
d5ae9aedc4 | ||
|
|
1b216e6019 | ||
|
|
83256c9ccd | ||
|
|
9f029336ca | ||
|
|
95476cf33c | ||
|
|
bf7c96807a | ||
|
|
d4a6aa7801 | ||
|
|
b767bda410 | ||
|
|
a39d436f9f | ||
|
|
50dbe1e62d | ||
|
|
be81a40b2b | ||
|
|
bbcb237f5b | ||
|
|
33be244d8a | ||
|
|
ca75619518 | ||
|
|
82acfb75a1 | ||
|
|
fc9e6d289a | ||
|
|
6838342d62 | ||
|
|
69b25e490e | ||
|
|
b8d7647c48 | ||
|
|
989443a569 | ||
|
|
c50a311ff3 | ||
|
|
b37e5a426a | ||
|
|
5e76318e44 | ||
|
|
8ed3971ef0 | ||
|
|
c2b6f0bc28 | ||
|
|
2c42daf609 | ||
|
|
8e2446a2fc | ||
|
|
19bb9e0181 | ||
|
|
e9b2dacb61 | ||
|
|
3df5d854b8 | ||
|
|
9545a81166 | ||
|
|
1712eceaf9 | ||
|
|
7d8c6cb9ed | ||
|
|
f123809d29 | ||
|
|
7abcdd34af | ||
|
|
ead56c59e2 | ||
|
|
19a8dfaa5c | ||
|
|
fa45ea1d84 | ||
|
|
8789edb65d | ||
|
|
b6abc034cf | ||
|
|
c92ea70453 | ||
|
|
07eee20525 | ||
|
|
6c9130be46 | ||
|
|
51f00cda92 | ||
|
|
7973567a7c | ||
|
|
b81b18814e | ||
|
|
bbfe71b0c6 | ||
|
|
7404183830 | ||
|
|
43aea3ce38 | ||
|
|
cbaf4b7536 | ||
|
|
570d84c031 | ||
|
|
9eeccc087d | ||
|
|
7404a8ec1a | ||
|
|
bfae86bdb6 | ||
|
|
66f6a1d186 | ||
|
|
17a4aa983e | ||
|
|
2a0a06d74a | ||
|
|
ccaa93655a | ||
|
|
65bc363685 | ||
|
|
293d411efb | ||
|
|
2a287e6def | ||
|
|
d96f4340e8 | ||
|
|
d3cbbe029c | ||
|
|
a1ccacb825 | ||
|
|
b04915161b | ||
|
|
8cb968c4b0 | ||
|
|
f645c6f3a5 | ||
|
|
4c1c690816 | ||
|
|
537a7cf03d | ||
|
|
662e8f8a4c | ||
|
|
7397348b9c | ||
|
|
5c43013692 | ||
|
|
908875a052 | ||
|
|
41ce2da080 | ||
|
|
6add6ce79b | ||
|
|
0fe9c029ab | ||
|
|
a6522b34c7 | ||
|
|
229f99fe6b | ||
|
|
bdc269d445 | ||
|
|
ff63132a32 | ||
|
|
e7fb22edc1 | ||
|
|
3c59303b68 | ||
|
|
fb4504c5a3 | ||
|
|
db22578c16 | ||
|
|
300727b8cf | ||
|
|
448fb14fc4 | ||
|
|
c42e8613e5 | ||
|
|
12de30a2b1 | ||
|
|
6f93d9848c | ||
|
|
3d019fa2dd | ||
|
|
d5aeb13601 | ||
|
|
230f7ab6d4 | ||
|
|
d71dd21abc | ||
|
|
0d00b72569 | ||
|
|
00f6deb9bd | ||
|
|
cce5054aec | ||
|
|
544ef3bc58 | ||
|
|
124cc43962 | ||
|
|
4237dd457e | ||
|
|
88ebbd90d8 | ||
|
|
298acb9645 | ||
|
|
c4f4edd743 | ||
|
|
258a4e5627 | ||
|
|
e1400e5745 | ||
|
|
593688d539 | ||
|
|
aed6823051 | ||
|
|
96f9e51546 | ||
|
|
161ea6d51f | ||
|
|
88e755037b | ||
|
|
cde706748a | ||
|
|
3e833a5bcd | ||
|
|
475a39ff90 | ||
|
|
2dd2b755f1 | ||
|
|
a6516341c5 | ||
|
|
9a70c3c275 | ||
|
|
5998445841 | ||
|
|
d9c39d0c41 | ||
|
|
4038b78377 | ||
|
|
dce8516da4 | ||
|
|
bde429cff6 | ||
|
|
4c8d33d1eb | ||
|
|
fac7826efa | ||
|
|
d439dee736 | ||
|
|
295c08fcf3 | ||
|
|
efa11cbc74 | ||
|
|
4a8e222763 | ||
|
|
75b9c7d6b8 | ||
|
|
d1648fb258 | ||
|
|
34cda095fe | ||
|
|
dad7bc82c3 | ||
|
|
0ee65ee954 | ||
|
|
ae0780fe3f | ||
|
|
d2a65ab1be | ||
|
|
f4516826ef | ||
|
|
b894380f86 | ||
|
|
b48a9d3f75 | ||
|
|
21b398252a | ||
|
|
80e03268fd | ||
|
|
135b3cf1ef | ||
|
|
b9e083da61 | ||
|
|
74aa446190 | ||
|
|
0d7548a381 | ||
|
|
428b2cca21 | ||
|
|
28a316f73f | ||
|
|
0532d639c2 | ||
|
|
c17717c5db | ||
|
|
8b00913579 | ||
|
|
cf95c4878d | ||
|
|
4958e3b42c | ||
|
|
cc3edeb6f5 | ||
|
|
20c296ce53 | ||
|
|
5ccbcb44f7 | ||
|
|
adcf28af7c | ||
|
|
5b206cd4a7 | ||
|
|
1eb70b66d8 | ||
|
|
3c1ff1fc63 | ||
|
|
d711f2ad4c | ||
|
|
ae8a1c992a | ||
|
|
580d3db5a8 | ||
|
|
042cc96968 | ||
|
|
d177043c9f | ||
|
|
4c1e2c2dd8 | ||
|
|
7dcb0cc11b | ||
|
|
837d9a4df0 | ||
|
|
ec1d5ead93 | ||
|
|
f485ed174d | ||
|
|
e8560d56f5 | ||
|
|
3a937fb969 | ||
|
|
c1aa96ebf7 | ||
|
|
17e012afc6 | ||
|
|
1c6796f907 | ||
|
|
3e133bbfa3 | ||
|
|
6c8d1bdffe | ||
|
|
59fc495593 | ||
|
|
60827bdcc4 | ||
|
|
f2c73c0f45 | ||
|
|
78492d0037 | ||
|
|
2b08519f5a | ||
|
|
c86b35da70 | ||
|
|
b2003e2c3c | ||
|
|
8a08cceccb | ||
|
|
9284b60a79 | ||
|
|
b69f8a3f29 | ||
|
|
8ea7c08f43 | ||
|
|
78197aa625 | ||
|
|
f992feb71c | ||
|
|
fcb065bcb2 | ||
|
|
cf66e66db8 | ||
|
|
63aa3948e5 | ||
|
|
3940fa5659 | ||
|
|
7899ed6f69 | ||
|
|
5e44239657 | ||
|
|
697fbf33c5 | ||
|
|
901785663e | ||
|
|
9e4ff8ce25 | ||
|
|
5f1b2b4bf7 | ||
|
|
271d280c91 | ||
|
|
8f708fef9c | ||
|
|
38de059156 | ||
|
|
f0b40ac15e | ||
|
|
5c47c9ed95 | ||
|
|
dafac11aaa | ||
|
|
1fc81457a1 | ||
|
|
0d47bb6878 | ||
|
|
17cd452fff | ||
|
|
f6f7e7e8d2 | ||
|
|
004861fbb7 | ||
|
|
483d450af4 | ||
|
|
decc14c324 | ||
|
|
1134be8d30 | ||
|
|
fb65c54123 | ||
|
|
fe803135d8 | ||
|
|
908ebed9fd | ||
|
|
bdb6b0d237 | ||
|
|
73a0866ac4 | ||
|
|
e6b1b20565 | ||
|
|
e40ea62c7c | ||
|
|
7864579b1e | ||
|
|
b62eb665c5 | ||
|
|
c72716eca7 | ||
|
|
530d816df6 | ||
|
|
23c47f78ea | ||
|
|
8727f12b18 | ||
|
|
4a4c43bb2c | ||
|
|
0159b631fc | ||
|
|
e74361c4db | ||
|
|
21299c6fc1 | ||
|
|
eec42d3bb3 | ||
|
|
bd049eddd4 | ||
|
|
e762347080 | ||
|
|
53ad04cdc4 | ||
|
|
148c3f9dc5 | ||
|
|
6f1188f44f | ||
|
|
78868314a7 | ||
|
|
dc2f293089 | ||
|
|
c7a0526428 | ||
|
|
498c021aec | ||
|
|
5ee133843f | ||
|
|
9ad2902add | ||
|
|
ef75d27afb | ||
|
|
965c51c2d4 | ||
|
|
05604e4bd2 | ||
|
|
fd7d497cd1 | ||
|
|
a974d0d52d | ||
|
|
5a6b14f878 | ||
|
|
de9a7f0fa9 | ||
|
|
3009c88d24 | ||
|
|
c850a61a89 | ||
|
|
f3fa2d853a | ||
|
|
a982aecd5b | ||
|
|
52bd27a028 | ||
|
|
e5e16da8cb | ||
|
|
3a2fdec241 | ||
|
|
b0adb70ffc | ||
|
|
2f4c619d51 | ||
|
|
6e36820b1b | ||
|
|
209d06a8f7 | ||
|
|
4a6d050e22 | ||
|
|
b033597ada | ||
|
|
08b804cd2d | ||
|
|
89342ca9fb | ||
|
|
892f4b4182 | ||
|
|
de7891771d | ||
|
|
602768209b | ||
|
|
73b1f8fcdd | ||
|
|
e1b923ab7d | ||
|
|
bed9876d68 | ||
|
|
d184e2708f | ||
|
|
580c3f4ffe | ||
|
|
158b8aea38 | ||
|
|
d22766f458 | ||
|
|
70391243dc | ||
|
|
61eef68ff3 | ||
|
|
41cc2854c5 | ||
|
|
ec68ede79f | ||
|
|
478014f02a | ||
|
|
aff7c2d771 | ||
|
|
00dd52317a | ||
|
|
17522b31e9 | ||
|
|
163b1ee9f8 | ||
|
|
7b9a992f83 | ||
|
|
4efb258671 | ||
|
|
7532358806 | ||
|
|
13c05e7937 | ||
|
|
c6e9bca76c | ||
|
|
3706afbd01 | ||
|
|
bcd0802ea4 | ||
|
|
9360148829 | ||
|
|
a6165c00ce | ||
|
|
a5826fec25 | ||
|
|
839c6668cf | ||
|
|
e9a9fc5050 | ||
|
|
426668cd2e | ||
|
|
926d7c56a6 | ||
|
|
9934dbfe69 | ||
|
|
b6314c109d | ||
|
|
f8955f90b8 | ||
|
|
9248fc96b3 | ||
|
|
2875ee2423 | ||
|
|
36f707b25e | ||
|
|
2a05bd9ed6 | ||
|
|
b7db9944ec | ||
|
|
86f7d08483 | ||
|
|
1358a81c32 | ||
|
|
09ad48c12b | ||
|
|
aa137fb2d2 | ||
|
|
09284d512d | ||
|
|
02fd7e51ff | ||
|
|
b359b89aa1 | ||
|
|
873b20677e | ||
|
|
a049664219 | ||
|
|
64c6e25896 | ||
|
|
9f9122ab8e | ||
|
|
d0661cd4a3 | ||
|
|
707b19dc35 | ||
|
|
6fd15d66a7 | ||
|
|
8c9a814e18 | ||
|
|
74ef5f38e9 | ||
|
|
624a3ee1a7 | ||
|
|
fc658a25d7 | ||
|
|
308619a726 | ||
|
|
e87d8d9856 | ||
|
|
7594264725 | ||
|
|
69533ce8f5 | ||
|
|
9fac43a3a3 | ||
|
|
b00db39739 | ||
|
|
6f2a584279 | ||
|
|
de717268f7 | ||
|
|
e27b19c756 | ||
|
|
045cb461f1 | ||
|
|
088c0eedc6 | ||
|
|
e5137b03fc | ||
|
|
76d34a4d74 | ||
|
|
ae4f0e5728 | ||
|
|
5df59027ad | ||
|
|
c888e33f04 | ||
|
|
1a56ecaa39 | ||
|
|
d778c3cf19 | ||
|
|
8bf57c6226 | ||
|
|
3c762b8809 | ||
|
|
3561fd7c43 | ||
|
|
66bfc0ec64 | ||
|
|
7d0e576e3b | ||
|
|
aa330bc8c7 | ||
|
|
b4de492e0d | ||
|
|
5bf3114e6f | ||
|
|
d2b1a2e5a3 | ||
|
|
4b01f6359b | ||
|
|
bcfa62f45a | ||
|
|
e7e8a2ca5f | ||
|
|
5edeb0250b | ||
|
|
0c2657df78 | ||
|
|
e4c57e8031 | ||
|
|
6a25548097 | ||
|
|
db7cbdfc44 | ||
|
|
2f26badb84 | ||
|
|
f7e665c42f | ||
|
|
3bc44ee451 | ||
|
|
125de855ef | ||
|
|
3881ebcce0 | ||
|
|
bef5324fea | ||
|
|
c2655370e0 | ||
|
|
d017e34795 | ||
|
|
aa44da35ba | ||
|
|
5c4c6e68f6 | ||
|
|
a435363b94 | ||
|
|
d6634eb14e | ||
|
|
afee2cf71a | ||
|
|
79b0a6ba9c | ||
|
|
0c2438b36a | ||
|
|
d6da46f94b | ||
|
|
562e39c9c5 | ||
|
|
2d08e0955a | ||
|
|
baffa969d3 | ||
|
|
1fbc8739b9 | ||
|
|
b9dec84489 | ||
|
|
6feb864c38 | ||
|
|
b6db1898b1 | ||
|
|
de902d179e | ||
|
|
58b77e3427 | ||
|
|
cdcac86256 | ||
|
|
79b05e48e8 | ||
|
|
541146e8ce | ||
|
|
97b161c536 | ||
|
|
ba3a6ecb52 | ||
|
|
cf27b7440d | ||
|
|
407b9c9cd7 | ||
|
|
d0055310ba | ||
|
|
02f5fa32af | ||
|
|
b6590e95b5 | ||
|
|
ec65211d54 | ||
|
|
8dfa08f146 | ||
|
|
daef2d0546 | ||
|
|
15eaa80301 | ||
|
|
1e924a8530 | ||
|
|
23995ccb07 | ||
|
|
a4f2603454 | ||
|
|
cc860b4a76 | ||
|
|
0be82602ce | ||
|
|
b42c42692e | ||
|
|
7fcbff3ceb | ||
|
|
efec0af394 | ||
|
|
aafecd9d1e | ||
|
|
e37c43ea06 | ||
|
|
3fac7b5bb7 | ||
|
|
9b90114d03 | ||
|
|
7c5cfe6697 | ||
|
|
d1fd69337f | ||
|
|
3fc218111a | ||
|
|
c63fb0fc6b | ||
|
|
6fe4ac241d | ||
|
|
c385b80807 | ||
|
|
97f36fa46f | ||
|
|
856d4b39d1 | ||
|
|
01abd73a2a | ||
|
|
375c2a87c7 | ||
|
|
6ca507f8dd | ||
|
|
86b4a53858 | ||
|
|
8959ba9b82 | ||
|
|
a62a230d3d | ||
|
|
cc45129e9f | ||
|
|
bffc9d5aba | ||
|
|
f2b121cd58 | ||
|
|
fd30be7644 | ||
|
|
d9052c7e3c | ||
|
|
dcfe10b691 | ||
|
|
914a096b42 | ||
|
|
5fa9dcbc7e | ||
|
|
93ec01e0a1 | ||
|
|
bbc98db6b4 | ||
|
|
1f8d29a221 | ||
|
|
d267dd2515 | ||
|
|
51954c7f3d | ||
|
|
df842a8e8d | ||
|
|
60919488f1 | ||
|
|
4dbaaa63bb | ||
|
|
8cc4003837 | ||
|
|
35790c584b | ||
|
|
09d7cf2cc1 | ||
|
|
58d7c7f6ae | ||
|
|
cab24836d8 | ||
|
|
cf9ef615c9 | ||
|
|
8c96032b2b | ||
|
|
d256551907 | ||
|
|
e800e2db2b | ||
|
|
cc9f41df5f | ||
|
|
bb3784d8dd | ||
|
|
e5539c0d01 | ||
|
|
c997360b4a | ||
|
|
ea8621d6ec | ||
|
|
88fa18204f | ||
|
|
ac05a2ede7 | ||
|
|
808baf203d | ||
|
|
beeafc6bc5 | ||
|
|
6f8c977e73 | ||
|
|
9a2fbdde20 | ||
|
|
b325b2c003 | ||
|
|
feda23587c |
@@ -1,8 +1,7 @@
|
||||
# Select image from https://hub.docker.com/_/php/
|
||||
#image: php:7.2
|
||||
#image: php:7.3
|
||||
# Use a prepared Hubzilla image to optimise pipeline duration
|
||||
image: registry.gitlab.com/dawnbreak/hubzilla/core:php7.2
|
||||
|
||||
image: registry.gitlab.com/dawnbreak/hubzilla/core:php7.3
|
||||
|
||||
stages:
|
||||
- test
|
||||
@@ -41,7 +40,8 @@ before_script:
|
||||
- curl -sS https://getcomposer.org/installer | php
|
||||
# Install dev libraries from composer
|
||||
- php ./composer.phar install --no-progress
|
||||
|
||||
# php.ini settings
|
||||
- echo 'xdebug.mode=coverage' >> /usr/local/etc/php/php.ini
|
||||
|
||||
# hidden job definition with template for MySQL/MariaDB
|
||||
.job_template_mysql: &job_definition_mysql
|
||||
@@ -82,23 +82,23 @@ before_script:
|
||||
- tests/results/
|
||||
|
||||
|
||||
# PHP7.2 with MySQL 5.7
|
||||
php7.2_mysql5.7:
|
||||
# PHP7.3 with MySQL 5.7
|
||||
php7.3_mysql5.7:
|
||||
<<: *job_definition_mysql
|
||||
services:
|
||||
- mysql:5.7
|
||||
|
||||
|
||||
# PHP7.2 with MySQL 8 (latest)
|
||||
php7.2_mysql8:
|
||||
# PHP7.3 with MySQL 8 (latest)
|
||||
php7.3_mysql8:
|
||||
<<: *job_definition_mysql
|
||||
services:
|
||||
- name: mysql:8
|
||||
command: ["--default-authentication-plugin=mysql_native_password"]
|
||||
|
||||
|
||||
# PHP7.2 with MariaDB 10.2
|
||||
php7.2_mariadb10.2:
|
||||
# PHP7.3 with MariaDB 10.2
|
||||
php7.3_mariadb10.2:
|
||||
<<: *job_definition_mysql
|
||||
services:
|
||||
- name: mariadb:10.2
|
||||
@@ -114,8 +114,8 @@ php7.3_mariadb10.3:
|
||||
alias: mysql
|
||||
|
||||
|
||||
# PHP7.2 with PostgreSQL latest (11)
|
||||
php7.2_postgres11:
|
||||
# PHP7.3 with PostgreSQL latest (11)
|
||||
php7.3_postgres11:
|
||||
<<: *job_definition_postgres
|
||||
artifacts: *artifacts_template
|
||||
|
||||
|
||||
@@ -1,49 +1,10 @@
|
||||
# Hubzilla at Home next to your Router
|
||||
|
||||
This readme will show you how to install and run Hubzilla (or Zap) at home.
|
||||
|
||||
The installation is done by a script.
|
||||
|
||||
What the script will do for you...
|
||||
|
||||
+ install everything required by Hubzilla, 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
|
||||
- backup to external disk (certificates, database, /var/www/)
|
||||
- renew certfificate (letsencrypt)
|
||||
- update of Hubzilla
|
||||
- update of Debian
|
||||
- restart
|
||||
+ create cron jobs for
|
||||
- DynDNS (selfHOST.de or freedns.afraid.org) every 5 minutes
|
||||
- Master.php for Zap/Hubzilla every 10 minutes
|
||||
- daily maintenance script every day at 05:30
|
||||
|
||||
The script is known to work without adjustments with
|
||||
|
||||
+ Hardware
|
||||
- Mini-PC with Debian 10 (stretch), or
|
||||
- Rapberry 3 with Raspbian, Debian 10
|
||||
+ DynDNS
|
||||
- selfHOST.de
|
||||
- freedns.afraid.org
|
||||
|
||||
The script can install both [Hubzilla](https://zotlabs.org/page/hubzilla/hubzilla-project) and [Zap](https://zotlabs.com/zap/). Make sure to use the correct GIT repositories.
|
||||
|
||||
+ Hubzilla
|
||||
- core: git clone https://framagit.org/hubzilla/core.git html (in this readme)
|
||||
- addons: util/add_addon_repo https://framagit.org/hubzilla/addons.git hzaddons (in hubzilla-setup.sh)
|
||||
+ Zap
|
||||
- core: git clone https://framagit.org/zot/zap.git html (in this readme)
|
||||
- addons: util/add_addon_repo https://framagit.org/zot/zap-addons.git zaddons (in hubzilla-setup.sh)
|
||||
# How to use
|
||||
|
||||
## Disclaimers
|
||||
|
||||
- This script does work with Debian 10 only.
|
||||
- This script has to be used on a fresh debian install only (it does not take account for a possibly already installed and configured webserver or sql implementation).
|
||||
|
||||
# Step-by-Step Overwiew
|
||||
- This script has to be used on a fresh debian install only (it does not take account for a possibly already installed and configured webserver or sql implementation). You may use it to install several hub/instances on the same server, though.
|
||||
|
||||
## Preconditions
|
||||
|
||||
@@ -55,66 +16,99 @@ Hardware
|
||||
|
||||
Software
|
||||
|
||||
+ Fresh installation of Debian 10 (Stretch)
|
||||
+ Fresh installation of Debian 10 (Buster)
|
||||
+ Router with open ports 80 and 443 for your web server
|
||||
|
||||
## The basic steps (quick overview)
|
||||
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
|
||||
- git clone https://framagit.org/hubzilla/core.git html (you can replace "html" with any folder name you like, which you'll have to do if you plan to have more than one hub/instance running on your server)
|
||||
- cd html/.homeinstall
|
||||
- cp hubzilla-config.txt.template hubzilla-config.txt
|
||||
- nano hubzilla-config.txt
|
||||
- cp zotserver-config.txt.template zotserver-config.txt
|
||||
- nano zotserver-config.txt
|
||||
- Read the comments carefully
|
||||
- Enter your values: db pass, domain, values for dyn DNS
|
||||
- Prepare your external disk for backups
|
||||
- hubzilla-setup.sh as root
|
||||
- ... wait, wait, wait until the script is finised
|
||||
+ Open your domain with a browser and step throught the initial configuration of hubzilla.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
If the check of the mail address fails when you try to register the very first user in the browser. Do...
|
||||
|
||||
cd /var/www/html
|
||||
util/config system.do_not_check_dns 1
|
||||
- ./zotserver-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 hub/instance.
|
||||
|
||||
## Optional - Set path to imagemagick
|
||||
|
||||
In Admin settings of hubzilla or via terminal
|
||||
In Admin settings of your hub/instance or via terminal
|
||||
|
||||
cd /var/www/html
|
||||
cd /var/www/html (or the custom path you chose)
|
||||
util/config system.imagick_convert_path /usr/bin/convert
|
||||
|
||||
# Step-by-Step in Detail
|
||||
## Optional - Switch verification of email on/off
|
||||
|
||||
## Preparations Software
|
||||
Do this just before you register the first user.
|
||||
|
||||
## Install Debian 9
|
||||
In Admin settings of your hub/instance or via terminal
|
||||
|
||||
Provided you use a Raspberry Pi 3...
|
||||
cd /var/www/html
|
||||
|
||||
Download the OS Raspbian from https://www.raspberrypi.org/downloads/raspbian/
|
||||
Check the current setting
|
||||
|
||||
Follow the installation instruction there.
|
||||
util/config system verify_email
|
||||
|
||||
Switch the verification on/off (1/0)
|
||||
|
||||
util/config system verify_email 0
|
||||
|
||||
## What the script will do for you...
|
||||
|
||||
+ install everything required by your hub/instance, basically a web server (Apache or Nginx), PHP, a database (MySQL), certbot,...
|
||||
+ create a database
|
||||
+ run certbot to have everything for a secure connection (httpS)
|
||||
+ create a script for daily maintenance
|
||||
- backup to external disk (certificates, database, /var/www/)
|
||||
- renew certfificate (letsencrypt)
|
||||
- update of your hub/instance (git)
|
||||
- update of Debian
|
||||
- restart
|
||||
+ create cron jobs for
|
||||
- DynDNS (selfHOST.de or freedns.afraid.org) every 5 minutes
|
||||
- Run.php for your hub/instance every 10 minutes
|
||||
- daily maintenance script every day at 05:30
|
||||
|
||||
The script is known to work without adjustments with
|
||||
|
||||
+ Hardware
|
||||
- Mini-PC with Debian 10 (stretch), or
|
||||
- Rapberry 3 with Raspbian, Debian 10
|
||||
- Rapberry 4 with Raspbian, Debian 10
|
||||
+ DynDNS
|
||||
- selfHOST.de
|
||||
- freedns.afraid.org
|
||||
|
||||
The script can install [Hubzilla](https://zotlabs.org/page/hubzilla/hubzilla-project), [Zap](https://zotlabs.com/zap/) and [Mistpark 2020, aka "Misty"](https://zotlabs.com/misty/). Make sure to use the correct GIT repositories.
|
||||
|
||||
|
||||
# Step-by-Step - some Details
|
||||
|
||||
## Preparations
|
||||
|
||||
## Configure your Router
|
||||
|
||||
Your web has to be visible in the internet.
|
||||
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 .homeinstall/hubzilla-config.txt.
|
||||
Follow the instructions in .homeinstall/zotserver-config.txt.
|
||||
|
||||
In short...
|
||||
|
||||
Your Hubzilla must be reachable by a domain that you can type in your browser
|
||||
Your Hubzilla server must be reachable by a domain that you can type in your browser
|
||||
|
||||
cooldomain.org
|
||||
|
||||
@@ -136,8 +130,6 @@ The cost is 1,50 € per month (2019).
|
||||
|
||||
## Note on Rasperry
|
||||
|
||||
The script was tested with an Raspberry 3 under Raspian, Debian 10.
|
||||
|
||||
It is recommended to run the Raspi without graphical frontend (X-Server). Use...
|
||||
|
||||
sudo raspi-config
|
||||
@@ -146,12 +138,6 @@ to boot the Rapsi to the client console.
|
||||
|
||||
DO NOT FORGET TO CHANGE THE DEFAULT PASSWORD FOR USER PI!
|
||||
|
||||
On a Raspian Stretch (Debian 10) the validation of the mail address fails for the very first user.
|
||||
This used to happen on some *bsd distros but there was some work to fix that a year ago (2017).
|
||||
|
||||
So if your system isn't registered in DNS or DNS isn't active do
|
||||
|
||||
cd /var/www/html
|
||||
util/config system.do_not_check_dns 1
|
||||
|
||||
## 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.
|
||||
|
||||
@@ -1,622 +0,0 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# How to use
|
||||
# ----------
|
||||
#
|
||||
# This file automates the installation of
|
||||
# - hubzilla: https://zotlabs.org/page/hubzilla/hubzilla-project and
|
||||
# - zap: https://zotlabs.com/zap/
|
||||
# under Debian Linux
|
||||
#
|
||||
# 1) Copy the file "hubzilla-config.txt.template" to "hubzilla-config.txt"
|
||||
# Follow the instuctions there
|
||||
#
|
||||
# 2) Switch to user "root" by typing "su -"
|
||||
#
|
||||
# 3) Run with "./hubzilla-setup.sh"
|
||||
# If this fails check if you can execute the script.
|
||||
# - To make it executable type "chmod +x hubzilla-setup.sh"
|
||||
# - or run "bash hubzilla-setup.sh"
|
||||
#
|
||||
#
|
||||
# What does this script do basically?
|
||||
# -----------------------------------
|
||||
#
|
||||
# This file automates the installation of hubzilla under Debian Linux
|
||||
# - install
|
||||
# * apache webserer,
|
||||
# * php,
|
||||
# * mariadb - the database for hubzilla,
|
||||
# * adminer,
|
||||
# * git to download and update hubzilla addon
|
||||
# - download hubzilla core and addons
|
||||
# - configure cron
|
||||
# * "Master.php" for regular background prozesses of hubzilla
|
||||
# * "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
|
||||
# * backup hubzillas database and files (rsync)
|
||||
# - letsencrypt
|
||||
#
|
||||
#
|
||||
# Discussion
|
||||
# ----------
|
||||
#
|
||||
# Security - password is the same for mysql-server, phpmyadmin and hubzilla db
|
||||
# - The script runs into installation errors for phpmyadmin if it uses
|
||||
# different passwords. For the sake of simplicity one singel password.
|
||||
#
|
||||
# How to restore from backup
|
||||
# --------------------------
|
||||
#
|
||||
# Daily backup
|
||||
# - - - - - -
|
||||
#
|
||||
# The installation
|
||||
# - writes a script /var/www/hubzilla-daily.sh
|
||||
# - creates a daily cron that runs the hubzilla-daily.sh
|
||||
#
|
||||
# hubzilla-daily.sh makes a (daily) backup of all relevant files
|
||||
# - /var/lib/mysql/ > hubzilla database
|
||||
# - /var/www/ > hubzilla/zap from github
|
||||
# - /etc/letsencrypt/ > certificates
|
||||
#
|
||||
# hubzilla-daily.sh writes the backup to an external disk compatible to LUKS+ext4 (see hubzilla-config.txt)
|
||||
#
|
||||
# Credits
|
||||
# -------
|
||||
#
|
||||
# The script is based on Thomas Willinghams script "debian-setup.sh"
|
||||
# which he used to install the red#matrix.
|
||||
#
|
||||
# The documentation for bash is here
|
||||
# https://www.gnu.org/software/bash/manual/bash.html
|
||||
#
|
||||
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 10' /etc/issue
|
||||
then
|
||||
die "Linux 10 (buster) 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
|
||||
# backup is important and should be checked
|
||||
if [ -n "$backup_device_name" ]
|
||||
then
|
||||
if [ ! -d "$backup_mount_point" ]
|
||||
then
|
||||
mkdir "$backup_mount_point"
|
||||
fi
|
||||
device_mounted=0
|
||||
if fdisk -l | grep -i "$backup_device_name.*linux"
|
||||
then
|
||||
print_info "ok - filesystem of external device is linux"
|
||||
if [ -n "$backup_device_pass" ]
|
||||
then
|
||||
echo "$backup_device_pass" | cryptsetup luksOpen $backup_device_name cryptobackup
|
||||
if mount /dev/mapper/cryptobackup /media/hubzilla_backup
|
||||
then
|
||||
device_mounted=1
|
||||
print_info "ok - could encrypt and mount external backup device"
|
||||
umount /media/hubzilla_backup
|
||||
else
|
||||
print_warn "backup to external device will fail because encryption failed"
|
||||
fi
|
||||
cryptsetup luksClose cryptobackup
|
||||
else
|
||||
if mount $backup_device_name /media/hubzilla_backup
|
||||
then
|
||||
device_mounted=1
|
||||
print_info "ok - could mount external backup device"
|
||||
umount /media/hubzilla_backup
|
||||
else
|
||||
print_warn "backup to external device will fail because mount failed"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
print_warn "backup to external device will fail because filesystem is either not linux or 'backup_device_name' is not correct in $configfile"
|
||||
fi
|
||||
if [ $device_mounted == 0 ]
|
||||
then
|
||||
die "backup device not ready"
|
||||
fi
|
||||
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
|
||||
print_info "updated and upgraded linux"
|
||||
}
|
||||
|
||||
function check_install {
|
||||
if [ -z "`which "$1" 2>/dev/null`" ]
|
||||
then
|
||||
# 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 -q -y install $2
|
||||
print_info "installed $2 installed for $1"
|
||||
else
|
||||
print_warn "$2 already installed"
|
||||
fi
|
||||
}
|
||||
|
||||
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_hubzilla {
|
||||
print_info "stopping apache webserver..."
|
||||
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_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-mysqli php-mbstring php-xml php-zip"
|
||||
sed -i "s/^upload_max_filesize =.*/upload_max_filesize = 100M/g" /etc/php/7.3/apache2/php.ini
|
||||
sed -i "s/^post_max_size =.*/post_max_size = 100M/g" /etc/php/7.3/apache2/php.ini
|
||||
}
|
||||
|
||||
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('${db_root_password}') 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
|
||||
a2enconf adminer
|
||||
systemctl reload apache2
|
||||
}
|
||||
|
||||
function create_hubzilla_db {
|
||||
print_info "creating hubzilla database..."
|
||||
if [ -z "$hubzilla_db_name" ]
|
||||
then
|
||||
die "hubzilla_db_name not set in $configfile"
|
||||
fi
|
||||
if [ -z "$hubzilla_db_user" ]
|
||||
then
|
||||
die "hubzilla_db_user not set in $configfile"
|
||||
fi
|
||||
if [ -z "$hubzilla_db_pass" ]
|
||||
then
|
||||
die "hubzilla_db_pass not set in $configfile"
|
||||
fi
|
||||
systemctl restart mariadb
|
||||
Q1="CREATE DATABASE IF NOT EXISTS $hubzilla_db_name;"
|
||||
Q2="GRANT USAGE ON *.* TO $hubzilla_db_user@localhost IDENTIFIED BY '$hubzilla_db_pass';"
|
||||
Q3="GRANT ALL PRIVILEGES ON $hubzilla_db_name.* to $hubzilla_db_user@localhost identified by '$hubzilla_db_pass';"
|
||||
Q4="FLUSH PRIVILEGES;"
|
||||
SQL="${Q1}${Q2}${Q3}${Q4}"
|
||||
mysql -uroot -p$phpmyadminpass -e "$SQL"
|
||||
}
|
||||
|
||||
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 - https://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 https://freedns.afraid.org/dynamic/update.php?$freedns_key > /dev/null 2>&1" >> /etc/crontab
|
||||
echo "*/30 * * * * root wget --no-check-certificate -O - https://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
|
||||
# check if user gave mail address
|
||||
if [ -z "$le_email" ]
|
||||
then
|
||||
die "Failed to install let's encrypt: 'le_domain' is empty in $configfile"
|
||||
fi
|
||||
nocheck_install "certbot python-certbot-apache"
|
||||
print_info "run certbot ..."
|
||||
certbot --apache -w /var/www/html -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_hubzilla {
|
||||
print_info "installing hubzilla addons..."
|
||||
cd /var/www/html/
|
||||
# if you install Hubzilla
|
||||
# util/add_addon_repo https://framagit.org/hubzilla/addons hzaddons
|
||||
# if you install ZAP
|
||||
util/add_addon_repo https://framagit.org/zot/zap-addons.git zaddons
|
||||
mkdir -p "store/[data]/smarty3"
|
||||
chmod -R 777 store
|
||||
touch .htconfig.php
|
||||
chmod ou+w .htconfig.php
|
||||
cd /var/www/
|
||||
chown -R www-data:www-data html
|
||||
chown root:www-data /var/www/html/
|
||||
chown root:www-data /var/www/html/.htaccess
|
||||
chmod 0644 /var/www/html/.htaccess
|
||||
print_info "installed hubzilla"
|
||||
}
|
||||
|
||||
function install_rsync {
|
||||
print_info "installing rsync..."
|
||||
nocheck_install "rsync"
|
||||
}
|
||||
|
||||
function install_cryptosetup {
|
||||
print_info "installing cryptsetup..."
|
||||
nocheck_install "cryptsetup"
|
||||
}
|
||||
|
||||
function configure_cron_daily {
|
||||
print_info "configuring cron..."
|
||||
# every 10 min for poller.php
|
||||
if [ -z "`grep 'Master.php' /etc/crontab`" ]
|
||||
then
|
||||
echo "*/10 * * * * www-data cd /var/www/html; php Zotlabs/Daemon/Master.php Cron >> /dev/null 2>&1" >> /etc/crontab
|
||||
fi
|
||||
# Run external script daily at 05:30
|
||||
# - stop apache and mysql-server
|
||||
# - renew the certificate of letsencrypt
|
||||
# - backup db, files (/var/www/html), certificates if letsencrypt
|
||||
# - update hubzilla 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/$hubzilladaily
|
||||
echo "#" >> /var/www/$hubzilladaily
|
||||
echo "echo \" \"" >> /var/www/$hubzilladaily
|
||||
echo "echo \"+++ \$(date) +++\"" >> /var/www/$hubzilladaily
|
||||
echo "echo \" \"" >> /var/www/$hubzilladaily
|
||||
echo "echo \"\$(date) - renew certificate...\"" >> /var/www/$hubzilladaily
|
||||
echo "certbot renew --noninteractive" >> /var/www/$hubzilladaily
|
||||
echo "#" >> /var/www/$hubzilladaily
|
||||
echo "echo \"\$(date) - stopping apache and mysql...\"" >> /var/www/$hubzilladaily
|
||||
echo "service apache2 stop" >> /var/www/$hubzilladaily
|
||||
echo "/etc/init.d/mysql stop # to avoid inconsistencies" >> /var/www/$hubzilladaily
|
||||
echo "#" >> /var/www/$hubzilladaily
|
||||
echo "# backup" >> /var/www/$hubzilladaily
|
||||
echo "echo \"\$(date) - try to mount external device for backup...\"" >> /var/www/$hubzilladaily
|
||||
echo "backup_device_name=$backup_device_name" >> /var/www/$hubzilladaily
|
||||
echo "backup_device_pass=$backup_device_pass" >> /var/www/$hubzilladaily
|
||||
echo "backup_mount_point=$backup_mount_point" >> /var/www/$hubzilladaily
|
||||
echo "device_mounted=0" >> /var/www/$hubzilladaily
|
||||
echo "if [ -n \"$backup_device_name\" ]" >> /var/www/$hubzilladaily
|
||||
echo "then" >> /var/www/$hubzilladaily
|
||||
echo " if blkid | grep $backup_device_name" >> /var/www/$hubzilladaily
|
||||
echo " then" >> /var/www/$hubzilladaily
|
||||
if [ -n "$backup_device_pass" ]
|
||||
then
|
||||
echo " echo \"decrypting backup device...\"" >> /var/www/$hubzilladaily
|
||||
echo " echo "\"$backup_device_pass\"" | cryptsetup luksOpen $backup_device_name cryptobackup" >> /var/www/$hubzilladaily
|
||||
fi
|
||||
echo " if [ ! -d $backup_mount_point ]" >> /var/www/$hubzilladaily
|
||||
echo " then" >> /var/www/$hubzilladaily
|
||||
echo " mkdir $backup_mount_point" >> /var/www/$hubzilladaily
|
||||
echo " fi" >> /var/www/$hubzilladaily
|
||||
echo " echo \"mounting backup device...\"" >> /var/www/$hubzilladaily
|
||||
if [ -n "$backup_device_pass" ]
|
||||
then
|
||||
echo " if mount /dev/mapper/cryptobackup $backup_mount_point" >> /var/www/$hubzilladaily
|
||||
else
|
||||
echo " if mount $backup_device_name $backup_mount_point" >> /var/www/$hubzilladaily
|
||||
fi
|
||||
echo " then" >> /var/www/$hubzilladaily
|
||||
echo " device_mounted=1" >> /var/www/$hubzilladaily
|
||||
echo " echo \"device $backup_device_name is now mounted. Starting backup...\"" >> /var/www/$hubzilladaily
|
||||
echo " rsync -a --delete /var/lib/mysql/ /media/hubzilla_backup/mysql" >> /var/www/$hubzilladaily
|
||||
echo " rsync -a --delete /var/www/ /media/hubzilla_backup/www" >> /var/www/$hubzilladaily
|
||||
echo " rsync -a --delete /etc/letsencrypt/ /media/hubzilla_backup/letsencrypt" >> /var/www/$hubzilladaily
|
||||
echo " echo \"\$(date) - disk sizes...\"" >> /var/www/$hubzilladaily
|
||||
echo " df -h" >> /var/www/$hubzilladaily
|
||||
echo " echo \"\$(date) - db size...\"" >> /var/www/$hubzilladaily
|
||||
echo " du -h $backup_mount_point | grep mysql/hubzilla" >> /var/www/$hubzilladaily
|
||||
echo " echo \"unmounting backup device...\"" >> /var/www/$hubzilladaily
|
||||
echo " umount $backup_mount_point" >> /var/www/$hubzilladaily
|
||||
echo " else" >> /var/www/$hubzilladaily
|
||||
echo " echo \"failed to mount device $backup_device_name\"" >> /var/www/$hubzilladaily
|
||||
echo " fi" >> /var/www/$hubzilladaily
|
||||
if [ -n "$backup_device_pass" ]
|
||||
then
|
||||
echo " echo \"closing decrypted backup device...\"" >> /var/www/$hubzilladaily
|
||||
echo " cryptsetup luksClose cryptobackup" >> /var/www/$hubzilladaily
|
||||
fi
|
||||
echo " fi" >> /var/www/$hubzilladaily
|
||||
echo "fi" >> /var/www/$hubzilladaily
|
||||
echo "if [ \$device_mounted == 0 ]" >> /var/www/$hubzilladaily
|
||||
echo "then" >> /var/www/$hubzilladaily
|
||||
echo " echo \"device could not be mounted $backup_device_name. No backup written.\"" >> /var/www/$hubzilladaily
|
||||
echo "fi" >> /var/www/$hubzilladaily
|
||||
echo "#" >> /var/www/$hubzilladaily
|
||||
echo "echo \"\$(date) - db size...\"" >> /var/www/$hubzilladaily
|
||||
echo "du -h /var/lib/mysql/ | grep mysql/hubzilla" >> /var/www/$hubzilladaily
|
||||
echo "#" >> /var/www/$hubzilladaily
|
||||
echo "# update" >> /var/www/$hubzilladaily
|
||||
echo "echo \"\$(date) - updating core and addons...\"" >> /var/www/$hubzilladaily
|
||||
echo "(cd /var/www/html/ ; util/udall)" >> /var/www/$hubzilladaily
|
||||
echo "chown -R www-data:www-data /var/www/html/ # make all accessable for the webserver" >> /var/www/$hubzilladaily
|
||||
echo "chown root:www-data /var/www/html/.htaccess" >> /var/www/$hubzilladaily
|
||||
echo "chmod 0644 /var/www/html/.htaccess # www-data can read but not write it" >> /var/www/$hubzilladaily
|
||||
echo "echo \"\$(date) - updating linux...\"" >> /var/www/$hubzilladaily
|
||||
echo "apt-get -q -y update && apt-get -q -y dist-upgrade && apt-get -q -y autoremove # update linux and upgrade" >> /var/www/$hubzilladaily
|
||||
echo "echo \"\$(date) - Backup and update finished. Rebooting...\"" >> /var/www/$hubzilladaily
|
||||
echo "#" >> /var/www/$hubzilladaily
|
||||
echo "shutdown -r now" >> /var/www/$hubzilladaily
|
||||
|
||||
if [ -z "`grep 'hubzilla-daily.sh' /etc/crontab`" ]
|
||||
then
|
||||
echo "30 05 * * * root /bin/bash /var/www/$hubzilladaily >> /var/www/html/hubzilla-daily.log 2>&1" >> /etc/crontab
|
||||
echo "0 0 1 * * root rm /var/www/html/hubzilla-daily.log" >> /etc/crontab
|
||||
fi
|
||||
|
||||
# This is active after either "reboot" or "/etc/init.d/cron reload"
|
||||
print_info "configured cron for updates/upgrades"
|
||||
}
|
||||
|
||||
########################################################################
|
||||
# START OF PROGRAM
|
||||
########################################################################
|
||||
export PATH=/bin:/usr/bin:/sbin:/usr/sbin
|
||||
|
||||
check_sanity
|
||||
|
||||
# Read config file edited by user
|
||||
configfile=hubzilla-config.txt
|
||||
source $configfile
|
||||
|
||||
selfhostdir=/etc/selfhost
|
||||
selfhostscript=selfhost-updater.sh
|
||||
hubzilladaily=hubzilla-daily.sh
|
||||
backup_mount_point=/media/hubzilla_backup
|
||||
|
||||
#set -x # activate debugging from here
|
||||
|
||||
check_config
|
||||
stop_hubzilla
|
||||
update_upgrade
|
||||
install_curl
|
||||
install_sendmail
|
||||
install_apache
|
||||
install_imagemagick
|
||||
install_php
|
||||
install_mysql
|
||||
install_adminer
|
||||
create_hubzilla_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_hubzilla
|
||||
|
||||
configure_cron_daily
|
||||
|
||||
if [ "$le_domain" != "localhost" ]
|
||||
then
|
||||
install_rsync
|
||||
install_cryptosetup
|
||||
else
|
||||
print_info "is localhost - skipped installation of cryptosetup"
|
||||
fi
|
||||
|
||||
#set +x # stop debugging from here
|
||||
|
||||
144
.homeinstall/nginx-zotserver.conf.template
Normal file
144
.homeinstall/nginx-zotserver.conf.template
Normal file
@@ -0,0 +1,144 @@
|
||||
##
|
||||
# Hubzilla/Zap/Mistpark/Osada Nginx block configuration template
|
||||
# based on the example created by Olaf Conradi
|
||||
#
|
||||
# The files generated with this template will be added to
|
||||
# /etc/nginx/sites-available & /etc/nginx/sites-enabled (symlink)
|
||||
##
|
||||
|
||||
##
|
||||
# You should look at the following URL's in order to grasp a solid understanding
|
||||
# of Nginx configuration files in order to fully unleash the power of Nginx.
|
||||
#
|
||||
# http://wiki.nginx.org/Pitfalls
|
||||
# http://wiki.nginx.org/QuickStart
|
||||
# http://wiki.nginx.org/Configuration
|
||||
##
|
||||
|
||||
##
|
||||
# This configuration assumes
|
||||
# You filled the zotserver-config.txt file
|
||||
# Your domain/subdomain is functionnal
|
||||
# You want all traffic to be https
|
||||
# You have PHP FastCGI Process Manager (php-fpm) running on localhost
|
||||
##
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
server_name SERVER_NAME;
|
||||
|
||||
# HTTP > HTTPS #
|
||||
return 301 https://$server_name$request_uri;
|
||||
}
|
||||
|
||||
##
|
||||
# Configure Red with SSL
|
||||
#
|
||||
# All requests are routed to the front controller
|
||||
# except for certain known file types like images, css, etc.
|
||||
# Those are served statically whenever possible with a
|
||||
# fall back to the front controller (needed for avatars, for example)
|
||||
##
|
||||
|
||||
server {
|
||||
listen 443 ssl;
|
||||
server_name SERVER_NAME;
|
||||
|
||||
ssl on;
|
||||
ssl_certificate /etc/letsencrypt/live/SERVER_NAME/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/SERVER_NAME/privkey.pem;
|
||||
ssl_session_timeout 5m;
|
||||
# DO WE NEED TO REVIEW THE FOLLOWING SETTINGS?
|
||||
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
|
||||
ssl_ciphers ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS;
|
||||
ssl_prefer_server_ciphers on;
|
||||
|
||||
fastcgi_param HTTPS on;
|
||||
|
||||
charset utf-8;
|
||||
root INSTALL_PATH;
|
||||
index index.php;
|
||||
access_log /var/log/nginx/ZOTSERVER_LOG;
|
||||
|
||||
#Uncomment the following line to include a standard configuration file
|
||||
#Note that the most specific rule wins and your standard configuration
|
||||
#will therefore *add* to this file, but not override it.
|
||||
#include standard.conf
|
||||
|
||||
# allow uploads up to 20MB in size
|
||||
client_max_body_size 20m;
|
||||
client_body_buffer_size 128k;
|
||||
|
||||
include mime.types;
|
||||
|
||||
# rewrite to front controller as default rule
|
||||
location / {
|
||||
if (!-e $request_filename) {
|
||||
rewrite ^(.*)$ /index.php?req=$1;
|
||||
}
|
||||
}
|
||||
|
||||
# make sure webfinger and other well known services aren't blocked
|
||||
# by denying dot files and rewrite request to the front controller
|
||||
location ^~ /.well-known/ {
|
||||
allow all;
|
||||
if (!-e $request_filename) {
|
||||
rewrite ^(.*)$ /index.php?req=$1;
|
||||
}
|
||||
}
|
||||
|
||||
# statically serve these file types when possible
|
||||
# otherwise fall back to front controller
|
||||
# allow browser to cache them
|
||||
# added .htm for advanced source code editor library
|
||||
# location ~* \.(jpg|jpeg|gif|png|ico|css|js|htm|html|map|ttf|woff|woff2|svg)$ {
|
||||
# expires 30d;
|
||||
# try_files $uri /index.php?req=$uri&$args;
|
||||
# }
|
||||
# SHOULD WE UNCOMMENT THE ABOVE LINES ?
|
||||
|
||||
# block these file types
|
||||
location ~* \.(tpl|md|tgz|log|out)$ {
|
||||
deny all;
|
||||
}
|
||||
|
||||
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
|
||||
# or a unix socket
|
||||
location ~* \.php$ {
|
||||
# IS THE FOLLOWING STILL RELEVANT AS OF AUGUST 2020?
|
||||
# Zero-day exploit defense.
|
||||
# http://forum.nginx.org/read.php?2,88845,page=3
|
||||
# Won't work properly (404 error) if the file is not stored on this
|
||||
# server, which is entirely possible with php-fpm/php-fcgi.
|
||||
# Comment the 'try_files' line out if you set up php-fpm/php-fcgi on
|
||||
# another machine. And then cross your fingers that you won't get hacked.
|
||||
try_files $uri =404;
|
||||
|
||||
# NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini
|
||||
fastcgi_split_path_info ^(.+\.php)(/.+)$;
|
||||
|
||||
# With php5-cgi alone:
|
||||
# fastcgi_pass 127.0.0.1:9000;
|
||||
|
||||
# With php-fpm:
|
||||
fastcgi_pass unix:PHP_FPM_SOCK;
|
||||
|
||||
include fastcgi_params;
|
||||
fastcgi_index index.php;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
}
|
||||
|
||||
# deny access to all dot files
|
||||
location ~ /\. {
|
||||
deny all;
|
||||
}
|
||||
|
||||
#deny access to store
|
||||
|
||||
location ~ /store {
|
||||
deny all;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -9,11 +9,11 @@ db_pass=
|
||||
###############################################
|
||||
### MANDATORY - let's encrypt #################
|
||||
#
|
||||
# Hubilla requires encrypted communication via secure HTTP (HTTPS).
|
||||
# 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
|
||||
# Please give the domain name of your hub/instance
|
||||
#
|
||||
# Example: my.cooldomain.org
|
||||
# Example: cooldomain.org
|
||||
@@ -29,6 +29,18 @@ db_pass=
|
||||
le_domain=
|
||||
le_email=
|
||||
|
||||
###############################################
|
||||
### OPTIONAL - Webserver choice ###############
|
||||
#
|
||||
# Please indicate if you want to choose Nginx
|
||||
# or Apache as your web server
|
||||
#
|
||||
# Valid strings are nginx or apache (lower case),
|
||||
# any other will stop the setup script.
|
||||
#
|
||||
webserver=apache
|
||||
|
||||
|
||||
###############################################
|
||||
### OPTIONAL - selfHOST - dynamic IP address ##
|
||||
#
|
||||
@@ -87,7 +99,7 @@ freedns_key=
|
||||
# - encrypted LUKS + ext4, or
|
||||
# - ext4
|
||||
#
|
||||
# You should test to mount the device befor you run the script
|
||||
# You should test to mount the device before you run the script
|
||||
# (hubzilla-setup.sh).
|
||||
# How to find your (pluged-in) devices?
|
||||
#
|
||||
@@ -144,10 +156,13 @@ backup_device_pass=
|
||||
#
|
||||
###############################################
|
||||
#
|
||||
# Database for hubzilla
|
||||
hubzilla_db_name=hubzilla
|
||||
hubzilla_db_user=hubzilla
|
||||
hubzilla_db_pass=$db_pass
|
||||
# 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
|
||||
793
.homeinstall/zotserver-setup.sh
Executable file
793
.homeinstall/zotserver-setup.sh
Executable file
@@ -0,0 +1,793 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# How to use
|
||||
# ----------
|
||||
#
|
||||
# This file automates the installation of
|
||||
# - hubzilla: https://zotlabs.org/page/hubzilla/hubzilla-project and
|
||||
# - zap: https://zotlabs.com/zap/
|
||||
# - misty : https://zotlabs.com/misty/
|
||||
# - osada : https://codeberg.org/zot/osada
|
||||
# - redmatrix : https://codeberg.org/zot/redmatrix
|
||||
# under Debian Linux "Buster"
|
||||
#
|
||||
# 1) Copy the file "zotserver-config.txt.template" to "zotserver-config.txt"
|
||||
# Follow the instuctions there
|
||||
#
|
||||
# 2) Switch to user "root" by typing "su -"
|
||||
#
|
||||
# 3) Run with "./zotserver-setup.sh"
|
||||
# If this fails check if you can execute the script.
|
||||
# - To make it executable type "chmod +x zotserver-setup.sh"
|
||||
# - or run "bash zotserver-setup.sh"
|
||||
#
|
||||
#
|
||||
# What does this script do basically?
|
||||
# -----------------------------------
|
||||
#
|
||||
# This file automates the installation of a Zot hub/instance under Debian Linux
|
||||
# - install
|
||||
# * apache webserver,
|
||||
# * php,
|
||||
# * mariadb - the database for zotserver,
|
||||
# * adminer,
|
||||
# * git to download and update addons
|
||||
# - configure cron
|
||||
# * "Run.php" for regular background processes of your Zot hub/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
|
||||
# * backup your server's database and files (rsync)
|
||||
# - run letsencrypt to create, register and use a certifacte for https
|
||||
#
|
||||
#
|
||||
# Discussion
|
||||
# ----------
|
||||
#
|
||||
# Security - password is the same for mysql-server, phpmyadmin and your hub/instance db
|
||||
# - The script runs into installation errors for phpmyadmin if it uses
|
||||
# different passwords. For the sake of simplicity one single password.
|
||||
#
|
||||
# How to restore from backup
|
||||
# --------------------------
|
||||
#
|
||||
# (Some explanations here would certainly be useful)
|
||||
#
|
||||
# Daily backup
|
||||
# ------------
|
||||
#
|
||||
# The installation
|
||||
# - writes a shell script in /var/www/
|
||||
# - creates a daily cron that runs this script
|
||||
#
|
||||
# The script makes a (daily) backup of all relevant files
|
||||
# - /var/lib/mysql/ > database
|
||||
# - /var/www/ > hubzilla/zap/misty from git repository
|
||||
# - /etc/letsencrypt/ > certificates
|
||||
#
|
||||
# The backup will be written on an external disk compatible to LUKS+ext4 (see zotserver-config.txt)
|
||||
#
|
||||
# How to restore from backup
|
||||
# --------------------------
|
||||
#
|
||||
# (Some explanations here would certainly be useful)
|
||||
#
|
||||
#
|
||||
# Credits
|
||||
# -------
|
||||
#
|
||||
# The script is based on Thomas Willinghams script "debian-setup.sh"
|
||||
# which he used to install the red#matrix.
|
||||
#
|
||||
# The documentation for bash is here
|
||||
# https://www.gnu.org/software/bash/manual/bash.html
|
||||
#
|
||||
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 10' /etc/issue
|
||||
then
|
||||
die "Linux 10 (buster) 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
|
||||
# backup is important and should be checked
|
||||
if [ -n "$backup_device_name" ]
|
||||
then
|
||||
if [ ! -d "$backup_mount_point" ]
|
||||
then
|
||||
mkdir "$backup_mount_point"
|
||||
fi
|
||||
device_mounted=0
|
||||
if fdisk -l | grep -i "$backup_device_name.*linux"
|
||||
then
|
||||
print_info "ok - filesystem of external device is linux"
|
||||
if [ -n "$backup_device_pass" ]
|
||||
then
|
||||
echo "$backup_device_pass" | cryptsetup luksOpen $backup_device_name cryptobackup
|
||||
if mount /dev/mapper/cryptobackup /media/zotserver_backup
|
||||
then
|
||||
device_mounted=1
|
||||
print_info "ok - could encrypt and mount external backup device"
|
||||
umount /media/zotserver_backup
|
||||
else
|
||||
print_warn "backup to external device will fail because encryption failed"
|
||||
fi
|
||||
cryptsetup luksClose cryptobackup
|
||||
else
|
||||
if mount $backup_device_name /media/zotserver_backup
|
||||
then
|
||||
device_mounted=1
|
||||
print_info "ok - could mount external backup device"
|
||||
umount /media/zotserver_backup
|
||||
else
|
||||
print_warn "backup to external device will fail because mount failed"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
print_warn "backup to external device will fail because filesystem is either not linux or 'backup_device_name' is not correct in $configfile"
|
||||
fi
|
||||
if [ $device_mounted == 0 ]
|
||||
then
|
||||
die "backup device not ready"
|
||||
fi
|
||||
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
|
||||
print_info "updated and upgraded linux"
|
||||
}
|
||||
|
||||
function check_install {
|
||||
if [ -z "`which "$1" 2>/dev/null`" ]
|
||||
then
|
||||
# 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 -q -y install $2
|
||||
print_info "installed $2 installed for $1"
|
||||
else
|
||||
print_warn "$2 already installed"
|
||||
fi
|
||||
}
|
||||
|
||||
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 {
|
||||
if [ $webserver = "nginx" ]
|
||||
then
|
||||
print_info "stopping nginx webserver..."
|
||||
systemctl stop nginx
|
||||
elif [ $webserver = "apache" ]
|
||||
then
|
||||
print_info "stopping apache webserver..."
|
||||
systemctl stop apache2
|
||||
fi
|
||||
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_nginx {
|
||||
print_info "installing nginx..."
|
||||
nocheck_install "nginx"
|
||||
systemctl restart nginx
|
||||
}
|
||||
|
||||
function add_vhost {
|
||||
print_info "adding apache vhost"
|
||||
echo "<VirtualHost *:80>" >> "/etc/apache2/sites-available/${le_domain}.conf"
|
||||
echo "ServerName ${le_domain}" >> "/etc/apache2/sites-available/${le_domain}.conf"
|
||||
echo "DocumentRoot $install_path" >> "/etc/apache2/sites-available/${le_domain}.conf"
|
||||
echo "</VirtualHost>" >> "/etc/apache2/sites-available/${le_domain}.conf"
|
||||
a2ensite $le_domain
|
||||
}
|
||||
|
||||
function add_nginx_block {
|
||||
print_info "adding nginx block"
|
||||
sed "s|SERVER_NAME|${le_domain}|g;s|INSTALL_PATH|${install_path}|g;s|ZOTSERVER_LOG|${install_folder}-${zotserver}.log|;s|PHP_FPM_SOCK|$(ls /var/run/php/*sock)|;" nginx-zotserver.conf.template >> /etc/nginx/sites-enabled/${le_domain}.conf
|
||||
ln -s /etc/nginx/sites-enabled/${le_domain}.conf /etc/nginx/sites-available/
|
||||
}
|
||||
|
||||
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..."
|
||||
if [ $webserver = "nginx" ]
|
||||
then
|
||||
nocheck_install "php php-pear php-curl php-gd php-mbstring php-xml php-zip php-fpm"
|
||||
sed -i "s/^upload_max_filesize =.*/upload_max_filesize = 100M/g" /etc/php/7.3/fpm/php.ini
|
||||
sed -i "s/^post_max_size =.*/post_max_size = 100M/g" /etc/php/7.3/fpm/php.ini
|
||||
systemctl reload php7.3-fpm
|
||||
elif [ $webserver = "apache" ]
|
||||
then
|
||||
nocheck_install "libapache2-mod-php php php-pear php-curl php-gd php-mbstring php-xml php-zip"
|
||||
sed -i "s/^upload_max_filesize =.*/upload_max_filesize = 100M/g" /etc/php/7.3/apache2/php.ini
|
||||
sed -i "s/^post_max_size =.*/post_max_size = 100M/g" /etc/php/7.3/apache2/php.ini
|
||||
fi
|
||||
}
|
||||
|
||||
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 "$zotserver_db_name" ]
|
||||
then
|
||||
zotserver_db_name=$zotserver
|
||||
fi
|
||||
if [ -z "$zotserver_db_user" ]
|
||||
then
|
||||
zotserver_db_user=$zotserver
|
||||
fi
|
||||
if [ -z "$zotserver_db_pass" ]
|
||||
then
|
||||
die "zotserver_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 $zotserver_db_name) ]
|
||||
then
|
||||
Q1="CREATE DATABASE IF NOT EXISTS $zotserver_db_name;"
|
||||
Q2="GRANT USAGE ON *.* TO $zotserver_db_user@localhost IDENTIFIED BY '$zotserver_db_pass';"
|
||||
Q3="GRANT ALL PRIVILEGES ON $zotserver_db_name.* to $zotserver_db_user@localhost identified by '$zotserver_db_pass';"
|
||||
Q4="FLUSH PRIVILEGES;"
|
||||
SQL="${Q1}${Q2}${Q3}${Q4}"
|
||||
mysql -uroot -p$mysqlpass -e "$SQL"
|
||||
else
|
||||
die "Can't write over an already existing database!"
|
||||
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
|
||||
if [ $webserver = "nginx" ]
|
||||
then
|
||||
nocheck_install "certbot"
|
||||
print_info "run certbot..."
|
||||
systemctl stop nginx
|
||||
certbot certonly --standalone -d $le_domain -m $le_email --agree-tos --non-interactive
|
||||
systemctl start nginx
|
||||
elif [ $webserver = "apache" ]
|
||||
then
|
||||
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
|
||||
fi
|
||||
}
|
||||
|
||||
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 zotserver_name {
|
||||
if git remote -v | grep -i "origin.*hubzilla.*"
|
||||
then
|
||||
zotserver=hubzilla
|
||||
elif git remote -v | grep -i "origin.*zap.*"
|
||||
then
|
||||
zotserver=zap
|
||||
elif git remote -v | grep -i "origin.*misty.*"
|
||||
then
|
||||
zotserver=misty
|
||||
elif git remote -v | grep -i "origin.*osada.*"
|
||||
then
|
||||
zotserver=osada
|
||||
elif git remote -v | grep -i "origin.*redmatrix.*"
|
||||
then
|
||||
zotserver=redmatrix
|
||||
else
|
||||
die "neither redmatrix, osada, misty, zap nor hubzilla repository > did not install redmatrix/osada/misty/zap/hubzilla"
|
||||
fi
|
||||
}
|
||||
|
||||
function install_zotserver {
|
||||
print_info "installing addons..."
|
||||
cd $install_path/
|
||||
if [ $zotserver = "hubzilla" ]
|
||||
then
|
||||
print_info "hubzilla"
|
||||
util/add_addon_repo https://framagit.org/hubzilla/addons hzaddons
|
||||
elif [ $zotserver = "zap" ]
|
||||
then
|
||||
print_info "zap"
|
||||
util/add_addon_repo https://codeberg.org/zot/zap-addons.git zaddons
|
||||
elif [ $zotserver = "misty" ]
|
||||
then
|
||||
print_info "misty"
|
||||
util/add_addon_repo https://codeberg.org/zot/misty-addons.git maddons
|
||||
elif [ $zotserver = "osada" ]
|
||||
then
|
||||
print_info "osada"
|
||||
util/add_addon_repo https://codeberg.org/zot/osada-addons.git oaddons
|
||||
elif [ $zotserver = "redmatrix" ]
|
||||
then
|
||||
print_info "redmatrix"
|
||||
util/add_addon_repo https://codeberg.org/zot/redmatrix-addons.git raddons
|
||||
else
|
||||
die "neither redmatrix, osada, misty, zap nor hubzilla repository > did not install addons or redmatrix/osada/misty/zap/hubzilla"
|
||||
fi
|
||||
mkdir -p "cache/smarty3"
|
||||
mkdir -p "store"
|
||||
chmod -R 777 store
|
||||
touch .htconfig.php
|
||||
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 install_rsync {
|
||||
print_info "installing rsync..."
|
||||
nocheck_install "rsync"
|
||||
}
|
||||
|
||||
function install_cryptosetup {
|
||||
print_info "installing cryptsetup..."
|
||||
nocheck_install "cryptsetup"
|
||||
}
|
||||
|
||||
function configure_zotserverdaily {
|
||||
echo "#!/bin/sh" >> /var/www/$zotserverdaily
|
||||
echo "#" >> /var/www/$zotserverdaily
|
||||
echo "# update of $le_domain Zot hub/instance" >> /var/www/$zotserverdaily
|
||||
echo "echo \"\$(date) - updating core and addons...\"" >> /var/www/$zotserverdaily
|
||||
echo "echo \"reaching git repository for $le_domain $zotserver hub/instance...\"" >> /var/www/$zotserverdaily
|
||||
echo "(cd $install_path ; util/udall)" >> /var/www/$zotserverdaily
|
||||
echo "chown -R www-data:www-data $install_path # make all accessible for the webserver" >> /var/www/$zotserverdaily
|
||||
if [ $webserver = "apache" ]
|
||||
then
|
||||
echo "chown root:www-data $install_path/.htaccess" >> /var/www/$zotserverdaily
|
||||
echo "chmod 0644 $install_path/.htaccess # www-data can read but not write it" >> /var/www/$zotserverdaily
|
||||
fi
|
||||
chmod a+x /var/www/$zotserverdaily
|
||||
}
|
||||
|
||||
function configure_cron_daily {
|
||||
print_info "configuring cron..."
|
||||
# every 10 min for poller.php
|
||||
if [ -z "`grep '$install_path.*Run.php' /etc/crontab`" ]
|
||||
then
|
||||
echo "*/10 * * * * www-data cd $install_path; php Zotlabs/Daemon/Run.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
|
||||
# - backup db, files ($install_path), certificates if letsencrypt
|
||||
# - update zotserver 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/$zotcron
|
||||
echo "#" >> /var/www/$zotcron
|
||||
echo "echo \" \"" >> /var/www/$zotcron
|
||||
echo "echo \"+++ \$(date) +++\"" >> /var/www/$zotcron
|
||||
echo "echo \" \"" >> /var/www/$zotcron
|
||||
echo "echo \"\$(date) - stopping $webserver and mysql...\"" >> /var/www/$zotcron
|
||||
if [ $webserver = "nginx" ]
|
||||
then
|
||||
echo "systemctl stop nginx" >> /var/www/$zotcron
|
||||
elif [ $webserver = "apache" ]
|
||||
then
|
||||
echo "service apache2 stop" >> /var/www/$zotcron
|
||||
fi
|
||||
echo "/etc/init.d/mysql stop # to avoid inconsistencies" >> /var/www/$zotcron
|
||||
echo "#" >> /var/www/$zotcron
|
||||
echo "echo \"\$(date) - renew certificate...\"" >> /var/www/$zotcron
|
||||
echo "certbot renew --noninteractive" >> /var/www/$zotcron
|
||||
echo "#" >> /var/www/$zotcron
|
||||
echo "# backup" >> /var/www/$zotcron
|
||||
echo "echo \"\$(date) - try to mount external device for backup...\"" >> /var/www/$zotcron
|
||||
echo "backup_device_name=$backup_device_name" >> /var/www/$zotcron
|
||||
echo "backup_device_pass=$backup_device_pass" >> /var/www/$zotcron
|
||||
echo "backup_mount_point=$backup_mount_point" >> /var/www/$zotcron
|
||||
echo "device_mounted=0" >> /var/www/$zotcron
|
||||
echo "if [ -n \"\$backup_device_name\" ]" >> /var/www/$zotcron
|
||||
echo "then" >> /var/www/$zotcron
|
||||
echo " if blkid | grep $backup_device_name" >> /var/www/$zotcron
|
||||
echo " then" >> /var/www/$zotcron
|
||||
if [ -n "$backup_device_pass" ]
|
||||
then
|
||||
echo " echo \"decrypting backup device...\"" >> /var/www/$zotcron
|
||||
echo " echo "\"$backup_device_pass\"" | cryptsetup luksOpen $backup_device_name cryptobackup" >> /var/www/$zotcron
|
||||
fi
|
||||
echo " if [ ! -d $backup_mount_point ]" >> /var/www/$zotcron
|
||||
echo " then" >> /var/www/$zotcron
|
||||
echo " mkdir $backup_mount_point" >> /var/www/$zotcron
|
||||
echo " fi" >> /var/www/$zotcron
|
||||
echo " echo \"mounting backup device...\"" >> /var/www/$zotcron
|
||||
if [ -n "$backup_device_pass" ]
|
||||
then
|
||||
echo " if mount /dev/mapper/cryptobackup $backup_mount_point" >> /var/www/$zotcron
|
||||
else
|
||||
echo " if mount $backup_device_name $backup_mount_point" >> /var/www/$zotcron
|
||||
fi
|
||||
echo " then" >> /var/www/$zotcron
|
||||
echo " device_mounted=1" >> /var/www/$zotcron
|
||||
echo " echo \"device $backup_device_name is now mounted. Starting backup...\"" >> /var/www/$zotcron
|
||||
echo " rsync -a --delete /var/lib/mysql/ /media/zotserver_backup/mysql" >> /var/www/$zotcron
|
||||
echo " rsync -a --delete /var/www/ /media/zotserver_backup/www" >> /var/www/$zotcron
|
||||
echo " rsync -a --delete /etc/letsencrypt/ /media/zotserver_backup/letsencrypt" >> /var/www/$zotcron
|
||||
echo " echo \"\$(date) - disk sizes...\"" >> /var/www/$zotcron
|
||||
echo " df -h" >> /var/www/$zotcron
|
||||
echo " echo \"\$(date) - db size...\"" >> /var/www/$zotcron
|
||||
echo " du -h $backup_mount_point | grep mysql/zotserver" >> /var/www/$zotcron
|
||||
echo " echo \"unmounting backup device...\"" >> /var/www/$zotcron
|
||||
echo " umount $backup_mount_point" >> /var/www/$zotcron
|
||||
echo " else" >> /var/www/$zotcron
|
||||
echo " echo \"failed to mount device $backup_device_name\"" >> /var/www/$zotcron
|
||||
echo " fi" >> /var/www/$zotcron
|
||||
if [ -n "$backup_device_pass" ]
|
||||
then
|
||||
echo " echo \"closing decrypted backup device...\"" >> /var/www/$zotcron
|
||||
echo " cryptsetup luksClose cryptobackup" >> /var/www/$zotcron
|
||||
fi
|
||||
echo " fi" >> /var/www/$zotcron
|
||||
echo "fi" >> /var/www/$zotcron
|
||||
echo "if [ \$device_mounted == 0 ]" >> /var/www/$zotcron
|
||||
echo "then" >> /var/www/$zotcron
|
||||
echo " echo \"device could not be mounted $backup_device_name. No backup written.\"" >> /var/www/$zotcron
|
||||
echo "fi" >> /var/www/$zotcron
|
||||
echo "#" >> /var/www/$zotcron
|
||||
echo "echo \"\$(date) - db size...\"" >> /var/www/$zotcron
|
||||
echo "du -h /var/lib/mysql/ | grep mysql/" >> /var/www/$zotcron
|
||||
echo "#" >> /var/www/$zotcron
|
||||
echo "cd /var/www" >> /var/www/$zotcron
|
||||
echo "for f in *-daily.sh; do \"./\${f}\"; done" >> /var/www/$zotcron
|
||||
echo "echo \"\$(date) - updating linux...\"" >> /var/www/$zotcron
|
||||
echo "apt-get -q -y update && apt-get -q -y dist-upgrade && apt-get -q -y autoremove # update linux and upgrade" >> /var/www/$zotcron
|
||||
echo "echo \"\$(date) - Backup and update finished. Rebooting...\"" >> /var/www/$zotcron
|
||||
echo "#" >> /var/www/$zotcron
|
||||
echo "shutdown -r now" >> /var/www/$zotcron
|
||||
|
||||
# If global cron job does not exist we add it to /etc/crontab
|
||||
if grep -q $zotcron /etc/crontab
|
||||
then
|
||||
echo "cron job already in /etc/crontab"
|
||||
else
|
||||
echo "30 05 * * * root /bin/bash /var/www/$zotcron >> /var/www/zot-daily.log 2>&1" >> /etc/crontab
|
||||
echo "0 0 1 * * root rm /var/www/zot-daily.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
|
||||
|
||||
zotserver_name
|
||||
print_info "We're installing a $zotserver instance"
|
||||
install_path="$(dirname "$(pwd)")"
|
||||
install_folder="$(basename $install_path)"
|
||||
|
||||
# Read config file edited by user
|
||||
configfile=zotserver-config.txt
|
||||
source $configfile
|
||||
|
||||
selfhostdir=/etc/selfhost
|
||||
selfhostscript=selfhost-updater.sh
|
||||
zotcron="zotcron.sh"
|
||||
zotserverdaily="${install_folder}-${zotserver}-daily.sh"
|
||||
backup_mount_point="/media/zotserver_backup"
|
||||
|
||||
#set -x # activate debugging from here
|
||||
|
||||
check_config
|
||||
stop_zotserver
|
||||
update_upgrade
|
||||
install_curl
|
||||
install_wget
|
||||
install_sendmail
|
||||
if [ $webserver = "nginx" ]
|
||||
then
|
||||
install_nginx
|
||||
elif [ $webserver = "apache" ]
|
||||
then
|
||||
install_apache
|
||||
else
|
||||
die "Failed to install a Web server: 'webserver' not set to \"apache\" or \"nginx\" in $configfile"
|
||||
fi
|
||||
install_imagemagick
|
||||
install_php
|
||||
if [ $webserver = "nginx" ]
|
||||
then
|
||||
add_nginx_block
|
||||
elif [ $webserver = "apache" ]
|
||||
then
|
||||
if [ "$install_path" != "/var/www/html" ]
|
||||
then
|
||||
add_vhost
|
||||
fi
|
||||
fi
|
||||
install_mysql
|
||||
if [ $webserver = "apache" ]
|
||||
then
|
||||
install_adminer
|
||||
fi
|
||||
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_zotserverdaily
|
||||
|
||||
configure_cron_daily
|
||||
|
||||
if [ "$le_domain" != "localhost" ]
|
||||
then
|
||||
install_cryptosetup
|
||||
install_rsync
|
||||
else
|
||||
print_info "is localhost - skipped installation of cryptosetup"
|
||||
fi
|
||||
|
||||
|
||||
#set +x # stop debugging from here
|
||||
331
CHANGELOG
331
CHANGELOG
@@ -1,3 +1,228 @@
|
||||
Hubzilla 5.0.5 (2020-12-12)
|
||||
- Fix hubloc issue in mod getfile
|
||||
- Remove duplicate SQL query
|
||||
|
||||
|
||||
Hubzilla 5.0.4 (2020-12-01)
|
||||
- Fix regression updating the primary
|
||||
- Dismiss title in response activities
|
||||
|
||||
|
||||
Hubzilla 5.0.3 (2020-11-26)
|
||||
- Upgrade phpunit to version 9
|
||||
- Remove dbunit because its not maintained anymore
|
||||
- Add uuid version 5 based uuid's to imported feeds
|
||||
- Fix potential delivery loop
|
||||
- Fix actor of fetched activities not stored
|
||||
- Improve update mechanism for comments and likes to prevent page jumps
|
||||
- Fix issue where channel suggestions was suggesting oneself
|
||||
- Do not auto-update except for own actions
|
||||
- Introduce ctrl-enter shortcut to send comments and posts
|
||||
|
||||
Addons
|
||||
Pubcrawl: improve addressing of mentioned actors
|
||||
|
||||
|
||||
Hubzilla 5.0.2 (2020-11-16)
|
||||
- Fix edge case in acl selector
|
||||
- Fix ping_site()
|
||||
- Fix directory post url
|
||||
- Update russian translation
|
||||
- Implement polling for notifications (default) - SSE can be enabled in /admin/site if desired
|
||||
- DB update to remove hublocs with no hubloc_hash or no hubloc_callback
|
||||
- Do not save actors without an inbox
|
||||
- Fix import_hublocs()
|
||||
|
||||
Addons
|
||||
- Pubcrawl: do not save actors without an inbox
|
||||
- Diaspora: fix issue with diaspora where hublocs without hubloc_hash were stored
|
||||
|
||||
|
||||
Hubzilla 5.0.1 (2020-11-12)
|
||||
- Fix share title size
|
||||
- Fix issue where hublocs could get mixed up between different protocols
|
||||
|
||||
Addons
|
||||
- Pubcrawl: implement authenticated profile fetches which are now partly required in mastodon
|
||||
- Sse: call xchan_query() just once per item
|
||||
- Pubcrawl: reject messages where sender is not the author if ld-signature is not ok
|
||||
|
||||
|
||||
Hubzilla 5.0 (2020-11-05)
|
||||
- Remove unmaintained and deprecated schemas
|
||||
- Deprecate HTML5_Parser library
|
||||
- Implement results caching for public tag and profile categories fetching
|
||||
- Deprecate $a variable for *_plugin_admin() and *_plugin_admin_post()
|
||||
- Support remote host cache directives on profile photo fetching
|
||||
- Disable community tags until it is agreed upon on how to implement in zot6 or activitypub
|
||||
- Improve home install setup script
|
||||
- Cryptojs moved to addon
|
||||
- Implement "more encryption" feature with the SJCL library
|
||||
- Add minimum form lifetime check
|
||||
- Improve updateConvItems() performance
|
||||
- Improve infinite scroll experience
|
||||
- Introduce a software bill of material (wip)
|
||||
- Implement new forum behaviour (direct-message a forum to post on its wall) for cross-plattform forum compatibility
|
||||
- Allow apps to be both pinned and starred independently
|
||||
- Add images load status to spinnner if preload images is enabled
|
||||
- Deprecate premium channel app
|
||||
- Allow to set different values for left and right aside width in $theme.php
|
||||
- Display complete permission info only to channel owner
|
||||
- Set CURLOPT_ENCODING to empty string so that compressed content will be uncompressed
|
||||
- Force browser photo revalidation
|
||||
- Deprecate ACTIVITY_OBJ_FILE and ACTIVITY_OBJ_WIKI in favour of other object types (Document, Audio, Video)
|
||||
- Use $mid as plink to prevent to long plinks
|
||||
- Handle some basic friendica attachment bbcodes
|
||||
- Deprecate is_edit_activity()
|
||||
- Deprecate voting feature in favour of polls
|
||||
- Show event timezone if it differs from the channel timezone
|
||||
- Avoid multiple run of expiry procedure on large sites
|
||||
- Implement zot6 as the primary protocol
|
||||
- Introduce polls
|
||||
- Provide titles for wiki links markup
|
||||
- Implement DAV calendars sync with clones
|
||||
- Optional events and poll filters for mod network
|
||||
- Add new addon hook get_banner
|
||||
- Provide tools to deal with spam channels for primary directory admin
|
||||
- Introduce pinned posts for mod channel
|
||||
- Refactor notifications to utilize server sent events
|
||||
- Provide more descriptive connection status icons
|
||||
|
||||
|
||||
Bugfixes
|
||||
- Fix issue where interrupted uploads could not be resumed
|
||||
- Fix photo sync issue between clones
|
||||
- Fix issue where profile photos were fetched for unknown channels
|
||||
- Apply channel name changes to all associated xchans
|
||||
- Show unchecked box in connedit if value is false
|
||||
- Reset their_perms before setting new permissions to reflect permission retractions on local hub
|
||||
- Respect advanced profile setting in sexual preference selector
|
||||
- Do not allow invite codes to be reused unlimited times
|
||||
- Fix issue with quoted hashtags/mentions
|
||||
- Fix issue generating photo thumbnails when uploaded via davfs
|
||||
- Do not call System::get_platform_name() within t() unless needed
|
||||
- Fix wrong URL detection with Markdown support enabled
|
||||
- Fix once cached embedded content is used and stored forever
|
||||
|
||||
Addons
|
||||
- Pubcrawl: fix issue where http signatures were not verified
|
||||
- Pubcrawl: fix issue where private keys were lost from storage
|
||||
- Pubcrawl: add host to signed headers (required by mastodon 3.2.1)
|
||||
- Diaspora: remove relay@relay.iliketoat.net as default relay (it does not exist anymore)
|
||||
- Diaspora: provide UI for admin to configure relay
|
||||
- Diaspora: move the-federation.info registration to statistics addon
|
||||
- Deprecate $a variable for *_plugin_admin() and *_plugin_admin_post()
|
||||
- Chess: moved to addons-unmaintained repository
|
||||
- Introduce cryptojs addon to allow decryption of legacy e2ee notes
|
||||
- Introduce the hide aside addon - fade out aside areas after a while when using endless scroll
|
||||
- Gallery: only show first row of images in the preview
|
||||
- Gallery: restrict height of images to divmore_height
|
||||
- Diaspora: make sure we only provide strings for unxmlify()
|
||||
- Pubcrawl: fix federation with pixelfed
|
||||
- Pubcrawl: dismiss announce if we already have the original item
|
||||
- Gallery: implement view_storage permission for channel_apps()
|
||||
- Cart: order currency param must be added to the sdk script url
|
||||
- Diaspora utilize Lib/Connect
|
||||
- Cart: utilize Lib/Connect
|
||||
- Cart: add per item and per order customer data entry
|
||||
- Pubcrawl: implement polls
|
||||
- Chord Generator: moved to addons-unmaintained repository
|
||||
- Custom Home: moved to addons-unmaintained repository
|
||||
- Flattr Widget: moved to addons-unmaintained repository
|
||||
- Friendica Photo Migrator: moved to addons-unmaintained repository
|
||||
- Jappix Mini: moved to addons-unmaintained repository
|
||||
- Mahjongg: moved to addons-unmaintained repository
|
||||
- Torch: moved to addons-unmaintained repository
|
||||
- Tour: moved to addons-unmaintained repository
|
||||
- Introduce navbanner_option addon
|
||||
- Pubcrawl: support image description
|
||||
- Queueworker: fix duplicate checking
|
||||
- Diaspora: fix dreport
|
||||
- Move legacy zot/diaspora mail frontend from core to mail addon
|
||||
- Diaspora: improve sql queries performance
|
||||
- Pubcrawl: introduce pubcrawl_activity_mod_init()
|
||||
- Twitter: replace Hubzilla bookmark with unicode icon
|
||||
- Pubcrawl: add sys channel to local subscribers
|
||||
- Pubcrawl: deal with arrays in attributedTo
|
||||
- Workflow: various fixes
|
||||
- Channelreputation: various fixes
|
||||
- Introduce SSE addon to provide realtime notifications utilizing server sent events
|
||||
|
||||
|
||||
Hubzilla 4.6 (2019-12-04)
|
||||
- Improve opengraph support for channels
|
||||
- Add opengraph support for articles
|
||||
- Update abook_connected for RSS feeds only if handle_feed() returned success
|
||||
- Do not embed PDF files by default but allow to enabled this feature in security options
|
||||
- Check if file exists before we include it in the router
|
||||
- Update jquery to version 3.4.1
|
||||
- Update composer libraries
|
||||
- Remove old and unused javascript libraries
|
||||
- Improved BBcode to Markdown conversion
|
||||
- Introduce inline SVG support via BBcode
|
||||
- Sanitize title on Atom/RSS feed import
|
||||
- Improved HTTP headers cache support for photos
|
||||
- Add date headers to signed headers
|
||||
- Add check if item['tag'] is an array
|
||||
- Add hook comments_are_now_closed for addons to override date based comment closure
|
||||
- Change mysql schema for item.llink and item.plink for new installs from char(191) to text
|
||||
- Improved photo cache expiration
|
||||
- Improved plural function processing on translation strings creation from .po file with util/po2php utlility
|
||||
- Improved support for CDN/Infrastructure caching (especially profile images)
|
||||
- New japanese translation
|
||||
- Add connect button for non-zot networks not connected in current location
|
||||
- Allow to send forum channels wall2wall or sent by mentions post to external sites via addons
|
||||
- Allow addons to process forum posts published through mentions
|
||||
- Improved internal routing for ActivityPub messages
|
||||
- Improved admin documentation
|
||||
- Add ITEM_TYPE_CUSTOM and hooks to permit addons to create and distribute custom item types
|
||||
- Support "comment policy" in Zot6 communications
|
||||
- Add selected text as quote on reply if comment button is used
|
||||
- Add more nofollow tags to links to discourage backlink farmers
|
||||
- Improved conversion of emoji reactions from zot to zot6
|
||||
- Add CardDAV/CalDAV autodiscovery
|
||||
- Label source project of zotfeed since it is not completely compatible across projects
|
||||
- Update homeinstall script
|
||||
|
||||
Bugfixes
|
||||
- Fix once cached embedded content is used and stored forever
|
||||
- Fix wildcard tag issue
|
||||
- Fix duplicate attachment in jot fileupload
|
||||
- Fix regression with audio file upload
|
||||
- Fix can not edit menu name or title (#1402)
|
||||
- Fix pagination encoding issue for some server setups
|
||||
- Fix Zap->Hubzilla event title compatibility
|
||||
- Fix event timezones for Zot6
|
||||
- Fix missing summary in mod article_edit
|
||||
- Fix PHP warning failed to write session data using user defined save handler
|
||||
- Fix possible thumbnails distortion on rebuild with util/thumbrepair utility
|
||||
- Fix issues with image import to zot6
|
||||
- Fix attachment permissions on clonned channels sync
|
||||
- Fix entries without sitekey returned from DB in queue_deliver() and Lib/Queue
|
||||
|
||||
Addons
|
||||
- Twitter: send tweet even if attached image uploading was unsuccessful
|
||||
- Livejournal: add link to original post option
|
||||
- Flashcards: update to version 2.08
|
||||
- Pubcrawl: compatibility changes to support pixelfed
|
||||
- Cart: update paypal button to API v2
|
||||
- Photocache: rework for speed and lower memory consumption
|
||||
- Photocache: etag support for cached photos
|
||||
- Photocache: purge cache on addon uninstall
|
||||
- Openstreetmap: fix regression if no default values set
|
||||
- Livejournal: allow send posts from non channel owner
|
||||
- Pubcrawl: fix event timezones
|
||||
- Pubcrawl: better ActivityPub channel URL detection
|
||||
- Pubcrawl: fix comments delivery for other channels on the same hub
|
||||
- New addon "workflow" with initial basic "issue tracker" capability
|
||||
|
||||
|
||||
Hubzilla 4.4.1 (2019-08-16)
|
||||
- Fix wrong profile photo displayed when previewing and editing profiles
|
||||
- Fix regression from 4.4 which prevented encrypted signatures from being used for encrypted messages
|
||||
- Fix typo in queueworker addon which broke filtering of duplicate work
|
||||
|
||||
|
||||
Hubzilla 4.4 (2019-08-13)
|
||||
- Change primary directory from zotadel.net to hub.netzgemeinde.eu (requested by zotadel admin)
|
||||
- Add Russian context help files
|
||||
@@ -130,7 +355,7 @@ Hubzilla 4.2 (2019-06-04)
|
||||
|
||||
Hubzilla 4.0.3 (2019-04-26)
|
||||
- Add attachments to zot6 event objects
|
||||
- Add zot6 to federated transports
|
||||
- Add zot6 to federated transports
|
||||
- Update import/export to handle zot6 hublocs and xchans
|
||||
- Update fix_system_urls() to handle zot6 hublocs
|
||||
- Fix infinite loop using postgres as backend
|
||||
@@ -183,7 +408,7 @@ Hubzilla 4.0.1 (2019-03-21)
|
||||
- Perform zot6 discovery in import_author_xchan
|
||||
- Fix authenticated fetches
|
||||
- Port zot_record_preferred() from zap
|
||||
|
||||
|
||||
Addons:
|
||||
- Pubcrawl: deliver comments to abook contacts and thread participants
|
||||
- Pubcrawl: fix can_comment_on_post()
|
||||
@@ -397,7 +622,7 @@ Hubzilla 3.8.3 (2018-11-05)
|
||||
- Fix forum notifications count not correct
|
||||
- Fix gallery addon which broke mod apps in some situations
|
||||
- Fix wiki_list widget not working on every page respectively level
|
||||
|
||||
|
||||
|
||||
Hubzilla 3.8.2 (2018-10-29)
|
||||
- Merge unmerged changes from dev into master
|
||||
@@ -413,7 +638,7 @@ Hubzilla 3.8.2 (2018-10-29)
|
||||
- Look for for matches in the entire string when suggesting emojis
|
||||
- Add [summary] bbcode to autocomplete list
|
||||
- Update blueimp_upload to version 9.23
|
||||
- Update spanish strings
|
||||
- Update spanish strings
|
||||
|
||||
Addons
|
||||
- Cart: don't allow items to be added unless user is logged into the Grid.
|
||||
@@ -471,7 +696,7 @@ Hubzilla 3.8 (2018-10-19)
|
||||
- Sanitise vcard fields
|
||||
- Don't sync system apps
|
||||
|
||||
|
||||
|
||||
Bugfixes
|
||||
- Fix issue with timeago plurals
|
||||
- Fix issue with HTTP signatures
|
||||
@@ -530,7 +755,7 @@ Hubzilla 3.8 (2018-10-19)
|
||||
Hubzilla 3.6 (2018-07-25)
|
||||
- Update jquery.timeago library
|
||||
- Implement Hookable CSP
|
||||
- ActivityStreams: accept header changes to support plume
|
||||
- ActivityStreams: accept header changes to support plume
|
||||
- Streamline inconsistencies in addon naming
|
||||
- SECURITY: hash the session_id in logs
|
||||
- Update justified gallery library
|
||||
@@ -543,9 +768,9 @@ Hubzilla 3.6 (2018-07-25)
|
||||
- Make droping posts of removed connections more memory efficient
|
||||
- Refactor getOutainfo() for DAV storage
|
||||
- Optionally report total available space when uploading
|
||||
- SECURITY: provide option to disable the cloud 'root' directory and make the cloud module require a target channel nickname
|
||||
- SECURITY: provide option to disable the cloud 'root' directory and make the cloud module require a target channel nickname
|
||||
- Add plink and llink to viewsource
|
||||
- Add new 'filter by name' feature
|
||||
- Add new 'filter by name' feature
|
||||
- Remove network tabs
|
||||
- New activity filter widget
|
||||
- New activity order widget
|
||||
@@ -587,8 +812,8 @@ Hubzilla 3.6 (2018-07-25)
|
||||
- Fix sys channels visible in dirsearch
|
||||
- Fix remote_self not working correctly
|
||||
- Fix photos not syncing properly if destination is a postgres site
|
||||
- Fix wrong hubloc_url for activitypub hublocs
|
||||
- Fix z_check_dns() for BSD
|
||||
- Fix wrong hubloc_url for activitypub hublocs
|
||||
- Fix z_check_dns() for BSD
|
||||
- Fix not null violation in oauth1
|
||||
- Fix DB issues with oauth2 on postgresql
|
||||
- Fix 'anybody authenticated' not correctly handled in can_comment_on_post()
|
||||
@@ -1150,10 +1375,10 @@ Hubzilla 2.6.2 (2017-08-31)
|
||||
Hubzilla 2.6.1 (2017-08-18)
|
||||
- Fix a regression with dav clients
|
||||
- Raise install requirements
|
||||
|
||||
|
||||
Plugins/Addon
|
||||
- Diaspora: fix PHP warning
|
||||
- GNU-Social: fix PHP warning
|
||||
- GNU-Social: fix PHP warning
|
||||
|
||||
|
||||
Hubzilla 2.6 (2017-08-16)
|
||||
@@ -1161,18 +1386,18 @@ Hubzilla 2.6 (2017-08-16)
|
||||
- Consolidate disable_discover_tab config
|
||||
- Fix some bbcode to markdown conversion issues
|
||||
- Improved finding of recursive attachment permissions
|
||||
- Smaller line-height for notification badges
|
||||
- Smaller line-height for notification badges
|
||||
- Bluegrid schema removed - will be added again if someone is willing to maintain it
|
||||
- Improved file_activity()
|
||||
- DB - add index for item.obj_type
|
||||
- Add options flag to bb_to_markdown() so we can distinguish between diaspora use and other use and therefore filter and adjust content selectively
|
||||
- Close the apps-menu if the notifications-menu is open and vice versa
|
||||
- Close the apps-menu if the notifications-menu is open and vice versa
|
||||
- Remove redundant call to jquery ready function in photo albums view
|
||||
- Remove borders from navbar toggler in mobile view
|
||||
- Improve the formatting of shares when converting from bbcode to markdown
|
||||
- Suppress fopen errors from dav
|
||||
- Make local channel (not our own) nav menus appear similar to what we are used from remote channels
|
||||
- Indicate the selected channel in the dropdown menu if the feature is enabled
|
||||
- Indicate the selected channel in the dropdown menu if the feature is enabled
|
||||
- Provide a mechanism to mark apps active in the app tray
|
||||
- Allow wildcard tag and category searches
|
||||
- Improved installer
|
||||
@@ -1184,7 +1409,7 @@ Hubzilla 2.6 (2017-08-16)
|
||||
- Update htmlpurifier to version 4.9.3
|
||||
- Update sabre/http to version 4.2.3
|
||||
- Add optimize-autoloader to composer config
|
||||
- Missing abook_{my,their}_perms in pg schema and missing keys in mysql schema
|
||||
- Missing abook_{my,their}_perms in pg schema and missing keys in mysql schema
|
||||
- Provide a gender icon on the profile sidebar within reason
|
||||
- Provide more comprehensible information on the admin summary page
|
||||
- Upgrade blueimp from 9.8 to 9.18
|
||||
@@ -1250,7 +1475,7 @@ Hubzilla 2.6 (2017-08-16)
|
||||
Cdav addon moved to core
|
||||
head_add_css() needs a preceding '/' to find files in the addons dir
|
||||
New addon code syntax highlighting (moved from core to addon)
|
||||
Pubsubhubbub: specify a minimum number of records - otherwise it defaults to zero
|
||||
Pubsubhubbub: specify a minimum number of records - otherwise it defaults to zero
|
||||
|
||||
|
||||
Hubzilla 2.4 (2017-05-31)
|
||||
@@ -1604,10 +1829,10 @@ Hubzilla 1.14 (2016-10-13)
|
||||
- Start grouping addons by server_role
|
||||
|
||||
Hubzilla 1.12
|
||||
- extensible permissions so you can create a new permission rule such as "can write to my wiki" or "can see me naked".
|
||||
- guest access tokens can do anything you let them, including create posts and administer your channel
|
||||
- extensible permissions so you can create a new permission rule such as "can write to my wiki" or "can see me naked".
|
||||
- guest access tokens can do anything you let them, including create posts and administer your channel
|
||||
- ACLs can be set on files and directories prior to creation.
|
||||
- ACL tool can now be used in multiple forms within a page
|
||||
- ACL tool can now be used in multiple forms within a page
|
||||
- a myriad of new drag/drop features (drop files or photos into /cloud or a post, or drop link into a post or comment, etc.)
|
||||
- multiple file uploads
|
||||
- improvements to website import
|
||||
@@ -1632,7 +1857,7 @@ Hubzilla 1.10
|
||||
Wiki:
|
||||
Lots of enhanced functionality, usability improvements, and bugfixes from v1.8
|
||||
Turned into an optional feature (default on) but disabled in UNO
|
||||
Sync:
|
||||
Sync:
|
||||
Items are now relocated (links patched) when syncing to clones
|
||||
Access Tokens:
|
||||
New feature - allows members to create access controlled guest logins and create/share 'dropbox' style links to protected resources.
|
||||
@@ -1640,7 +1865,7 @@ Hubzilla 1.10
|
||||
Use icons instead of iconic text constructs
|
||||
Only request geolocation permission when creating a post, not on page load
|
||||
provide 'redeliver' option on Delivery Report page for when things really stuff up
|
||||
CalDAV/CardDAV management pages with heaps of functionality
|
||||
CalDAV/CardDAV management pages with heaps of functionality
|
||||
Lib:
|
||||
z_fetch_url() updated to accept different request methods and request bodies
|
||||
item_store(), item_store_update() now return the stored items
|
||||
@@ -1664,7 +1889,7 @@ Hubzilla 1.10
|
||||
issues with 'use existing photo' for profile photo
|
||||
layout editor "list all layouts" returned empty
|
||||
oembed - better detect video file URLs so they aren't loaded into memory.
|
||||
handcrafted bbcode tables could end up with way too much whitespace due to CRLF translation
|
||||
handcrafted bbcode tables could end up with way too much whitespace due to CRLF translation
|
||||
refresh permissions whitescreen in 1.8
|
||||
force immediate profile photo update on local site
|
||||
regression: 'save bookmarks' post action missing
|
||||
@@ -1689,7 +1914,7 @@ Hubzilla 1.8
|
||||
Documentation:
|
||||
Clarify privacy rights of commenters w/r/t conversation owners, as this policy is network dependent.
|
||||
Wiki (Git backed):
|
||||
Brand new feature. We'll call it experimental until it has undergone a bit more testing.
|
||||
Brand new feature. We'll call it experimental until it has undergone a bit more testing.
|
||||
Account Cloning:
|
||||
Regression on clone channel creation created a new channel name each time.
|
||||
New issue (fixed) with directory creation on cloned file content
|
||||
@@ -1712,7 +1937,7 @@ Hubzilla 1.8
|
||||
Experimental PDO database driver
|
||||
Creation of Daemon Master class and port all daemon (background task) interfaces to use it
|
||||
Create separate class for each of 'Cron', 'Cron daily', and 'Cron weekly'.
|
||||
Always run a Cron maintenance task if not run in the last four hours
|
||||
Always run a Cron maintenance task if not run in the last four hours
|
||||
Refactor the template classes
|
||||
Refactor the ConversationItem mess into ThreadItem and ThreadStream
|
||||
Refactor Apps, Enotify, and Chat library code
|
||||
@@ -1720,7 +1945,7 @@ Hubzilla 1.8
|
||||
Created WebServer class for top level
|
||||
Remove mcrypt dependencies (deprecated in PHP 7.1)
|
||||
Remove all reserved (including merely 'not recommended') words as DB table column names
|
||||
Provide mutex lock on DB logging to prevent recursion under rare failure modes.
|
||||
Provide mutex lock on DB logging to prevent recursion under rare failure modes.
|
||||
Bugfixes:
|
||||
Remove db_close function on page end - not needed and will not work with persistent DB connections.
|
||||
Undefined ref_session_write
|
||||
@@ -1740,7 +1965,7 @@ Hubzilla 1.8
|
||||
CalDAV/CardDAV plugin provided
|
||||
Issue sending Diaspora 'like' activities from sources that did not propagate the DCV
|
||||
Allow 'superblock' to work across API calls from third party clients
|
||||
statistics.json: use 'zot' as protocol
|
||||
statistics.json: use 'zot' as protocol
|
||||
Issues fixed during testing of ability to follow Diaspora tags
|
||||
Parse issue with Diaspora reshare content
|
||||
Chess: moved to main repo, ported to 1.8
|
||||
@@ -1752,7 +1977,7 @@ Hubzilla 1.6
|
||||
Plugin hook interface adapted to call static class methods
|
||||
Context help improved dramatically with content for the most accessed pages.
|
||||
Reverted a compatibility change to support GNU-social events. We copied their feed format and their feed format is wrong (XML namespace collisions).
|
||||
Provide a querystring attribute to CSS/JS resources to avoid caching issues when our code changes (which is often).
|
||||
Provide a querystring attribute to CSS/JS resources to avoid caching issues when our code changes (which is often).
|
||||
Fix javascript detection and allow either positive or negative detection.
|
||||
Refactor the plugin hook registration procedure, provide 'unregister all' ability.
|
||||
Fix RSD (Real Simple Discovery) which has been broken for some time.
|
||||
@@ -1761,7 +1986,7 @@ Hubzilla 1.6
|
||||
Update font-awesome to 4.6.1
|
||||
Update SabreDAV to 3.0 (PHP version requirements prevent us from pushing it further at this time)
|
||||
Help text added to cmdline utilities config and pconfig
|
||||
Reworking of the database logging facility to avoid the rare but troublesome recursion when the log facility needed to query the DB internally to obtain config parameters.
|
||||
Reworking of the database logging facility to avoid the rare but troublesome recursion when the log facility needed to query the DB internally to obtain config parameters.
|
||||
Implement singleton delivery (emulate nomadic identity to singleton networks and services)
|
||||
Fix empty album name in photo activities when photo is stored in top level folder.
|
||||
Allow engineering units to be used in service class data size restrictions (400M, 1G, etc.)
|
||||
@@ -1769,7 +1994,7 @@ Hubzilla 1.6
|
||||
Admin interface provided to manage external resource repositories
|
||||
Oembed security reworked. Now all sources are filtered by default unless blocked.
|
||||
Remove the date-string version and use only STD_VERSION
|
||||
Add categories and categorisation filtering and the ability to edit all apps (including system apps) for a given channel
|
||||
Add categories and categorisation filtering and the ability to edit all apps (including system apps) for a given channel
|
||||
Ensure the ability to translate names of all system apps (except those provided in addons)
|
||||
Provide ability to add categories to content from channel sources
|
||||
Lots of work on the presentation of the ACL widget to enhance usability and intuitiveness
|
||||
@@ -1783,24 +2008,24 @@ Hubzilla 1.6
|
||||
Provide some extra security checks to import data and files to prevent mischief
|
||||
Block CalDAV/CardDAV namespace reserved words from being used as a channel nickname/redress since Sabre is somewhat inflexible in this regard
|
||||
Plugins:
|
||||
Diaspora
|
||||
markdown translator work needed to eradicate the Diaspora Comment Virus.
|
||||
Diaspora
|
||||
markdown translator work needed to eradicate the Diaspora Comment Virus.
|
||||
upgrade all inbound paths with the most recent protocol changes (several of these)
|
||||
convert 'diaspora_meta' (Diaspora Comment Virus) to iconfig and eradicate from sites with Diaspora disabled
|
||||
implement social relay and allow following tags
|
||||
upgrade statistics.json to NodeInfo. Currently hubzilla sites are tagged as 'redmatrix' because the NodeInfo schema lacks extensibility and project names are used to designate protocol compatibility rather than protocol names.
|
||||
Std-embeds
|
||||
New addon to allow a handful of corporate providers to run unfiltered embed code (youtube, vimeo, soundcloud)
|
||||
New addon to allow a handful of corporate providers to run unfiltered embed code (youtube, vimeo, soundcloud)
|
||||
Various:
|
||||
upgrade font-awesome icons and adapt a few addons to Objects and the new hook interface and new controller interface
|
||||
|
||||
|
||||
Hubzilla 1.4
|
||||
[This list may appear brief, but encompasses a huge amount of re-writing and re-factoring
|
||||
of the internal code structure to gain long-term performance and stability and provide a standard
|
||||
interface to alternate protocol federation plugins which were made possible by the UNO configuration.
|
||||
UNO is a configuration of hubzilla introduced in 1.3 with reduced complexity and which provides
|
||||
improved protocol federation potential to other networks by virtue of removing nomadic identity
|
||||
(which is not possible to model or work around using other network protocols).]
|
||||
UNO is a configuration of hubzilla introduced in 1.3 with reduced complexity and which provides
|
||||
improved protocol federation potential to other networks by virtue of removing nomadic identity
|
||||
(which is not possible to model or work around using other network protocols).]
|
||||
|
||||
Implement channel move operation for UNO configuration
|
||||
Remove bookmark references in UNO (which has no bookmarks by default)
|
||||
@@ -1823,10 +2048,10 @@ Hubzilla 1.4
|
||||
Rework detection of JavaScript to avoid reload penalty under normal operation
|
||||
Changed primary directory server to a hubzilla server
|
||||
Plugins:
|
||||
Diaspora - switch to alternate XML parser to avoid storing compound objects
|
||||
Diaspora - switch to alternate XML parser to avoid storing compound objects
|
||||
GNU-Social - Huge amounts of work, federation somewhat working now, several issues remain
|
||||
Friendica - Initial federation work (not yet published)
|
||||
|
||||
|
||||
Hubzilla 1.3
|
||||
Admin Security configuration page created which consolidates several previously hidden settings:
|
||||
Communication white/black lists
|
||||
@@ -1842,26 +2067,26 @@ Hubzilla 1.3
|
||||
"pubsites" module UI reworked
|
||||
item-meta ("iconfig") created which implements arbitrary storage for item metadata for plugins
|
||||
abook-meta ("abconfig") created which implements arbitrary storage for connection metadata for plugins
|
||||
"Strict transport security header" made optional as it conflicts with some existing Apache/nginx configurations
|
||||
"Hubzilla UNO" (Hubzilla with radically simplified and locked site settings) implemented as an install configuration.
|
||||
"Strict transport security header" made optional as it conflicts with some existing Apache/nginx configurations
|
||||
"Hubzilla UNO" (Hubzilla with radically simplified and locked site settings) implemented as an install configuration.
|
||||
.well-known directory conflict worked out to support LetsEncrypt cert ownership checks without disrupting webfinger and other internal uses of .well-known
|
||||
Lots of work on 'zcards' which are self-contained HTML representations of a channel including cover photos, profile photos, and some text information
|
||||
Long standing bug uncovered which failed to properly restrict the lower time limit for public feed requests
|
||||
A number of fixes to "readmore" to fix page jumping
|
||||
Bugfix: persons other than the channel owner who have permission to upload photos to a channel could not do so if the js_upload plugin/addon was enabled
|
||||
Siteinfo incorrectly identifying secondary directory servers
|
||||
Allow admin to set and lock features when UNO is configured
|
||||
Allow admin to set and lock features when UNO is configured
|
||||
Atom feeds: alter how events are formatted to be compatible with GNU-social
|
||||
Allow guest/visitor access to view personal calendar
|
||||
Moved several more classes to "composer format" and provided an autoloader.
|
||||
Bugfix: require existing password to change password
|
||||
Bugfix: allow relative_date() to be translated to Polish which has more than two plural forms.
|
||||
Bugfix: allow relative_date() to be translated to Polish which has more than two plural forms.
|
||||
Plugin API: add "requires" keyword to module header to indicate dependent addons
|
||||
ActivityStreams improvements and cleanup: photo and file activities
|
||||
UI cleanup for editing profile when multiple profiles enabled
|
||||
Removed the "markdown" feature as there are numerous issues and no maintainer.
|
||||
Provide "footer" bbcode to ease theming of post footer content
|
||||
Bugfix: install issues caused by composer code refactor and typo in postgres load file
|
||||
Bugfix: install issues caused by composer code refactor and typo in postgres load file
|
||||
Plugins:
|
||||
keepout - "block public on steroids"
|
||||
pubsubhubbub - provides PuSH support to Atom feeds, required for GNU-social federation
|
||||
@@ -1869,7 +2094,7 @@ Hubzilla 1.3
|
||||
Diaspora protocol - some work to ease migration to the new signing format
|
||||
Diaspost - disabled; numerous issues and no maintainer
|
||||
smileybutton - theme work and fixed compatibility with other jot-tools plugins
|
||||
|
||||
|
||||
|
||||
Hubzilla 1.2
|
||||
Provide extra HTTP security headers (several of them).
|
||||
@@ -1879,7 +2104,7 @@ Hubzilla 1.2
|
||||
Add locked features to siteinfo report to aid remote debugging
|
||||
Provide version compatibility checking to plugins (minversion, maxversion, and minphpversion)
|
||||
Account config storage
|
||||
Provide optional integrated registration and channel create form
|
||||
Provide optional integrated registration and channel create form
|
||||
cli utility for managing addons
|
||||
issue with sharing photo "items"
|
||||
cover photo manager: upload, crop, and store
|
||||
@@ -1901,7 +2126,7 @@ Hubzilla 1.2
|
||||
proc_run modified to use exec() instead of proc_open() - causing issues on some PHP installations
|
||||
remote delegation failure under a specific set of circumstances which we were finally able to duplicate
|
||||
Delegation section of Channel Manager was missing names and contained useless notification icons.
|
||||
Change "expire" channel setting to show system limit if there is one.
|
||||
Change "expire" channel setting to show system limit if there is one.
|
||||
Regression: provide a one-click ignore of pending connection
|
||||
Config to control directory keyword generation on client and server.
|
||||
"Collections" renamed to "Privacy Groups", documentation improved
|
||||
@@ -1954,11 +2179,11 @@ Hubzilla 1.1
|
||||
Addons/Plugins:
|
||||
Pageheader addon ported from Friendica
|
||||
Hubwall (allow admin to send email to all accounts on this hub) created
|
||||
GNU-social - queueing added
|
||||
Diaspora - fixes for various failures to update profile photos, updates to queue API
|
||||
GNU-social - queueing added
|
||||
Diaspora - fixes for various failures to update profile photos, updates to queue API
|
||||
Cross Domain Authenticated Chess (Andrew Manning's repository)
|
||||
|
||||
And... the normal "lots of bugs fixed, translations updated, and documentation improved"
|
||||
|
||||
|
||||
|
||||
And... the normal "lots of bugs fixed, translations updated, and documentation improved"
|
||||
|
||||
|
||||
|
||||
|
||||
32
SBOM.md
Normal file
32
SBOM.md
Normal file
@@ -0,0 +1,32 @@
|
||||
# Hubzilla Software Bill of Materials - WIP
|
||||
|
||||
|Name|Version|License|Source|
|
||||
|----|-------|-------|------|
|
||||
|blueimp/jquery-file-upload|10.31.0.0|MIT|https://github.com/vkhramtsov/jQuery-File-Upload.git|
|
||||
|bshaffer/oauth2-server-php|1.11.1.0|MIT|https://github.com/bshaffer/oauth2-server-php.git|
|
||||
|commerceguys/intl|1.0.5.0|MIT|https://github.com/commerceguys/intl.git|
|
||||
|desandro/imagesloaded|4.1.4.0|MIT|https://github.com/desandro/imagesloaded.git|
|
||||
|ezyang/htmlpurifier|4.13.0.0|LGPL-2.1-or-later|https://github.com/ezyang/htmlpurifier.git|
|
||||
|league/html-to-markdown|4.10.0.0|MIT|https://github.com/thephpleague/html-to-markdown.git|
|
||||
|lukasreschke/id3parser|0.0.3.0|GPL|https://github.com/LukasReschke/ID3Parser.git|
|
||||
|michelf/php-markdown|1.9.0.0|BSD-3-Clause|https://github.com/michelf/php-markdown.git|
|
||||
|paragonie/random_compat|9.99.99.0|MIT|https://github.com/paragonie/random_compat.git|
|
||||
|pear/text_languagedetect|1.0.0.0|BSD-2-Clause|https://github.com/pear/Text_LanguageDetect.git|
|
||||
|psr/log|1.1.3.0|MIT|https://github.com/php-fig/log.git|
|
||||
|ramsey/uuid|3.9.3.0|MIT|https://github.com/ramsey/uuid.git|
|
||||
|sabre/dav|4.1.1.0|BSD-3-Clause|https://github.com/sabre-io/dav.git|
|
||||
|sabre/event|5.1.0.0|BSD-3-Clause|https://github.com/sabre-io/event.git|
|
||||
|sabre/http|5.1.0.0|BSD-3-Clause|https://github.com/sabre-io/http.git|
|
||||
|sabre/uri|2.2.0.0|BSD-3-Clause|https://github.com/sabre-io/uri.git|
|
||||
|sabre/vobject|4.3.1.0|BSD-3-Clause|https://github.com/sabre-io/vobject.git|
|
||||
|sabre/xml|2.2.1.0|BSD-3-Clause|https://github.com/sabre-io/xml.git|
|
||||
|simplepie/simplepie|1.5.5.0|BSD-3-Clause|https://github.com/simplepie/simplepie.git|
|
||||
|smarty/smarty|3.1.36.0|LGPL-3.0|https://github.com/smarty-php/smarty.git|
|
||||
|symfony/polyfill-ctype|1.13.1.0|MIT|https://github.com/symfony/polyfill-ctype.git|
|
||||
|twbs/bootstrap|4.5.2.0|MIT|https://github.com/twbs/bootstrap.git|
|
||||
|fullcalendar/fullcalendar|4.4.2.0|MIT|https://github.com/fullcalendar/fullcalendar.git|
|
||||
|miromannino/Justified-Gallery|3.8.1.0|MIT|https://github.com/miromannino/Justified-Gallery.git|
|
||||
|fengyuanchen/cropperjs|1.5.7.0|MIT|https://github.com/fengyuanchen/cropperjs.git|
|
||||
|ForkAwesome/Fork-Awesome|1.1.7.0|MIT,SIL OFL,CC BY 3.0|https://github.com/ForkAwesome/Fork-Awesome.git|
|
||||
|leafo/sticky-kit|1.1.2.0|MIT|https://github.com/leafo/sticky-kit.git|
|
||||
|jquery/jquery|3.5.1.0|MIT|https://github.com/jquery/jquery.git|
|
||||
@@ -100,6 +100,7 @@ class PermissionRoles {
|
||||
'post_mail', 'post_like' , 'republish', 'chat'
|
||||
];
|
||||
$ret['limits'] = PermissionLimits::Std_Limits();
|
||||
$ret['channel_type'] = 'group';
|
||||
|
||||
break;
|
||||
|
||||
@@ -113,6 +114,7 @@ class PermissionRoles {
|
||||
'view_pages', 'view_wiki', 'post_wall', 'post_comments', 'tag_deliver',
|
||||
'post_mail', 'post_like' , 'chat' ];
|
||||
$ret['limits'] = PermissionLimits::Std_Limits();
|
||||
$ret['channel_type'] = 'group';
|
||||
|
||||
break;
|
||||
|
||||
@@ -132,6 +134,7 @@ class PermissionRoles {
|
||||
$ret['limits']['view_storage'] = PERMS_SPECIFIC;
|
||||
$ret['limits']['view_pages'] = PERMS_SPECIFIC;
|
||||
$ret['limits']['view_wiki'] = PERMS_SPECIFIC;
|
||||
$ret['channel_type'] = 'group';
|
||||
|
||||
break;
|
||||
|
||||
@@ -187,6 +190,7 @@ class PermissionRoles {
|
||||
'post_mail', 'post_like' , 'republish', 'chat', 'write_wiki'
|
||||
];
|
||||
$ret['limits'] = PermissionLimits::Std_Limits();
|
||||
$ret['channel_type'] = 'group';
|
||||
|
||||
break;
|
||||
|
||||
|
||||
@@ -283,4 +283,15 @@ class Permissions {
|
||||
return ( [ 'perms' => $my_perms, 'automatic' => $automatic ] );
|
||||
}
|
||||
|
||||
}
|
||||
static public function serialise($p) {
|
||||
$n = [];
|
||||
if($p) {
|
||||
foreach($p as $k => $v) {
|
||||
if(intval($v)) {
|
||||
$n[] = $k;
|
||||
}
|
||||
}
|
||||
}
|
||||
return implode(',',$n);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,7 @@
|
||||
|
||||
namespace Zotlabs\Daemon;
|
||||
|
||||
require_once('include/zot.php');
|
||||
|
||||
require_once('include/hubloc.php');
|
||||
|
||||
class Checksites {
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
namespace Zotlabs\Daemon;
|
||||
|
||||
use Zotlabs\Lib\Libsync;
|
||||
|
||||
class Cron {
|
||||
|
||||
static public function run($argc,$argv) {
|
||||
@@ -36,10 +38,14 @@ class Cron {
|
||||
|
||||
Master::Summon(array('Poller'));
|
||||
|
||||
// maintenance for mod sharedwithme - check for updated items and remove them
|
||||
|
||||
require_once('include/sharedwithme.php');
|
||||
apply_updates();
|
||||
/**
|
||||
* Chatpresence: if somebody hasn't pinged recently, they've most likely left the page
|
||||
* and shouldn't count as online anymore. We allow an expection for bots.
|
||||
*/
|
||||
q("delete from chatpresence where cp_last < %s - INTERVAL %s and cp_client != 'auto' ",
|
||||
db_utcnow(),
|
||||
db_quoteinterval('3 MINUTE')
|
||||
);
|
||||
|
||||
// expire any expired mail
|
||||
|
||||
@@ -97,13 +103,17 @@ class Cron {
|
||||
|
||||
// Clean expired photos from cache
|
||||
|
||||
$age = get_config('system','active_expire_days', '30');
|
||||
$r = q("SELECT DISTINCT xchan, content FROM photo WHERE photo_usage = %d AND expires < %s - INTERVAL %s",
|
||||
intval(PHOTO_CACHE),
|
||||
db_utcnow(),
|
||||
db_quoteinterval($age . ' DAY')
|
||||
db_utcnow(),
|
||||
db_quoteinterval(get_config('system','active_expire_days', '30') . ' DAY')
|
||||
);
|
||||
if($r) {
|
||||
q("DELETE FROM photo WHERE photo_usage = %d AND expires < %s - INTERVAL %s",
|
||||
intval(PHOTO_CACHE),
|
||||
db_utcnow(),
|
||||
db_quoteinterval(get_config('system','active_expire_days', '30') . ' DAY')
|
||||
);
|
||||
foreach($r as $rr) {
|
||||
$file = dbunescbin($rr['content']);
|
||||
if(is_file($file)) {
|
||||
@@ -113,11 +123,6 @@ class Cron {
|
||||
}
|
||||
}
|
||||
}
|
||||
q("DELETE FROM photo WHERE photo_usage = %d AND expires < %s - INTERVAL %s",
|
||||
intval(PHOTO_CACHE),
|
||||
db_utcnow(),
|
||||
db_quoteinterval($age . ' DAY')
|
||||
);
|
||||
|
||||
// publish any applicable items that were set to be published in the future
|
||||
// (time travel posts). Restrict to items that have come of age in the last
|
||||
@@ -139,7 +144,7 @@ class Cron {
|
||||
if($z) {
|
||||
xchan_query($z);
|
||||
$sync_item = fetch_post_tags($z);
|
||||
build_sync_packet($sync_item[0]['uid'],
|
||||
Libsync::build_sync_packet($sync_item[0]['uid'],
|
||||
[
|
||||
'item' => [ encode_item($sync_item[0],true) ]
|
||||
]
|
||||
@@ -150,6 +155,11 @@ class Cron {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// check if any connections transitioned to zot6 and upgrade the connections to zot6 at this hub if so.
|
||||
require_once('include/connections.php');
|
||||
z6trans_connections();
|
||||
|
||||
require_once('include/attach.php');
|
||||
attach_upgrade();
|
||||
|
||||
@@ -215,7 +225,7 @@ class Cron {
|
||||
$restart = true;
|
||||
$generation = intval($argv[2]);
|
||||
if(! $generation)
|
||||
killme();
|
||||
return;
|
||||
}
|
||||
|
||||
reload_plugins();
|
||||
|
||||
@@ -44,6 +44,17 @@ class Cron_daily {
|
||||
db_utcnow(), db_quoteinterval('1 YEAR')
|
||||
);
|
||||
|
||||
// expire anonymous sse notification entries once a day
|
||||
|
||||
q("delete from xconfig where xchan like '%s'",
|
||||
dbesc('sse_id.%')
|
||||
);
|
||||
|
||||
// Clean up emdedded content cache
|
||||
q("DELETE FROM cache WHERE updated < %s - INTERVAL %s",
|
||||
db_utcnow(),
|
||||
db_quoteinterval(get_config('system','active_expire_days', '30') . ' DAY')
|
||||
);
|
||||
|
||||
//update statistics in config
|
||||
require_once('include/statistics_fns.php');
|
||||
@@ -85,6 +96,7 @@ class Cron_daily {
|
||||
Master::Summon(array('Cli_suggest'));
|
||||
|
||||
remove_obsolete_hublocs();
|
||||
|
||||
z6_discover();
|
||||
|
||||
call_hooks('cron_daily',datetime_convert());
|
||||
|
||||
@@ -13,7 +13,7 @@ class CurlAuth {
|
||||
static public function run($argc,$argv) {
|
||||
|
||||
if($argc != 2)
|
||||
killme();
|
||||
return;
|
||||
|
||||
\App::$session->start();
|
||||
|
||||
@@ -50,6 +50,6 @@ class CurlAuth {
|
||||
|
||||
file_put_contents($c,$x);
|
||||
|
||||
killme();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,12 +2,8 @@
|
||||
|
||||
namespace Zotlabs\Daemon;
|
||||
|
||||
use Zotlabs\Lib\DReport;
|
||||
|
||||
require_once('include/zot.php');
|
||||
require_once('include/queue_fn.php');
|
||||
|
||||
|
||||
class Deliver {
|
||||
|
||||
static public function run($argc,$argv) {
|
||||
@@ -22,72 +18,16 @@ class Deliver {
|
||||
if(! $argv[$x])
|
||||
continue;
|
||||
|
||||
$dresult = null;
|
||||
$r = q("select * from outq where outq_hash = '%s' limit 1",
|
||||
$r = q("select * from outq where outq_hash = '%s'",
|
||||
dbesc($argv[$x])
|
||||
);
|
||||
|
||||
if($r) {
|
||||
|
||||
$notify = json_decode($r[0]['outq_notify'],true);
|
||||
|
||||
// Messages without an outq_msg will need to go via the web, even if it's a
|
||||
// local delivery. This includes conversation requests and refresh packets.
|
||||
|
||||
if(($r[0]['outq_posturl'] === z_root() . '/post') && ($r[0]['outq_msg'])) {
|
||||
logger('deliver: local delivery', LOGGER_DEBUG);
|
||||
|
||||
// local delivery
|
||||
// we should probably batch these and save a few delivery processes
|
||||
|
||||
if($r[0]['outq_msg']) {
|
||||
$m = json_decode($r[0]['outq_msg'],true);
|
||||
if(array_key_exists('message_list',$m)) {
|
||||
foreach($m['message_list'] as $mm) {
|
||||
$msg = array('body' => json_encode(array('success' => true, 'pickup' => array(array('notify' => $notify,'message' => $mm)))));
|
||||
zot_import($msg,z_root());
|
||||
}
|
||||
}
|
||||
else {
|
||||
$msg = array('body' => json_encode(array('success' => true, 'pickup' => array(array('notify' => $notify,'message' => $m)))));
|
||||
$dresult = zot_import($msg,z_root());
|
||||
}
|
||||
|
||||
remove_queue_item($r[0]['outq_hash']);
|
||||
|
||||
if($dresult && is_array($dresult)) {
|
||||
|
||||
// delivery reports for local deliveries do not require encryption
|
||||
|
||||
foreach($dresult as $xx) {
|
||||
if(is_array($xx) && array_key_exists('message_id',$xx)) {
|
||||
if(DReport::is_storable($xx)) {
|
||||
q("insert into dreport ( dreport_mid, dreport_site, dreport_recip, dreport_name, dreport_result, dreport_time, dreport_xchan ) values ( '%s', '%s', '%s', '%s', '%s', '%s', '%s' ) ",
|
||||
dbesc($xx['message_id']),
|
||||
dbesc($xx['location']),
|
||||
dbesc($xx['recipient']),
|
||||
dbesc(($xx['name']) ? $xx['name'] : EMPTY_STR),
|
||||
dbesc($xx['status']),
|
||||
dbesc(datetime_convert($xx['date'])),
|
||||
dbesc($xx['sender'])
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
q("delete from dreport where dreport_queue = '%s'",
|
||||
dbesc($argv[$x])
|
||||
);
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// otherwise it's a remote delivery - call queue_deliver() with the $immediate flag
|
||||
|
||||
queue_deliver($r[0],true);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,10 +2,9 @@
|
||||
|
||||
namespace Zotlabs\Daemon;
|
||||
|
||||
require_once('include/zot.php');
|
||||
require_once('include/dir_fns.php');
|
||||
require_once('include/queue_fn.php');
|
||||
|
||||
use Zotlabs\Lib\Libzot;
|
||||
use Zotlabs\Lib\Libzotdir;
|
||||
use Zotlabs\Lib\Queue;
|
||||
|
||||
class Directory {
|
||||
|
||||
@@ -42,7 +41,7 @@ class Directory {
|
||||
|
||||
// this is an in-memory update and we don't need to send a network packet.
|
||||
|
||||
local_dir_update($argv[1],$force);
|
||||
Libzotdir::local_dir_update($argv[1],$force);
|
||||
|
||||
q("update channel set channel_dirdate = '%s' where channel_id = %d",
|
||||
dbesc(datetime_convert()),
|
||||
@@ -58,13 +57,16 @@ class Directory {
|
||||
|
||||
// otherwise send the changes upstream
|
||||
|
||||
$directory = find_upstream_directory($dirmode);
|
||||
$url = $directory['url'] . '/post';
|
||||
$directory = Libzotdir::find_upstream_directory($dirmode);
|
||||
|
||||
$url = $directory['url'] . '/zot';
|
||||
|
||||
// ensure the upstream directory is updated
|
||||
|
||||
$packet = zot_build_packet($channel,(($force) ? 'force_refresh' : 'refresh'));
|
||||
$z = zot_zot($url,$packet);
|
||||
|
||||
$packet = Libzot::build_packet($channel,(($force) ? 'force_refresh' : 'refresh'));
|
||||
$z = Libzot::zot($url,$packet,$channel);
|
||||
|
||||
|
||||
// re-queue if unsuccessful
|
||||
|
||||
@@ -76,7 +78,7 @@ class Directory {
|
||||
|
||||
$hash = random_string();
|
||||
|
||||
queue_insert(array(
|
||||
Queue::insert(array(
|
||||
'hash' => $hash,
|
||||
'account_id' => $channel['channel_account_id'],
|
||||
'channel_id' => $channel['channel_id'],
|
||||
|
||||
@@ -8,6 +8,15 @@ class Expire {
|
||||
static public function run($argc,$argv){
|
||||
|
||||
cli_startup();
|
||||
|
||||
$pid = get_config('expire', 'procid', false);
|
||||
if ($pid && (function_exists('posix_kill') ? posix_kill($pid, 0) : true)) {
|
||||
logger('Expire: procedure already run with pid ' . $pid, LOGGER_DEBUG);
|
||||
return;
|
||||
}
|
||||
|
||||
$pid = getmypid();
|
||||
set_config('expire', 'procid', $pid);
|
||||
|
||||
// perform final cleanup on previously delete items
|
||||
|
||||
@@ -32,7 +41,7 @@ class Expire {
|
||||
if (intval(get_config('system', 'optimize_items')))
|
||||
q("optimize table item");
|
||||
|
||||
logger('expire: start', LOGGER_DEBUG);
|
||||
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'));
|
||||
@@ -90,5 +99,7 @@ class Expire {
|
||||
|
||||
logger('Expire: sys: done', LOGGER_DEBUG);
|
||||
}
|
||||
|
||||
del_config('expire', 'procid');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
|
||||
namespace Zotlabs\Daemon;
|
||||
|
||||
require_once('include/zot.php');
|
||||
use Zotlabs\Lib\Libzot;
|
||||
use Zotlabs\Lib\Webfinger;
|
||||
use Zotlabs\Lib\Zotfinger;
|
||||
|
||||
// performs zot_finger on $argv[1], which is a hex_encoded webbie/reddress
|
||||
|
||||
@@ -22,12 +24,16 @@ class Gprobe {
|
||||
);
|
||||
|
||||
if(! $r) {
|
||||
$j = \Zotlabs\Zot\Finger::run($url,null);
|
||||
if($j['success']) {
|
||||
$y = import_xchan($j);
|
||||
$href = Webfinger::zot_url(punify($url));
|
||||
if($href) {
|
||||
$zf = Zotfinger::exec($href, null);
|
||||
}
|
||||
if(is_array($zf) && array_path_exists('signature/signer',$zf) && $zf['signature']['signer'] === $href && intval($zf['signature']['header_valid'])) {
|
||||
$xc = Libzot::import_xchan($zf['data']);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
namespace Zotlabs\Daemon;
|
||||
|
||||
use Zotlabs\Lib\Libsync;
|
||||
|
||||
class Importfile {
|
||||
|
||||
static public function run($argc,$argv){
|
||||
@@ -40,7 +42,7 @@ class Importfile {
|
||||
|
||||
$sync = attach_export_data($channel,$hash);
|
||||
if($sync)
|
||||
build_sync_packet($channel['channel_id'],array('file' => array($sync)));
|
||||
Libsync::build_sync_packet($channel['channel_id'],array('file' => array($sync)));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ if(array_search( __file__ , get_included_files()) === 0) {
|
||||
|
||||
if($argc)
|
||||
Master::Release($argc,$argv);
|
||||
killme();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
namespace Zotlabs\Daemon;
|
||||
|
||||
use Zotlabs\Lib\Libzot;
|
||||
use Zotlabs\Lib\Activity;
|
||||
use Zotlabs\Lib\Queue;
|
||||
|
||||
require_once('include/queue_fn.php');
|
||||
require_once('include/html2plain.php');
|
||||
@@ -44,18 +46,18 @@ require_once('include/bbcode.php');
|
||||
*
|
||||
* where COMMAND is one of the following:
|
||||
*
|
||||
* activity (in diaspora.php, dfrn_confirm.php, profiles.php)
|
||||
* comment-import (in diaspora.php, items.php)
|
||||
* comment-new (in item.php)
|
||||
* drop (in diaspora.php, items.php, photos.php)
|
||||
* edit_post (in item.php)
|
||||
* event (in events.php)
|
||||
* expire (in items.php)
|
||||
* like (in like.php, poke.php)
|
||||
* mail (in message.php)
|
||||
* tag (in photos.php, poke.php, tagger.php)
|
||||
* tgroup (in items.php)
|
||||
* wall-new (in photos.php, item.php)
|
||||
* activity (in diaspora.php, dfrn_confirm.php, profiles.php)
|
||||
* comment-import (in diaspora.php, items.php)
|
||||
* comment-new (in item.php)
|
||||
* drop (in diaspora.php, items.php, photos.php)
|
||||
* edit_post (in item.php)
|
||||
* event (in events.php)
|
||||
* expire (in items.php)
|
||||
* like (in like.php, poke.php)
|
||||
* mail (in message.php)
|
||||
* tag (in photos.php, poke.php, tagger.php)
|
||||
* tgroup (in items.php)
|
||||
* wall-new (in photos.php, item.php)
|
||||
*
|
||||
* and ITEM_ID is the id of the item in the database that needs to be sent to others.
|
||||
*
|
||||
@@ -65,9 +67,10 @@ require_once('include/bbcode.php');
|
||||
* permission_reject abook_id
|
||||
* permission_update abook_id
|
||||
* refresh_all channel_id
|
||||
* purge channel_id xchan_hash
|
||||
* purge_all channel_id
|
||||
* expire channel_id
|
||||
* relay item_id (item was relayed to owner, we will deliver it as owner)
|
||||
* relay item_id (item was relayed to owner, we will deliver it as owner)
|
||||
* single_activity item_id (deliver to a singleton network from the appropriate clone)
|
||||
* single_mail mail_id (deliver to a singleton network from the appropriate clone)
|
||||
* location channel_id
|
||||
@@ -239,25 +242,40 @@ class Notifier {
|
||||
$packet_type = 'location';
|
||||
$location = true;
|
||||
}
|
||||
elseif($cmd === 'purge') {
|
||||
$xchan = $argv[3];
|
||||
logger('notifier: purge: ' . $item_id . ' => ' . $xchan);
|
||||
if (! $xchan) {
|
||||
return;
|
||||
}
|
||||
|
||||
$channel = channelx_by_n($item_id);
|
||||
$recipients[] = $xchan;
|
||||
$private = true;
|
||||
$packet_type = 'purge';
|
||||
$packet_recips[] = ['hash' => $xchan];
|
||||
}
|
||||
elseif($cmd === 'purge_all') {
|
||||
|
||||
logger('notifier: purge_all: ' . $item_id);
|
||||
$s = q("select * from channel where channel_id = %d limit 1",
|
||||
intval($item_id)
|
||||
);
|
||||
if($s)
|
||||
$channel = $s[0];
|
||||
$uid = $item_id;
|
||||
$recipients = array();
|
||||
$channel = channelx_by_n($item_id);
|
||||
|
||||
$recipients = [];
|
||||
$r = q("select abook_xchan from abook where abook_channel = %d and abook_self = 0",
|
||||
intval($item_id)
|
||||
);
|
||||
if($r) {
|
||||
foreach($r as $rr) {
|
||||
$recipients[] = $rr['abook_xchan'];
|
||||
}
|
||||
if (! $r) {
|
||||
return;
|
||||
}
|
||||
foreach ($r as $rr) {
|
||||
$recipients[] = $rr['abook_xchan'];
|
||||
$packet_recips[] = ['hash' => $rr['abook_xchan']];
|
||||
}
|
||||
|
||||
$private = false;
|
||||
$packet_type = 'purge';
|
||||
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -277,6 +295,12 @@ class Notifier {
|
||||
$r = fetch_post_tags($r);
|
||||
|
||||
$target_item = $r[0];
|
||||
|
||||
if(in_array($target_item['author']['xchan_network'], ['rss', 'anon'])) {
|
||||
logger('notifier: target item author is not a fetchable actor', LOGGER_DEBUG);
|
||||
return;
|
||||
}
|
||||
|
||||
$deleted_item = false;
|
||||
|
||||
if(intval($target_item['item_deleted'])) {
|
||||
@@ -285,8 +309,21 @@ class Notifier {
|
||||
}
|
||||
|
||||
if(! in_array(intval($target_item['item_type']), [ ITEM_TYPE_POST ] )) {
|
||||
logger('notifier: target item not forwardable: type ' . $target_item['item_type'], LOGGER_DEBUG);
|
||||
return;
|
||||
$hookinfo=[
|
||||
'targetitem'=>$target_item,
|
||||
'deliver'=>false
|
||||
];
|
||||
if (intval($target_item['item_type'] == ITEM_TYPE_CUSTOM)) {
|
||||
call_hooks('customitem_deliver',$hookinfo);
|
||||
}
|
||||
|
||||
if (!$hookinfo['deliver']) {
|
||||
logger('notifier: target item not forwardable: type ' . $target_item['item_type'], LOGGER_DEBUG);
|
||||
return;
|
||||
}
|
||||
|
||||
$target_item = $hookinfo['targetitem'];
|
||||
|
||||
}
|
||||
|
||||
// Check for non published items, but allow an exclusion for transmitting hidden file activities
|
||||
@@ -347,15 +384,24 @@ class Notifier {
|
||||
|
||||
$encoded_item = encode_item($target_item);
|
||||
|
||||
// activitystreams version
|
||||
$m = get_iconfig($target_item,'activitystreams','signed_data');
|
||||
// Re-use existing signature unless the activity type changed to a Tombstone, which won't verify.
|
||||
$m = ((intval($target_item['item_deleted'])) ? '' : get_iconfig($target_item,'activitystreams','signed_data'));
|
||||
|
||||
if($m) {
|
||||
$activity = json_decode($m,true);
|
||||
}
|
||||
else {
|
||||
$activity = \Zotlabs\Lib\Activity::encode_activity($target_item);
|
||||
$activity = array_merge(['@context' => [
|
||||
ACTIVITYSTREAMS_JSONLD_REV,
|
||||
'https://w3id.org/security/v1',
|
||||
z_root() . ZOT_APSCHEMA_REV
|
||||
]], Activity::encode_activity($target_item)
|
||||
);
|
||||
}
|
||||
|
||||
logger('target_item: ' . print_r($target_item,true), LOGGER_DEBUG);
|
||||
logger('encoded: ' . print_r($activity,true), LOGGER_DEBUG);
|
||||
|
||||
// Send comments to the owner to re-deliver to everybody in the conversation
|
||||
// We only do this if the item in question originated on this site. This prevents looping.
|
||||
// To clarify, a site accepting a new comment is responsible for sending it to the owner for relay.
|
||||
@@ -454,7 +500,6 @@ class Notifier {
|
||||
|
||||
$details = q("select xchan_hash, xchan_network, xchan_addr, xchan_guid, xchan_guid_sig from xchan where xchan_hash in (" . protect_sprintf(implode(',',$recipients)) . ")");
|
||||
|
||||
|
||||
$recip_list = array();
|
||||
|
||||
if($details) {
|
||||
@@ -519,18 +564,40 @@ class Notifier {
|
||||
// Now we have collected recipients (except for external mentions, FIXME)
|
||||
// Let's reduce this to a set of hubs; checking that the site is not dead.
|
||||
|
||||
$r = q("select hubloc.*, site.site_crypto, site.site_flags from hubloc left join site on site_url = hubloc_url where hubloc_hash in (" . protect_sprintf(implode(',',$recipients)) . ")
|
||||
and hubloc_error = 0 and hubloc_deleted = 0 and ( site_dead = 0 OR site_dead is null ) "
|
||||
);
|
||||
|
||||
$hubs = q("select hubloc.*, site.site_crypto, site.site_flags, site.site_version, site.site_project, site.site_dead from hubloc left join site on site_url = hubloc_url
|
||||
where hubloc_hash in (" . protect_sprintf(implode(',',$recipients)) . ")
|
||||
and hubloc_error = 0 and hubloc_deleted = 0"
|
||||
);
|
||||
|
||||
if(! $r) {
|
||||
// public posts won't make it to the local public stream unless there's a recipient on this site.
|
||||
// This code block sees if it's a public post and localhost is missing, and if so adds an entry for the local sys channel to the $hubs list
|
||||
|
||||
if (! $private) {
|
||||
$found_localhost = false;
|
||||
if ($hubs) {
|
||||
foreach ($hubs as $h) {
|
||||
if ($h['hubloc_url'] === z_root()) {
|
||||
$found_localhost = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (! $found_localhost) {
|
||||
$localhub = q("select hubloc.*, site.site_crypto, site.site_flags, site.site_version, site.site_project, site.site_dead from hubloc
|
||||
left join site on site_url = hubloc_url where hubloc_id_url = '%s' and hubloc_error = 0 and hubloc_deleted = 0",
|
||||
dbesc(z_root() . '/channel/sys')
|
||||
);
|
||||
if ($localhub) {
|
||||
$hubs = array_merge($hubs, $localhub);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(! $hubs) {
|
||||
logger('notifier: no hubs', LOGGER_NORMAL, LOG_NOTICE);
|
||||
return;
|
||||
}
|
||||
|
||||
$hubs = $r;
|
||||
|
||||
/**
|
||||
* Reduce the hubs to those that are unique. For zot hubs, we need to verify uniqueness by the sitekey,
|
||||
* since it may have been a re-install which has not yet been detected and pruned.
|
||||
@@ -543,9 +610,15 @@ class Notifier {
|
||||
$keys = []; // array of keys to check uniquness for zot hubs
|
||||
$urls = []; // array of urls to check uniqueness of hubs from other networks
|
||||
$hub_env = []; // per-hub envelope so we don't broadcast the entire envelope to all
|
||||
$dead = []; // known dead hubs - report them as undeliverable
|
||||
|
||||
foreach($hubs as $hub) {
|
||||
|
||||
if (intval($hub['site_dead'])) {
|
||||
$dead[] = $hub;
|
||||
continue;
|
||||
}
|
||||
|
||||
if($env_recips) {
|
||||
foreach($env_recips as $er) {
|
||||
if($hub['hubloc_hash'] === $er['hash']) {
|
||||
@@ -567,9 +640,16 @@ class Notifier {
|
||||
}
|
||||
else {
|
||||
if(! in_array($hub['hubloc_url'],$urls)) {
|
||||
$hublist[] = $hub['hubloc_host'] . ' ' . $hub['hubloc_network'];
|
||||
$dhubs[] = $hub;
|
||||
$urls[] = $hub['hubloc_url'];
|
||||
if($hub['hubloc_url'] === z_root()) {
|
||||
//deliver to local hub first
|
||||
array_unshift($hublist, $hub['hubloc_host'] . ' ' . $hub['hubloc_network']);
|
||||
array_unshift($dhubs, $hub);
|
||||
}
|
||||
else {
|
||||
$hublist[] = $hub['hubloc_host'] . ' ' . $hub['hubloc_network'];
|
||||
$dhubs[] = $hub;
|
||||
}
|
||||
$urls[] = $hub['hubloc_url'];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -617,7 +697,7 @@ class Notifier {
|
||||
}
|
||||
|
||||
// singleton deliveries by definition 'not got zot'.
|
||||
// Single deliveries are other federated networks (plugins) and we're essentially
|
||||
// Single deliveries are other federated networks (plugins) and we're essentially
|
||||
// delivering only to those that have this site url in their abook_instance
|
||||
// and only from within a sync operation. This means if you post from a clone,
|
||||
// and a connection is connected to one of your other clones; assuming that hub
|
||||
@@ -662,15 +742,17 @@ class Notifier {
|
||||
}
|
||||
|
||||
if($packet) {
|
||||
queue_insert(array(
|
||||
'hash' => $hash,
|
||||
'account_id' => $channel['channel_account_id'],
|
||||
'channel_id' => $channel['channel_id'],
|
||||
'posturl' => $hub['hubloc_callback'],
|
||||
'driver' => $hub['hubloc_network'],
|
||||
'notify' => $packet,
|
||||
'msg' => (($pmsg) ? json_encode($pmsg) : '')
|
||||
));
|
||||
Queue::insert(
|
||||
[
|
||||
'hash' => $hash,
|
||||
'account_id' => $channel['channel_account_id'],
|
||||
'channel_id' => $channel['channel_id'],
|
||||
'posturl' => $hub['hubloc_callback'],
|
||||
'driver' => $hub['hubloc_network'],
|
||||
'notify' => $packet,
|
||||
'msg' => (($pmsg) ? json_encode($pmsg) : '')
|
||||
]
|
||||
);
|
||||
}
|
||||
else {
|
||||
$env = (($hub_env && $hub_env[$hub['hubloc_host'] . $hub['hubloc_sitekey']]) ? $hub_env[$hub['hubloc_host'] . $hub['hubloc_sitekey']] : '');
|
||||
@@ -712,9 +794,26 @@ class Notifier {
|
||||
$packet = zot_build_packet($channel,'notify',$env, (($private) ? $hub['hubloc_sitekey'] : null), $hub['site_crypto'],$hash);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
queue_insert(
|
||||
|
||||
// remove this after most hubs have updated to version 5.0
|
||||
if(stripos($hub['site_project'], 'hubzilla') !== false && version_compare($hub['site_version'], '4.7.3', '<=')) {
|
||||
if($encoded_item['type'] === 'mail') {
|
||||
$encoded_item['from']['network'] = 'zot';
|
||||
$encoded_item['from']['guid_sig'] = str_replace('sha256.', '', $encoded_item['from']['guid_sig']);
|
||||
}
|
||||
else {
|
||||
$encoded_item['owner']['network'] = 'zot';
|
||||
$encoded_item['owner']['guid_sig'] = str_replace('sha256.', '', $encoded_item['owner']['guid_sig']);
|
||||
if(strpos($encoded_item['author']['url'], z_root()) === 0) {
|
||||
$encoded_item['author']['network'] = 'zot';
|
||||
$encoded_item['author']['guid_sig'] = str_replace('sha256.', '', $encoded_item['author']['guid_sig']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Queue::insert(
|
||||
[
|
||||
'hash' => $hash,
|
||||
'account_id' => $target_item['aid'],
|
||||
@@ -755,6 +854,24 @@ class Notifier {
|
||||
|
||||
logger('notifier: basic loop complete.', LOGGER_DEBUG);
|
||||
|
||||
if ($dead) {
|
||||
foreach ($dead as $deceased) {
|
||||
if (is_array($target_item) && (! $target_item['item_deleted']) && (! get_config('system','disable_dreport'))) {
|
||||
q("insert into dreport ( dreport_mid, dreport_site, dreport_recip, dreport_name, dreport_result, dreport_time, dreport_xchan, dreport_queue )
|
||||
values ( '%s', '%s','%s','%s','%s','%s','%s','%s' ) ",
|
||||
dbesc($target_item['mid']),
|
||||
dbesc($deceased['hubloc_host']),
|
||||
dbesc($deceased['hubloc_host']),
|
||||
dbesc($deceased['hubloc_host']),
|
||||
dbesc('undeliverable/unresponsive site'),
|
||||
dbesc(datetime_convert()),
|
||||
dbesc($channel['channel_hash']),
|
||||
dbesc(random_string(48))
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
call_hooks('notifier_end',$target_item);
|
||||
|
||||
logger('notifer: complete.');
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
namespace Zotlabs\Daemon;
|
||||
|
||||
use Zotlabs\Lib\Libzot;
|
||||
|
||||
require_once('include/zot.php');
|
||||
require_once('include/socgraph.php');
|
||||
|
||||
@@ -61,11 +63,13 @@ class Onepoll {
|
||||
|
||||
if($contact['xchan_network'] === 'rss') {
|
||||
logger('onepoll: processing feed ' . $contact['xchan_name'], LOGGER_DEBUG);
|
||||
handle_feed($importer['channel_id'],$contact_id,$contact['xchan_hash']);
|
||||
q("update abook set abook_connected = '%s' where abook_id = %d",
|
||||
dbesc(datetime_convert()),
|
||||
intval($contact['abook_id'])
|
||||
);
|
||||
$alive = handle_feed($importer['channel_id'],$contact_id,$contact['xchan_hash']);
|
||||
if ($alive) {
|
||||
q("update abook set abook_connected = '%s' where abook_id = %d",
|
||||
dbesc(datetime_convert()),
|
||||
intval($contact['abook_id'])
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -74,7 +78,11 @@ class Onepoll {
|
||||
|
||||
// update permissions
|
||||
|
||||
$x = zot_refresh($contact,$importer);
|
||||
if($contact['xchan_network'] === 'zot6')
|
||||
$x = Libzot::refresh($contact,$importer);
|
||||
|
||||
if($contact['xchan_network'] === 'zot')
|
||||
$x = zot_refresh($contact,$importer);
|
||||
|
||||
$responded = false;
|
||||
$updated = datetime_convert();
|
||||
|
||||
@@ -47,7 +47,7 @@ class Poller {
|
||||
$restart = true;
|
||||
$generation = intval($argv[2]);
|
||||
if(! $generation)
|
||||
killme();
|
||||
return;
|
||||
}
|
||||
|
||||
if(($argc > 1) && intval($argv[1])) {
|
||||
|
||||
@@ -10,6 +10,11 @@ class Ratenotif {
|
||||
|
||||
static public function run($argc,$argv) {
|
||||
|
||||
|
||||
// Deprecated
|
||||
return;
|
||||
|
||||
|
||||
require_once("datetime.php");
|
||||
require_once('include/items.php');
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Identity\BasicId;
|
||||
namespace Zotlabs\Identity;
|
||||
|
||||
class BasicId {
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?php
|
||||
namespace Zotlabs\Identity\ProfilePhoto;
|
||||
namespace Zotlabs\Identity;
|
||||
|
||||
class ProfilePhoto {
|
||||
|
||||
|
||||
411
Zotlabs/Lib/AccessList.php
Normal file
411
Zotlabs/Lib/AccessList.php
Normal file
@@ -0,0 +1,411 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
use Zotlabs\Lib\Libsync;
|
||||
|
||||
|
||||
class AccessList {
|
||||
|
||||
static function add($uid,$name,$public = 0) {
|
||||
|
||||
$ret = false;
|
||||
if ($uid && $name) {
|
||||
$r = self::byname($uid,$name); // check for dups
|
||||
if ($r !== false) {
|
||||
|
||||
// This could be a problem.
|
||||
// Let's assume we've just created a list which we once deleted
|
||||
// all the old members are gone, but the list remains so we don't break any security
|
||||
// access lists. What we're doing here is reviving the dead list, but old content which
|
||||
// was restricted to this list may now be seen by the new list members.
|
||||
|
||||
$z = q("SELECT * FROM pgrp WHERE id = %d LIMIT 1",
|
||||
intval($r)
|
||||
);
|
||||
if(($z) && $z[0]['deleted']) {
|
||||
q('UPDATE pgrp SET deleted = 0 WHERE id = %d', intval($z[0]['id']));
|
||||
notice( t('A deleted list with this name was revived. Existing item permissions <strong>may</strong> apply to this list and any future members. If this is not what you intended, please create another list with a different name.') . EOL);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
$hash = new_uuid();
|
||||
|
||||
$r = q("INSERT INTO pgrp ( hash, uid, visible, gname )
|
||||
VALUES( '%s', %d, %d, '%s' ) ",
|
||||
dbesc($hash),
|
||||
intval($uid),
|
||||
intval($public),
|
||||
dbesc($name)
|
||||
);
|
||||
$ret = $r;
|
||||
}
|
||||
|
||||
Libsync::build_sync_packet($uid,null,true);
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
static function remove($uid,$name) {
|
||||
$ret = false;
|
||||
if ($uid && $name) {
|
||||
$r = q("SELECT id, hash FROM pgrp WHERE uid = %d AND gname = '%s' LIMIT 1",
|
||||
intval($uid),
|
||||
dbesc($name)
|
||||
);
|
||||
if ($r) {
|
||||
$group_id = $r[0]['id'];
|
||||
$group_hash = $r[0]['hash'];
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
|
||||
// remove group from default posting lists
|
||||
$r = q("SELECT channel_default_group, channel_allow_gid, channel_deny_gid FROM channel WHERE channel_id = %d LIMIT 1",
|
||||
intval($uid)
|
||||
);
|
||||
if ($r) {
|
||||
$user_info = array_shift($r);
|
||||
$change = false;
|
||||
|
||||
if ($user_info['channel_default_group'] == $group_hash) {
|
||||
$user_info['channel_default_group'] = '';
|
||||
$change = true;
|
||||
}
|
||||
if (strpos($user_info['channel_allow_gid'], '<' . $group_hash . '>') !== false) {
|
||||
$user_info['channel_allow_gid'] = str_replace('<' . $group_hash . '>', '', $user_info['channel_allow_gid']);
|
||||
$change = true;
|
||||
}
|
||||
if (strpos($user_info['channel_deny_gid'], '<' . $group_hash . '>') !== false) {
|
||||
$user_info['channel_deny_gid'] = str_replace('<' . $group_hash . '>', '', $user_info['channel_deny_gid']);
|
||||
$change = true;
|
||||
}
|
||||
|
||||
if ($change) {
|
||||
q("UPDATE channel SET channel_default_group = '%s', channel_allow_gid = '%s', channel_deny_gid = '%s'
|
||||
WHERE channel_id = %d",
|
||||
intval($user_info['channel_default_group']),
|
||||
dbesc($user_info['channel_allow_gid']),
|
||||
dbesc($user_info['channel_deny_gid']),
|
||||
intval($uid)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// remove all members
|
||||
$r = q("DELETE FROM pgrp_member WHERE uid = %d AND gid = %d ",
|
||||
intval($uid),
|
||||
intval($group_id)
|
||||
);
|
||||
|
||||
// remove group
|
||||
$r = q("UPDATE pgrp SET deleted = 1 WHERE uid = %d AND gname = '%s'",
|
||||
intval($uid),
|
||||
dbesc($name)
|
||||
);
|
||||
|
||||
$ret = $r;
|
||||
|
||||
}
|
||||
|
||||
Libsync::build_sync_packet($uid,null,true);
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
// returns the integer id of an access group owned by $uid and named $name
|
||||
// or false.
|
||||
|
||||
static function byname($uid,$name) {
|
||||
if (! ($uid && $name)) {
|
||||
return false;
|
||||
}
|
||||
$r = q("SELECT id FROM pgrp WHERE uid = %d AND gname = '%s' LIMIT 1",
|
||||
intval($uid),
|
||||
dbesc($name)
|
||||
);
|
||||
if ($r) {
|
||||
return $r[0]['id'];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static function by_id($uid,$id) {
|
||||
if (! ($uid && $id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$r = q("SELECT * FROM pgrp WHERE uid = %d AND id = %d and deleted = 0",
|
||||
intval($uid),
|
||||
intval($id)
|
||||
);
|
||||
if ($r) {
|
||||
return array_shift($r);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static function rec_byhash($uid,$hash) {
|
||||
if (! ( $uid && $hash)) {
|
||||
return false;
|
||||
}
|
||||
$r = q("SELECT * FROM pgrp WHERE uid = %d AND hash = '%s' LIMIT 1",
|
||||
intval($uid),
|
||||
dbesc($hash)
|
||||
);
|
||||
if ($r) {
|
||||
return array_shift($r);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static function member_remove($uid,$name,$member) {
|
||||
$gid = self::byname($uid,$name);
|
||||
if (! $gid) {
|
||||
return false;
|
||||
}
|
||||
if (! ($uid && $gid && $member)) {
|
||||
return false;
|
||||
}
|
||||
$r = q("DELETE FROM pgrp_member WHERE uid = %d AND gid = %d AND xchan = '%s' ",
|
||||
intval($uid),
|
||||
intval($gid),
|
||||
dbesc($member)
|
||||
);
|
||||
|
||||
Libsync::build_sync_packet($uid,null,true);
|
||||
|
||||
return $r;
|
||||
}
|
||||
|
||||
|
||||
static function member_add($uid,$name,$member,$gid = 0) {
|
||||
if (! $gid) {
|
||||
$gid = self::byname($uid,$name);
|
||||
}
|
||||
if (! ($gid && $uid && $member)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$r = q("SELECT * FROM pgrp_member WHERE uid = %d AND gid = %d AND xchan = '%s' LIMIT 1",
|
||||
intval($uid),
|
||||
intval($gid),
|
||||
dbesc($member)
|
||||
);
|
||||
if ($r) {
|
||||
return true; // You might question this, but
|
||||
// we indicate success because the group member was in fact created
|
||||
// -- It was just created at another time
|
||||
}
|
||||
else {
|
||||
$r = q("INSERT INTO pgrp_member (uid, gid, xchan)
|
||||
VALUES( %d, %d, '%s' ) ",
|
||||
intval($uid),
|
||||
intval($gid),
|
||||
dbesc($member)
|
||||
);
|
||||
}
|
||||
Libsync::build_sync_packet($uid,null,true);
|
||||
return $r;
|
||||
}
|
||||
|
||||
|
||||
static function members($uid, $gid) {
|
||||
$ret = [];
|
||||
if (intval($gid)) {
|
||||
$r = q("SELECT * FROM pgrp_member
|
||||
LEFT JOIN abook ON abook_xchan = pgrp_member.xchan left join xchan on xchan_hash = abook_xchan
|
||||
WHERE gid = %d AND abook_channel = %d and pgrp_member.uid = %d and xchan_deleted = 0 and abook_self = 0 and abook_blocked = 0 and abook_pending = 0 ORDER BY xchan_name ASC ",
|
||||
intval($gid),
|
||||
intval($uid),
|
||||
intval($uid)
|
||||
);
|
||||
if ($r) {
|
||||
$ret = $r;
|
||||
}
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
static function members_xchan($uid,$gid) {
|
||||
$ret = [];
|
||||
if (intval($gid)) {
|
||||
$r = q("SELECT xchan FROM pgrp_member WHERE gid = %d AND uid = %d",
|
||||
intval($gid),
|
||||
intval($uid)
|
||||
);
|
||||
if ($r) {
|
||||
foreach ($r as $rv) {
|
||||
$ret[] = $rv['xchan'];
|
||||
}
|
||||
}
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
static function members_profile_xchan($uid,$gid) {
|
||||
$ret = [];
|
||||
if (intval($gid)) {
|
||||
$r = q("SELECT abook_xchan as xchan from abook left join profile on abook_profile = profile_guid where profile.id = %d and profile.uid = %d",
|
||||
intval($gid),
|
||||
intval($uid)
|
||||
);
|
||||
if ($r) {
|
||||
foreach($r as $rv) {
|
||||
$ret[] = $rv['xchan'];
|
||||
}
|
||||
}
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static function select($uid,$group = '') {
|
||||
|
||||
$grps = [];
|
||||
|
||||
$r = q("SELECT * FROM pgrp WHERE deleted = 0 AND uid = %d ORDER BY gname ASC",
|
||||
intval($uid)
|
||||
);
|
||||
$grps[] = [ 'name' => '', 'hash' => '0', 'selected' => '' ];
|
||||
if ($r) {
|
||||
foreach ($r as $rr) {
|
||||
$grps[] = [ 'name' => $rr['gname'], 'id' => $rr['hash'], 'selected' => (($group == $rr['hash']) ? 'true' : '') ];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return replace_macros(get_markup_template('group_selection.tpl'), [
|
||||
'$label' => t('Add new connections to this access list'),
|
||||
'$groups' => $grps
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
static function widget($every="connections",$each="lists",$edit = false, $group_id = 0, $cid = '',$mode = 1) {
|
||||
|
||||
$o = '';
|
||||
|
||||
$groups = [];
|
||||
|
||||
$r = q("SELECT * FROM pgrp WHERE deleted = 0 AND uid = %d ORDER BY gname ASC",
|
||||
intval($_SESSION['uid'])
|
||||
);
|
||||
$member_of = [];
|
||||
if ($cid) {
|
||||
$member_of = self::containing(local_channel(),$cid);
|
||||
}
|
||||
|
||||
if ($r) {
|
||||
foreach ($r as $rr) {
|
||||
$selected = (($group_id == $rr['id']) ? ' group-selected' : '');
|
||||
|
||||
if ($edit) {
|
||||
$groupedit = [ 'href' => "lists/".$rr['id'], 'title' => t('edit') ];
|
||||
}
|
||||
else {
|
||||
$groupedit = null;
|
||||
}
|
||||
|
||||
$groups[] = [
|
||||
'id' => $rr['id'],
|
||||
'enc_cid' => base64url_encode($cid),
|
||||
'cid' => $cid,
|
||||
'text' => $rr['gname'],
|
||||
'selected' => $selected,
|
||||
'href' => (($mode == 0) ? $each.'?f=&gid='.$rr['id'] : $each."/".$rr['id']) . ((x($_GET,'new')) ? '&new=' . $_GET['new'] : '') . ((x($_GET,'order')) ? '&order=' . $_GET['order'] : ''),
|
||||
'edit' => $groupedit,
|
||||
'ismember' => in_array($rr['id'],$member_of),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return replace_macros(get_markup_template('group_side.tpl'), [
|
||||
'$title' => t('Lists'),
|
||||
'$edittext' => t('Edit list'),
|
||||
'$createtext' => t('Create new list'),
|
||||
'$ungrouped' => (($every === 'contacts') ? t('Channels not in any access list') : ''),
|
||||
'$groups' => $groups,
|
||||
'$add' => t('add'),
|
||||
]);
|
||||
|
||||
}
|
||||
|
||||
|
||||
static function expand($g) {
|
||||
if (! (is_array($g) && count($g))) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$ret = [];
|
||||
$x = [];
|
||||
|
||||
// private profile linked virtual groups
|
||||
|
||||
foreach ($g as $gv) {
|
||||
if (substr($gv,0,3) === 'vp.') {
|
||||
$profile_hash = substr($gv,3);
|
||||
if ($profile_hash) {
|
||||
$r = q("select abook_xchan from abook where abook_profile = '%s'",
|
||||
dbesc($profile_hash)
|
||||
);
|
||||
if ($r) {
|
||||
foreach ($r as $rv) {
|
||||
$ret[] = $rv['abook_xchan'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
$x[] = $gv;
|
||||
}
|
||||
}
|
||||
|
||||
if ($x) {
|
||||
stringify_array_elms($x,true);
|
||||
$groups = implode(',', $x);
|
||||
if ($groups) {
|
||||
$r = q("SELECT xchan FROM pgrp_member WHERE gid IN ( select id from pgrp where hash in ( $groups ))");
|
||||
if ($r) {
|
||||
foreach ($r as $rv) {
|
||||
$ret[] = $rv['xchan'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
static function member_of($c) {
|
||||
$r = q("SELECT pgrp.gname, pgrp.id FROM pgrp LEFT JOIN pgrp_member ON pgrp_member.gid = pgrp.id
|
||||
WHERE pgrp_member.xchan = '%s' AND pgrp.deleted = 0 ORDER BY pgrp.gname ASC ",
|
||||
dbesc($c)
|
||||
);
|
||||
|
||||
return $r;
|
||||
}
|
||||
|
||||
static function containing($uid,$c) {
|
||||
|
||||
$r = q("SELECT gid FROM pgrp_member WHERE uid = %d AND pgrp_member.xchan = '%s' ",
|
||||
intval($uid),
|
||||
dbesc($c)
|
||||
);
|
||||
|
||||
$ret = [];
|
||||
if ($r) {
|
||||
foreach ($r as $rv)
|
||||
$ret[] = $rv['gid'];
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -101,7 +101,13 @@ class ActivityStreams {
|
||||
$this->actor = $this->get_actor('attributedTo',$this->obj);
|
||||
}
|
||||
}
|
||||
|
||||
// fetch recursive or embedded activities
|
||||
|
||||
if ($this->obj && is_array($this->obj) && array_key_exists('object',$this->obj)) {
|
||||
$this->obj['object'] = $this->get_compound_property($this->obj['object']);
|
||||
}
|
||||
|
||||
if($this->obj && is_array($this->obj) && $this->obj['actor'])
|
||||
$this->obj['actor'] = $this->get_actor('actor',$this->obj);
|
||||
if($this->tgt && is_array($this->tgt) && $this->tgt['actor'])
|
||||
@@ -140,15 +146,20 @@ class ActivityStreams {
|
||||
*/
|
||||
function collect_recips($base = '', $namespace = '') {
|
||||
$x = [];
|
||||
|
||||
$fields = [ 'to', 'cc', 'bto', 'bcc', 'audience'];
|
||||
foreach($fields as $f) {
|
||||
$y = $this->get_compound_property($f, $base, $namespace);
|
||||
if($y) {
|
||||
$x = array_merge($x, $y);
|
||||
if(! is_array($this->raw_recips))
|
||||
if (! is_array($this->raw_recips)) {
|
||||
$this->raw_recips = [];
|
||||
}
|
||||
|
||||
$this->raw_recips[$f] = $x;
|
||||
if (! is_array($y)) {
|
||||
$y = [ $y ];
|
||||
}
|
||||
$this->raw_recips[$f] = $y;
|
||||
$x = array_merge($x, $y);
|
||||
}
|
||||
}
|
||||
// not yet ready for prime time
|
||||
@@ -263,12 +274,19 @@ class ActivityStreams {
|
||||
return self::fetch($url);
|
||||
}
|
||||
|
||||
static function fetch($url,$channel = null) {
|
||||
return Activity::fetch($url,$channel);
|
||||
static function fetch($url, $channel = null) {
|
||||
return Activity::fetch($url, $channel);
|
||||
}
|
||||
|
||||
static function is_an_actor($s) {
|
||||
return(in_array($s,[ 'Application','Group','Organization','Person','Service' ]));
|
||||
return (in_array($s, [ 'Application','Group','Organization','Person','Service' ]));
|
||||
}
|
||||
|
||||
static function is_response_activity($s) {
|
||||
if (! $s) {
|
||||
return false;
|
||||
}
|
||||
return (in_array($s, [ 'Like', 'Dislike', 'Flag', 'Block', 'Announce', 'Accept', 'Reject', 'TentativeAccept', 'TentativeReject', 'emojiReaction', 'EmojiReaction', 'EmojiReact' ]));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -391,7 +409,6 @@ class ActivityStreams {
|
||||
return $x;
|
||||
}
|
||||
|
||||
|
||||
static function is_as_request() {
|
||||
|
||||
$x = getBestSupportedMimeType([
|
||||
@@ -404,5 +421,4 @@ class ActivityStreams {
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
use Zotlabs\Lib\Libsync;
|
||||
|
||||
require_once('include/plugin.php');
|
||||
require_once('include/channel.php');
|
||||
|
||||
@@ -74,7 +76,6 @@ class Apps {
|
||||
'Directory',
|
||||
'Search',
|
||||
'Help',
|
||||
'Mail',
|
||||
'Profile Photo'
|
||||
]);
|
||||
|
||||
@@ -371,7 +372,6 @@ class Apps {
|
||||
'OAuth2 Apps Manager' => t('OAuth2 Apps Manager'),
|
||||
'PDL Editor' => t('PDL Editor'),
|
||||
'Permission Categories' => t('Permission Categories'),
|
||||
'Premium Channel' => t('Premium Channel'),
|
||||
'Public Stream' => t('Public Stream'),
|
||||
'My Chatrooms' => t('My Chatrooms'),
|
||||
'Channel Export' => t('Channel Export')
|
||||
@@ -564,7 +564,8 @@ class Apps {
|
||||
'$featured' => ((strpos($papp['categories'], 'nav_featured_app') === false) ? false : true),
|
||||
'$pinned' => ((strpos($papp['categories'], 'nav_pinned_app') === false) ? false : true),
|
||||
'$navapps' => (($mode == 'nav') ? true : false),
|
||||
'$order' => (($mode == 'nav-order') ? true : false),
|
||||
'$order' => (($mode === 'nav-order' || $mode === 'nav-order-pinned') ? true : false),
|
||||
'$mode' => $mode,
|
||||
'$add' => t('Add to app-tray'),
|
||||
'$remove' => t('Remove from app-tray'),
|
||||
'$add_nav' => t('Pin to navbar'),
|
||||
@@ -604,7 +605,7 @@ class Apps {
|
||||
intval(TERM_OBJ_APP),
|
||||
intval($r[0]['id'])
|
||||
);
|
||||
build_sync_packet($uid,array('app' => $r[0]));
|
||||
Libsync::build_sync_packet($uid,array('app' => $r[0]));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -670,7 +671,7 @@ class Apps {
|
||||
);
|
||||
}
|
||||
if(! intval($x[0]['app_system'])) {
|
||||
build_sync_packet($uid,array('app' => $x));
|
||||
Libsync::build_sync_packet($uid,array('app' => $x));
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -959,9 +960,6 @@ class Apps {
|
||||
if($list) {
|
||||
foreach($list as $li) {
|
||||
$papp = self::app_encode($li);
|
||||
if($menu !== 'nav_pinned_app' && strpos($papp['categories'],'nav_pinned_app') !== false)
|
||||
continue;
|
||||
|
||||
$syslist[] = $papp;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,12 +7,23 @@ namespace Zotlabs\Lib;
|
||||
*/
|
||||
|
||||
class Cache {
|
||||
public static function get($key) {
|
||||
|
||||
/**
|
||||
* @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);
|
||||
|
||||
$r = q("SELECT v FROM cache WHERE k = '%s' limit 1",
|
||||
dbesc($hash)
|
||||
$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)
|
||||
@@ -40,12 +51,4 @@ class Cache {
|
||||
dbesc(datetime_convert()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static function clear() {
|
||||
q("DELETE FROM cache WHERE updated < '%s'",
|
||||
dbesc(datetime_convert('UTC','UTC',"now - 30 days")));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
<?php
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
use Zotlabs\Lib\Libsync;
|
||||
|
||||
/**
|
||||
* @brief A class with chatroom related static methods.
|
||||
*/
|
||||
@@ -91,7 +93,7 @@ class Chatroom {
|
||||
return $ret;
|
||||
}
|
||||
|
||||
build_sync_packet($channel['channel_id'],array('chatroom' => $r));
|
||||
Libsync::build_sync_packet($channel['channel_id'],array('chatroom' => $r));
|
||||
|
||||
q("delete from chatroom where cr_id = %d",
|
||||
intval($r[0]['cr_id'])
|
||||
|
||||
312
Zotlabs/Lib/Connect.php
Normal file
312
Zotlabs/Lib/Connect.php
Normal file
@@ -0,0 +1,312 @@
|
||||
<?php /** @file */
|
||||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
use App;
|
||||
use Zotlabs\Access\Permissions;
|
||||
use Zotlabs\Daemon\Master;
|
||||
|
||||
|
||||
|
||||
class Connect {
|
||||
|
||||
/**
|
||||
* Takes a $channel and a $url/handle and adds a new connection
|
||||
*
|
||||
* Returns array
|
||||
* $return['success'] boolean true if successful
|
||||
* $return['abook'] Address book entry joined with xchan if successful
|
||||
* $return['message'] error text if success is false.
|
||||
*
|
||||
* This function does NOT send sync packets to clones. The caller is responsible for doing this
|
||||
*/
|
||||
|
||||
static function connect($channel, $url, $sub_channel = false) {
|
||||
|
||||
$uid = $channel['channel_id'];
|
||||
|
||||
if (strpos($url,'@') === false && strpos($url,'/') === false) {
|
||||
$url = $url . '@' . App::get_hostname();
|
||||
}
|
||||
|
||||
$result = [ 'success' => false, 'message' => '' ];
|
||||
|
||||
$my_perms = false;
|
||||
$protocol = '';
|
||||
|
||||
if (substr($url,0,1) === '[') {
|
||||
$x = strpos($url,']');
|
||||
if ($x) {
|
||||
$protocol = substr($url,1,$x-1);
|
||||
$url = substr($url,$x+1);
|
||||
}
|
||||
}
|
||||
|
||||
if (! check_siteallowed($url)) {
|
||||
$result['message'] = t('Channel is blocked on this site.');
|
||||
return $result;
|
||||
}
|
||||
|
||||
if (! $url) {
|
||||
$result['message'] = t('Channel location missing.');
|
||||
return $result;
|
||||
}
|
||||
|
||||
// check service class limits
|
||||
|
||||
$r = q("select count(*) as total from abook where abook_channel = %d and abook_self = 0 ",
|
||||
intval($uid)
|
||||
);
|
||||
if ($r) {
|
||||
$total_channels = $r[0]['total'];
|
||||
}
|
||||
|
||||
if (! service_class_allows($uid,'total_channels',$total_channels)) {
|
||||
$result['message'] = upgrade_message();
|
||||
return $result;
|
||||
}
|
||||
|
||||
$xchan_hash = '';
|
||||
$sql_options = (($protocol) ? " and xchan_network = '" . dbesc($protocol) . "' " : '');
|
||||
|
||||
$r = q("select * from xchan where ( xchan_hash = '%s' or xchan_url = '%s' or xchan_addr = '%s') $sql_options ",
|
||||
dbesc($url),
|
||||
dbesc($url),
|
||||
dbesc($url)
|
||||
);
|
||||
|
||||
if ($r) {
|
||||
|
||||
// reset results to the best record or the first if we don't have the best
|
||||
// note: this is a single record and not an array of results
|
||||
|
||||
$r = Libzot::zot_record_preferred($r,'xchan_network');
|
||||
|
||||
}
|
||||
|
||||
$singleton = false;
|
||||
$d = false;
|
||||
|
||||
if (! $r) {
|
||||
|
||||
// not in cache - try discovery
|
||||
|
||||
$wf = discover_by_webbie($url,$protocol);
|
||||
|
||||
if (! $wf) {
|
||||
$feeds = get_config('system','feed_contacts');
|
||||
|
||||
if (($feeds) && (in_array($protocol, [ '', 'feed', 'rss' ]))) {
|
||||
$d = discover_by_url($url);
|
||||
}
|
||||
else {
|
||||
$result['message'] = t('Remote channel or protocol unavailable.');
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($wf || $d) {
|
||||
|
||||
// something was discovered - find the record which was just created.
|
||||
|
||||
$r = q("select * from xchan where ( xchan_hash = '%s' or xchan_url = '%s' or xchan_addr = '%s' ) $sql_options",
|
||||
dbesc(($wf) ? $wf : $url),
|
||||
dbesc($url),
|
||||
dbesc($url)
|
||||
);
|
||||
|
||||
// convert to a single record (once again preferring a zot solution in the case of multiples)
|
||||
|
||||
if ($r) {
|
||||
$r = Libzot::zot_record_preferred($r,'xchan_network');
|
||||
}
|
||||
}
|
||||
|
||||
// if discovery was a success or the channel was already cached we should have an xchan record in $r
|
||||
|
||||
if ($r) {
|
||||
$xchan = $r;
|
||||
$xchan_hash = $r['xchan_hash'];
|
||||
$their_perms = EMPTY_STR;
|
||||
}
|
||||
|
||||
// failure case
|
||||
|
||||
if (! $xchan_hash) {
|
||||
$result['message'] = t('Channel discovery failed.');
|
||||
logger('follow: ' . $result['message']);
|
||||
return $result;
|
||||
}
|
||||
|
||||
if (! check_channelallowed($xchan_hash)) {
|
||||
$result['message'] = t('Channel is blocked on this site.');
|
||||
logger('follow: ' . $result['message']);
|
||||
return $result;
|
||||
|
||||
}
|
||||
|
||||
$allowed = ((in_array($xchan['xchan_network'],['rss','zot','zot6'])) ? 1 : 0);
|
||||
|
||||
$hookdata = ['channel_id' => $uid, 'follow_address' => $url, 'xchan' => $xchan, 'allowed' => $allowed, 'singleton' => 0];
|
||||
call_hooks('follow_allow',$hookdata);
|
||||
|
||||
if(! $hookdata['allowed']) {
|
||||
$result['message'] = t('Protocol disabled.');
|
||||
return $result;
|
||||
}
|
||||
|
||||
$singleton = intval($hookdata['singleton']);
|
||||
|
||||
// Now start processing the new connection
|
||||
|
||||
$aid = $channel['channel_account_id'];
|
||||
$default_group = $channel['channel_default_group'];
|
||||
|
||||
if (in_array($xchan_hash, [$channel['channel_hash'], $channel['channel_portable_id']])) {
|
||||
$result['message'] = t('Cannot connect to yourself.');
|
||||
return $result;
|
||||
}
|
||||
|
||||
if ($xchan['xchan_network'] === 'rss') {
|
||||
|
||||
// check service class feed limits
|
||||
|
||||
$t = q("select count(*) as total from abook where abook_account = %d and abook_feed = 1 ",
|
||||
intval($aid)
|
||||
);
|
||||
if ($t) {
|
||||
$total_feeds = $t[0]['total'];
|
||||
}
|
||||
|
||||
if (! service_class_allows($uid,'total_feeds',$total_feeds)) {
|
||||
$result['message'] = upgrade_message();
|
||||
return $result;
|
||||
}
|
||||
|
||||
// Always set these "remote" permissions for feeds since we cannot interact with them
|
||||
// to negotiate a suitable permission response
|
||||
|
||||
set_abconfig($uid,$xchan_hash,'their_perms','view_stream',1);
|
||||
set_abconfig($uid,$xchan_hash,'their_perms','republish',1);
|
||||
|
||||
}
|
||||
|
||||
|
||||
$p = Permissions::connect_perms($uid);
|
||||
|
||||
// parent channels have unencumbered write permission
|
||||
|
||||
if ($sub_channel) {
|
||||
$p['perms']['post_wall'] = 1;
|
||||
$p['perms']['post_comments'] = 1;
|
||||
$p['perms']['write_storage'] = 1;
|
||||
$p['perms']['post_like'] = 1;
|
||||
$p['perms']['delegate'] = 0;
|
||||
$p['perms']['moderated'] = 0;
|
||||
}
|
||||
|
||||
$my_perms = $p['perms'];
|
||||
|
||||
$profile_assign = get_pconfig($uid,'system','profile_assign','');
|
||||
|
||||
|
||||
// See if we are already connected by virtue of having an abook record
|
||||
|
||||
$r = q("select abook_id, abook_xchan, abook_pending, abook_instance from abook
|
||||
where abook_xchan = '%s' and abook_channel = %d limit 1",
|
||||
dbesc($xchan_hash),
|
||||
intval($uid)
|
||||
);
|
||||
|
||||
if ($r) {
|
||||
|
||||
$abook_instance = $r[0]['abook_instance'];
|
||||
|
||||
// If they are on a non-nomadic network, add them to this location
|
||||
|
||||
if (($singleton) && strpos($abook_instance,z_root()) === false) {
|
||||
if ($abook_instance) {
|
||||
$abook_instance .= ',';
|
||||
}
|
||||
$abook_instance .= z_root();
|
||||
|
||||
$x = q("update abook set abook_instance = '%s', abook_not_here = 0 where abook_id = %d",
|
||||
dbesc($abook_instance),
|
||||
intval($r[0]['abook_id'])
|
||||
);
|
||||
}
|
||||
|
||||
// if they have a pending connection, we just followed them so approve the connection request
|
||||
|
||||
if (intval($r[0]['abook_pending'])) {
|
||||
$x = q("update abook set abook_pending = 0 where abook_id = %d",
|
||||
intval($r[0]['abook_id'])
|
||||
);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
// create a new abook record
|
||||
|
||||
$closeness = get_pconfig($uid,'system','new_abook_closeness',80);
|
||||
|
||||
$r = abook_store_lowlevel(
|
||||
[
|
||||
'abook_account' => intval($aid),
|
||||
'abook_channel' => intval($uid),
|
||||
'abook_closeness' => intval($closeness),
|
||||
'abook_xchan' => $xchan_hash,
|
||||
'abook_profile' => $profile_assign,
|
||||
'abook_feed' => intval(($xchan['xchan_network'] === 'rss') ? 1 : 0),
|
||||
'abook_created' => datetime_convert(),
|
||||
'abook_updated' => datetime_convert(),
|
||||
'abook_instance' => (($singleton) ? z_root() : '')
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
if (! $r) {
|
||||
logger('abook creation failed');
|
||||
$result['message'] = t('error saving data');
|
||||
return $result;
|
||||
}
|
||||
|
||||
// Set suitable permissions to the connection
|
||||
|
||||
if($my_perms) {
|
||||
foreach($my_perms as $k => $v) {
|
||||
set_abconfig($uid,$xchan_hash,'my_perms',$k,$v);
|
||||
}
|
||||
}
|
||||
|
||||
// fetch the entire record
|
||||
|
||||
$r = q("select abook.*, xchan.* from abook left join xchan on abook_xchan = xchan_hash
|
||||
where abook_xchan = '%s' and abook_channel = %d limit 1",
|
||||
dbesc($xchan_hash),
|
||||
intval($uid)
|
||||
);
|
||||
|
||||
if ($r) {
|
||||
$result['abook'] = array_shift($r);
|
||||
Master::Summon([ 'Notifier', 'permission_create', $result['abook']['abook_id'] ]);
|
||||
}
|
||||
|
||||
$arr = [ 'channel_id' => $uid, 'channel' => $channel, 'abook' => $result['abook'] ];
|
||||
|
||||
call_hooks('follow', $arr);
|
||||
|
||||
/** If there is a default group for this channel, add this connection to it */
|
||||
|
||||
if ($default_group) {
|
||||
$g = AccessList::rec_byhash($uid,$default_group);
|
||||
if ($g) {
|
||||
AccessList::member_add($uid,'',$xchan_hash,$g['id']);
|
||||
}
|
||||
}
|
||||
|
||||
$result['success'] = true;
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
@@ -143,19 +143,26 @@ class Enotify {
|
||||
|
||||
$action = t('commented on');
|
||||
|
||||
if(array_key_exists('item',$params) && in_array($params['item']['verb'], [ACTIVITY_LIKE, ACTIVITY_DISLIKE])) {
|
||||
if(array_key_exists('item',$params)) {
|
||||
|
||||
if(in_array($params['item']['verb'], [ACTIVITY_LIKE, ACTIVITY_DISLIKE])) {
|
||||
|
||||
if(! $always_show_in_notices || !($vnotify & VNOTIFY_LIKE)) {
|
||||
logger('notification: not a visible activity. Ignoring.');
|
||||
pop_lang();
|
||||
return;
|
||||
}
|
||||
|
||||
if(activity_match($params['verb'], ACTIVITY_LIKE))
|
||||
$action = t('liked');
|
||||
|
||||
if(activity_match($params['verb'], ACTIVITY_DISLIKE))
|
||||
$action = t('disliked');
|
||||
|
||||
if(! $always_show_in_notices || !($vnotify & VNOTIFY_LIKE)) {
|
||||
logger('notification: not a visible activity. Ignoring.');
|
||||
pop_lang();
|
||||
return;
|
||||
}
|
||||
|
||||
if(activity_match($params['verb'], ACTIVITY_LIKE))
|
||||
$action = t('liked');
|
||||
|
||||
if(activity_match($params['verb'], ACTIVITY_DISLIKE))
|
||||
$action = t('disliked');
|
||||
if($params['item']['obj_type'] === 'Answer')
|
||||
$action = t('voted on');
|
||||
|
||||
}
|
||||
|
||||
@@ -550,6 +557,11 @@ class Enotify {
|
||||
if ((\App::$language === 'en' || (! \App::$language)) && strpos($msg,', '))
|
||||
$msg = substr($msg,strpos($msg,', ')+1);
|
||||
|
||||
$datarray['id'] = $notify_id;
|
||||
$datarray['msg'] = $msg;
|
||||
|
||||
call_hooks('enotify_store_end', $datarray);
|
||||
|
||||
$r = q("update notify set msg = '%s' where id = %d and uid = %d",
|
||||
dbesc($msg),
|
||||
intval($notify_id),
|
||||
@@ -805,13 +817,17 @@ class Enotify {
|
||||
}
|
||||
else {
|
||||
$itemem_text = (($item['item_thread_top'])
|
||||
? t('created a new post')
|
||||
: sprintf( t('commented on %s\'s post'), $item['owner']['xchan_name']));
|
||||
? (($item['obj_type'] === 'Question') ? t('created a new poll') : t('created a new post'))
|
||||
: (($item['obj_type'] === 'Answer') ? sprintf( t('voted on %s\'s poll'), '[bdi]' . $item['owner']['xchan_name'] . '[/bdi]') : sprintf( t('commented on %s\'s post'), '[bdi]' . $item['owner']['xchan_name'] . '[/bdi]'))
|
||||
);
|
||||
|
||||
if($item['verb'] === ACTIVITY_SHARE) {
|
||||
$itemem_text = sprintf( t('repeated %s\'s post'), $item['author']['xchan_name']);
|
||||
$itemem_text = sprintf( t('repeated %s\'s post'), '[bdi]' . $item['author']['xchan_name'] . '[/bdi]');
|
||||
}
|
||||
|
||||
if(in_array($item['obj_type'], ['Document', 'Video', 'Audio', 'Image'])) {
|
||||
$itemem_text = t('shared a file with you');
|
||||
}
|
||||
}
|
||||
|
||||
$edit = false;
|
||||
@@ -838,15 +854,16 @@ class Enotify {
|
||||
'addr' => (($item[$who]['xchan_addr']) ? $item[$who]['xchan_addr'] : $item[$who]['xchan_url']),
|
||||
'url' => $item[$who]['xchan_url'],
|
||||
'photo' => $item[$who]['xchan_photo_s'],
|
||||
'when' => relative_date(($edit)? $item['edited'] : $item['created']),
|
||||
'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' => ((in_array($item['verb'], [ACTIVITY_LIKE, ACTIVITY_DISLIKE])) ? 'b64.' . base64url_encode($item['thr_parent']) : 'b64.' . base64url_encode($item['mid'])),
|
||||
'notify_id' => 'undefined',
|
||||
'b64mid' => (($item['mid']) ? 'b64.' . base64url_encode($item['mid']) : ''),
|
||||
//'b64mid' => ((in_array($item['verb'], [ACTIVITY_LIKE, ACTIVITY_DISLIKE])) ? 'b64.' . base64url_encode($item['thr_parent']) : 'b64.' . base64url_encode($item['mid'])),
|
||||
'thread_top' => (($item['item_thread_top']) ? true : false),
|
||||
'message' => strip_tags(bbcode($itemem_text)),
|
||||
'message' => bbcode(escape_tags($itemem_text)),
|
||||
'body' => htmlentities(html2plain(bbcode($item['body']), 75, true), ENT_COMPAT, 'UTF-8', false),
|
||||
// these are for the superblock addon
|
||||
'hash' => $item[$who]['xchan_hash'],
|
||||
'uid' => local_channel(),
|
||||
'uid' => $item['uid'],
|
||||
'display' => true
|
||||
);
|
||||
|
||||
@@ -858,4 +875,118 @@ class Enotify {
|
||||
return $x;
|
||||
}
|
||||
|
||||
static public function format_notify($tt) {
|
||||
|
||||
$message = trim(strip_tags(bbcode($tt['msg'])));
|
||||
|
||||
if(strpos($message, $tt['xname']) === 0)
|
||||
$message = substr($message, strlen($tt['xname']) + 1);
|
||||
|
||||
$mid = basename($tt['link']);
|
||||
|
||||
$b64mid = ((strpos($mid, 'b64.') === 0) ? $mid : 'b64.' . base64url_encode($mid));
|
||||
$x = [
|
||||
'notify_link' => z_root() . '/notify/view/' . $tt['id'],
|
||||
'name' => $tt['xname'],
|
||||
'url' => $tt['url'],
|
||||
'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 : ''),
|
||||
'notify_id' => (($tt['otype'] == 'item') ? $tt['id'] : ''),
|
||||
'message' => $message
|
||||
];
|
||||
|
||||
return $x;
|
||||
|
||||
}
|
||||
|
||||
static public function format_intros($rr) {
|
||||
|
||||
$x = [
|
||||
'notify_link' => z_root() . '/connections/ifpending',
|
||||
'name' => $rr['xchan_name'],
|
||||
'addr' => $rr['xchan_addr'],
|
||||
'url' => $rr['xchan_url'],
|
||||
'photo' => $rr['xchan_photo_s'],
|
||||
'when' => datetime_convert('UTC', date_default_timezone_get(), $rr['abook_created']),
|
||||
'hclass' => ('notify-unseen'),
|
||||
'message' => t('added your channel')
|
||||
];
|
||||
|
||||
return $x;
|
||||
|
||||
}
|
||||
|
||||
static public function format_files($rr) {
|
||||
|
||||
$x = [
|
||||
'notify_link' => z_root() . '/sharedwithme',
|
||||
'name' => $rr['author']['xchan_name'],
|
||||
'addr' => $rr['author']['xchan_addr'],
|
||||
'url' => $rr['author']['xchan_url'],
|
||||
'photo' => $rr['author']['xchan_photo_s'],
|
||||
'when' => datetime_convert('UTC', date_default_timezone_get(), $rr['created']),
|
||||
'hclass' => ('notify-unseen'),
|
||||
'message' => t('shared a file with you')
|
||||
];
|
||||
|
||||
return $x;
|
||||
|
||||
}
|
||||
|
||||
static public function format_mail($rr) {
|
||||
|
||||
$x = [
|
||||
'notify_link' => z_root() . '/mail/' . $rr['id'],
|
||||
'name' => $rr['xchan_name'],
|
||||
'addr' => $rr['xchan_addr'],
|
||||
'url' => $rr['xchan_url'],
|
||||
'photo' => $rr['xchan_photo_s'],
|
||||
'when' => datetime_convert('UTC', date_default_timezone_get(), $rr['created']),
|
||||
'hclass' => (intval($rr['mail_seen']) ? 'notify-seen' : 'notify-unseen'),
|
||||
'message' => t('sent you a private message'),
|
||||
];
|
||||
|
||||
return $x;
|
||||
|
||||
}
|
||||
|
||||
static public function format_all_events($rr) {
|
||||
|
||||
$bd_format = t('g A l F d') ; // 8 AM Friday January 18
|
||||
$strt = datetime_convert('UTC', (($rr['adjust']) ? date_default_timezone_get() : 'UTC'), $rr['dtstart']);
|
||||
$today = ((substr($strt, 0, 10) === datetime_convert('UTC', date_default_timezone_get(), 'now', 'Y-m-d')) ? true : false);
|
||||
$when = day_translate(datetime_convert('UTC', (($rr['adjust']) ? date_default_timezone_get() : 'UTC'), $rr['dtstart'], $bd_format)) . (($today) ? ' ' . t('[today]') : '');
|
||||
|
||||
$x = [
|
||||
'notify_link' => z_root() . '/cdav/calendar/' . $rr['event_hash'],
|
||||
'name' => $rr['xchan_name'],
|
||||
'addr' => $rr['xchan_addr'],
|
||||
'url' => $rr['xchan_url'],
|
||||
'photo' => $rr['xchan_photo_s'],
|
||||
'when' => $when,
|
||||
'hclass' => (($today) ? 'notify-unseen bg-warning' : 'notify-unseen'),
|
||||
'message' => t('created an event')
|
||||
];
|
||||
|
||||
return $x;
|
||||
|
||||
}
|
||||
|
||||
static public function format_register($rr) {
|
||||
|
||||
$x = [
|
||||
'notify_link' => z_root() . '/admin/accounts',
|
||||
'name' => $rr['account_email'],
|
||||
//'addr' => $rr['account_email'],
|
||||
'photo' => z_root() . '/' . get_default_profile_photo(48),
|
||||
'when' => datetime_convert('UTC', date_default_timezone_get(),$rr['account_created']),
|
||||
'hclass' => ('notify-unseen'),
|
||||
'message' => t('requires approval')
|
||||
];
|
||||
|
||||
return $x;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ class JSalmon {
|
||||
. base64url_encode($x['encoding'],true) . '.'
|
||||
. base64url_encode($x['alg'],true);
|
||||
|
||||
$key = HTTPSig::get_key(EMPTY_STR,base64url_decode($x['sigs']['key_id']));
|
||||
$key = HTTPSig::get_key(EMPTY_STR,'zot6',base64url_decode($x['sigs']['key_id']));
|
||||
logger('key: ' . print_r($key,true));
|
||||
if($key['portable_id'] && $key['public_key']) {
|
||||
if(rsa_verify($signed_data,base64url_decode($x['sigs']['value']),$key['public_key'])) {
|
||||
@@ -69,4 +69,4 @@ class JSalmon {
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ class LDSignatures {
|
||||
'type' => 'RsaSignature2017',
|
||||
'nonce' => random_string(64),
|
||||
'creator' => z_root() . '/channel/' . $channel['channel_address'],
|
||||
'created' => datetime_convert('UTC','UTC', 'now', 'Y-m-d\Th:i:s\Z')
|
||||
'created' => datetime_convert('UTC','UTC', 'now', 'Y-m-d\TH:i:s\Z')
|
||||
];
|
||||
|
||||
$ohash = self::hash(self::signable_options($options));
|
||||
@@ -93,7 +93,8 @@ class LDSignatures {
|
||||
$d = jsonld_normalize($data,[ 'algorithm' => 'URDNA2015', 'format' => 'application/nquads' ]);
|
||||
}
|
||||
catch (\Exception $e) {
|
||||
logger('normalise error:' . print_r($e,true));
|
||||
// Don't log the exception - this can exhaust memory
|
||||
// logger('normalise error:' . print_r($e,true));
|
||||
logger('normalise error: ' . print_r($data,true));
|
||||
}
|
||||
|
||||
|
||||
@@ -83,7 +83,7 @@ class Libsync {
|
||||
|
||||
$info = (($packet) ? $packet : array());
|
||||
$info['type'] = 'sync';
|
||||
$info['encoding'] = 'red'; // note: not zot, this packet is very platform specific
|
||||
$info['encoding'] = 'hz'; // note: not zot, this packet is very platform specific
|
||||
$info['relocate'] = ['channel_address' => $channel['channel_address'], 'url' => z_root() ];
|
||||
|
||||
if(array_key_exists($uid,\App::$config) && array_key_exists('transient',\App::$config[$uid])) {
|
||||
@@ -144,12 +144,13 @@ class Libsync {
|
||||
|
||||
foreach($synchubs as $hub) {
|
||||
$hash = random_string();
|
||||
$n = Libzot::build_packet($channel,'sync',$env_recips,json_encode($info),'red',$hub['hubloc_sitekey'],$hub['site_crypto']);
|
||||
$n = Libzot::build_packet($channel,'sync',$env_recips,json_encode($info),'hz',$hub['hubloc_sitekey'],$hub['site_crypto']);
|
||||
Queue::insert(array(
|
||||
'hash' => $hash,
|
||||
'account_id' => $channel['channel_account_id'],
|
||||
'channel_id' => $channel['channel_id'],
|
||||
'posturl' => $hub['hubloc_callback'],
|
||||
'driver' => $hub['hubloc_network'],
|
||||
'notify' => $n,
|
||||
'msg' => EMPTY_STR
|
||||
));
|
||||
@@ -244,7 +245,13 @@ class Libsync {
|
||||
|
||||
if(array_key_exists('app',$arr) && $arr['app'])
|
||||
sync_apps($channel,$arr['app']);
|
||||
|
||||
|
||||
if(array_key_exists('addressbook',$arr) && $arr['addressbook'])
|
||||
sync_addressbook($channel,$arr['addressbook']);
|
||||
|
||||
if(array_key_exists('calendar',$arr) && $arr['calendar'])
|
||||
sync_calendar($channel,$arr['calendar']);
|
||||
|
||||
if(array_key_exists('chatroom',$arr) && $arr['chatroom'])
|
||||
sync_chatrooms($channel,$arr['chatroom']);
|
||||
|
||||
@@ -812,9 +819,9 @@ class Libsync {
|
||||
}
|
||||
|
||||
if(intval($r[0]['hubloc_primary']) && (! $location['primary'])) {
|
||||
$m = q("update hubloc set hubloc_primary = 0, hubloc_updated = '%s' where hubloc_id = %d",
|
||||
$m = q("update hubloc set hubloc_primary = 0, hubloc_updated = '%s' where hubloc_id_url = '%s'",
|
||||
dbesc(datetime_convert()),
|
||||
intval($r[0]['hubloc_id'])
|
||||
dbesc($r[0]['hubloc_id_url'])
|
||||
);
|
||||
$r[0]['hubloc_primary'] = intval($location['primary']);
|
||||
hubloc_change_primary($r[0]);
|
||||
@@ -841,18 +848,18 @@ class Libsync {
|
||||
}
|
||||
}
|
||||
if(intval($r[0]['hubloc_deleted']) && (! intval($location['deleted']))) {
|
||||
$n = q("update hubloc set hubloc_deleted = 0, hubloc_updated = '%s' where hubloc_id = %d",
|
||||
$n = q("update hubloc set hubloc_deleted = 0, hubloc_updated = '%s' where hubloc_id_url = '%s'",
|
||||
dbesc(datetime_convert()),
|
||||
intval($r[0]['hubloc_id'])
|
||||
dbesc($r[0]['hubloc_id_url'])
|
||||
);
|
||||
$what .= 'undelete_hub ';
|
||||
$changed = true;
|
||||
}
|
||||
elseif((! intval($r[0]['hubloc_deleted'])) && (intval($location['deleted']))) {
|
||||
logger('deleting hubloc: ' . $r[0]['hubloc_addr']);
|
||||
$n = q("update hubloc set hubloc_deleted = 1, hubloc_updated = '%s' where hubloc_id = %d",
|
||||
$n = q("update hubloc set hubloc_deleted = 1, hubloc_updated = '%s' where hubloc_id_url = '%s'",
|
||||
dbesc(datetime_convert()),
|
||||
intval($r[0]['hubloc_id'])
|
||||
dbesc($r[0]['hubloc_id_url'])
|
||||
);
|
||||
$what .= 'delete_hub ';
|
||||
$changed = true;
|
||||
@@ -911,9 +918,9 @@ class Libsync {
|
||||
foreach($xisting as $x) {
|
||||
if(! array_key_exists('updated',$x)) {
|
||||
logger('Deleting unreferenced hub location ' . $x['hubloc_addr']);
|
||||
$r = q("update hubloc set hubloc_deleted = 1, hubloc_updated = '%s' where hubloc_id = %d",
|
||||
$r = q("update hubloc set hubloc_deleted = 1, hubloc_updated = '%s' where hubloc_id_url = '%s'",
|
||||
dbesc(datetime_convert()),
|
||||
intval($x['hubloc_id'])
|
||||
dbesc($x['hubloc_id_url'])
|
||||
);
|
||||
$what .= 'removed_hub ';
|
||||
$changed = true;
|
||||
@@ -1016,4 +1023,4 @@ class Libsync {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,7 +105,7 @@ class Libzot {
|
||||
$data = [
|
||||
'type' => $type,
|
||||
'encoding' => $encoding,
|
||||
'sender' => $channel['channel_portable_id'],
|
||||
'sender' => $channel['channel_hash'],
|
||||
'site_id' => self::make_xchan_hash(z_root(), get_config('system','pubkey')),
|
||||
'version' => System::get_zot_revision(),
|
||||
];
|
||||
@@ -316,16 +316,20 @@ class Libzot {
|
||||
|
||||
$x = self::import_xchan($record['data'], (($force) ? UPDATE_FLAGS_FORCED : UPDATE_FLAGS_UPDATED));
|
||||
|
||||
|
||||
if(! $x['success'])
|
||||
return false;
|
||||
|
||||
if($channel && $record['data']['permissions']) {
|
||||
$permissions = explode(',',$record['data']['permissions']);
|
||||
|
||||
if($permissions && is_array($permissions)) {
|
||||
$old_read_stream_perm = get_abconfig($channel['channel_id'],$x['hash'],'their_perms','view_stream');
|
||||
|
||||
foreach($permissions as $p) {
|
||||
set_abconfig($channel['channel_id'],$x['hash'],'their_perms',$p,'1');
|
||||
$permissions = Permissions::FilledPerms($permissions);
|
||||
|
||||
foreach($permissions as $k => $v) {
|
||||
set_abconfig($channel['channel_id'],$x['hash'],'their_perms',$k,$v);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -422,7 +426,7 @@ class Libzot {
|
||||
[
|
||||
'type' => NOTIFY_INTRO,
|
||||
'from_xchan' => $x['hash'],
|
||||
'to_xchan' => $channel['channel_portable_id'],
|
||||
'to_xchan' => $channel['channel_hash'],
|
||||
'link' => z_root() . '/connedit/' . $new_connection[0]['abook_id']
|
||||
]
|
||||
);
|
||||
@@ -788,7 +792,7 @@ class Libzot {
|
||||
|
||||
// see if this is a channel clone that's hosted locally - which we treat different from other xchans/connections
|
||||
|
||||
$local = q("select channel_account_id, channel_id from channel where channel_portable_id = '%s' limit 1",
|
||||
$local = q("select channel_account_id, channel_id from channel where channel_hash = '%s' limit 1",
|
||||
dbesc($xchan_hash)
|
||||
);
|
||||
if($local) {
|
||||
@@ -1133,6 +1137,7 @@ class Libzot {
|
||||
}
|
||||
|
||||
logger($AS->debug(),LOGGER_DATA);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1151,7 +1156,7 @@ class Libzot {
|
||||
if($recip_arr) {
|
||||
stringify_array_elms($recip_arr,true);
|
||||
$recips = implode(',',$recip_arr);
|
||||
$r = q("select channel_portable_id as hash from channel where channel_portable_id in ( " . $recips . " ) and channel_removed = 0 ");
|
||||
$r = q("select channel_hash as hash from channel where channel_hash in ( " . $recips . " ) and channel_removed = 0 ");
|
||||
}
|
||||
|
||||
if(! $r) {
|
||||
@@ -1193,10 +1198,6 @@ class Libzot {
|
||||
|
||||
if(in_array($env['type'],['activity','response'])) {
|
||||
|
||||
$arr = Activity::decode_note($AS);
|
||||
|
||||
//logger($AS->debug());
|
||||
|
||||
$r = q("select hubloc_hash, hubloc_network from hubloc where hubloc_id_url = '%s' ",
|
||||
dbesc($AS->actor['id'])
|
||||
);
|
||||
@@ -1207,6 +1208,10 @@ class Libzot {
|
||||
$arr['author_xchan'] = $r['hubloc_hash'];
|
||||
}
|
||||
|
||||
if (! $arr['author_xchan']) {
|
||||
logger('No author!');
|
||||
return;
|
||||
}
|
||||
|
||||
$s = q("select hubloc_hash from hubloc where hubloc_id_url = '%s' and hubloc_network = 'zot6' limit 1",
|
||||
dbesc($env['sender'])
|
||||
@@ -1220,12 +1225,42 @@ class Libzot {
|
||||
$arr['owner_xchan'] = $env['sender'];
|
||||
}
|
||||
|
||||
if($private) {
|
||||
$arr['item_private'] = true;
|
||||
if ($private && (! intval($arr['item_private']))) {
|
||||
$arr['item_private'] = 1;
|
||||
}
|
||||
|
||||
if ($arr['mid'] === $arr['parent_mid']) {
|
||||
if (is_array($AS->obj) && array_key_exists('commentPolicy',$AS->obj)) {
|
||||
$p = strstr($AS->obj['commentPolicy'],'until=');
|
||||
if($p !== false) {
|
||||
$arr['comments_closed'] = datetime_convert('UTC','UTC', substr($p,6));
|
||||
$arr['comment_policy'] = trim(str_replace($p,'',$AS->obj['commentPolicy']));
|
||||
}
|
||||
else {
|
||||
$arr['comment_policy'] = $AS->obj['commentPolicy'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// @FIXME - spoofable
|
||||
if($AS->data['hubloc']) {
|
||||
$arr['item_verified'] = true;
|
||||
|
||||
if (! array_key_exists('comment_policy',$arr)) {
|
||||
// set comment policy depending on source hub. Unknown or osada is ActivityPub.
|
||||
// Anything else we'll say is zot - which could have a range of project names
|
||||
$s = q("select site_project from site where site_url = '%s' limit 1",
|
||||
dbesc($r[0]['hubloc_url'])
|
||||
);
|
||||
|
||||
if ((! $s) || (in_array($s[0]['site_project'],[ '', 'osada' ]))) {
|
||||
$arr['comment_policy'] = 'authenticated';
|
||||
}
|
||||
else {
|
||||
$arr['comment_policy'] = 'contacts';
|
||||
}
|
||||
}
|
||||
}
|
||||
if($AS->data['signed_data']) {
|
||||
IConfig::Set($arr,'activitystreams','signed_data',$AS->data['signed_data'],false);
|
||||
@@ -1247,7 +1282,12 @@ class Libzot {
|
||||
logger('Channel sync received: ' . print_r($arr,true), LOGGER_DATA, LOG_DEBUG);
|
||||
logger('Channel sync recipients: ' . print_r($deliveries,true), LOGGER_DATA, LOG_DEBUG);
|
||||
|
||||
$result = Libsync::process_channel_sync_delivery($env['sender'],$arr,$deliveries);
|
||||
if ($env['encoding'] === 'hz') {
|
||||
$result = Libsync::process_channel_sync_delivery($env['sender'],$arr,$deliveries);
|
||||
}
|
||||
else {
|
||||
logger('sync packet type not supported.');
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($result) {
|
||||
@@ -1333,12 +1373,12 @@ class Libzot {
|
||||
|
||||
$r = [];
|
||||
|
||||
$c = q("select channel_id, channel_portable_id from channel where channel_removed = 0");
|
||||
$c = q("select channel_id, channel_hash from channel where channel_removed = 0");
|
||||
|
||||
if($c) {
|
||||
foreach($c as $cc) {
|
||||
if(perm_is_allowed($cc['channel_id'],$msg['sender'],$perm)) {
|
||||
$r[] = $cc['channel_portable_id'];
|
||||
$r[] = $cc['channel_hash'];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1346,7 +1386,7 @@ class Libzot {
|
||||
if($include_sys) {
|
||||
$sys = get_sys_channel();
|
||||
if($sys)
|
||||
$r[] = $sys['channel_portable_id'];
|
||||
$r[] = $sys['channel_hash'];
|
||||
}
|
||||
|
||||
|
||||
@@ -1362,7 +1402,7 @@ class Libzot {
|
||||
if($tag['type'] === 'Mention' && (strpos($tag['href'],z_root()) !== false)) {
|
||||
$address = basename($tag['href']);
|
||||
if($address) {
|
||||
$z = q("select channel_portable_id as hash from channel where channel_address = '%s'
|
||||
$z = q("select channel_hash as hash from channel where channel_address = '%s'
|
||||
and channel_removed = 0 limit 1",
|
||||
dbesc($address)
|
||||
);
|
||||
@@ -1383,7 +1423,7 @@ class Libzot {
|
||||
$thread_parent = self::find_parent($msg,$act);
|
||||
|
||||
if($thread_parent) {
|
||||
$z = q("select channel_portable_id as hash from channel left join item on channel.channel_id = item.uid where ( item.thr_parent = '%s' OR item.parent_mid = '%s' ) ",
|
||||
$z = q("select channel_hash as hash from channel left join item on channel.channel_id = item.uid where ( item.thr_parent = '%s' OR item.parent_mid = '%s' ) ",
|
||||
dbesc($thread_parent),
|
||||
dbesc($thread_parent)
|
||||
);
|
||||
@@ -1438,7 +1478,7 @@ class Libzot {
|
||||
|
||||
$DR = new DReport(z_root(),$sender,$d,$arr['mid']);
|
||||
|
||||
$channel = channelx_by_portid($d);
|
||||
$channel = channelx_by_hash($d);
|
||||
|
||||
if (! $channel) {
|
||||
$DR->update('recipient not found');
|
||||
@@ -1453,13 +1493,14 @@ class Libzot {
|
||||
// Try again using the delivery channel credentials.
|
||||
// We will also need to re-parse the $item array,
|
||||
// but preserve any values that were set during anonymous parsing.
|
||||
|
||||
|
||||
$o = Activity::fetch($act->obj,$channel);
|
||||
if($o) {
|
||||
$act->obj = $o;
|
||||
$arr = array_merge(Activity::decode_note($act),$arr);
|
||||
}
|
||||
else {
|
||||
|
||||
$DR->update('Incomplete or corrupt activity');
|
||||
$result[] = $DR->get();
|
||||
continue;
|
||||
@@ -1475,7 +1516,7 @@ class Libzot {
|
||||
* access checks.
|
||||
*/
|
||||
|
||||
if($sender === $channel['channel_portable_id'] && $arr['author_xchan'] === $channel['channel_portable_id'] && $arr['mid'] === $arr['parent_mid']) {
|
||||
if($sender === $channel['channel_hash'] && $arr['author_xchan'] === $channel['channel_hash'] && $arr['mid'] === $arr['parent_mid']) {
|
||||
$DR->update('self delivery ignored');
|
||||
$result[] = $DR->get();
|
||||
continue;
|
||||
@@ -1578,10 +1619,11 @@ class Libzot {
|
||||
// As a side effect we will also do a preliminary check that we have the top-level-post, otherwise
|
||||
// processing it is pointless.
|
||||
|
||||
$r = q("select route, id, owner_xchan, item_private from item where mid = '%s' and uid = %d limit 1",
|
||||
$r = q("select route, id, parent_mid, mid, owner_xchan, item_private, obj_type from item where mid = '%s' and uid = %d limit 1",
|
||||
dbesc($arr['parent_mid']),
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
|
||||
if(! $r) {
|
||||
$DR->update('comment parent not found');
|
||||
$result[] = $DR->get();
|
||||
@@ -1604,6 +1646,16 @@ class Libzot {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($r[0]['obj_type'] === 'Question') {
|
||||
// route checking doesn't work correctly here because we've changed the privacy
|
||||
$r[0]['route'] = EMPTY_STR;
|
||||
// If this is a poll response, convert the obj_type to our (internal-only) "Answer" type
|
||||
if ($arr['obj_type'] === ACTIVITY_OBJ_COMMENT && $arr['title'] && (! $arr['body'])) {
|
||||
$arr['obj_type'] = 'Answer';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if($relay || $friendofriend || (intval($r[0]['item_private']) === 0 && intval($arr['item_private']) === 0)) {
|
||||
// reset the route in case it travelled a great distance upstream
|
||||
// use our parent's route so when we go back downstream we'll match
|
||||
@@ -1671,7 +1723,7 @@ class Libzot {
|
||||
$arr['aid'] = $channel['channel_account_id'];
|
||||
$arr['uid'] = $channel['channel_id'];
|
||||
|
||||
$item_id = self::delete_imported_item($sender,$arr,$channel['channel_id'],$relay);
|
||||
$item_id = self::delete_imported_item($sender,$act,$arr,$channel['channel_id'],$relay);
|
||||
$DR->update(($item_id) ? 'deleted' : 'delete_failed');
|
||||
$result[] = $DR->get();
|
||||
|
||||
@@ -1685,11 +1737,15 @@ class Libzot {
|
||||
continue;
|
||||
}
|
||||
|
||||
// reactions such as like and dislike could have an mid with /activity/ in it.
|
||||
// Check for both forms in order to prevent duplicates.
|
||||
|
||||
$r = q("select * from item where mid = '%s' and uid = %d limit 1",
|
||||
$r = q("select * from item where mid in ('%s','%s') and uid = %d limit 1",
|
||||
dbesc($arr['mid']),
|
||||
dbesc(str_replace(z_root() . '/activity/', z_root() . '/item/', $arr['mid'])),
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
|
||||
if($r) {
|
||||
// We already have this post.
|
||||
$item_id = $r[0]['id'];
|
||||
@@ -1734,7 +1790,7 @@ class Libzot {
|
||||
// if it's a sourced post, call the post_local hooks as if it were
|
||||
// posted locally so that crosspost connectors will be triggered.
|
||||
|
||||
if(check_item_source($arr['uid'], $arr)) {
|
||||
if(check_item_source($arr['uid'], $arr) || ($channel['xchan_pubforum'] == 1)) {
|
||||
/**
|
||||
* @hooks post_local
|
||||
* Called when an item has been posted on this machine via mod/item.php (also via API).
|
||||
@@ -1781,7 +1837,7 @@ class Libzot {
|
||||
|
||||
$stored = (($item_result && $item_result['item']) ? $item_result['item'] : false);
|
||||
if((is_array($stored)) && ($stored['id'] != $stored['parent'])
|
||||
&& ($stored['author_xchan'] === $channel['channel_hash'] || $stored['author_xchan'] === $channel['channel_portable_id'])) {
|
||||
&& ($stored['author_xchan'] === $channel['channel_hash'] || $stored['author_xchan'] === $channel['channel_hash'])) {
|
||||
retain_item($stored['item']['parent']);
|
||||
}
|
||||
|
||||
@@ -1819,6 +1875,10 @@ class Libzot {
|
||||
|
||||
$ret = [];
|
||||
|
||||
$signer = q("select hubloc_hash, hubloc_url from hubloc where hubloc_id_url = '%s' and hubloc_network = 'zot6' limit 1",
|
||||
dbesc($a['signature']['signer'])
|
||||
);
|
||||
|
||||
foreach($a['data']['orderedItems'] as $activity) {
|
||||
|
||||
$AS = new ActivityStreams($activity);
|
||||
@@ -1877,14 +1937,31 @@ class Libzot {
|
||||
if($AS->data['hubloc']) {
|
||||
$arr['item_verified'] = true;
|
||||
}
|
||||
|
||||
// set comment policy depending on source hub. Unknown or osada is ActivityPub.
|
||||
// Anything else we'll say is zot - which could have a range of project names
|
||||
|
||||
if ($signer) {
|
||||
$s = q("select site_project from site where site_url = '%s' limit 1",
|
||||
dbesc($signer[0]['hubloc_url'])
|
||||
);
|
||||
if ((! $s) || (in_array($s[0]['site_project'],[ '', 'osada' ]))) {
|
||||
$arr['comment_policy'] = 'authenticated';
|
||||
}
|
||||
else {
|
||||
$arr['comment_policy'] = 'contacts';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if($AS->data['signed_data']) {
|
||||
IConfig::Set($arr,'activitystreams','signed_data',$AS->data['signed_data'],false);
|
||||
}
|
||||
|
||||
logger('FOF Activity received: ' . print_r($arr,true), LOGGER_DATA, LOG_DEBUG);
|
||||
logger('FOF Activity recipient: ' . $channel['channel_portable_id'], LOGGER_DATA, LOG_DEBUG);
|
||||
logger('FOF Activity recipient: ' . $channel['channel_hash'], LOGGER_DATA, LOG_DEBUG);
|
||||
|
||||
$result = self::process_delivery($arr['owner_xchan'],$AS, $arr, [ $channel['channel_portable_id'] ],false,false,true);
|
||||
$result = self::process_delivery($arr['owner_xchan'],$AS, $arr, [ $channel['channel_hash'] ],false,false,true);
|
||||
if ($result) {
|
||||
$ret = array_merge($ret, $result);
|
||||
}
|
||||
@@ -2029,7 +2106,7 @@ class Libzot {
|
||||
* @return boolean|int post_id
|
||||
*/
|
||||
|
||||
static function delete_imported_item($sender, $item, $uid, $relay) {
|
||||
static function delete_imported_item($sender, $act, $item, $uid, $relay) {
|
||||
|
||||
logger('invoked', LOGGER_DEBUG);
|
||||
|
||||
@@ -2037,38 +2114,39 @@ class Libzot {
|
||||
$item_found = false;
|
||||
$post_id = 0;
|
||||
|
||||
if ($item['verb'] === 'Tombstone') {
|
||||
// The id of the deleted thing is the item mid (activity id)
|
||||
$mid = $item['mid'];
|
||||
}
|
||||
else {
|
||||
// The id is the object id if the type is Undo or Delete
|
||||
$mid = ((is_array($act->obj)) ? $act->obj['id'] : $act->obj);
|
||||
}
|
||||
|
||||
// we may have stored either the object id or the activity id if it was a response activity (like, dislike, etc.)
|
||||
|
||||
$r = q("select * from item where ( author_xchan = '%s' or owner_xchan = '%s' or source_xchan = '%s' )
|
||||
and mid = '%s' and uid = %d limit 1",
|
||||
and mid IN ('%s', '%s') and uid = %d limit 1",
|
||||
dbesc($sender),
|
||||
dbesc($sender),
|
||||
dbesc($sender),
|
||||
dbesc($item['mid']),
|
||||
dbesc($mid),
|
||||
dbesc(str_replace('/activity/','/item/',$mid)),
|
||||
intval($uid)
|
||||
);
|
||||
|
||||
if($r) {
|
||||
$stored = $r[0];
|
||||
|
||||
if($stored['author_xchan'] === $sender || $stored['owner_xchan'] === $sender || $stored['source_xchan'] === $sender)
|
||||
$ownership_valid = true;
|
||||
// we proved ownership in the sql query
|
||||
$ownership_valid = true;
|
||||
|
||||
$post_id = $stored['id'];
|
||||
$item_found = true;
|
||||
}
|
||||
else {
|
||||
|
||||
// perhaps the item is still in transit and the delete notification got here before the actual item did. Store it with the deleted flag set.
|
||||
// item_store() won't try to deliver any notifications or start delivery chains if this flag is set.
|
||||
// This means we won't end up with potentially even more delivery threads trying to push this delete notification.
|
||||
// But this will ensure that if the (undeleted) original post comes in at a later date, we'll reject it because it will have an older timestamp.
|
||||
|
||||
logger('delete received for non-existent item - storing item data.');
|
||||
|
||||
if($item['author_xchan'] === $sender || $item['owner_xchan'] === $sender || $item['source_xchan'] === $sender) {
|
||||
$ownership_valid = true;
|
||||
$item_result = item_store($item);
|
||||
$post_id = $item_result['item_id'];
|
||||
}
|
||||
// this will fail with an ownership issue, so explain the real reason
|
||||
logger('delete received for non-existent item or not owned by sender - ignoring.');
|
||||
}
|
||||
|
||||
if($ownership_valid === false) {
|
||||
@@ -2140,7 +2218,7 @@ class Libzot {
|
||||
|
||||
$DR = new DReport(z_root(),$sender,$d,$arr['mid']);
|
||||
|
||||
$r = q("select * from channel where channel_portable_id = '%s' limit 1",
|
||||
$r = q("select * from channel where channel_hash = '%s' limit 1",
|
||||
dbesc($d['hash'])
|
||||
);
|
||||
|
||||
@@ -2295,7 +2373,7 @@ class Libzot {
|
||||
|
||||
$loc = $locations[0];
|
||||
|
||||
$r = q("select * from channel where channel_portable_id = '%s' limit 1",
|
||||
$r = q("select * from channel where channel_hash = '%s' limit 1",
|
||||
dbesc($sender_hash)
|
||||
);
|
||||
|
||||
@@ -2303,7 +2381,7 @@ class Libzot {
|
||||
return;
|
||||
|
||||
if($loc['url'] !== z_root()) {
|
||||
$x = q("update channel set channel_moved = '%s' where channel_portable_id = '%s' limit 1",
|
||||
$x = q("update channel set channel_moved = '%s' where channel_hash = '%s' limit 1",
|
||||
dbesc($loc['url']),
|
||||
dbesc($sender_hash)
|
||||
);
|
||||
@@ -2337,7 +2415,7 @@ class Libzot {
|
||||
static function encode_locations($channel) {
|
||||
$ret = [];
|
||||
|
||||
$x = self::get_hublocs($channel['channel_portable_id']);
|
||||
$x = self::get_hublocs($channel['channel_hash']);
|
||||
|
||||
if($x && count($x)) {
|
||||
foreach($x as $hub) {
|
||||
@@ -2685,13 +2763,13 @@ class Libzot {
|
||||
$r = null;
|
||||
|
||||
if(strlen($zhash)) {
|
||||
$r = q("select channel.*, xchan.* from channel left join xchan on channel_portable_id = xchan_hash
|
||||
where channel_portable_id = '%s' limit 1",
|
||||
$r = q("select channel.*, xchan.* from channel left join xchan on channel_hash = xchan_hash
|
||||
where channel_hash = '%s' limit 1",
|
||||
dbesc($zhash)
|
||||
);
|
||||
}
|
||||
elseif(strlen($zguid) && strlen($zguid_sig)) {
|
||||
$r = q("select channel.*, xchan.* from channel left join xchan on channel_portable_id = xchan_hash
|
||||
$r = q("select channel.*, xchan.* from channel left join xchan on channel_hash = xchan_hash
|
||||
where channel_guid = '%s' and channel_guid_sig = '%s' limit 1",
|
||||
dbesc($zguid),
|
||||
dbesc($zguid_sig)
|
||||
@@ -2699,7 +2777,7 @@ class Libzot {
|
||||
}
|
||||
elseif(strlen($zaddr)) {
|
||||
if(strpos($zaddr,'[system]') === false) { /* normal address lookup */
|
||||
$r = q("select channel.*, xchan.* from channel left join xchan on channel_portable_id = xchan_hash
|
||||
$r = q("select channel.*, xchan.* from channel left join xchan on channel_hash = xchan_hash
|
||||
where ( channel_address = '%s' or xchan_addr = '%s' ) limit 1",
|
||||
dbesc($zaddr),
|
||||
dbesc($zaddr)
|
||||
@@ -2719,10 +2797,10 @@ class Libzot {
|
||||
*
|
||||
*/
|
||||
|
||||
$r = q("select channel.*, xchan.* from channel left join xchan on channel_portable_id = xchan_hash
|
||||
$r = q("select channel.*, xchan.* from channel left join xchan on channel_hash = xchan_hash
|
||||
where channel_system = 1 order by channel_id limit 1");
|
||||
if(! $r) {
|
||||
$r = q("select channel.*, xchan.* from channel left join xchan on channel_portable_id = xchan_hash
|
||||
$r = q("select channel.*, xchan.* from channel left join xchan on channel_hash = xchan_hash
|
||||
where channel_removed = 0 order by channel_id limit 1");
|
||||
}
|
||||
}
|
||||
@@ -2841,7 +2919,7 @@ class Libzot {
|
||||
];
|
||||
|
||||
$ret['channel_role'] = get_pconfig($e['channel_id'],'system','permissions_role','custom');
|
||||
$ret['protocols'] = [ 'zot', 'zot6' ];
|
||||
$ret['protocols'] = [ 'zot6', 'zot' ];
|
||||
$ret['searchable'] = $searchable;
|
||||
$ret['adult_content'] = $adult_channel;
|
||||
$ret['public_forum'] = $public_forum;
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
use Zotlabs\Lib\Libzot;
|
||||
use Zotlabs\Lib\Zotfinger;
|
||||
use Zotlabs\Lib\Webfinger;
|
||||
|
||||
require_once('include/permissions.php');
|
||||
|
||||
@@ -307,9 +309,9 @@ class Libzotdir {
|
||||
if ($ud['ud_addr'] && (! ($ud['ud_flags'] & UPDATE_FLAGS_DELETED))) {
|
||||
$success = false;
|
||||
|
||||
$href = \Zotlabs\Lib\Webfinger::zot_url(punify($ud['ud_addr']));
|
||||
$href = Webfinger::zot_url(punify($ud['ud_addr']));
|
||||
if($href) {
|
||||
$zf = \Zotlabs\Lib\Zotfinger::exec($href);
|
||||
$zf = Zotfinger::exec($href);
|
||||
}
|
||||
if(is_array($zf) && array_path_exists('signature/signer',$zf) && $zf['signature']['signer'] === $href && intval($zf['signature']['header_valid'])) {
|
||||
$xc = Libzot::import_xchan($zf['data'], 0, $ud);
|
||||
@@ -339,7 +341,7 @@ class Libzotdir {
|
||||
|
||||
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, channel_portable_id, profile.* from profile left join channel on channel_id = uid where uid = %d and is_default = 1",
|
||||
intval($uid)
|
||||
);
|
||||
|
||||
@@ -348,6 +350,7 @@ class Libzotdir {
|
||||
|
||||
if ($p) {
|
||||
$hash = $p[0]['channel_hash'];
|
||||
$legacy_hash = $p[0]['channel_portable_id'];
|
||||
|
||||
$profile['description'] = $p[0]['pdesc'];
|
||||
$profile['birthday'] = $p[0]['dob'];
|
||||
@@ -381,14 +384,15 @@ class Libzotdir {
|
||||
|
||||
logger('hidden: ' . $hidden);
|
||||
|
||||
$r = q("select xchan_hidden from xchan where xchan_hash = '%s' limit 1",
|
||||
$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'",
|
||||
$r = q("update xchan set xchan_hidden = %d where xchan_hash in ('%s', '%s')",
|
||||
intval($hidden),
|
||||
dbesc($p[0]['channel_hash'])
|
||||
dbesc($hash),
|
||||
dbesc($legacy_hash)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -402,11 +406,13 @@ class Libzotdir {
|
||||
}
|
||||
else {
|
||||
// they may have made it private
|
||||
$r = q("delete from xprof where xprof_hash = '%s'",
|
||||
dbesc($hash)
|
||||
q("delete from xprof where xprof_hash in ('%s', '%s')",
|
||||
dbesc($hash),
|
||||
dbesc($legacy_hash)
|
||||
);
|
||||
$r = q("delete from xtag where xtag_hash = '%s'",
|
||||
dbesc($hash)
|
||||
q("delete from xtag where xtag_hash in ('%s', '%s')",
|
||||
dbesc($hash),
|
||||
dbesc($legacy_hash)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
use Zotlabs\Lib\Libsync;
|
||||
|
||||
define ( 'NWIKI_ITEM_RESOURCE_TYPE', 'nwiki' );
|
||||
|
||||
class NativeWiki {
|
||||
@@ -71,7 +73,7 @@ class NativeWiki {
|
||||
$arr['item_thread_top'] = 1;
|
||||
$arr['item_private'] = intval($acl->is_private());
|
||||
$arr['verb'] = ACTIVITY_CREATE;
|
||||
$arr['obj_type'] = ACTIVITY_OBJ_WIKI;
|
||||
$arr['obj_type'] = 'Document';
|
||||
$arr['body'] = '[table][tr][td][h1]New Wiki[/h1][/td][/tr][tr][td][zrl=' . $wiki_url . ']' . $wiki['htmlName'] . '[/zrl][/td][/tr][/table]';
|
||||
|
||||
$arr['public_policy'] = map_scope(\Zotlabs\Access\PermissionLimits::Get($channel['channel_id'],'view_wiki'),true);
|
||||
@@ -178,7 +180,7 @@ class NativeWiki {
|
||||
foreach($sync_item as $w) {
|
||||
$pkt[] = encode_item($w,true);
|
||||
}
|
||||
build_sync_packet($uid,array('wiki' => $pkt));
|
||||
Libsync::build_sync_packet($uid,array('wiki' => $pkt));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -530,8 +530,11 @@ class NativeWikiPage {
|
||||
foreach ($match[1] as $m) {
|
||||
// TODO: Why do we need to double urlencode for this to work?
|
||||
//$pageURLs[] = urlencode(urlencode(escape_tags($m)));
|
||||
$pageURLs[] = Zlib\NativeWiki::name_encode(escape_tags($m));
|
||||
$pages[] = $m;
|
||||
$titleUri = explode('|',$m);
|
||||
$page = $titleUri[0] ?? '';
|
||||
$title = $titleUri[1] ?? $page;
|
||||
$pageURLs[] = Zlib\NativeWiki::name_encode(escape_tags($page));
|
||||
$pages[] = $title;
|
||||
}
|
||||
$idx = 0;
|
||||
while(strpos($s,'[[') !== false) {
|
||||
|
||||
@@ -116,7 +116,7 @@ class Queue {
|
||||
dbesc($arr['hash']),
|
||||
intval($arr['account_id']),
|
||||
intval($arr['channel_id']),
|
||||
dbesc(($arr['driver']) ? $arr['driver'] : 'zot'),
|
||||
dbesc(($arr['driver']) ? $arr['driver'] : 'zot6'),
|
||||
dbesc($arr['posturl']),
|
||||
intval(1),
|
||||
intval(($arr['priority']) ? $arr['priority'] : 0),
|
||||
@@ -250,7 +250,7 @@ class Queue {
|
||||
$host_crypto = null;
|
||||
|
||||
if($channel && $base) {
|
||||
$h = q("select hubloc_sitekey, site_crypto from hubloc left join site on hubloc_url = site_url where site_url = '%s' order by hubloc_id desc limit 1",
|
||||
$h = q("select hubloc_sitekey, site_crypto from hubloc left join site on hubloc_url = site_url where site_url = '%s' and hubloc_sitekey != '' order by hubloc_id desc limit 1",
|
||||
dbesc($base)
|
||||
);
|
||||
if($h) {
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
use Zotlabs\Lib\Activity;
|
||||
|
||||
class Share {
|
||||
|
||||
@@ -54,7 +55,7 @@ class Share {
|
||||
if(! $this->item)
|
||||
return $obj;
|
||||
|
||||
$obj['asld'] = $this->item['mid'];
|
||||
$obj['asld'] = Activity::fetch_item( [ 'id' => $this->item['mid'] ] );
|
||||
$obj['type'] = $this->item['obj_type'];
|
||||
$obj['id'] = $this->item['mid'];
|
||||
$obj['content'] = $this->item['body'];
|
||||
@@ -127,12 +128,12 @@ class Share {
|
||||
"' profile='" . $this->item['author']['xchan_url'] .
|
||||
"' avatar='" . $this->item['author']['xchan_photo_s'] .
|
||||
"' link='" . $this->item['plink'] .
|
||||
"' auth='" . (($this->item['author']['network'] === 'zot') ? 'true' : 'false') .
|
||||
"' auth='" . ((in_array($this->item['author']['xchan_network'], ['zot6', 'zot'])) ? 'true' : 'false') .
|
||||
"' posted='" . $this->item['created'] .
|
||||
"' message_id='" . $this->item['mid'] .
|
||||
"']";
|
||||
if($this->item['title'])
|
||||
$bb .= '[b]'.$this->item['title'].'[/b]'."\r\n";
|
||||
$bb .= '[h3][b]'.$this->item['title'].'[/b][/h3]'."\r\n";
|
||||
$bb .= (($is_photo) ? $photo_bb . "\r\n" . $this->item['body'] : $this->item['body']);
|
||||
$bb .= "[/share]";
|
||||
}
|
||||
|
||||
150
Zotlabs/Lib/SvgSanitizer.php
Normal file
150
Zotlabs/Lib/SvgSanitizer.php
Normal file
@@ -0,0 +1,150 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Lib;
|
||||
use DomDocument;
|
||||
|
||||
/**
|
||||
* SVGSantiizer
|
||||
*
|
||||
* Whitelist-based PHP SVG sanitizer.
|
||||
*
|
||||
* @link https://github.com/alister-/SVG-Sanitizer}
|
||||
* @author Alister Norris
|
||||
* @copyright Copyright (c) 2013 Alister Norris
|
||||
* @license http://opensource.org/licenses/mit-license.php The MIT License
|
||||
* @package svgsanitizer
|
||||
*/
|
||||
|
||||
class SvgSanitizer {
|
||||
|
||||
private $xmlDoc; // PHP XML DOMDocument
|
||||
|
||||
private $removedattrs = [];
|
||||
|
||||
private static $allowed_functions = [ 'matrix', 'url', 'translate', 'rgb' ];
|
||||
|
||||
// defines the whitelist of elements and attributes allowed.
|
||||
private static $whitelist = [
|
||||
'a' => [ 'class', 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'mask', 'opacity', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform', 'href', 'xlink:href', 'xlink:title' ],
|
||||
'circle' => [ 'class', 'clip-path', 'clip-rule', 'cx', 'cy', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'mask', 'opacity', 'r', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform' ],
|
||||
'clipPath' => [ 'class', 'clipPathUnits', 'id' ],
|
||||
'defs' => [ ],
|
||||
'style' => [ 'type' ],
|
||||
'desc' => [ ],
|
||||
'ellipse' => [ 'class', 'clip-path', 'clip-rule', 'cx', 'cy', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'mask', 'opacity', 'requiredFeatures', 'rx', 'ry', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform' ],
|
||||
'feGaussianBlur' => [ 'class', 'color-interpolation-filters', 'id', 'requiredFeatures', 'stdDeviation' ],
|
||||
'filter' => [ 'class', 'color-interpolation-filters', 'filterRes', 'filterUnits', 'height', 'id', 'primitiveUnits', 'requiredFeatures', 'width', 'x', 'xlink:href', 'y' ],
|
||||
'foreignObject' => [ 'class', 'font-size', 'height', 'id', 'opacity', 'requiredFeatures', 'style', 'transform', 'width', 'x', 'y' ],
|
||||
'g' => [ 'class', 'clip-path', 'clip-rule', 'id', 'display', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'mask', 'opacity', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform', 'font-family', 'font-size', 'font-style', 'font-weight', 'text-anchor' ],
|
||||
'image' => [ 'class', 'clip-path', 'clip-rule', 'filter', 'height', 'id', 'mask', 'opacity', 'requiredFeatures', 'style', 'systemLanguage', 'transform', 'width', 'x', 'xlink:href', 'xlink:title', 'y' ],
|
||||
'line' => [ 'class', 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'marker-end', 'marker-mid', 'marker-start', 'mask', 'opacity', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform', 'x1', 'x2', 'y1', 'y2' ],
|
||||
'linearGradient' => [ 'class', 'id', 'gradientTransform', 'gradientUnits', 'requiredFeatures', 'spreadMethod', 'systemLanguage', 'x1', 'x2', 'xlink:href', 'y1', 'y2' ],
|
||||
'marker' => [ 'id', 'class', 'markerHeight', 'markerUnits', 'markerWidth', 'orient', 'preserveAspectRatio', 'refX', 'refY', 'systemLanguage', 'viewBox' ],
|
||||
'mask' => [ 'class', 'height', 'id', 'maskContentUnits', 'maskUnits', 'width', 'x', 'y' ],
|
||||
'metadata' => [ 'class', 'id' ],
|
||||
'path' => [ 'class', 'clip-path', 'clip-rule', 'd', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'marker-end', 'marker-mid', 'marker-start', 'mask', 'opacity', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform' ],
|
||||
'pattern' => [ 'class', 'height', 'id', 'patternContentUnits', 'patternTransform', 'patternUnits', 'requiredFeatures', 'style', 'systemLanguage', 'viewBox', 'width', 'x', 'xlink:href', 'y' ],
|
||||
'polygon' => [ 'class', 'clip-path', 'clip-rule', 'id', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'class', 'marker-end', 'marker-mid', 'marker-start', 'mask', 'opacity', 'points', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform' ],
|
||||
'polyline' => [ 'class', 'clip-path', 'clip-rule', 'id', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'marker-end', 'marker-mid', 'marker-start', 'mask', 'opacity', 'points', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform' ],
|
||||
'radialGradient' => [ 'class', 'cx', 'cy', 'fx', 'fy', 'gradientTransform', 'gradientUnits', 'id', 'r', 'requiredFeatures', 'spreadMethod', 'systemLanguage', 'xlink:href' ],
|
||||
'rect' => [ 'class', 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'height', 'id', 'mask', 'opacity', 'requiredFeatures', 'rx', 'ry', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform', 'width', 'x', 'y' ],
|
||||
'stop' => [ 'class', 'id', 'offset', 'requiredFeatures', 'stop-color', 'stop-opacity', 'style', 'systemLanguage' ],
|
||||
'svg' => [ 'class', 'clip-path', 'clip-rule', 'filter', 'id', 'height', 'mask', 'preserveAspectRatio', 'requiredFeatures', 'style', 'systemLanguage', 'viewBox', 'width', 'x', 'xmlns', 'xmlns:se', 'xmlns:xlink', 'y' ],
|
||||
'switch' => [ 'class', 'id', 'requiredFeatures', 'systemLanguage' ],
|
||||
'symbol' => [ 'class', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'font-family', 'font-size', 'font-style', 'font-weight', 'id', 'opacity', 'preserveAspectRatio', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform', 'viewBox' ],
|
||||
'text' => [ 'class', 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'font-family', 'font-size', 'font-style', 'font-weight', 'id', 'mask', 'opacity', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'text-anchor', 'transform', 'x', 'xml:space', 'y' ],
|
||||
'textPath' => [ 'class', 'id', 'method', 'requiredFeatures', 'spacing', 'startOffset', 'style', 'systemLanguage', 'transform', 'xlink:href' ],
|
||||
'title' => [ ],
|
||||
'tspan' => [ 'class', 'clip-path', 'clip-rule', 'dx', 'dy', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'font-family', 'font-size', 'font-style', 'font-weight', 'id', 'mask', 'opacity', 'requiredFeatures', 'rotate', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'text-anchor', 'textLength', 'transform', 'x', 'xml:space', 'y' ],
|
||||
'use' => [ 'class', 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'height', 'id', 'mask', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'transform', 'width', 'x', 'xlink:href', 'y' ],
|
||||
];
|
||||
|
||||
function __construct() {
|
||||
$this->xmlDoc = new DOMDocument('1.0','UTF-8');
|
||||
$this->xmlDoc->preserveWhiteSpace = false;
|
||||
libxml_use_internal_errors(true);
|
||||
}
|
||||
|
||||
// load XML SVG
|
||||
function load($file) {
|
||||
$this->xmlDoc->load($file);
|
||||
}
|
||||
|
||||
function loadXML($str) {
|
||||
if (! $this->xmlDoc->loadXML($str)) {
|
||||
logger('loadxml: ' . print_r(libxml_get_errors(),true), LOGGER_DEBUG);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function sanitize()
|
||||
{
|
||||
// all elements in xml doc
|
||||
$allElements = $this->xmlDoc->getElementsByTagName('*');
|
||||
|
||||
// loop through all elements
|
||||
for($i = 0; $i < $allElements->length; $i++)
|
||||
{
|
||||
$this->removedattrs = [];
|
||||
|
||||
$currentNode = $allElements->item($i);
|
||||
|
||||
// logger('current_node: ' . print_r($currentNode,true));
|
||||
|
||||
// array of allowed attributes in specific element
|
||||
$whitelist_attr_arr = self::$whitelist[$currentNode->tagName];
|
||||
|
||||
// does element exist in whitelist?
|
||||
if(isset($whitelist_attr_arr)) {
|
||||
$total = $currentNode->attributes->length;
|
||||
|
||||
for($x = 0; $x < $total; $x++) {
|
||||
|
||||
// get attributes name
|
||||
$attrName = $currentNode->attributes->item($x)->nodeName;
|
||||
|
||||
// logger('checking: ' . print_r($currentNode->attributes->item($x),true));
|
||||
$matches = false;
|
||||
|
||||
// check if attribute isn't in whitelist
|
||||
if(! in_array($attrName, $whitelist_attr_arr)) {
|
||||
$this->removedattrs[] = $attrName;
|
||||
}
|
||||
// check for disallowed functions
|
||||
elseif (preg_match_all('/([a-zA-Z0-9]+)[\s]*\(/',
|
||||
$currentNode->attributes->item($x)->textContent,$matches,PREG_SET_ORDER)) {
|
||||
if ($attrName === 'text') {
|
||||
continue;
|
||||
}
|
||||
foreach ($matches as $match) {
|
||||
if(! in_array($match[1],self::$allowed_functions)) {
|
||||
logger('queue_remove_function: ' . $match[1],LOGGER_DEBUG);
|
||||
$this->removedattrs[] = $attrName;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($this->removedattrs) {
|
||||
foreach ($this->removedattrs as $attr) {
|
||||
$currentNode->removeAttribute($attr);
|
||||
logger('removed: ' . $attr, LOGGER_DEBUG);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// else remove element
|
||||
else {
|
||||
logger('remove_node: ' . print_r($currentNode,true));
|
||||
$currentNode->parentNode->removeChild($currentNode);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function saveSVG() {
|
||||
$this->xmlDoc->formatOutput = true;
|
||||
return($this->xmlDoc->saveXML());
|
||||
}
|
||||
}
|
||||
@@ -5,9 +5,14 @@ namespace Zotlabs\Lib;
|
||||
class System {
|
||||
|
||||
static public function get_platform_name() {
|
||||
if(is_array(\App::$config) && is_array(\App::$config['system']) && array_key_exists('platform_name',\App::$config['system']))
|
||||
return \App::$config['system']['platform_name'];
|
||||
return PLATFORM_NAME;
|
||||
static $platform_name = '';
|
||||
if(empty($platform_name)) {
|
||||
if(is_array(\App::$config) && is_array(\App::$config['system']) && array_key_exists('platform_name',\App::$config['system']))
|
||||
$platform_name = \App::$config['system']['platform_name'];
|
||||
else
|
||||
$platform_name = PLATFORM_NAME;
|
||||
}
|
||||
return $platform_name;
|
||||
}
|
||||
|
||||
static public function get_site_name() {
|
||||
|
||||
@@ -78,7 +78,7 @@ class ThreadItem {
|
||||
*/
|
||||
|
||||
public function get_template_data($conv_responses, $thread_level=1, $conv_flags = []) {
|
||||
|
||||
|
||||
$result = array();
|
||||
|
||||
$item = $this->get_data();
|
||||
@@ -95,7 +95,7 @@ class ThreadItem {
|
||||
$total_children = $this->count_descendants();
|
||||
$unseen_comments = (($item['real_uid']) ? 0 : $this->count_unseen_descendants());
|
||||
|
||||
$conv = $this->get_conversation();
|
||||
$conv = $this->get_conversation();
|
||||
$observer = $conv->get_observer();
|
||||
|
||||
$lock = (((intval($item['item_private'])) || (($item['uid'] == local_channel()) && (strlen($item['allow_cid']) || strlen($item['allow_gid'])
|
||||
@@ -113,7 +113,7 @@ class ThreadItem {
|
||||
if(intval($item['item_private']) && ($item['owner']['xchan_network'] === 'activitypub')) {
|
||||
$recips = get_iconfig($item['parent'], 'activitypub', 'recips');
|
||||
|
||||
if(! in_array($observer['xchan_url'], $recips['to']))
|
||||
if(! is_array($recips['to']) || ! in_array($observer['xchan_url'], $recips['to']))
|
||||
$privacy_warning = true;
|
||||
}
|
||||
|
||||
@@ -150,9 +150,11 @@ class ThreadItem {
|
||||
$edpost = false;
|
||||
|
||||
|
||||
if($observer['xchan_hash'] == $this->get_data_value('author_xchan')
|
||||
if($observer && $observer['xchan_hash']
|
||||
&& ($observer['xchan_hash'] == $this->get_data_value('author_xchan')
|
||||
|| $observer['xchan_hash'] == $this->get_data_value('owner_xchan')
|
||||
|| $this->get_data_value('uid') == local_channel())
|
||||
|| $observer['xchan_hash'] == $this->get_data_value('source_xchan')
|
||||
|| $this->get_data_value('uid') == local_channel()))
|
||||
$dropping = true;
|
||||
|
||||
|
||||
@@ -204,6 +206,10 @@ class ThreadItem {
|
||||
}
|
||||
}
|
||||
|
||||
if($item['obj_type'] === 'Question') {
|
||||
$response_verbs[] = 'answer';
|
||||
}
|
||||
|
||||
$consensus = (intval($item['item_consensus']) ? true : false);
|
||||
if($consensus) {
|
||||
$response_verbs[] = 'agree';
|
||||
@@ -281,12 +287,16 @@ class ThreadItem {
|
||||
|
||||
$settings = '';
|
||||
|
||||
$tagger = [];
|
||||
|
||||
// FIXME - check this permission
|
||||
if($conv->get_profile_owner() == local_channel()) {
|
||||
/* disable until we agree on how to implemnt this in zot6/activitypub
|
||||
$tagger = array(
|
||||
'tagit' => t("Add Tag"),
|
||||
'classtagger' => "",
|
||||
);
|
||||
*/
|
||||
|
||||
$settings = t('Conversation Tools');
|
||||
}
|
||||
@@ -346,7 +356,7 @@ class ThreadItem {
|
||||
$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('%d unseen',$unseen_comments) : '');
|
||||
$list_unseen_txt = (($unseen_comments) ? sprintf( t('%d unseen'),$unseen_comments) : '');
|
||||
|
||||
$children = $this->get_children();
|
||||
|
||||
@@ -356,11 +366,28 @@ class ThreadItem {
|
||||
call_hooks('dropdown_extras',$dropdown_extras_arr);
|
||||
$dropdown_extras = $dropdown_extras_arr['dropdown_extras'];
|
||||
|
||||
$midb64 = 'b64.' . base64url_encode($item['mid']);
|
||||
$mids = [ $midb64 ];
|
||||
$response_mids = [];
|
||||
foreach($response_verbs as $v) {
|
||||
if(isset($conv_responses[$v]['mids'][$item['mid']])) {
|
||||
$response_mids = array_merge($response_mids, $conv_responses[$v]['mids'][$item['mid']]);
|
||||
}
|
||||
}
|
||||
|
||||
$mids = array_merge($mids, $response_mids);
|
||||
$json_mids = json_encode($mids);
|
||||
|
||||
// Pinned item processing
|
||||
$allowed_type = (in_array($item['item_type'], get_config('system', 'pin_types', [ ITEM_TYPE_POST ])) ? true : false);
|
||||
$pinned_items = ($allowed_type ? get_pconfig($item['uid'], 'pinned', $item['item_type'], []) : []);
|
||||
$pinned = ((!empty($pinned_items) && in_array($midb64, $pinned_items)) ? true : false);
|
||||
|
||||
$tmp_item = array(
|
||||
'template' => $this->get_template(),
|
||||
'mode' => $mode,
|
||||
'item_type' => intval($item['item_type']),
|
||||
'type' => implode("",array_slice(explode("/",$item['verb']),-1)),
|
||||
//'type' => implode("",array_slice(explode("/",$item['verb']),-1)),
|
||||
'body' => $body['html'],
|
||||
'tags' => $body['tags'],
|
||||
'categories' => $body['categories'],
|
||||
@@ -369,7 +396,8 @@ class ThreadItem {
|
||||
'folders' => $body['folders'],
|
||||
'text' => strip_tags($body['html']),
|
||||
'id' => $this->get_id(),
|
||||
'mid' => $item['mid'],
|
||||
'mid' => $midb64,
|
||||
'mids' => $json_mids,
|
||||
'parent' => $item['parent'],
|
||||
'author_id' => (($item['author']['xchan_addr']) ? $item['author']['xchan_addr'] : $item['author']['xchan_url']),
|
||||
'isevent' => $isevent,
|
||||
@@ -377,8 +405,8 @@ class ThreadItem {
|
||||
'consensus' => $consensus,
|
||||
'conlabels' => $conlabels,
|
||||
'canvote' => $canvote,
|
||||
'linktitle' => sprintf( t('View %s\'s profile - %s'), $profile_name, (($item['author']['xchan_addr']) ? $item['author']['xchan_addr'] : $item['author']['xchan_url'])),
|
||||
'olinktitle' => sprintf( t('View %s\'s profile - %s'), $this->get_owner_name(), (($item['owner']['xchan_addr']) ? $item['owner']['xchan_addr'] : $item['owner']['xchan_url'])),
|
||||
'linktitle' => (($item['author']['xchan_addr']) ? $item['author']['xchan_addr'] : $item['author']['xchan_url']),
|
||||
'olinktitle' => (($item['owner']['xchan_addr']) ? $item['owner']['xchan_addr'] : $item['owner']['xchan_url']),
|
||||
'llink' => $item['llink'],
|
||||
'viewthread' => $viewthread,
|
||||
'to' => t('to'),
|
||||
@@ -396,7 +424,7 @@ class ThreadItem {
|
||||
'sparkle' => $sparkle,
|
||||
'title' => $item['title'],
|
||||
'title_tosource' => get_pconfig($conv->get_profile_owner(),'system','title_tosource'),
|
||||
'ago' => relative_date($item['created']),
|
||||
//'ago' => relative_date($item['created']),
|
||||
'app' => $item['app'],
|
||||
'str_app' => sprintf( t('from %s'), $item['app']),
|
||||
'isotime' => datetime_convert('UTC', date_default_timezone_get(), $item['created'], 'c'),
|
||||
@@ -404,6 +432,7 @@ class ThreadItem {
|
||||
'editedtime' => (($item['edited'] != $item['created']) ? sprintf( t('last edited: %s'), datetime_convert('UTC', date_default_timezone_get(), $item['edited'], 'r')) : ''),
|
||||
'expiretime' => (($item['expires'] > NULL_DATE) ? sprintf( t('Expires: %s'), datetime_convert('UTC', date_default_timezone_get(), $item['expires'], 'r')):''),
|
||||
'lock' => $lock,
|
||||
'delayed' => $item['item_delayed'],
|
||||
'privacy_warning' => $privacy_warning,
|
||||
'verified' => $verified,
|
||||
'unverified' => $unverified,
|
||||
@@ -437,6 +466,9 @@ class ThreadItem {
|
||||
'star' => ((feature_enabled($conv->get_profile_owner(),'star_posts') && ($item['item_type'] == ITEM_TYPE_POST)) ? $star : ''),
|
||||
'tagger' => ((feature_enabled($conv->get_profile_owner(),'commtag')) ? $tagger : ''),
|
||||
'filer' => ((feature_enabled($conv->get_profile_owner(),'filing') && ($item['item_type'] == ITEM_TYPE_POST)) ? $filer : ''),
|
||||
'pinned' => ($pinned ? t('Pinned post') : ''),
|
||||
'pinnable' => (($this->is_toplevel() && local_channel() && $item['owner_xchan'] == $observer['xchan_hash'] && $allowed_type && $item['item_private'] == 0 && $item['item_delayed'] == 0) ? '1' : ''),
|
||||
'pinme' => ($pinned ? t('Unpin from the top') : t('Pin to the top')),
|
||||
'bookmark' => (($conv->get_profile_owner() == local_channel() && local_channel() && $has_bookmarks) ? t('Save Bookmarks') : ''),
|
||||
'addtocal' => (($has_event) ? t('Add to Calendar') : ''),
|
||||
'drop' => $drop,
|
||||
@@ -463,14 +495,13 @@ class ThreadItem {
|
||||
'modal_dismiss' => t('Close'),
|
||||
'showlike' => $showlike,
|
||||
'showdislike' => $showdislike,
|
||||
'comment' => $this->get_comment_box($indent),
|
||||
'comment' => ($item['item_delayed'] ? '' : $this->get_comment_box($indent)),
|
||||
'previewing' => ($conv->is_preview() ? true : false ),
|
||||
'preview_lbl' => t('This is an unsaved preview'),
|
||||
'wait' => t('Please wait'),
|
||||
'submid' => str_replace(['+','='], ['',''], base64_encode($item['mid'])),
|
||||
'thread_level' => $thread_level,
|
||||
'settings' => $settings,
|
||||
'thr_parent' => (($item['parent_mid'] != $item['thr_parent']) ? $item['thr_parent'] : '')
|
||||
'thr_parent' => (($item['parent_mid'] != $item['thr_parent']) ? 'b64.' . base64url_encode($item['thr_parent']) : '')
|
||||
);
|
||||
|
||||
$arr = array('item' => $item, 'output' => $tmp_item);
|
||||
@@ -778,8 +809,6 @@ class ThreadItem {
|
||||
call_hooks('comment_buttons',$arr);
|
||||
$comment_buttons = $arr['comment_buttons'];
|
||||
|
||||
$feature_auto_save_draft = ((feature_enabled($conv->get_profile_owner(), 'auto_save_draft')) ? "true" : "false");
|
||||
|
||||
$comment_box = replace_macros($template,array(
|
||||
'$return_path' => '',
|
||||
'$threaded' => $this->is_threaded(),
|
||||
@@ -814,8 +843,7 @@ class ThreadItem {
|
||||
'$anoncomments' => ((($conv->get_mode() === 'channel' || $conv->get_mode() === 'display') && perm_is_allowed($conv->get_profile_owner(),'','post_comments')) ? true : false),
|
||||
'$anonname' => [ 'anonname', t('Your full name (required)') ],
|
||||
'$anonmail' => [ 'anonmail', t('Your email address (required)') ],
|
||||
'$anonurl' => [ 'anonurl', t('Your website URL (optional)') ],
|
||||
'$auto_save_draft' => $feature_auto_save_draft
|
||||
'$anonurl' => [ 'anonurl', t('Your website URL (optional)') ]
|
||||
));
|
||||
|
||||
return $comment_box;
|
||||
@@ -866,7 +894,4 @@ class ThreadItem {
|
||||
return $this->visiting;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ class ThreadStream {
|
||||
private $preview = false;
|
||||
private $prepared_item = '';
|
||||
public $reload = '';
|
||||
private $cipher = 'aes256';
|
||||
private $cipher = 'AES-128-CCM';
|
||||
|
||||
// $prepared_item is for use by alternate conversation structures such as photos
|
||||
// wherein we've already prepared a top level item which doesn't look anything like
|
||||
|
||||
@@ -106,4 +106,4 @@ class Webfinger {
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ use Zotlabs\Web\HTTPSig;
|
||||
|
||||
class Zotfinger {
|
||||
|
||||
static function exec($resource,$channel = null) {
|
||||
static function exec($resource,$channel = null, $verify = true) {
|
||||
|
||||
if(! $resource) {
|
||||
return false;
|
||||
@@ -41,8 +41,9 @@ class Zotfinger {
|
||||
logger('fetch: ' . print_r($x,true));
|
||||
|
||||
if($x['success']) {
|
||||
|
||||
$result['signature'] = HTTPSig::verify($x);
|
||||
if ($verify) {
|
||||
$result['signature'] = HTTPSig::verify($x, EMPTY_STR, 'zot6');
|
||||
}
|
||||
|
||||
$result['data'] = json_decode($x['body'],true);
|
||||
|
||||
@@ -60,4 +61,4 @@ class Zotfinger {
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ class Acl extends \Zotlabs\Web\Controller {
|
||||
|
||||
|
||||
// $type =
|
||||
// 'm' => autocomplete private mail recipient (checks post_mail permission)
|
||||
// 'm' => autocomplete private mail recipient (checks post_mail permission and displays only zot, diaspora, friendica-over-diaspora xchan_network xchan's)
|
||||
// 'a' => autocomplete connections (mod_connections, mod_poke, mod_sources, mod_photos)
|
||||
// 'x' => nav search bar autocomplete (match any xchan)
|
||||
// $_REQUEST['query'] contains autocomplete search text.
|
||||
@@ -286,6 +286,7 @@ class Acl extends \Zotlabs\Web\Controller {
|
||||
FROM abook left join xchan on abook_xchan = xchan_hash
|
||||
WHERE abook_channel = %d
|
||||
and xchan_deleted = 0
|
||||
and xchan_network IN ('zot', 'diaspora', 'friendica-over-diaspora')
|
||||
$sql_extra3
|
||||
ORDER BY xchan_name ASC ",
|
||||
intval(local_channel())
|
||||
|
||||
269
Zotlabs/Module/Activity.php
Normal file
269
Zotlabs/Module/Activity.php
Normal file
@@ -0,0 +1,269 @@
|
||||
<?php
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
use Zotlabs\Lib\IConfig;
|
||||
use Zotlabs\Lib\Enotify;
|
||||
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;
|
||||
use App;
|
||||
|
||||
|
||||
class Activity extends Controller {
|
||||
|
||||
function init() {
|
||||
|
||||
if (Libzot::is_zot_request()) {
|
||||
|
||||
$item_id = argv(1);
|
||||
if (! $item_id)
|
||||
http_status_exit(404, 'Not found');
|
||||
|
||||
$portable_id = EMPTY_STR;
|
||||
|
||||
$item_normal = " and item.item_hidden = 0 and item.item_type = 0 and item.item_unpublished = 0 and item.item_delayed = 0 and item.item_blocked = 0 ";
|
||||
|
||||
$i = null;
|
||||
|
||||
// do we have the item (at all)?
|
||||
|
||||
$r = q("select * from item where mid = '%s' $item_normal limit 1",
|
||||
dbesc(z_root() . '/activity/' . $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'])
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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');
|
||||
|
||||
$items = q("SELECT item.*, item.id AS item_id FROM item WHERE item.parent IN ( %s ) $item_normal ",
|
||||
dbesc($parents_str)
|
||||
);
|
||||
|
||||
if(! $items) {
|
||||
http_status_exit(404, 'Not found');
|
||||
}
|
||||
|
||||
xchan_query($items,true);
|
||||
$items = fetch_post_tags($items,true);
|
||||
|
||||
$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');
|
||||
|
||||
$chan = channelx_by_n($nitems[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 = ZlibActivity::encode_item_collection($nitems,'conversation/' . $item_id,'OrderedCollection');
|
||||
if($portable_id) {
|
||||
ThreadListener::store(z_root() . '/activity/' . $item_id,$portable_id);
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
}
|
||||
|
||||
if(ActivityStreams::is_as_request()) {
|
||||
|
||||
$item_id = argv(1);
|
||||
|
||||
if (! $item_id) {
|
||||
return;
|
||||
}
|
||||
|
||||
$ob_authorise = false;
|
||||
$item_uid = 0;
|
||||
|
||||
$bear = ZlibActivity::token_from_request();
|
||||
if ($bear) {
|
||||
logger('bear: ' . $bear, LOGGER_DEBUG);
|
||||
$t = q("select item.uid, iconfig.v from iconfig left join item on iid = item.id where cat = 'ocap' and item.uuid = '%s'",
|
||||
dbesc($item_id)
|
||||
);
|
||||
if ($t) {
|
||||
foreach ($t as $token) {
|
||||
if ($token['v'] === $bear) {
|
||||
$ob_authorize = true;
|
||||
$item_uid = $token['uid'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$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 ";
|
||||
|
||||
$sigdata = HTTPSig::verify(EMPTY_STR);
|
||||
if ($sigdata['portable_id'] && $sigdata['header_valid']) {
|
||||
$portable_id = $sigdata['portable_id'];
|
||||
if (! check_channelallowed($portable_id)) {
|
||||
http_status_exit(403, 'Permission denied');
|
||||
}
|
||||
if (! check_siteallowed($sigdata['signer'])) {
|
||||
http_status_exit(403, 'Permission denied');
|
||||
}
|
||||
observer_auth($portable_id);
|
||||
}
|
||||
|
||||
// if passed an owner_id of 0 to item_permissions_sql(), we force "guest access" or observer checking
|
||||
// Give ocap tokens priority
|
||||
|
||||
if ($ob_authorize) {
|
||||
$sql_extra = " and item.uid = " . intval($token['uid']) . " ";
|
||||
}
|
||||
else {
|
||||
$sql_extra = item_permissions_sql(0);
|
||||
}
|
||||
|
||||
$r = q("select * from item where uuid = '%s' $item_normal $sql_extra limit 1",
|
||||
dbesc($item_id)
|
||||
);
|
||||
|
||||
if (! $r) {
|
||||
$r = q("select * from item where uuid = '%s' $item_normal limit 1",
|
||||
dbesc($item_id)
|
||||
);
|
||||
if($r) {
|
||||
http_status_exit(403, 'Forbidden');
|
||||
}
|
||||
http_status_exit(404, 'Not found');
|
||||
}
|
||||
|
||||
xchan_query($r,true);
|
||||
$items = fetch_post_tags($r,false);
|
||||
|
||||
$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();
|
||||
|
||||
}
|
||||
|
||||
goaway(z_root() . '/item/' . argv(1));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace Zotlabs\Module\Admin;
|
||||
|
||||
use App;
|
||||
use \Zotlabs\Storage\GitRepo;
|
||||
use \Michelf\MarkdownExtra;
|
||||
|
||||
@@ -17,7 +18,7 @@ class Addons {
|
||||
@include_once("addon/" . argv(2) . "/" . argv(2) . ".php");
|
||||
if(function_exists(argv(2).'_plugin_admin_post')) {
|
||||
$func = argv(2) . '_plugin_admin_post';
|
||||
$func($a);
|
||||
$func();
|
||||
}
|
||||
|
||||
goaway(z_root() . '/admin/addons/' . argv(2) );
|
||||
@@ -253,14 +254,14 @@ class Addons {
|
||||
* Single plugin
|
||||
*/
|
||||
|
||||
if (\App::$argc == 3){
|
||||
$plugin = \App::$argv[2];
|
||||
if (App::$argc == 3){
|
||||
$plugin = App::$argv[2];
|
||||
if (!is_file("addon/$plugin/$plugin.php")){
|
||||
notice( t("Item not found.") );
|
||||
return '';
|
||||
}
|
||||
|
||||
$enabled = in_array($plugin,\App::$plugins);
|
||||
$enabled = in_array($plugin,App::$plugins);
|
||||
$info = get_plugin_info($plugin);
|
||||
$x = check_plugin_versions($info);
|
||||
|
||||
@@ -268,11 +269,11 @@ class Addons {
|
||||
|
||||
if($enabled && ! $x) {
|
||||
$enabled = false;
|
||||
$idz = array_search($plugin, \App::$plugins);
|
||||
$idz = array_search($plugin, App::$plugins);
|
||||
if ($idz !== false) {
|
||||
unset(\App::$plugins[$idz]);
|
||||
unset(App::$plugins[$idz]);
|
||||
uninstall_plugin($plugin);
|
||||
set_config("system","addon", implode(", ",\App::$plugins));
|
||||
set_config("system","addon", implode(", ",App::$plugins));
|
||||
}
|
||||
}
|
||||
$info['disabled'] = 1-intval($x);
|
||||
@@ -281,19 +282,19 @@ class Addons {
|
||||
check_form_security_token_redirectOnErr('/admin/addons', 'admin_addons', 't');
|
||||
$pinstalled = false;
|
||||
// Toggle plugin status
|
||||
$idx = array_search($plugin, \App::$plugins);
|
||||
$idx = array_search($plugin, App::$plugins);
|
||||
if ($idx !== false){
|
||||
unset(\App::$plugins[$idx]);
|
||||
unset(App::$plugins[$idx]);
|
||||
uninstall_plugin($plugin);
|
||||
$pinstalled = false;
|
||||
info( sprintf( t("Plugin %s disabled."), $plugin ) );
|
||||
} else {
|
||||
\App::$plugins[] = $plugin;
|
||||
App::$plugins[] = $plugin;
|
||||
install_plugin($plugin);
|
||||
$pinstalled = true;
|
||||
info( sprintf( t("Plugin %s enabled."), $plugin ) );
|
||||
}
|
||||
set_config("system","addon", implode(", ",\App::$plugins));
|
||||
set_config("system","addon", implode(", ",App::$plugins));
|
||||
|
||||
if($pinstalled) {
|
||||
@require_once("addon/$plugin/$plugin.php");
|
||||
@@ -305,7 +306,7 @@ class Addons {
|
||||
|
||||
// display plugin details
|
||||
|
||||
if (in_array($plugin, \App::$plugins)){
|
||||
if (in_array($plugin, App::$plugins)){
|
||||
$status = 'on';
|
||||
$action = t('Disable');
|
||||
} else {
|
||||
@@ -331,7 +332,7 @@ class Addons {
|
||||
@require_once("addon/$plugin/$plugin.php");
|
||||
if(function_exists($plugin.'_plugin_admin')) {
|
||||
$func = $plugin.'_plugin_admin';
|
||||
$func($a, $admin_form);
|
||||
$func($admin_form);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -380,18 +381,18 @@ class Addons {
|
||||
|
||||
list($tmp, $id) = array_map('trim', explode('/', $file));
|
||||
$info = get_plugin_info($id);
|
||||
$enabled = in_array($id,\App::$plugins);
|
||||
$enabled = in_array($id,App::$plugins);
|
||||
$x = check_plugin_versions($info);
|
||||
|
||||
// disable plugins which are installed but incompatible versions
|
||||
|
||||
if($enabled && ! $x) {
|
||||
$enabled = false;
|
||||
$idz = array_search($id, \App::$plugins);
|
||||
$idz = array_search($id, App::$plugins);
|
||||
if ($idz !== false) {
|
||||
unset(\App::$plugins[$idz]);
|
||||
unset(App::$plugins[$idz]);
|
||||
uninstall_plugin($id);
|
||||
set_config("system","addon", implode(", ",\App::$plugins));
|
||||
set_config("system","addon", implode(", ",App::$plugins));
|
||||
}
|
||||
}
|
||||
$info['disabled'] = 1-intval($x);
|
||||
|
||||
@@ -43,6 +43,12 @@ class Security {
|
||||
|
||||
$be = $this->trim_array_elems(explode("\n",$_POST['embed_deny']));
|
||||
set_config('system','embed_deny',$be);
|
||||
|
||||
$thumbnail_security = ((x($_POST,'thumbnail_security')) ? intval($_POST['thumbnail_security']) : 0);
|
||||
set_config('system', 'thumbnail_security' , $thumbnail_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);
|
||||
@@ -86,7 +92,7 @@ class Security {
|
||||
$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.");
|
||||
|
||||
|
||||
$t = get_markup_template('admin_security.tpl');
|
||||
return replace_macros($t, array(
|
||||
'$title' => t('Administration'),
|
||||
@@ -106,7 +112,9 @@ class Security {
|
||||
'$embed_sslonly' => array('embed_sslonly',t('Only allow embeds from secure (SSL) websites and links.'), intval(get_config('system','embed_sslonly')),''),
|
||||
'$embed_allow' => array('embed_allow', t('Allow unfiltered embedded HTML content only from these domains'), $whiteembeds_str, t('One site per line. By default embedded content is filtered.')),
|
||||
'$embed_deny' => array('embed_deny', t('Block embedded HTML from these domains'), $blackembeds_str, ''),
|
||||
|
||||
'$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), '' ],
|
||||
|
||||
// '$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')
|
||||
@@ -128,4 +136,4 @@ class Security {
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,6 +62,9 @@ class Site {
|
||||
$from_email = ((array_key_exists('from_email',$_POST) && trim($_POST['from_email'])) ? trim($_POST['from_email']) : 'Administrator@' . \App::get_hostname());
|
||||
$from_email_name = ((array_key_exists('from_email_name',$_POST) && trim($_POST['from_email_name'])) ? trim($_POST['from_email_name']) : \Zotlabs\Lib\System::get_site_name());
|
||||
|
||||
|
||||
$sse_enabled = ((x($_POST,'sse_enabled')) ? true : false);
|
||||
|
||||
$verifyssl = ((x($_POST,'verifyssl')) ? True : False);
|
||||
$proxyuser = ((x($_POST,'proxyuser')) ? notags(trim($_POST['proxyuser'])) : '');
|
||||
$proxy = ((x($_POST,'proxy')) ? notags(trim($_POST['proxy'])) : '');
|
||||
@@ -73,7 +76,6 @@ class Site {
|
||||
$feed_contacts = ((x($_POST,'feed_contacts')) ? intval($_POST['feed_contacts']) : 0);
|
||||
$verify_email = ((x($_POST,'verify_email')) ? 1 : 0);
|
||||
$imagick_path = ((x($_POST,'imagick_path')) ? trim($_POST['imagick_path']) : '');
|
||||
$thumbnail_security = ((x($_POST,'thumbnail_security')) ? intval($_POST['thumbnail_security']) : 0);
|
||||
$force_queue = ((intval($_POST['force_queue']) > 0) ? intval($_POST['force_queue']) : 3000);
|
||||
$pub_incl = escape_tags(trim($_POST['pub_incl']));
|
||||
$pub_excl = escape_tags(trim($_POST['pub_excl']));
|
||||
@@ -100,7 +102,6 @@ class Site {
|
||||
set_config('system', 'from_email', $from_email);
|
||||
set_config('system', 'from_email_name' , $from_email_name);
|
||||
set_config('system', 'imagick_convert_path' , $imagick_path);
|
||||
set_config('system', 'thumbnail_security' , $thumbnail_security);
|
||||
set_config('system', 'default_permissions_role', $permissions_role);
|
||||
set_config('system', 'pubstream_incl',$pub_incl);
|
||||
set_config('system', 'pubstream_excl',$pub_excl);
|
||||
@@ -153,6 +154,9 @@ class Site {
|
||||
|
||||
set_config('system','no_community_page', $no_community_page);
|
||||
set_config('system','no_utf', $no_utf);
|
||||
|
||||
set_config('system','sse_enabled', $sse_enabled);
|
||||
|
||||
set_config('system','verifyssl', $verifyssl);
|
||||
set_config('system','proxyuser', $proxyuser);
|
||||
set_config('system','proxy', $proxy);
|
||||
@@ -333,6 +337,8 @@ class Site {
|
||||
|
||||
'$directory_server' => (($dir_choices) ? array('directory_server', t("Directory Server URL"), get_config('system','directory_server'), t("Default directory server"), $dir_choices) : null),
|
||||
|
||||
'$sse_enabled' => array('sse_enabled', t('Enable SSE Notifications'), get_config('system', 'sse_enabled', 0), t('If disabled, traditional polling will be used. Warning: this setting might not be suited for shared hosting')),
|
||||
|
||||
'$proxyuser' => array('proxyuser', t("Proxy user"), get_config('system','proxyuser'), ""),
|
||||
'$proxy' => array('proxy', t("Proxy URL"), get_config('system','proxy'), ""),
|
||||
'$timeout' => array('timeout', t("Network timeout"), (x(get_config('system','curl_timeout'))?get_config('system','curl_timeout'):60), t("Value is in seconds. Set to 0 for unlimited (not recommended).")),
|
||||
@@ -341,7 +347,6 @@ class Site {
|
||||
'$force_queue' => array('force_queue', t("Queue Threshold"), get_config('system','force_queue_threshold',3000), t("Always defer immediate delivery if queue contains more than this number of entries.")),
|
||||
'$poll_interval' => array('poll_interval', t("Poll interval"), (x(get_config('system','poll_interval'))?get_config('system','poll_interval'):2), t("Delay background polling processes by this many seconds to reduce system load. If 0, use delivery interval.")),
|
||||
'$imagick_path' => array('imagick_path', t("Path to ImageMagick convert program"), get_config('system','imagick_convert_path'), t("If set, use this program to generate photo thumbnails for huge images ( > 4000 pixels in either dimension), otherwise memory exhaustion may occur. Example: /usr/bin/convert")),
|
||||
'$thumbnail_security' => array('thumbnail_security', t("Allow SVG thumbnails in file browser"), get_config('system','thumbnail_security',0), t("WARNING: SVG images may contain malicious code.")),
|
||||
'$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')),
|
||||
'$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)), ''),
|
||||
|
||||
@@ -34,9 +34,9 @@ class Apporder extends \Zotlabs\Web\Controller {
|
||||
|
||||
foreach($syslist as $app) {
|
||||
if($l === 'nav_pinned_app') {
|
||||
$navbar_apps[] = Zlib\Apps::app_render($app,'nav-order');
|
||||
$navbar_apps[] = Zlib\Apps::app_render($app,'nav-order-pinned');
|
||||
}
|
||||
elseif(strpos($app['categories'],'nav_pinned_app') === false) {
|
||||
else {
|
||||
$nav_apps[] = Zlib\Apps::app_render($app,'nav-order');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,10 @@ class Apschema extends \Zotlabs\Web\Controller {
|
||||
'emojiReaction' => 'zot:emojiReaction',
|
||||
'expires' => 'zot:expires',
|
||||
'directMessage' => 'zot:directMessage',
|
||||
|
||||
'schema' => 'http://schema.org#',
|
||||
'PropertyValue' => 'schema:PropertyValue',
|
||||
'value' => 'schema:value',
|
||||
|
||||
'magicEnv' => [
|
||||
'@id' => 'zot:magicEnv',
|
||||
'@type' => '@id'
|
||||
|
||||
@@ -85,10 +85,9 @@ class Article_edit extends \Zotlabs\Web\Controller {
|
||||
|
||||
$mimetype = $itm[0]['mimetype'];
|
||||
|
||||
$summary = (($itm[0]['summary']) ? '[summary]' . $itm[0]['summary'] . '[/summary]' . "\r\n" : '');
|
||||
$content = $itm[0]['body'];
|
||||
|
||||
|
||||
|
||||
$rp = 'articles/' . $channel['channel_address'];
|
||||
|
||||
$x = array(
|
||||
@@ -110,7 +109,7 @@ class Article_edit extends \Zotlabs\Web\Controller {
|
||||
'ptyp' => $itm[0]['type'],
|
||||
'mimeselect' => false,
|
||||
'mimetype' => $itm[0]['mimetype'],
|
||||
'body' => undo_post_tagging($content),
|
||||
'body' => $summary . undo_post_tagging($content),
|
||||
'post_id' => $post_id,
|
||||
'visitor' => true,
|
||||
'title' => htmlspecialchars($itm[0]['title'],ENT_COMPAT,'UTF-8'),
|
||||
|
||||
@@ -9,6 +9,7 @@ use Zotlabs\Lib\PermissionDescription;
|
||||
require_once('include/channel.php');
|
||||
require_once('include/conversation.php');
|
||||
require_once('include/acl_selectors.php');
|
||||
require_once('include/opengraph.php');
|
||||
|
||||
|
||||
class Articles extends Controller {
|
||||
@@ -148,7 +149,7 @@ class Articles extends Controller {
|
||||
}
|
||||
|
||||
$itemspage = get_pconfig(local_channel(),'system','itemspage');
|
||||
App::set_pager_itemspage(((intval($itemspage)) ? $itemspage : 20));
|
||||
App::set_pager_itemspage(((intval($itemspage)) ? $itemspage : 10));
|
||||
$pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(App::$pager['itemspage']), intval(App::$pager['start']));
|
||||
|
||||
|
||||
@@ -192,7 +193,7 @@ class Articles extends Controller {
|
||||
|
||||
$parents_str = ids_to_querystr($r,'id');
|
||||
|
||||
$items = q("SELECT item.*, item.id AS item_id
|
||||
$r = q("SELECT item.*, item.id AS item_id
|
||||
FROM item
|
||||
WHERE item.uid = %d $item_normal
|
||||
AND item.parent IN ( %s )
|
||||
@@ -200,15 +201,18 @@ class Articles extends Controller {
|
||||
intval(App::$profile['profile_uid']),
|
||||
dbesc($parents_str)
|
||||
);
|
||||
if($items) {
|
||||
xchan_query($items);
|
||||
$items = fetch_post_tags($items, true);
|
||||
if($r) {
|
||||
xchan_query($r);
|
||||
$items = fetch_post_tags($r, true);
|
||||
$items = conv_sort($items,'updated');
|
||||
}
|
||||
else
|
||||
$items = [];
|
||||
}
|
||||
|
||||
// Add Opengraph markup
|
||||
opengraph_add_meta((! empty($items) ? $r[0] : []), $channel);
|
||||
|
||||
$mode = 'articles';
|
||||
|
||||
if(get_pconfig(local_channel(),'system','articles_list_mode') && (! $selected_card))
|
||||
|
||||
@@ -145,7 +145,7 @@ class Cards extends Controller {
|
||||
|
||||
|
||||
$itemspage = get_pconfig(local_channel(),'system','itemspage');
|
||||
App::set_pager_itemspage(((intval($itemspage)) ? $itemspage : 20));
|
||||
App::set_pager_itemspage(((intval($itemspage)) ? $itemspage : 10));
|
||||
$pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(App::$pager['itemspage']), intval(App::$pager['start']));
|
||||
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ require_once('include/event.php');
|
||||
|
||||
require_once('include/auth.php');
|
||||
require_once('include/security.php');
|
||||
require_once('include/cdav.php');
|
||||
|
||||
class Cdav extends Controller {
|
||||
|
||||
@@ -156,6 +157,79 @@ class Cdav extends Controller {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Track CDAV updates from remote clients
|
||||
|
||||
$httpmethod = $_SERVER['REQUEST_METHOD'];
|
||||
|
||||
if($httpmethod === 'PUT' || $httpmethod === 'DELETE') {
|
||||
|
||||
$httpuri = $_SERVER['REQUEST_URI'];
|
||||
|
||||
logger("debug: method: " . $httpmethod, LOGGER_DEBUG);
|
||||
logger("debug: uri: " . $httpuri, LOGGER_DEBUG);
|
||||
|
||||
if(strpos($httpuri, 'cdav/addressbooks')) {
|
||||
$sync = 'addressbook';
|
||||
$cdavtable = 'addressbooks';
|
||||
}
|
||||
elseif(strpos($httpuri, 'cdav/calendars')) {
|
||||
$sync = 'calendar';
|
||||
$cdavtable = 'calendarinstances';
|
||||
}
|
||||
else
|
||||
$sync = false;
|
||||
|
||||
if($sync) {
|
||||
|
||||
$uri = basename($httpuri);
|
||||
$httpbody = file_get_contents('php://input');
|
||||
|
||||
logger("debug: body: " . $httpbody, LOGGER_DEBUG);
|
||||
|
||||
if($x = get_cdav_id($principalUri, explode("/", $httpuri)[4], $cdavtable)) {
|
||||
|
||||
$cdavdata = $this->get_cdav_data($x['id'], $cdavtable);
|
||||
|
||||
$etag = (isset($_SERVER['HTTP_IF_MATCH']) ? $_SERVER['HTTP_IF_MATCH'] : false);
|
||||
|
||||
// delete
|
||||
if($httpmethod === 'DELETE' && $cdavdata['etag'] == $etag)
|
||||
build_sync_packet($channel['channel_id'], [
|
||||
$sync => [
|
||||
'action' => 'delete_card',
|
||||
'uri' => $cdavdata['uri'],
|
||||
'carduri' => $uri
|
||||
]
|
||||
]);
|
||||
else {
|
||||
if($etag) {
|
||||
// update
|
||||
if($cdavdata['etag'] !== $etag)
|
||||
build_sync_packet($channel['channel_id'], [
|
||||
$sync => [
|
||||
'action' => 'update_card',
|
||||
'uri' => $cdavdata['uri'],
|
||||
'carduri' => $uri,
|
||||
'card' => $httpbody
|
||||
]
|
||||
]);
|
||||
}
|
||||
else {
|
||||
// new
|
||||
build_sync_packet($channel['channel_id'], [
|
||||
$sync => [
|
||||
'action' => 'import',
|
||||
'uri' => $cdavdata['uri'],
|
||||
'ids' => [ $uri ],
|
||||
'card' => $httpbody
|
||||
]
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$principalBackend = new \Sabre\DAVACL\PrincipalBackend\PDO($pdo);
|
||||
@@ -262,6 +336,14 @@ class Cdav extends Controller {
|
||||
|
||||
// set new calendar to be visible
|
||||
set_pconfig(local_channel(), 'cdav_calendar' , $id[0], 1);
|
||||
|
||||
build_sync_packet($channel['channel_id'], [
|
||||
'calendar' => [
|
||||
'action' => 'create',
|
||||
'uri' => $calendarUri,
|
||||
'properties' => $properties
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
//create new calendar object via ajax request
|
||||
@@ -272,6 +354,8 @@ class Cdav extends Controller {
|
||||
if(!cdav_perms($id[0],$calendars,true))
|
||||
return;
|
||||
|
||||
$cdavdata = $this->get_cdav_data($id[0], 'calendarinstances');
|
||||
|
||||
$timezone = ((x($_POST,'timezone_select')) ? escape_tags(trim($_POST['timezone_select'])) : '');
|
||||
$tz = (($timezone) ? $timezone : date_default_timezone_get());
|
||||
|
||||
@@ -327,9 +411,17 @@ class Cdav extends Controller {
|
||||
$vcalendar->VEVENT->DTSTART['TZID'] = $tz;
|
||||
|
||||
$calendarData = $vcalendar->serialize();
|
||||
|
||||
$caldavBackend->createCalendarObject($id, $objectUri, $calendarData);
|
||||
|
||||
build_sync_packet($channel['channel_id'], [
|
||||
'calendar' => [
|
||||
'action' => 'import',
|
||||
'uri' => $cdavdata['uri'],
|
||||
'ids' => [ $objectUri ],
|
||||
'card' => $calendarData
|
||||
]
|
||||
]);
|
||||
|
||||
killme();
|
||||
}
|
||||
|
||||
@@ -341,17 +433,24 @@ class Cdav extends Controller {
|
||||
if(! cdav_perms($id[0],$calendars))
|
||||
return;
|
||||
|
||||
$cdavdata = $this->get_cdav_data($id[0], 'calendarinstances');
|
||||
|
||||
$mutations = [
|
||||
'{DAV:}displayname' => $_REQUEST['{DAV:}displayname'],
|
||||
'{http://apple.com/ns/ical/}calendar-color' => $_REQUEST['color']
|
||||
];
|
||||
|
||||
$patch = new \Sabre\DAV\PropPatch($mutations);
|
||||
|
||||
$caldavBackend->updateCalendar($id, $patch);
|
||||
|
||||
$patch->commit();
|
||||
|
||||
build_sync_packet($channel['channel_id'], [
|
||||
'calendar' => [
|
||||
'action' => 'edit',
|
||||
'uri' => $cdavdata['uri'],
|
||||
'mutations' => $mutations,
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
//edit calendar object via ajax request
|
||||
@@ -359,9 +458,11 @@ class Cdav extends Controller {
|
||||
|
||||
$id = explode(':', $_REQUEST['target']);
|
||||
|
||||
if(!cdav_perms($id[0],$calendars,true))
|
||||
if(! cdav_perms($id[0],$calendars,true))
|
||||
return;
|
||||
|
||||
$cdavdata = $this->get_cdav_data($id[0], 'calendarinstances');
|
||||
|
||||
$timezone = ((x($_POST,'timezone_select')) ? escape_tags(trim($_POST['timezone_select'])) : '');
|
||||
$tz = (($timezone) ? $timezone : date_default_timezone_get());
|
||||
|
||||
@@ -407,9 +508,17 @@ class Cdav extends Controller {
|
||||
$vcalendar->VEVENT->LOCATION = $location;
|
||||
|
||||
$calendarData = $vcalendar->serialize();
|
||||
|
||||
$caldavBackend->updateCalendarObject($id, $uri, $calendarData);
|
||||
|
||||
build_sync_packet($channel['channel_id'], [
|
||||
'calendar' => [
|
||||
'action' => 'update_card',
|
||||
'uri' => $cdavdata['uri'],
|
||||
'carduri' => $uri,
|
||||
'card' => $calendarData
|
||||
]
|
||||
]);
|
||||
|
||||
killme();
|
||||
}
|
||||
|
||||
@@ -418,13 +527,23 @@ class Cdav extends Controller {
|
||||
|
||||
$id = explode(':', $_REQUEST['target']);
|
||||
|
||||
if(!cdav_perms($id[0],$calendars,true))
|
||||
if(! cdav_perms($id[0],$calendars,true))
|
||||
return;
|
||||
|
||||
$cdavdata = $this->get_cdav_data($id[0], 'calendarinstances');
|
||||
|
||||
$uri = $_REQUEST['uri'];
|
||||
|
||||
$caldavBackend->deleteCalendarObject($id, $uri);
|
||||
|
||||
build_sync_packet($channel['channel_id'], [
|
||||
'calendar' => [
|
||||
'action' => 'delete_card',
|
||||
'uri' => $cdavdata['uri'],
|
||||
'carduri' => $uri
|
||||
]
|
||||
]);
|
||||
|
||||
killme();
|
||||
}
|
||||
|
||||
@@ -433,9 +552,11 @@ class Cdav extends Controller {
|
||||
|
||||
$id = [$_REQUEST['id'][0], $_REQUEST['id'][1]];
|
||||
|
||||
if(!cdav_perms($id[0],$calendars,true))
|
||||
if(! cdav_perms($id[0],$calendars,true))
|
||||
return;
|
||||
|
||||
$cdavdata = $this->get_cdav_data($id[0], 'calendarinstances');
|
||||
|
||||
$timezone = ((x($_POST,'timezone_select')) ? escape_tags(trim($_POST['timezone_select'])) : '');
|
||||
$tz = (($timezone) ? $timezone : date_default_timezone_get());
|
||||
|
||||
@@ -471,9 +592,17 @@ class Cdav extends Controller {
|
||||
unset($vcalendar->VEVENT->DTEND);
|
||||
|
||||
$calendarData = $vcalendar->serialize();
|
||||
|
||||
$caldavBackend->updateCalendarObject($id, $uri, $calendarData);
|
||||
|
||||
build_sync_packet($channel['channel_id'], [
|
||||
'calendar' => [
|
||||
'action' => 'update_card',
|
||||
'uri' => $cdavdata['uri'],
|
||||
'carduri' => $uri,
|
||||
'card' => $calendarData
|
||||
]
|
||||
]);
|
||||
|
||||
killme();
|
||||
}
|
||||
|
||||
@@ -523,6 +652,14 @@ class Cdav extends Controller {
|
||||
$properties = ['{DAV:}displayname' => $_REQUEST['{DAV:}displayname']];
|
||||
|
||||
$carddavBackend->createAddressBook($principalUri, $addressbookUri, $properties);
|
||||
|
||||
build_sync_packet($channel['channel_id'], [
|
||||
'addressbook' => [
|
||||
'action' => 'create',
|
||||
'uri' => $addressbookUri,
|
||||
'properties' => $properties
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
//edit addressbook
|
||||
@@ -533,21 +670,32 @@ class Cdav extends Controller {
|
||||
if(! cdav_perms($id,$addressbooks))
|
||||
return;
|
||||
|
||||
$cdavdata = $this->get_cdav_data($id, 'addressbooks');
|
||||
|
||||
$mutations = [
|
||||
'{DAV:}displayname' => $_REQUEST['{DAV:}displayname']
|
||||
];
|
||||
|
||||
$patch = new \Sabre\DAV\PropPatch($mutations);
|
||||
|
||||
$carddavBackend->updateAddressBook($id, $patch);
|
||||
|
||||
$patch->commit();
|
||||
|
||||
build_sync_packet($channel['channel_id'], [
|
||||
'addressbook' => [
|
||||
'action' => 'edit',
|
||||
'uri' => $cdavdata['uri'],
|
||||
'mutations' => $mutations,
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
//create addressbook card
|
||||
if($_REQUEST['create'] && $_REQUEST['target'] && $_REQUEST['fn']) {
|
||||
|
||||
$id = $_REQUEST['target'];
|
||||
|
||||
$cdavdata = $this->get_cdav_data($id, 'addressbooks');
|
||||
|
||||
do {
|
||||
$duplicate = false;
|
||||
$uri = random_string(40) . '.vcf';
|
||||
@@ -569,86 +717,21 @@ class Cdav extends Controller {
|
||||
'N' => array_reverse(explode(' ', $fn))
|
||||
]);
|
||||
|
||||
$org = $_REQUEST['org'];
|
||||
if($org) {
|
||||
$vcard->ORG = $org;
|
||||
}
|
||||
$fields = $this->request_to_array($_REQUEST);
|
||||
|
||||
$title = $_REQUEST['title'];
|
||||
if($title) {
|
||||
$vcard->TITLE = $title;
|
||||
}
|
||||
|
||||
$tel = $_REQUEST['tel'];
|
||||
$tel_type = $_REQUEST['tel_type'];
|
||||
if($tel) {
|
||||
$i = 0;
|
||||
foreach($tel as $item) {
|
||||
if($item) {
|
||||
$vcard->add('TEL', $item, ['type' => $tel_type[$i]]);
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
|
||||
$email = $_REQUEST['email'];
|
||||
$email_type = $_REQUEST['email_type'];
|
||||
if($email) {
|
||||
$i = 0;
|
||||
foreach($email as $item) {
|
||||
if($item) {
|
||||
$vcard->add('EMAIL', $item, ['type' => $email_type[$i]]);
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
|
||||
$impp = $_REQUEST['impp'];
|
||||
$impp_type = $_REQUEST['impp_type'];
|
||||
if($impp) {
|
||||
$i = 0;
|
||||
foreach($impp as $item) {
|
||||
if($item) {
|
||||
$vcard->add('IMPP', $item, ['type' => $impp_type[$i]]);
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
|
||||
$url = $_REQUEST['url'];
|
||||
$url_type = $_REQUEST['url_type'];
|
||||
if($url) {
|
||||
$i = 0;
|
||||
foreach($url as $item) {
|
||||
if($item) {
|
||||
$vcard->add('URL', $item, ['type' => $url_type[$i]]);
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
|
||||
$adr = $_REQUEST['adr'];
|
||||
$adr_type = $_REQUEST['adr_type'];
|
||||
|
||||
if($adr) {
|
||||
$i = 0;
|
||||
foreach($adr as $item) {
|
||||
if($item) {
|
||||
$vcard->add('ADR', $item, ['type' => $adr_type[$i]]);
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
|
||||
$note = $_REQUEST['note'];
|
||||
if($note) {
|
||||
$vcard->NOTE = $note;
|
||||
}
|
||||
process_cdav_card($fields, $vcard);
|
||||
|
||||
$cardData = $vcard->serialize();
|
||||
|
||||
$carddavBackend->createCard($id, $uri, $cardData);
|
||||
|
||||
build_sync_packet($channel['channel_id'], [
|
||||
'addressbook' => [
|
||||
'action' => 'import',
|
||||
'uri' => $cdavdata['uri'],
|
||||
'ids' => [ $uri ],
|
||||
'card' => $cardData
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
//edit addressbook card
|
||||
@@ -656,9 +739,11 @@ class Cdav extends Controller {
|
||||
|
||||
$id = $_REQUEST['target'];
|
||||
|
||||
if(!cdav_perms($id,$addressbooks))
|
||||
if(! cdav_perms($id,$addressbooks))
|
||||
return;
|
||||
|
||||
$cdavdata = $this->get_cdav_data($id, 'addressbooks');
|
||||
|
||||
$uri = $_REQUEST['uri'];
|
||||
|
||||
$object = $carddavBackend->getCard($id, $uri);
|
||||
@@ -670,113 +755,23 @@ class Cdav extends Controller {
|
||||
$vcard->N = array_reverse(explode(' ', $fn));
|
||||
}
|
||||
|
||||
$org = $_REQUEST['org'];
|
||||
if($org) {
|
||||
$vcard->ORG = $org;
|
||||
}
|
||||
else {
|
||||
unset($vcard->ORG);
|
||||
}
|
||||
$fields = $this->request_to_array($_REQUEST);
|
||||
|
||||
$title = $_REQUEST['title'];
|
||||
if($title) {
|
||||
$vcard->TITLE = $title;
|
||||
}
|
||||
else {
|
||||
unset($vcard->TITLE);
|
||||
}
|
||||
|
||||
$tel = $_REQUEST['tel'];
|
||||
$tel_type = $_REQUEST['tel_type'];
|
||||
if($tel) {
|
||||
$i = 0;
|
||||
unset($vcard->TEL);
|
||||
foreach($tel as $item) {
|
||||
if($item) {
|
||||
$vcard->add('TEL', $item, ['type' => $tel_type[$i]]);
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
unset($vcard->TEL);
|
||||
}
|
||||
|
||||
$email = $_REQUEST['email'];
|
||||
$email_type = $_REQUEST['email_type'];
|
||||
if($email) {
|
||||
$i = 0;
|
||||
unset($vcard->EMAIL);
|
||||
foreach($email as $item) {
|
||||
if($item) {
|
||||
$vcard->add('EMAIL', $item, ['type' => $email_type[$i]]);
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
unset($vcard->EMAIL);
|
||||
}
|
||||
|
||||
$impp = $_REQUEST['impp'];
|
||||
$impp_type = $_REQUEST['impp_type'];
|
||||
if($impp) {
|
||||
$i = 0;
|
||||
unset($vcard->IMPP);
|
||||
foreach($impp as $item) {
|
||||
if($item) {
|
||||
$vcard->add('IMPP', $item, ['type' => $impp_type[$i]]);
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
unset($vcard->IMPP);
|
||||
}
|
||||
|
||||
$url = $_REQUEST['url'];
|
||||
$url_type = $_REQUEST['url_type'];
|
||||
if($url) {
|
||||
$i = 0;
|
||||
unset($vcard->URL);
|
||||
foreach($url as $item) {
|
||||
if($item) {
|
||||
$vcard->add('URL', $item, ['type' => $url_type[$i]]);
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
unset($vcard->URL);
|
||||
}
|
||||
|
||||
$adr = $_REQUEST['adr'];
|
||||
$adr_type = $_REQUEST['adr_type'];
|
||||
if($adr) {
|
||||
$i = 0;
|
||||
unset($vcard->ADR);
|
||||
foreach($adr as $item) {
|
||||
if($item) {
|
||||
$vcard->add('ADR', $item, ['type' => $adr_type[$i]]);
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
unset($vcard->ADR);
|
||||
}
|
||||
|
||||
$note = $_REQUEST['note'];
|
||||
if($note) {
|
||||
$vcard->NOTE = $note;
|
||||
}
|
||||
else {
|
||||
unset($vcard->NOTE);
|
||||
}
|
||||
process_cdav_card($fields, $vcard, true);
|
||||
|
||||
$cardData = $vcard->serialize();
|
||||
|
||||
$carddavBackend->updateCard($id, $uri, $cardData);
|
||||
|
||||
build_sync_packet($channel['channel_id'], [
|
||||
'addressbook' => [
|
||||
'action' => 'update_card',
|
||||
'uri' => $cdavdata['uri'],
|
||||
'carduri' => $uri,
|
||||
'card' => $cardData
|
||||
]
|
||||
]);
|
||||
|
||||
}
|
||||
|
||||
//delete addressbook card
|
||||
@@ -784,12 +779,22 @@ class Cdav extends Controller {
|
||||
|
||||
$id = $_REQUEST['target'];
|
||||
|
||||
if(!cdav_perms($id,$addressbooks))
|
||||
if(! cdav_perms($id,$addressbooks))
|
||||
return;
|
||||
|
||||
$cdavdata = $this->get_cdav_data($id, 'addressbooks');
|
||||
|
||||
$uri = $_REQUEST['uri'];
|
||||
|
||||
$carddavBackend->deleteCard($id, $uri);
|
||||
|
||||
build_sync_packet($channel['channel_id'], [
|
||||
'addressbook' => [
|
||||
'action' => 'delete_card',
|
||||
'uri' => $cdavdata['uri'],
|
||||
'carduri' => $uri
|
||||
]
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -799,6 +804,8 @@ class Cdav extends Controller {
|
||||
$src = $_FILES['userfile']['tmp_name'];
|
||||
|
||||
if($src) {
|
||||
|
||||
$carddata = @file_get_contents($src);
|
||||
|
||||
if($_REQUEST['c_upload']) {
|
||||
if($_REQUEST['target'] == 'channel_calendar') {
|
||||
@@ -816,72 +823,38 @@ class Cdav extends Controller {
|
||||
$ext = 'ics';
|
||||
$table = 'calendarobjects';
|
||||
$column = 'calendarid';
|
||||
$objects = new \Sabre\VObject\Splitter\ICalendar(@file_get_contents($src));
|
||||
$sync = 'calendar';
|
||||
$objects = new \Sabre\VObject\Splitter\ICalendar($carddata);
|
||||
$profile = \Sabre\VObject\Node::PROFILE_CALDAV;
|
||||
$backend = new \Sabre\CalDAV\Backend\PDO($pdo);
|
||||
|
||||
$cdavdata = $this->get_cdav_data($id, 'calendarinstances');
|
||||
}
|
||||
|
||||
if($_REQUEST['a_upload']) {
|
||||
$id[] = intval($_REQUEST['target']);
|
||||
$id = intval($_REQUEST['target']);
|
||||
$ext = 'vcf';
|
||||
$table = 'cards';
|
||||
$column = 'addressbookid';
|
||||
$objects = new \Sabre\VObject\Splitter\VCard(@file_get_contents($src));
|
||||
$sync = 'addressbook';
|
||||
$objects = new \Sabre\VObject\Splitter\VCard($carddata);
|
||||
$profile = \Sabre\VObject\Node::PROFILE_CARDDAV;
|
||||
$backend = new \Sabre\CardDAV\Backend\PDO($pdo);
|
||||
|
||||
$cdavdata = $this->get_cdav_data($id, 'addressbooks');
|
||||
}
|
||||
|
||||
while ($object = $objects->getNext()) {
|
||||
|
||||
if($_REQUEST['a_upload']) {
|
||||
$object = $object->convert(\Sabre\VObject\Document::VCARD40);
|
||||
}
|
||||
|
||||
$ret = $object->validate($profile & \Sabre\VObject\Node::REPAIR);
|
||||
|
||||
//level 3 Means that the document is invalid,
|
||||
//level 2 means a warning. A warning means it's valid but it could cause interopability issues,
|
||||
//level 1 means that there was a problem earlier, but the problem was automatically repaired.
|
||||
|
||||
if($ret[0]['level'] < 3) {
|
||||
do {
|
||||
$duplicate = false;
|
||||
$objectUri = random_string(40) . '.' . $ext;
|
||||
|
||||
$r = q("SELECT uri FROM $table WHERE $column = %d AND uri = '%s' LIMIT 1",
|
||||
dbesc($id[0]),
|
||||
dbesc($objectUri)
|
||||
);
|
||||
|
||||
if (count($r))
|
||||
$duplicate = true;
|
||||
} while ($duplicate == true);
|
||||
|
||||
if($_REQUEST['c_upload']) {
|
||||
$backend->createCalendarObject($id, $objectUri, $object->serialize());
|
||||
}
|
||||
|
||||
if($_REQUEST['a_upload']) {
|
||||
$backend->createCard($id[0], $objectUri, $object->serialize());
|
||||
}
|
||||
}
|
||||
else {
|
||||
if($_REQUEST['c_upload']) {
|
||||
notice( '<strong>' . t('INVALID EVENT DISMISSED!') . '</strong>' . EOL .
|
||||
'<strong>' . t('Summary: ') . '</strong>' . (($object->VEVENT->SUMMARY) ? $object->VEVENT->SUMMARY : t('Unknown')) . EOL .
|
||||
'<strong>' . t('Date: ') . '</strong>' . (($object->VEVENT->DTSTART) ? $object->VEVENT->DTSTART : t('Unknown')) . EOL .
|
||||
'<strong>' . t('Reason: ') . '</strong>' . $ret[0]['message'] . EOL
|
||||
);
|
||||
}
|
||||
|
||||
if($_REQUEST['a_upload']) {
|
||||
notice( '<strong>' . t('INVALID CARD DISMISSED!') . '</strong>' . EOL .
|
||||
'<strong>' . t('Name: ') . '</strong>' . (($object->FN) ? $object->FN : t('Unknown')) . EOL .
|
||||
'<strong>' . t('Reason: ') . '</strong>' . $ret[0]['message'] . EOL
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$ids = [];
|
||||
import_cdav_card($id, $ext, $table, $column, $objects, $profile, $backend, $ids, true);
|
||||
|
||||
build_sync_packet($channel['channel_id'], [
|
||||
$sync => [
|
||||
'action' => 'import',
|
||||
'uri' => $cdavdata['uri'],
|
||||
'ids' => $ids,
|
||||
'card' => $carddata
|
||||
]
|
||||
]);
|
||||
}
|
||||
@unlink($src);
|
||||
}
|
||||
@@ -910,8 +883,6 @@ class Cdav extends Controller {
|
||||
|
||||
require_once 'vendor/autoload.php';
|
||||
|
||||
head_add_css('cdav.css');
|
||||
|
||||
if(!cdav_principal($principalUri)) {
|
||||
$this->activate($pdo, $channel);
|
||||
if(!cdav_principal($principalUri)) {
|
||||
@@ -1192,7 +1163,18 @@ class Cdav extends Controller {
|
||||
if(! cdav_perms($id,$calendars))
|
||||
killme();
|
||||
|
||||
set_pconfig(local_channel(), 'cdav_calendar' , argv(3), argv(4));
|
||||
$cdavdata = $this->get_cdav_data($id, 'calendarinstances');
|
||||
|
||||
set_pconfig(local_channel(), 'cdav_calendar', $id, argv(4));
|
||||
|
||||
build_sync_packet(local_channel(), [
|
||||
'calendar' => [
|
||||
'action' => 'switch',
|
||||
'uri' => $cdavdata['uri'],
|
||||
'switch' => intval(argv(4))
|
||||
]
|
||||
]);
|
||||
|
||||
killme();
|
||||
}
|
||||
|
||||
@@ -1203,7 +1185,18 @@ class Cdav extends Controller {
|
||||
if(! cdav_perms($id[0],$calendars))
|
||||
killme();
|
||||
|
||||
// get metadata before we delete it
|
||||
$cdavdata = $this->get_cdav_data($id[0], 'calendarinstances');
|
||||
|
||||
$caldavBackend->deleteCalendar($id);
|
||||
|
||||
build_sync_packet($channel['channel_id'], [
|
||||
'calendar' => [
|
||||
'action' => 'drop',
|
||||
'uri' => $cdavdata['uri']
|
||||
]
|
||||
]);
|
||||
|
||||
killme();
|
||||
}
|
||||
|
||||
@@ -1410,7 +1403,19 @@ class Cdav extends Controller {
|
||||
if(! cdav_perms($id,$addressbooks))
|
||||
return;
|
||||
|
||||
// get metadata before we delete it
|
||||
$cdavdata = $this->get_cdav_data($id, 'addressbooks');
|
||||
|
||||
$carddavBackend->deleteAddressBook($id);
|
||||
|
||||
if($cdavdata)
|
||||
build_sync_packet($channel['channel_id'], [
|
||||
'addressbook' => [
|
||||
'action' => 'drop',
|
||||
'uri' => $cdavdata['uri']
|
||||
]
|
||||
]);
|
||||
|
||||
killme();
|
||||
}
|
||||
|
||||
@@ -1462,4 +1467,36 @@ class Cdav extends Controller {
|
||||
}
|
||||
|
||||
|
||||
function get_cdav_data($id, $table) {
|
||||
|
||||
$r = q("SELECT * FROM $table WHERE id = %d LIMIT 1",
|
||||
intval($id)
|
||||
);
|
||||
|
||||
if(! $r)
|
||||
return false;
|
||||
|
||||
return $r[0];
|
||||
}
|
||||
|
||||
function request_to_array($req) {
|
||||
|
||||
$f = [];
|
||||
|
||||
$f['org'] = $req['org'];
|
||||
$f['title'] = $req['title'];
|
||||
$f['tel'] = $req['tel'];
|
||||
$f['tel_type'] = $req['tel_type'];
|
||||
$f['email'] = $req['email'];
|
||||
$f['email_type'] = $req['email_type'];
|
||||
$f['impp'] = $req['impp'];
|
||||
$f['impp_type'] = $req['impp_type'];
|
||||
$f['url'] = $req['url'];
|
||||
$f['url_type'] = $req['url_type'];
|
||||
$f['adr'] = $req['adr'];
|
||||
$f['adr_type'] = $req['adr_type'];
|
||||
$f['note'] = $req['note'];
|
||||
|
||||
return $f;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ require_once('include/items.php');
|
||||
require_once('include/security.php');
|
||||
require_once('include/conversation.php');
|
||||
require_once('include/acl_selectors.php');
|
||||
require_once('include/opengraph.php');
|
||||
|
||||
|
||||
/**
|
||||
@@ -59,7 +60,7 @@ class Channel extends Controller {
|
||||
|
||||
if(Libzot::is_zot_request()) {
|
||||
|
||||
$sigdata = HTTPSig::verify(file_get_contents('php://input'));
|
||||
$sigdata = HTTPSig::verify(file_get_contents('php://input'), EMPTY_STR, 'zot6');
|
||||
|
||||
if($sigdata && $sigdata['signer'] && $sigdata['header_valid']) {
|
||||
$data = json_encode(Libzot::zotinfo([ 'address' => $channel['channel_address'], 'target_url' => $sigdata['signer'] ]));
|
||||
@@ -109,28 +110,26 @@ class Channel extends Controller {
|
||||
|
||||
// Run profile_load() here to make sure the theme is set before
|
||||
// we start loading content
|
||||
|
||||
profile_load($which,$profile);
|
||||
|
||||
App::$page['htmlhead'] .= '<meta property="og:title" content="' . htmlspecialchars($channel['channel_name']) . '">' . "\r\n";
|
||||
App::$page['htmlhead'] .= '<meta property="og:image" content="' . $channel['xchan_photo_l'] . '">' . "\r\n";
|
||||
|
||||
if(App::$profile['about'] && perm_is_allowed($channel['channel_id'],get_observer_hash(),'view_profile')) {
|
||||
App::$page['htmlhead'] .= '<meta property="og:description" content="' . htmlspecialchars(App::$profile['about']) . '">' . "\r\n";
|
||||
}
|
||||
else {
|
||||
App::$page['htmlhead'] .= '<meta property="og:description" content="' . htmlspecialchars(sprintf( t('This is the home page of %s.'), $channel['channel_name'])) . '">' . "\r\n";
|
||||
}
|
||||
|
||||
|
||||
// Add Opengraph markup
|
||||
$mid = ((x($_REQUEST,'mid')) ? $_REQUEST['mid'] : '');
|
||||
if(strpos($mid,'b64.') === 0)
|
||||
$mid = @base64url_decode(substr($mid,4));
|
||||
|
||||
if($mid)
|
||||
$r = q("SELECT * FROM item WHERE mid = '%s' AND uid = %d AND item_private = 0 LIMIT 1",
|
||||
dbesc($mid),
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
|
||||
opengraph_add_meta($r ? $r[0] : [], $channel);
|
||||
}
|
||||
|
||||
function get($update = 0, $load = false) {
|
||||
|
||||
$noscript_content = get_config('system', 'noscript_content', '1');
|
||||
|
||||
if($load)
|
||||
$_SESSION['loadtime'] = datetime_convert();
|
||||
|
||||
$category = $datequery = $datequery2 = '';
|
||||
|
||||
$mid = ((x($_REQUEST,'mid')) ? $_REQUEST['mid'] : '');
|
||||
@@ -150,7 +149,6 @@ class Channel extends Controller {
|
||||
$category = ((x($_REQUEST,'cat')) ? $_REQUEST['cat'] : '');
|
||||
$hashtags = ((x($_REQUEST,'tag')) ? $_REQUEST['tag'] : '');
|
||||
$order = ((x($_GET,'order')) ? notags($_GET['order']) : 'post');
|
||||
$static = ((array_key_exists('static',$_REQUEST)) ? intval($_REQUEST['static']) : 0);
|
||||
$search = ((x($_GET,'search')) ? $_GET['search'] : EMPTY_STR);
|
||||
|
||||
$groups = array();
|
||||
@@ -185,8 +183,6 @@ class Channel extends Controller {
|
||||
|
||||
nav_set_selected('Channel Home');
|
||||
|
||||
$static = channel_manual_conv_update(App::$profile['profile_uid']);
|
||||
|
||||
// search terms header
|
||||
if($search) {
|
||||
$o .= replace_macros(get_markup_template("section_title.tpl"),array(
|
||||
@@ -237,8 +233,12 @@ 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 = item_normal();
|
||||
|
||||
$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_update = item_normal_update();
|
||||
$sql_extra = item_permissions_sql(App::$profile['profile_uid']);
|
||||
|
||||
@@ -249,7 +249,9 @@ class Channel extends Controller {
|
||||
|
||||
$abook_uids = " and abook.abook_channel = " . intval(App::$profile['profile_uid']) . " ";
|
||||
|
||||
$simple_update = (($update) ? " AND item_unseen = 1 " : '');
|
||||
$simple_update = '';
|
||||
if($update && $_SESSION['loadtime'])
|
||||
$simple_update = " AND (( item_unseen = 1 AND item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' ) OR item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' ) ";
|
||||
|
||||
if($search) {
|
||||
$search = escape_tags($search);
|
||||
@@ -264,7 +266,6 @@ class Channel extends Controller {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
head_add_link([
|
||||
'rel' => 'alternate',
|
||||
'type' => 'application/json+oembed',
|
||||
@@ -272,14 +273,6 @@ class Channel extends Controller {
|
||||
'title' => 'oembed'
|
||||
]);
|
||||
|
||||
if($update && $_SESSION['loadtime'])
|
||||
$simple_update = " AND (( item_unseen = 1 AND item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' ) OR item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' ) ";
|
||||
if($load)
|
||||
$simple_update = '';
|
||||
|
||||
if($static && $simple_update)
|
||||
$simple_update .= " and author_xchan = '" . protect_sprintf(get_observer_hash()) . "' ";
|
||||
|
||||
if(($update) && (! $load)) {
|
||||
|
||||
if($mid) {
|
||||
@@ -288,7 +281,6 @@ class Channel extends Controller {
|
||||
dbesc($mid . '%'),
|
||||
intval(App::$profile['profile_uid'])
|
||||
);
|
||||
$_SESSION['loadtime'] = datetime_convert();
|
||||
}
|
||||
else {
|
||||
$r = q("SELECT parent AS item_id from item
|
||||
@@ -300,9 +292,7 @@ class Channel extends Controller {
|
||||
ORDER BY created DESC",
|
||||
intval(App::$profile['profile_uid'])
|
||||
);
|
||||
$_SESSION['loadtime'] = datetime_convert();
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -328,7 +318,7 @@ class Channel extends Controller {
|
||||
|
||||
|
||||
$itemspage = get_pconfig(local_channel(),'system','itemspage');
|
||||
App::set_pager_itemspage(((intval($itemspage)) ? $itemspage : 20));
|
||||
App::set_pager_itemspage(((intval($itemspage)) ? $itemspage : 10));
|
||||
$pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(App::$pager['itemspage']), intval(App::$pager['start']));
|
||||
|
||||
if($noscript_content || $load) {
|
||||
@@ -362,7 +352,7 @@ class Channel extends Controller {
|
||||
|
||||
$parents_str = ids_to_querystr($r,'item_id');
|
||||
|
||||
$items = q("SELECT item.*, item.id AS item_id
|
||||
$r = q("SELECT item.*, item.id AS item_id
|
||||
FROM item
|
||||
WHERE item.uid = %d $item_normal
|
||||
AND item.parent IN ( %s )
|
||||
@@ -371,8 +361,8 @@ class Channel extends Controller {
|
||||
dbesc($parents_str)
|
||||
);
|
||||
|
||||
xchan_query($items);
|
||||
$items = fetch_post_tags($items, true);
|
||||
xchan_query($r);
|
||||
$items = fetch_post_tags($r, true);
|
||||
$items = conv_sort($items,$ordering);
|
||||
|
||||
if($load && $mid && (! count($items))) {
|
||||
@@ -400,7 +390,7 @@ class Channel extends Controller {
|
||||
$o .= '<div id="live-channel"></div>' . "\r\n";
|
||||
$o .= "<script> var profile_uid = " . App::$profile['profile_uid']
|
||||
. "; var netargs = '?f='; var profile_page = " . App::$pager['page']
|
||||
. "; divmore_height = " . intval($maxheight) . "; </script>\r\n";
|
||||
. "; divmore_height = " . intval($maxheight) . ";</script>\r\n";
|
||||
|
||||
App::$page['htmlhead'] .= replace_macros(get_markup_template("build_query.tpl"),array(
|
||||
'$baseurl' => z_root(),
|
||||
@@ -417,7 +407,7 @@ class Channel extends Controller {
|
||||
'$nouveau' => '0',
|
||||
'$wall' => '1',
|
||||
'$fh' => '0',
|
||||
'$static' => $static,
|
||||
'$dm' => '0',
|
||||
'$page' => ((App::$pager['page'] != 1) ? App::$pager['page'] : 1),
|
||||
'$search' => $search,
|
||||
'$xchan' => '',
|
||||
@@ -430,41 +420,17 @@ class Channel extends Controller {
|
||||
'$verb' => '',
|
||||
'$net' => '',
|
||||
'$dend' => $datequery,
|
||||
'$dbegin' => $datequery2
|
||||
'$dbegin' => $datequery2,
|
||||
'$conv_mode' => 'channel'
|
||||
));
|
||||
|
||||
}
|
||||
|
||||
$update_unseen = '';
|
||||
|
||||
if($page_mode === 'list') {
|
||||
|
||||
/**
|
||||
* in "list mode", only mark the parent item and any like activities as "seen".
|
||||
* We won't distinguish between comment likes and post likes. The important thing
|
||||
* is that the number of unseen comments will be accurate. The SQL to separate the
|
||||
* comment likes could also get somewhat hairy.
|
||||
*/
|
||||
|
||||
if($parents_str) {
|
||||
$update_unseen = " AND ( id IN ( " . dbesc($parents_str) . " )";
|
||||
$update_unseen .= " OR ( parent IN ( " . dbesc($parents_str) . " ) AND verb in ( '" . dbesc(ACTIVITY_LIKE) . "','" . dbesc(ACTIVITY_DISLIKE) . "' ))) ";
|
||||
}
|
||||
}
|
||||
else {
|
||||
if($parents_str) {
|
||||
$update_unseen = " AND parent IN ( " . dbesc($parents_str) . " )";
|
||||
}
|
||||
}
|
||||
|
||||
if($is_owner && $update_unseen) {
|
||||
$x = [ 'channel_id' => local_channel(), 'update' => 'unset' ];
|
||||
call_hooks('update_unseen',$x);
|
||||
if($x['update'] === 'unset' || intval($x['update'])) {
|
||||
$r = q("UPDATE item SET item_unseen = 0 where item_unseen = 1 and item_wall = 1 AND uid = %d $update_unseen",
|
||||
intval(local_channel())
|
||||
);
|
||||
}
|
||||
// Add pinned content
|
||||
if(! x($_REQUEST,'mid') && ! $search) {
|
||||
$pinned = new \Zotlabs\Widget\Pinned;
|
||||
$r = $pinned->widget(intval(App::$profile['profile_uid']), [ITEM_TYPE_POST]);
|
||||
$o .= $r['html'];
|
||||
}
|
||||
|
||||
$mode = (($search) ? 'search' : 'channel');
|
||||
@@ -494,6 +460,8 @@ class Channel extends Controller {
|
||||
if($mid)
|
||||
$o .= '<div id="content-complete"></div>';
|
||||
|
||||
$_SESSION['loadtime'] = datetime_convert();
|
||||
|
||||
return $o;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
<?php
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
use Zotlabs\Lib\Libsync;
|
||||
|
||||
require_once('include/conversation.php');
|
||||
require_once('include/bbcode.php');
|
||||
require_once('include/datetime.php');
|
||||
@@ -16,7 +18,7 @@ class Channel_calendar extends \Zotlabs\Web\Controller {
|
||||
|
||||
if(! local_channel())
|
||||
return;
|
||||
|
||||
|
||||
$event_id = ((x($_POST,'event_id')) ? intval($_POST['event_id']) : 0);
|
||||
$event_hash = ((x($_POST,'event_hash')) ? $_POST['event_hash'] : '');
|
||||
|
||||
@@ -27,15 +29,19 @@ class Channel_calendar extends \Zotlabs\Web\Controller {
|
||||
if(($xchan) && ($xchan !== get_observer_hash()))
|
||||
return;
|
||||
|
||||
$categories = escape_tags(trim($_POST['categories']));
|
||||
|
||||
// allday events have adjust = 0, normal events have adjust = 1
|
||||
$adjust = intval($_POST['adjust']);
|
||||
|
||||
$start = datetime_convert((($adjust) ? $tz : 'UTC'), 'UTC', escape_tags($_REQUEST['dtstart']));
|
||||
$finish = datetime_convert((($adjust) ? $tz : 'UTC'), 'UTC', escape_tags($_REQUEST['dtend']));
|
||||
|
||||
$timezone = ((x($_POST,'timezone_select')) ? escape_tags(trim($_POST['timezone_select'])) : '');
|
||||
$tz = (($timezone) ? $timezone : date_default_timezone_get());
|
||||
|
||||
$categories = escape_tags(trim($_POST['categories']));
|
||||
|
||||
$adjust = intval($_POST['adjust']);
|
||||
|
||||
$start = datetime_convert('UTC', 'UTC', escape_tags($_REQUEST['dtstart']));
|
||||
$finish = datetime_convert('UTC', 'UTC', escape_tags($_REQUEST['dtend']));
|
||||
if(! $adjust)
|
||||
$tz = 'UTC';
|
||||
|
||||
$summary = escape_tags(trim($_POST['summary']));
|
||||
$desc = escape_tags(trim($_POST['desc']));
|
||||
@@ -184,7 +190,7 @@ class Channel_calendar extends \Zotlabs\Web\Controller {
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
if($z) {
|
||||
build_sync_packet($channel['channel_id'],array('event_item' => array(encode_item($sync_item[0],true)),'event' => $z));
|
||||
Libsync::build_sync_packet($channel['channel_id'],array('event_item' => array(encode_item($sync_item[0],true)),'event' => $z));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -337,21 +343,16 @@ class Channel_calendar extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
|
||||
$events = [];
|
||||
|
||||
|
||||
if($r) {
|
||||
|
||||
foreach($r as $rr) {
|
||||
|
||||
$tz = get_iconfig($rr, 'event', 'timezone');
|
||||
|
||||
if(! $tz)
|
||||
$tz = 'UTC';
|
||||
|
||||
$start = (($rr['adjust']) ? datetime_convert($tz, date_default_timezone_get(), $rr['dtstart'], 'c') : datetime_convert('UTC', 'UTC', $rr['dtstart'], 'c'));
|
||||
$start = (($rr['adjust']) ? datetime_convert('UTC', date_default_timezone_get(), $rr['dtstart'], 'c') : datetime_convert('UTC', 'UTC', $rr['dtstart'], 'c'));
|
||||
if ($rr['nofinish']){
|
||||
$end = null;
|
||||
} else {
|
||||
$end = (($rr['adjust']) ? datetime_convert($tz, date_default_timezone_get(), $rr['dtend'], 'c') : datetime_convert('UTC', 'UTC', $rr['dtend'], 'c'));
|
||||
$end = (($rr['adjust']) ? datetime_convert('UTC', date_default_timezone_get(), $rr['dtend'], 'c') : datetime_convert('UTC', 'UTC', $rr['dtend'], 'c'));
|
||||
}
|
||||
|
||||
$catsenabled = feature_enabled(local_channel(),'categories');
|
||||
@@ -371,6 +372,11 @@ class Channel_calendar extends \Zotlabs\Web\Controller {
|
||||
|
||||
$drop = array(z_root().'/events/drop/'.$rr['event_hash'],t('Delete event'),'','');
|
||||
|
||||
$tz = get_iconfig($rr, 'event', 'timezone');
|
||||
|
||||
if(! $tz)
|
||||
$tz = 'UTC';
|
||||
|
||||
$events[] = array(
|
||||
'calendar_id' => 'channel_calendar',
|
||||
'rw' => true,
|
||||
@@ -426,7 +432,7 @@ class Channel_calendar extends \Zotlabs\Web\Controller {
|
||||
if($r) {
|
||||
|
||||
$sync_event['event_deleted'] = 1;
|
||||
build_sync_packet(0,array('event' => array($sync_event)));
|
||||
Libsync::build_sync_packet(0,array('event' => array($sync_event)));
|
||||
|
||||
$i = q("select * from item where resource_type = 'event' and resource_id = '%s' and uid = %d",
|
||||
dbesc($event_id),
|
||||
@@ -475,7 +481,7 @@ class Channel_calendar extends \Zotlabs\Web\Controller {
|
||||
if($ii) {
|
||||
xchan_query($ii);
|
||||
$sync_item = fetch_post_tags($ii);
|
||||
build_sync_packet($i[0]['uid'],array('item' => array(encode_item($sync_item[0],true))));
|
||||
Libsync::build_sync_packet($i[0]['uid'],array('item' => array(encode_item($sync_item[0],true))));
|
||||
}
|
||||
|
||||
if($complex) {
|
||||
|
||||
@@ -1,31 +1,35 @@
|
||||
<?php
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
require_once('include/zot.php');
|
||||
use App;
|
||||
use Zotlabs\Lib\Libzot;
|
||||
use Zotlabs\Lib\Webfinger;
|
||||
use Zotlabs\Lib\Zotfinger;
|
||||
|
||||
|
||||
class Chanview extends \Zotlabs\Web\Controller {
|
||||
|
||||
function get() {
|
||||
|
||||
$observer = \App::get_observer();
|
||||
$observer = App::get_observer();
|
||||
$xchan = null;
|
||||
|
||||
$r = null;
|
||||
|
||||
if($_REQUEST['hash']) {
|
||||
$r = q("select * from xchan where xchan_hash = '%s' limit 1",
|
||||
$r = q("select * from xchan where xchan_hash = '%s'",
|
||||
dbesc($_REQUEST['hash'])
|
||||
);
|
||||
}
|
||||
if($_REQUEST['address']) {
|
||||
$r = q("select * from xchan where xchan_addr = '%s' limit 1",
|
||||
$r = q("select * from xchan where xchan_addr = '%s'",
|
||||
dbesc(punify($_REQUEST['address']))
|
||||
);
|
||||
}
|
||||
elseif(local_channel() && intval($_REQUEST['cid'])) {
|
||||
$r = q("SELECT abook.*, xchan.*
|
||||
FROM abook left join xchan on abook_xchan = xchan_hash
|
||||
WHERE abook_channel = %d and abook_id = %d LIMIT 1",
|
||||
WHERE abook_channel = %d and abook_id = %d",
|
||||
intval(local_channel()),
|
||||
intval($_REQUEST['cid'])
|
||||
);
|
||||
@@ -35,12 +39,12 @@ class Chanview extends \Zotlabs\Web\Controller {
|
||||
// if somebody re-installed they will have more than one xchan, use the most recent name date as this is
|
||||
// the most useful consistently ascending table item we have.
|
||||
|
||||
$r = q("select * from xchan where xchan_url = '%s' order by xchan_name_date desc limit 1",
|
||||
$r = q("select * from xchan where xchan_url = '%s' order by xchan_name_date desc",
|
||||
dbesc($_REQUEST['url'])
|
||||
);
|
||||
}
|
||||
if($r) {
|
||||
\App::$poi = $r[0];
|
||||
App::$poi = Libzot::zot_record_preferred($r, 'xchan_network');
|
||||
}
|
||||
|
||||
|
||||
@@ -49,74 +53,63 @@ class Chanview extends \Zotlabs\Web\Controller {
|
||||
// address, we can and should try to import it. If it's just a hash, we can't continue, but we
|
||||
// probably wouldn't have a hash if we don't already have an xchan for this channel.
|
||||
|
||||
if(! \App::$poi) {
|
||||
if(! App::$poi) {
|
||||
logger('mod_chanview: fallback');
|
||||
// This is hackish - construct a zot address from the url
|
||||
if($_REQUEST['url']) {
|
||||
if(preg_match('/https?\:\/\/(.*?)(\/channel\/|\/profile\/)(.*?)$/ism',$_REQUEST['url'],$matches)) {
|
||||
$_REQUEST['address'] = $matches[3] . '@' . $matches[1];
|
||||
|
||||
if($_REQUEST['address']) {
|
||||
$href = Webfinger::zot_url(punify($_REQUEST['address']));
|
||||
if($href) {
|
||||
$_REQUEST['url'] = $href;
|
||||
}
|
||||
logger('mod_chanview: constructed address ' . print_r($matches,true));
|
||||
}
|
||||
|
||||
$r = null;
|
||||
|
||||
if($_REQUEST['address']) {
|
||||
$j = \Zotlabs\Zot\Finger::run($_REQUEST['address'],null);
|
||||
if($j['success']) {
|
||||
import_xchan($j);
|
||||
$r = q("select * from xchan where xchan_addr = '%s' limit 1",
|
||||
dbesc($_REQUEST['address'])
|
||||
if($_REQUEST['url']) {
|
||||
|
||||
$zf = Zotfinger::exec($_REQUEST['url'], null);
|
||||
|
||||
if(array_path_exists('signature/signer',$zf) && $zf['signature']['signer'] === $_REQUEST['url'] && intval($zf['signature']['header_valid'])) {
|
||||
Libzot::import_xchan($j);
|
||||
$r = q("select * from xchan where xchan_url = '%s'",
|
||||
dbesc($_REQUEST['url'])
|
||||
);
|
||||
if($r) {
|
||||
\App::$poi = $r[0];
|
||||
App::$poi = Libzot::zot_record_preferred($r, 'xchan_network');
|
||||
}
|
||||
}
|
||||
if(! $r) {
|
||||
if(discover_by_webbie($_REQUEST['address'])) {
|
||||
$r = q("select * from xchan where xchan_addr = '%s' limit 1",
|
||||
dbesc($_REQUEST['address'])
|
||||
if(discover_by_webbie($_REQUEST['url'])) {
|
||||
$r = q("select * from xchan where xchan_url = '%s'",
|
||||
dbesc($_REQUEST['url'])
|
||||
);
|
||||
if($r) {
|
||||
\App::$poi = $r[0];
|
||||
App::$poi = Libzot::zot_record_preferred($r, 'xchan_network');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(! \App::$poi) {
|
||||
|
||||
// We don't know who this is, and we can't figure it out from the URL
|
||||
// On the plus side, there's a good chance we know somebody else at that
|
||||
// hub so sending them there with a Zid will probably work anyway.
|
||||
|
||||
$url = ($_REQUEST['url']);
|
||||
if(! $url) {
|
||||
notice( t('Channel not found.') . EOL);
|
||||
return;
|
||||
}
|
||||
if($observer)
|
||||
$url = zid($url);
|
||||
|
||||
if(! App::$poi) {
|
||||
notice( t('Channel not found.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
$is_zot = false;
|
||||
$connected = false;
|
||||
|
||||
if (\App::$poi) {
|
||||
$url = \App::$poi['xchan_url'];
|
||||
if(in_array(\App::$poi['xchan_network'], ['zot', 'zot6'])) {
|
||||
$is_zot = true;
|
||||
}
|
||||
if(local_channel()) {
|
||||
$c = q("select abook_id from abook where abook_channel = %d and abook_xchan = '%s' limit 1",
|
||||
intval(local_channel()),
|
||||
dbesc(\App::$poi['xchan_hash'])
|
||||
);
|
||||
if($c)
|
||||
$connected = true;
|
||||
}
|
||||
$url = App::$poi['xchan_url'];
|
||||
if(in_array(App::$poi['xchan_network'], ['zot', 'zot6'])) {
|
||||
$is_zot = true;
|
||||
}
|
||||
if(local_channel()) {
|
||||
$c = q("select abook_id from abook where abook_channel = %d and abook_xchan = '%s' limit 1",
|
||||
intval(local_channel()),
|
||||
dbesc(App::$poi['xchan_hash'])
|
||||
);
|
||||
if($c)
|
||||
$connected = true;
|
||||
}
|
||||
|
||||
// We will load the chanview template if it's a foreign network,
|
||||
|
||||
@@ -7,9 +7,7 @@ use Zotlabs\Lib\Apps;
|
||||
use Zotlabs\Web\Controller;
|
||||
use Zotlabs\Lib\Chatroom;
|
||||
use Zotlabs\Access\AccessList;
|
||||
|
||||
|
||||
|
||||
use Zotlabs\Lib\Libsync;
|
||||
|
||||
require_once('include/bookmarks.php');
|
||||
|
||||
@@ -80,7 +78,7 @@ class Chat extends Controller {
|
||||
intval(local_channel())
|
||||
);
|
||||
|
||||
build_sync_packet(0, array('chatroom' => $x));
|
||||
Libsync::build_sync_packet(0, array('chatroom' => $x));
|
||||
|
||||
if($x)
|
||||
goaway(z_root() . '/chat/' . $channel['channel_address'] . '/' . $x[0]['cr_id']);
|
||||
@@ -199,7 +197,7 @@ class Chat extends Controller {
|
||||
|
||||
$cipher = get_pconfig(local_channel(),'system','default_cipher');
|
||||
if(! $cipher)
|
||||
$cipher = 'aes256';
|
||||
$cipher = 'AES-128-CCM';
|
||||
|
||||
|
||||
$o = replace_macros(get_markup_template('chat.tpl'),array(
|
||||
|
||||
@@ -35,13 +35,6 @@ class Cloud extends \Zotlabs\Web\Controller {
|
||||
if (argc() > 1)
|
||||
$which = argv(1);
|
||||
|
||||
|
||||
if (argc() < 2 && intval(get_config('system','cloud_disable_siteroot'))) {
|
||||
notice( t('Permission denied.') . EOL);
|
||||
construct_page();
|
||||
killme();
|
||||
}
|
||||
|
||||
$profile = 0;
|
||||
|
||||
if ($which)
|
||||
|
||||
@@ -28,10 +28,6 @@ class Connect extends Controller {
|
||||
|
||||
$channel_id = App::$data['channel']['channel_id'];
|
||||
|
||||
if(! Apps::system_app_installed($channel_id, 'Premium Channel')) {
|
||||
return;
|
||||
}
|
||||
|
||||
profile_load($which,'');
|
||||
}
|
||||
|
||||
@@ -42,10 +38,6 @@ class Connect extends Controller {
|
||||
|
||||
$channel_id = App::$data['channel']['channel_id'];
|
||||
|
||||
if(! Apps::system_app_installed($channel_id, 'Premium Channel')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$edit = ((local_channel() && (local_channel() == $channel_id)) ? true : false);
|
||||
|
||||
if($edit) {
|
||||
@@ -97,15 +89,6 @@ class Connect extends Controller {
|
||||
|
||||
$channel_id = App::$data['channel']['channel_id'];
|
||||
|
||||
if(! Apps::system_app_installed($channel_id, 'Premium Channel')) {
|
||||
//Do not display any associated widgets at this point
|
||||
App::$pdl = '';
|
||||
|
||||
$o = '<b>' . t('Premium Channel App') . ' (' . t('Not Installed') . '):</b><br>';
|
||||
$o .= t('Allows you to set restrictions and terms on those that connect with your channel');
|
||||
return $o;
|
||||
}
|
||||
|
||||
$edit = ((local_channel() && (local_channel() == $channel_id)) ? true : false);
|
||||
|
||||
$text = get_pconfig($channel_id,'system','selltext');
|
||||
|
||||
@@ -34,7 +34,7 @@ class Connections extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
|
||||
nav_set_selected('Connections');
|
||||
|
||||
|
||||
$active = false;
|
||||
$blocked = false;
|
||||
$hidden = false;
|
||||
@@ -283,6 +283,28 @@ class Connections extends \Zotlabs\Web\Controller {
|
||||
if(! intval(get_abconfig(local_channel(),$rr['xchan_hash'],'their_perms','post_comments'))) {
|
||||
$oneway = true;
|
||||
}
|
||||
|
||||
$perminfo['connpermcount']=0;
|
||||
$perminfo['connperms']=t('Accepts').': ';
|
||||
if(intval(get_abconfig(local_channel(),$rr['xchan_hash'],'their_perms','post_comments'))) {
|
||||
$perminfo['connpermcount']++;
|
||||
$perminfo['connperms'] .= t('Comments');
|
||||
}
|
||||
if(intval(get_abconfig(local_channel(),$rr['xchan_hash'],'their_perms','send_stream'))) {
|
||||
$perminfo['connpermcount']++;
|
||||
$perminfo['connperms'] = ($perminfo['connperms']) ? $perminfo['connperms'] . ', ' : $perminfo['connperms'] ;
|
||||
$perminfo['connperms'] .= t('Stream items');
|
||||
}
|
||||
if(intval(get_abconfig(local_channel(),$rr['xchan_hash'],'their_perms','post_wall'))) {
|
||||
$perminfo['connpermcount']++;
|
||||
$perminfo['connperms'] = ($perminfo['connperms']) ? $perminfo['connperms'] . ', ' : $perminfo['connperms'] ;
|
||||
$perminfo['connperms'] .= t('Wall posts');
|
||||
}
|
||||
|
||||
if ($perminfo['connpermcount'] == 0) {
|
||||
$perminfo['connperms'] .= t('Nothing');
|
||||
}
|
||||
|
||||
|
||||
foreach($status as $str) {
|
||||
if(!$str)
|
||||
@@ -322,7 +344,11 @@ class Connections extends \Zotlabs\Web\Controller {
|
||||
'ignore' => ((! $rr['abook_ignored']) ? t('Ignore') : false),
|
||||
'recent_label' => t('Recent activity'),
|
||||
'recentlink' => z_root() . '/network/?f=&cid=' . intval($rr['abook_id']) . '&name=' . $rr['xchan_name'],
|
||||
'oneway' => $oneway
|
||||
'oneway' => $oneway,
|
||||
'perminfo' => $perminfo,
|
||||
'connect' => (intval($rr['abook_not_here']) ? t('Connect') : ''),
|
||||
'follow' => z_root() . '/follow/?f=&url=' . urlencode($rr['xchan_hash']) . '&interactive=0',
|
||||
'connect_hover' => t('Connect at this location')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,8 +7,16 @@ namespace Zotlabs\Module;
|
||||
*
|
||||
*/
|
||||
|
||||
use App;
|
||||
use Zotlabs\Lib\Apps;
|
||||
use Zotlabs\Lib\Libzot;
|
||||
use Zotlabs\Lib\Libsync;
|
||||
use Zotlabs\Daemon\Master;
|
||||
use Zotlabs\Web\Controller;
|
||||
use Zotlabs\Access\Permissions;
|
||||
use Zotlabs\Access\PermissionLimits;
|
||||
use Zotlabs\Web\HTTPHeaders;
|
||||
use Zotlabs\Lib\Permcat;
|
||||
|
||||
require_once('include/socgraph.php');
|
||||
require_once('include/selectors.php');
|
||||
@@ -16,7 +24,7 @@ require_once('include/group.php');
|
||||
require_once('include/photos.php');
|
||||
|
||||
|
||||
class Connedit extends \Zotlabs\Web\Controller {
|
||||
class Connedit extends Controller {
|
||||
|
||||
/* @brief Initialize the connection-editor
|
||||
*
|
||||
@@ -36,12 +44,12 @@ class Connedit extends \Zotlabs\Web\Controller {
|
||||
intval(argv(1))
|
||||
);
|
||||
if($r) {
|
||||
\App::$poi = array_shift($r);
|
||||
App::$poi = array_shift($r);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$channel = \App::get_channel();
|
||||
$channel = App::get_channel();
|
||||
if($channel)
|
||||
head_set_icon($channel['xchan_photo_s']);
|
||||
|
||||
@@ -61,7 +69,7 @@ class Connedit extends \Zotlabs\Web\Controller {
|
||||
if(! $contact_id)
|
||||
return;
|
||||
|
||||
$channel = \App::get_channel();
|
||||
$channel = App::get_channel();
|
||||
|
||||
// TODO if configured for hassle-free permissions, we'll post the form with ajax as soon as the
|
||||
// connection enable is toggled to a special autopost url and set permissions immediately, leaving
|
||||
@@ -140,7 +148,7 @@ class Connedit extends \Zotlabs\Web\Controller {
|
||||
|
||||
$rating_text = trim(escape_tags($_REQUEST['rating_text']));
|
||||
|
||||
$all_perms = \Zotlabs\Access\Permissions::Perms();
|
||||
$all_perms = Permissions::Perms();
|
||||
|
||||
if($all_perms) {
|
||||
foreach($all_perms as $perm => $desc) {
|
||||
@@ -212,7 +220,7 @@ class Connedit extends \Zotlabs\Web\Controller {
|
||||
$record = $z[0]['xlink_id'];
|
||||
}
|
||||
if($record) {
|
||||
\Zotlabs\Daemon\Master::Summon(array('Ratenotif','rating',$record));
|
||||
Master::Summon(array('Ratenotif','rating',$record));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -227,7 +235,7 @@ class Connedit extends \Zotlabs\Web\Controller {
|
||||
// request. The workaround is to approve the connection, then go back and
|
||||
// adjust permissions as desired.
|
||||
|
||||
$p = \Zotlabs\Access\Permissions::connect_perms(local_channel());
|
||||
$p = Permissions::connect_perms(local_channel());
|
||||
$my_perms = $p['perms'];
|
||||
if($my_perms) {
|
||||
foreach($my_perms as $k => $v) {
|
||||
@@ -257,12 +265,12 @@ class Connedit extends \Zotlabs\Web\Controller {
|
||||
else
|
||||
notice( t('Failed to update connection record.') . EOL);
|
||||
|
||||
if(! intval(\App::$poi['abook_self'])) {
|
||||
if(! intval(App::$poi['abook_self'])) {
|
||||
if($new_friend) {
|
||||
\Zotlabs\Daemon\Master::Summon( [ 'Notifier', 'permission_accept', $contact_id ] );
|
||||
Master::Summon( [ 'Notifier', 'permission_accept', $contact_id ] );
|
||||
}
|
||||
|
||||
\Zotlabs\Daemon\Master::Summon( [
|
||||
Master::Summon( [
|
||||
'Notifier',
|
||||
(($new_friend) ? 'permission_create' : 'permission_update'),
|
||||
$contact_id
|
||||
@@ -275,7 +283,7 @@ class Connedit extends \Zotlabs\Web\Controller {
|
||||
require_once('include/group.php');
|
||||
$g = group_rec_byhash(local_channel(),$default_group);
|
||||
if($g)
|
||||
group_add_member(local_channel(),'',\App::$poi['abook_xchan'],$g['id']);
|
||||
group_add_member(local_channel(),'',App::$poi['abook_xchan'],$g['id']);
|
||||
}
|
||||
|
||||
// Check if settings permit ("post new friend activity" is allowed, and
|
||||
@@ -286,8 +294,8 @@ class Connedit extends \Zotlabs\Web\Controller {
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
if(($pr) && (! intval($orig_record[0]['abook_hidden'])) && (intval(get_pconfig($channel['channel_id'],'system','post_newfriend')))) {
|
||||
$xarr = array();
|
||||
$xarr['verb'] = ACTIVITY_FRIEND;
|
||||
$xarr = [];
|
||||
|
||||
$xarr['item_wall'] = 1;
|
||||
$xarr['item_origin'] = 1;
|
||||
$xarr['item_thread_top'] = 1;
|
||||
@@ -297,21 +305,10 @@ class Connedit extends \Zotlabs\Web\Controller {
|
||||
$xarr['deny_cid'] = $channel['channel_deny_cid'];
|
||||
$xarr['deny_gid'] = $channel['channel_deny_gid'];
|
||||
$xarr['item_private'] = (($xarr['allow_cid']||$xarr['allow_gid']||$xarr['deny_cid']||$xarr['deny_gid']) ? 1 : 0);
|
||||
$obj = array(
|
||||
'type' => ACTIVITY_OBJ_PERSON,
|
||||
'title' => \App::$poi['xchan_name'],
|
||||
'id' => \App::$poi['xchan_hash'],
|
||||
'link' => array(
|
||||
array('rel' => 'alternate', 'type' => 'text/html', 'href' => \App::$poi['xchan_url']),
|
||||
array('rel' => 'photo', 'type' => \App::$poi['xchan_photo_mimetype'], 'href' => \App::$poi['xchan_photo_l'])
|
||||
),
|
||||
);
|
||||
$xarr['obj'] = json_encode($obj);
|
||||
$xarr['obj_type'] = ACTIVITY_OBJ_PERSON;
|
||||
|
||||
$xarr['body'] = '[zrl=' . $channel['xchan_url'] . ']' . $channel['xchan_name'] . '[/zrl]' . ' ' . t('is now connected to') . ' ' . '[zrl=' . \App::$poi['xchan_url'] . ']' . \App::$poi['xchan_name'] . '[/zrl]';
|
||||
$xarr['body'] = '[zrl=' . $channel['xchan_url'] . ']' . $channel['xchan_name'] . '[/zrl]' . ' ' . t('is now connected to') . ' ' . '[zrl=' . App::$poi['xchan_url'] . ']' . App::$poi['xchan_name'] . '[/zrl]';
|
||||
|
||||
$xarr['body'] .= "\n\n\n" . '[zrl=' . \App::$poi['xchan_url'] . '][zmg=80x80]' . \App::$poi['xchan_photo_m'] . '[/zmg][/zrl]';
|
||||
$xarr['body'] .= "\n\n\n" . '[zrl=' . App::$poi['xchan_url'] . '][zmg=80x80]' . App::$poi['xchan_photo_m'] . '[/zmg][/zrl]';
|
||||
|
||||
post_activity_item($xarr);
|
||||
|
||||
@@ -319,7 +316,7 @@ class Connedit extends \Zotlabs\Web\Controller {
|
||||
|
||||
|
||||
// pull in a bit of content if there is any to pull in
|
||||
\Zotlabs\Daemon\Master::Summon(array('Onepoll',$contact_id));
|
||||
Master::Summon(array('Onepoll',$contact_id));
|
||||
|
||||
}
|
||||
|
||||
@@ -332,11 +329,11 @@ class Connedit extends \Zotlabs\Web\Controller {
|
||||
intval($contact_id)
|
||||
);
|
||||
if($r) {
|
||||
\App::$poi = $r[0];
|
||||
App::$poi = $r[0];
|
||||
}
|
||||
|
||||
if($new_friend) {
|
||||
$arr = array('channel_id' => local_channel(), 'abook' => \App::$poi);
|
||||
$arr = array('channel_id' => local_channel(), 'abook' => App::$poi);
|
||||
call_hooks('accept_follow', $arr);
|
||||
}
|
||||
|
||||
@@ -356,23 +353,23 @@ class Connedit extends \Zotlabs\Web\Controller {
|
||||
|
||||
function connedit_clone(&$a) {
|
||||
|
||||
if(! \App::$poi)
|
||||
if(! App::$poi)
|
||||
return;
|
||||
|
||||
|
||||
$channel = \App::get_channel();
|
||||
$channel = App::get_channel();
|
||||
|
||||
$r = q("SELECT abook.*, xchan.*
|
||||
FROM abook left join xchan on abook_xchan = xchan_hash
|
||||
WHERE abook_channel = %d and abook_id = %d LIMIT 1",
|
||||
intval(local_channel()),
|
||||
intval(\App::$poi['abook_id'])
|
||||
intval(App::$poi['abook_id'])
|
||||
);
|
||||
if($r) {
|
||||
\App::$poi = array_shift($r);
|
||||
App::$poi = array_shift($r);
|
||||
}
|
||||
|
||||
$clone = \App::$poi;
|
||||
$clone = App::$poi;
|
||||
|
||||
unset($clone['abook_id']);
|
||||
unset($clone['abook_account']);
|
||||
@@ -382,7 +379,7 @@ class Connedit extends \Zotlabs\Web\Controller {
|
||||
if($abconfig)
|
||||
$clone['abconfig'] = $abconfig;
|
||||
|
||||
build_sync_packet(0 /* use the current local_channel */, array('abook' => array($clone)));
|
||||
Libsync::build_sync_packet(0 /* use the current local_channel */, array('abook' => array($clone)));
|
||||
}
|
||||
|
||||
/* @brief Generate content of connection edit page
|
||||
@@ -401,11 +398,11 @@ class Connedit extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
|
||||
$section = ((array_key_exists('section',$_REQUEST)) ? $_REQUEST['section'] : '');
|
||||
$channel = \App::get_channel();
|
||||
$channel = App::get_channel();
|
||||
|
||||
$yes_no = array(t('No'),t('Yes'));
|
||||
|
||||
$connect_perms = \Zotlabs\Access\Permissions::connect_perms(local_channel());
|
||||
$connect_perms = Permissions::connect_perms(local_channel());
|
||||
|
||||
$o .= "<script>function connectDefaultShare() {
|
||||
\$('.abook-edit-me').each(function() {
|
||||
@@ -426,7 +423,7 @@ class Connedit extends \Zotlabs\Web\Controller {
|
||||
return;
|
||||
|
||||
$cmd = argv(2);
|
||||
|
||||
|
||||
$orig_record = q("SELECT abook.*, xchan.* FROM abook left join xchan on abook_xchan = xchan_hash
|
||||
WHERE abook_id = %d AND abook_channel = %d AND abook_self = 0 LIMIT 1",
|
||||
intval($contact_id),
|
||||
@@ -440,7 +437,7 @@ class Connedit extends \Zotlabs\Web\Controller {
|
||||
|
||||
if($cmd === 'update') {
|
||||
// pull feed and consume it, which should subscribe to the hub.
|
||||
\Zotlabs\Daemon\Master::Summon(array('Poller',$contact_id));
|
||||
Master::Summon(array('Poller',$contact_id));
|
||||
goaway(z_root() . '/connedit/' . $contact_id);
|
||||
|
||||
}
|
||||
@@ -450,7 +447,7 @@ class Connedit extends \Zotlabs\Web\Controller {
|
||||
$recurse = 0;
|
||||
$x = z_fetch_url(zid($url),false,$recurse,['session' => true]);
|
||||
if($x['success']) {
|
||||
$h = new \Zotlabs\Web\HTTPHeaders($x['header']);
|
||||
$h = new HTTPHeaders($x['header']);
|
||||
$fields = $h->fetch();
|
||||
if($fields) {
|
||||
foreach($fields as $y) {
|
||||
@@ -481,17 +478,17 @@ class Connedit extends \Zotlabs\Web\Controller {
|
||||
|
||||
if($cmd === 'refresh') {
|
||||
if($orig_record[0]['xchan_network'] === 'zot') {
|
||||
if(! zot_refresh($orig_record[0],\App::get_channel()))
|
||||
if(! zot_refresh($orig_record[0],App::get_channel()))
|
||||
notice( t('Refresh failed - channel is currently unavailable.') );
|
||||
}
|
||||
elseif($orig_record[0]['xchan_network'] === 'zot6') {
|
||||
if(! Libzot::refresh($orig_record[0],\App::get_channel()))
|
||||
if(! Libzot::refresh($orig_record[0],App::get_channel()))
|
||||
notice( t('Refresh failed - channel is currently unavailable.') );
|
||||
}
|
||||
else {
|
||||
|
||||
// if you are on a different network we'll force a refresh of the connection basic info
|
||||
\Zotlabs\Daemon\Master::Summon(array('Notifier','permission_update',$contact_id));
|
||||
Master::Summon(array('Notifier','permission_update',$contact_id));
|
||||
}
|
||||
goaway(z_root() . '/connedit/' . $contact_id);
|
||||
}
|
||||
@@ -549,16 +546,11 @@ class Connedit extends \Zotlabs\Web\Controller {
|
||||
|
||||
if($cmd === 'drop') {
|
||||
|
||||
|
||||
// @FIXME
|
||||
// We need to send either a purge or a refresh packet to the other side (the channel being unfriended).
|
||||
// The issue is that the abook DB record _may_ get destroyed when we call contact_remove. As the notifier
|
||||
// runs in the background there could be a race condition preventing this packet from being sent in all
|
||||
// cases.
|
||||
// PLACEHOLDER
|
||||
|
||||
contact_remove(local_channel(), $orig_record[0]['abook_id']);
|
||||
build_sync_packet(0 /* use the current local_channel */,
|
||||
|
||||
Master::Summon( [ 'Notifier', 'purge', local_channel(), $orig_record[0]['xchan_hash'] ] );
|
||||
|
||||
Libsync::build_sync_packet(0 /* use the current local_channel */,
|
||||
array('abook' => array(array(
|
||||
'abook_xchan' => $orig_record[0]['abook_xchan'],
|
||||
'entry_deleted' => true))
|
||||
@@ -573,13 +565,13 @@ class Connedit extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
}
|
||||
|
||||
if(\App::$poi) {
|
||||
if(App::$poi) {
|
||||
|
||||
$abook_prev = 0;
|
||||
$abook_next = 0;
|
||||
|
||||
$contact_id = \App::$poi['abook_id'];
|
||||
$contact = \App::$poi;
|
||||
$contact_id = App::$poi['abook_id'];
|
||||
$contact = App::$poi;
|
||||
|
||||
$cn = q("SELECT abook_id, xchan_name from abook left join xchan on abook_xchan = xchan_hash where abook_channel = %d and abook_self = 0 and xchan_deleted = 0 order by xchan_name",
|
||||
intval(local_channel())
|
||||
@@ -787,9 +779,9 @@ class Connedit extends \Zotlabs\Web\Controller {
|
||||
|
||||
|
||||
$perms = array();
|
||||
$channel = \App::get_channel();
|
||||
$channel = App::get_channel();
|
||||
|
||||
$global_perms = \Zotlabs\Access\Permissions::Perms();
|
||||
$global_perms = Permissions::Perms();
|
||||
|
||||
$existing = get_all_perms(local_channel(),$contact['abook_xchan'],false);
|
||||
|
||||
@@ -821,7 +813,7 @@ class Connedit extends \Zotlabs\Web\Controller {
|
||||
$thisperm = get_abconfig(local_channel(),$contact['abook_xchan'],'my_perms',$k);
|
||||
//fixme
|
||||
|
||||
$checkinherited = \Zotlabs\Access\PermissionLimits::Get(local_channel(),$k);
|
||||
$checkinherited = PermissionLimits::Get(local_channel(),$k);
|
||||
|
||||
// For auto permissions (when $self is true) we don't want to look at existing
|
||||
// permissions because they are enabled for the channel owner
|
||||
@@ -834,7 +826,7 @@ class Connedit extends \Zotlabs\Web\Controller {
|
||||
$perms[] = array('perms_' . $k, $v, ((array_key_exists($k,$their_perms)) ? intval($their_perms[$k]) : ''),$thisperm, 1, (($checkinherited & PERMS_SPECIFIC) ? '' : '1'), '', $checkinherited);
|
||||
}
|
||||
|
||||
$pcat = new \Zotlabs\Lib\Permcat(local_channel());
|
||||
$pcat = new Permcat(local_channel());
|
||||
$pcatlist = $pcat->listing();
|
||||
$permcats = [];
|
||||
if($pcatlist) {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
<?php
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
use Zotlabs\Lib\Libsync;
|
||||
|
||||
/*
|
||||
@file cover_photo.php
|
||||
@brief Module-file with functions for handling of cover-photos
|
||||
@@ -66,7 +68,7 @@ class Cover_photo extends \Zotlabs\Web\Controller {
|
||||
|
||||
$sync = attach_export_data($channel,$r[0]['resource_id']);
|
||||
if($sync)
|
||||
build_sync_packet($channel['channel_id'],array('file' => array($sync)));
|
||||
Libsync::build_sync_packet($channel['channel_id'],array('file' => array($sync)));
|
||||
}
|
||||
|
||||
// Update directory in background
|
||||
@@ -230,7 +232,7 @@ class Cover_photo extends \Zotlabs\Web\Controller {
|
||||
|
||||
$sync = attach_export_data($channel,$base_image['resource_id']);
|
||||
if($sync)
|
||||
build_sync_packet($channel['channel_id'],array('file' => array($sync)));
|
||||
Libsync::build_sync_packet($channel['channel_id'],array('file' => array($sync)));
|
||||
|
||||
// Update directory in background
|
||||
\Zotlabs\Daemon\Master::Summon(array('Directory',$channel['channel_id']));
|
||||
@@ -291,14 +293,6 @@ class Cover_photo extends \Zotlabs\Web\Controller {
|
||||
$arr['item_thread_top'] = 1;
|
||||
$arr['item_origin'] = 1;
|
||||
$arr['item_wall'] = 1;
|
||||
$arr['obj_type'] = ACTIVITY_OBJ_PHOTO;
|
||||
$arr['verb'] = ACTIVITY_UPDATE;
|
||||
|
||||
$arr['obj'] = json_encode(array(
|
||||
'type' => $arr['obj_type'],
|
||||
'id' => z_root() . '/photo/' . $photo['resource_id'] . '-7',
|
||||
'link' => array('rel' => 'photo', 'type' => $photo['mimetype'], 'href' => z_root() . '/photo/' . $photo['resource_id'] . '-7')
|
||||
));
|
||||
|
||||
if($profile && stripos($profile['gender'],t('female')) !== false)
|
||||
$t = t('%1$s updated her %2$s');
|
||||
|
||||
@@ -95,6 +95,8 @@ class Dav extends \Zotlabs\Web\Controller {
|
||||
|
||||
|
||||
$auth = new \Zotlabs\Storage\BasicAuth();
|
||||
// $auth->observer = get_observer_hash();
|
||||
|
||||
$auth->setRealm(ucfirst(\Zotlabs\Lib\System::get_platform_name()) . ' ' . 'WebDAV');
|
||||
|
||||
$rootDirectory = new \Zotlabs\Storage\Directory('/', $auth);
|
||||
|
||||
@@ -4,6 +4,7 @@ namespace Zotlabs\Module;
|
||||
use App;
|
||||
use Zotlabs\Lib\Apps;
|
||||
use Zotlabs\Web\Controller;
|
||||
use Zotlabs\Lib\Libsync;
|
||||
|
||||
require_once('include/socgraph.php');
|
||||
require_once('include/selectors.php');
|
||||
@@ -164,7 +165,7 @@ class Defperms extends Controller {
|
||||
if($abconfig)
|
||||
$clone['abconfig'] = $abconfig;
|
||||
|
||||
build_sync_packet(0 /* use the current local_channel */, array('abook' => array($clone)));
|
||||
Libsync::build_sync_packet(0 /* use the current local_channel */, array('abook' => array($clone)));
|
||||
}
|
||||
|
||||
/* @brief Generate content of connection default permissions page
|
||||
|
||||
52
Zotlabs/Module/Dircensor.php
Normal file
52
Zotlabs/Module/Dircensor.php
Normal file
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
use App;
|
||||
use Zotlabs\Web\Controller;
|
||||
|
||||
|
||||
class Dircensor extends Controller {
|
||||
|
||||
function get() {
|
||||
if(! is_site_admin()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$dirmode = intval(get_config('system','directory_mode'));
|
||||
|
||||
if (! ($dirmode == DIRECTORY_MODE_PRIMARY || $dirmode == DIRECTORY_MODE_STANDALONE)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$xchan = argv(1);
|
||||
if(! $xchan) {
|
||||
return;
|
||||
}
|
||||
|
||||
$r = q("select * from xchan where xchan_hash = '%s'",
|
||||
dbesc($xchan)
|
||||
);
|
||||
|
||||
if(! $r) {
|
||||
return;
|
||||
}
|
||||
|
||||
$val = (($r[0]['xchan_censored']) ? 0 : 1);
|
||||
|
||||
q("update xchan set xchan_censored = $val where xchan_hash = '%s'",
|
||||
dbesc($xchan)
|
||||
);
|
||||
|
||||
if($val) {
|
||||
info( t('Entry censored') . EOL);
|
||||
}
|
||||
else {
|
||||
info( t('Entry uncensored') . EOL);
|
||||
}
|
||||
|
||||
goaway(z_root() . '/directory');
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,15 +2,19 @@
|
||||
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
use App;
|
||||
use Zotlabs\Web\Controller;
|
||||
|
||||
require_once('include/socgraph.php');
|
||||
require_once('include/dir_fns.php');
|
||||
require_once('include/bbcode.php');
|
||||
require_once('include/html2plain.php');
|
||||
|
||||
|
||||
class Directory extends \Zotlabs\Web\Controller {
|
||||
class Directory extends Controller {
|
||||
|
||||
function init() {
|
||||
\App::set_pager_itemspage(60);
|
||||
App::set_pager_itemspage(30);
|
||||
|
||||
if(local_channel() && x($_GET,'ignore')) {
|
||||
q("insert into xign ( uid, xchan ) values ( %d, '%s' ) ",
|
||||
@@ -21,7 +25,7 @@ class Directory extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
|
||||
if(local_channel())
|
||||
\App::$profile_uid = local_channel();
|
||||
App::$profile_uid = local_channel();
|
||||
|
||||
$observer = get_observer_hash();
|
||||
$global_changed = false;
|
||||
@@ -140,9 +144,15 @@ class Directory extends \Zotlabs\Web\Controller {
|
||||
|
||||
$dirmode = intval(get_config('system','directory_mode'));
|
||||
|
||||
$directory_admin = false;
|
||||
|
||||
if(($dirmode == DIRECTORY_MODE_PRIMARY) || ($dirmode == DIRECTORY_MODE_STANDALONE)) {
|
||||
$url = z_root() . '/dirsearch';
|
||||
}
|
||||
if (is_site_admin()) {
|
||||
$directory_admin = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(! $url) {
|
||||
$directory = find_upstream_directory($dirmode);
|
||||
if((! $directory) || (! array_key_exists('url',$directory)) || (! $directory['url']))
|
||||
@@ -182,7 +192,7 @@ class Directory extends \Zotlabs\Web\Controller {
|
||||
$query .= '&t=' . $token;
|
||||
|
||||
if(! $globaldir)
|
||||
$query .= '&hub=' . \App::get_hostname();
|
||||
$query .= '&hub=' . App::get_hostname();
|
||||
|
||||
if($search)
|
||||
$query .= '&name=' . urlencode($search) . '&keywords=' . urlencode($search);
|
||||
@@ -204,8 +214,8 @@ class Directory extends \Zotlabs\Web\Controller {
|
||||
if($sort_order)
|
||||
$query .= '&order=' . urlencode($sort_order);
|
||||
|
||||
if(\App::$pager['page'] != 1)
|
||||
$query .= '&p=' . \App::$pager['page'];
|
||||
if(App::$pager['page'] != 1)
|
||||
$query .= '&p=' . App::$pager['page'];
|
||||
|
||||
logger('mod_directory: query: ' . $query);
|
||||
|
||||
@@ -283,12 +293,15 @@ class Directory extends \Zotlabs\Web\Controller {
|
||||
$marital = ((x($profile,'marital') == 1) ? t('Status: ') . $profile['marital']: False);
|
||||
|
||||
$homepage = ((x($profile,'homepage') == 1) ? t('Homepage: ') : False);
|
||||
$homepageurl = ((x($profile,'homepage') == 1) ? $profile['homepage'] : '');
|
||||
$homepageurl = ((x($profile,'homepage') == 1) ? html2plain($profile['homepage']) : '');
|
||||
|
||||
$hometown = ((x($profile,'hometown') == 1) ? $profile['hometown'] : False);
|
||||
|
||||
$about = ((x($profile,'about') == 1) ? zidify_links(bbcode($profile['about'])) : False);
|
||||
$hometown = ((x($profile,'hometown') == 1) ? html2plain($profile['hometown']) : False);
|
||||
|
||||
$about = ((x($profile,'about') == 1) ? zidify_links(bbcode($profile['about'], ['tryoembed' => false])) : False);
|
||||
if ($about && $safe_mode) {
|
||||
$about = html2plain($about);
|
||||
}
|
||||
|
||||
$keywords = ((x($profile,'keywords')) ? $profile['keywords'] : '');
|
||||
|
||||
|
||||
@@ -343,9 +356,11 @@ class Directory extends \Zotlabs\Web\Controller {
|
||||
'canrate' => (($rating_enabled && local_channel()) ? true : false),
|
||||
'pdesc' => $pdesc,
|
||||
'pdesc_label' => t('Description:'),
|
||||
'censor' => (($directory_admin) ? 'dircensor/' . $rr['hash'] : ''),
|
||||
'censor_label' => (($rr['censored']) ? t('Uncensor') : t('Censor')),
|
||||
'marital' => $marital,
|
||||
'homepage' => $homepage,
|
||||
'homepageurl' => linkify($homepageurl),
|
||||
'homepageurl' => (($safe_mode) ? $homepageurl : linkify($homepageurl)),
|
||||
'hometown' => $hometown,
|
||||
'hometown_label' => t('Hometown:'),
|
||||
'about' => $about,
|
||||
@@ -387,7 +402,7 @@ class Directory extends \Zotlabs\Web\Controller {
|
||||
ksort($entries); // Sort array by key so that foreach-constructs work as expected
|
||||
|
||||
if($j['keywords']) {
|
||||
\App::$data['directory_keywords'] = $j['keywords'];
|
||||
App::$data['directory_keywords'] = $j['keywords'];
|
||||
}
|
||||
|
||||
logger('mod_directory: entries: ' . print_r($entries,true), LOGGER_DATA);
|
||||
@@ -438,7 +453,7 @@ class Directory extends \Zotlabs\Web\Controller {
|
||||
echo $o;
|
||||
killme();
|
||||
}
|
||||
if(\App::$pager['page'] == 1 && $j['records'] == 0 && strpos($search,'@')) {
|
||||
if(App::$pager['page'] == 1 && $j['records'] == 0 && strpos($search,'@')) {
|
||||
goaway(z_root() . '/chanview/?f=&address=' . $search);
|
||||
}
|
||||
info( t("No entries (some entries may be hidden).") . EOL);
|
||||
|
||||
@@ -1,14 +1,17 @@
|
||||
<?php
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
use App;
|
||||
use Zotlabs\Web\Controller;
|
||||
|
||||
require_once('include/dir_fns.php');
|
||||
|
||||
|
||||
|
||||
class Dirsearch extends \Zotlabs\Web\Controller {
|
||||
class Dirsearch extends Controller {
|
||||
|
||||
function init() {
|
||||
\App::set_pager_itemspage(60);
|
||||
App::set_pager_itemspage(30);
|
||||
|
||||
}
|
||||
|
||||
@@ -25,7 +28,8 @@ class Dirsearch extends \Zotlabs\Web\Controller {
|
||||
$ret['message'] = t('This site is not a directory server');
|
||||
json_return_and_die($ret);
|
||||
}
|
||||
|
||||
|
||||
|
||||
$access_token = $_REQUEST['t'];
|
||||
|
||||
$token = get_config('system','realm_token');
|
||||
@@ -286,29 +290,29 @@ class Dirsearch extends \Zotlabs\Web\Controller {
|
||||
else
|
||||
$entry['total_ratings'] = 0;
|
||||
|
||||
$entry['name'] = $rr['xchan_name'];
|
||||
$entry['hash'] = $rr['xchan_hash'];
|
||||
|
||||
$entry['name'] = $rr['xchan_name'];
|
||||
$entry['hash'] = $rr['xchan_hash'];
|
||||
$entry['censored'] = $rr['xchan_censored'];
|
||||
$entry['selfcensored'] = $rr['xchan_selfcensored'];
|
||||
$entry['public_forum'] = (intval($rr['xchan_pubforum']) ? true : false);
|
||||
|
||||
$entry['url'] = $rr['xchan_url'];
|
||||
$entry['photo_l'] = $rr['xchan_photo_l'];
|
||||
$entry['photo'] = $rr['xchan_photo_m'];
|
||||
$entry['address'] = $rr['xchan_addr'];
|
||||
$entry['description'] = $rr['xprof_desc'];
|
||||
$entry['locale'] = $rr['xprof_locale'];
|
||||
$entry['region'] = $rr['xprof_region'];
|
||||
$entry['postcode'] = $rr['xprof_postcode'];
|
||||
$entry['country'] = $rr['xprof_country'];
|
||||
$entry['birthday'] = $rr['xprof_dob'];
|
||||
$entry['age'] = $rr['xprof_age'];
|
||||
$entry['gender'] = $rr['xprof_gender'];
|
||||
$entry['marital'] = $rr['xprof_marital'];
|
||||
$entry['sexual'] = $rr['xprof_sexual'];
|
||||
$entry['about'] = $rr['xprof_about'];
|
||||
$entry['homepage'] = $rr['xprof_homepage'];
|
||||
$entry['hometown'] = $rr['xprof_hometown'];
|
||||
$entry['keywords'] = $rr['xprof_keywords'];
|
||||
$entry['url'] = $rr['xchan_url'];
|
||||
$entry['photo_l'] = $rr['xchan_photo_l'];
|
||||
$entry['photo'] = $rr['xchan_photo_m'];
|
||||
$entry['address'] = $rr['xchan_addr'];
|
||||
$entry['description'] = $rr['xprof_desc'];
|
||||
$entry['locale'] = $rr['xprof_locale'];
|
||||
$entry['region'] = $rr['xprof_region'];
|
||||
$entry['postcode'] = $rr['xprof_postcode'];
|
||||
$entry['country'] = $rr['xprof_country'];
|
||||
$entry['birthday'] = $rr['xprof_dob'];
|
||||
$entry['age'] = $rr['xprof_age'];
|
||||
$entry['gender'] = $rr['xprof_gender'];
|
||||
$entry['marital'] = $rr['xprof_marital'];
|
||||
$entry['sexual'] = $rr['xprof_sexual'];
|
||||
$entry['about'] = $rr['xprof_about'];
|
||||
$entry['homepage'] = $rr['xprof_homepage'];
|
||||
$entry['hometown'] = $rr['xprof_hometown'];
|
||||
$entry['keywords'] = $rr['xprof_keywords'];
|
||||
|
||||
$entries[] = $entry;
|
||||
|
||||
|
||||
@@ -22,9 +22,6 @@ class Display extends \Zotlabs\Web\Controller {
|
||||
$module_format = 'html';
|
||||
}
|
||||
|
||||
if($load)
|
||||
$_SESSION['loadtime'] = datetime_convert();
|
||||
|
||||
if(observer_prohibited()) {
|
||||
notice( t('Public access denied.') . EOL);
|
||||
return;
|
||||
@@ -47,7 +44,6 @@ class Display extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
|
||||
$observer_is_owner = false;
|
||||
$updateable = false;
|
||||
|
||||
if(local_channel() && (! $update)) {
|
||||
|
||||
@@ -101,7 +97,7 @@ class Display extends \Zotlabs\Web\Controller {
|
||||
if($decoded)
|
||||
$item_hash = $decoded;
|
||||
|
||||
$r = q("select id, uid, mid, parent_mid, thr_parent, verb, item_type, item_deleted, author_xchan, item_blocked from item where mid like '%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 mid like '%s' limit 1",
|
||||
dbesc($item_hash . '%')
|
||||
);
|
||||
|
||||
@@ -159,14 +155,17 @@ class Display extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
}
|
||||
if($target_item['item_type'] == ITEM_TYPE_CARD) {
|
||||
|
||||
$x = q("select * from channel where channel_id = %d limit 1",
|
||||
intval($target_item['uid'])
|
||||
);
|
||||
|
||||
$y = q("select * from iconfig left join item on iconfig.iid = item.id
|
||||
where item.uid = %d and iconfig.cat = 'system' and iconfig.k = 'CARD' and item.id = %d limit 1",
|
||||
intval($target_item['uid']),
|
||||
intval($target_item['parent'])
|
||||
);
|
||||
|
||||
if($x && $y) {
|
||||
goaway(z_root() . '/cards/' . $x[0]['channel_address'] . '/' . $y[0]['v']);
|
||||
}
|
||||
@@ -181,26 +180,16 @@ class Display extends \Zotlabs\Web\Controller {
|
||||
return '';
|
||||
}
|
||||
|
||||
|
||||
$static = ((array_key_exists('static',$_REQUEST)) ? intval($_REQUEST['static']) : 0);
|
||||
|
||||
$simple_update = (($update) ? " AND item_unseen = 1 " : '');
|
||||
|
||||
$simple_update = '';
|
||||
if($update && $_SESSION['loadtime'])
|
||||
$simple_update = " AND (( item_unseen = 1 AND item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' ) OR item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' ) ";
|
||||
if($load)
|
||||
$simple_update = '';
|
||||
|
||||
if($static && $simple_update)
|
||||
$simple_update .= " and item_thread_top = 0 and author_xchan = '" . protect_sprintf(get_observer_hash()) . "' ";
|
||||
|
||||
if((! $update) && (! $load)) {
|
||||
|
||||
$static = ((local_channel()) ? channel_manual_conv_update(local_channel()) : 1);
|
||||
if((! $update) && (! $load)) {
|
||||
|
||||
// if the target item is not a post (eg a like) we want to address its thread parent
|
||||
|
||||
$mid = ((($target_item['verb'] == ACTIVITY_LIKE) || ($target_item['verb'] == ACTIVITY_DISLIKE)) ? $target_item['thr_parent'] : $target_item['mid']);
|
||||
//$mid = ((($target_item['verb'] == ACTIVITY_LIKE) || ($target_item['verb'] == ACTIVITY_DISLIKE)) ? $target_item['thr_parent'] : $target_item['mid']);
|
||||
$mid = $target_item['mid'];
|
||||
|
||||
// if we got a decoded hash we must encode it again before handing to javascript
|
||||
if($decoded)
|
||||
@@ -223,9 +212,9 @@ class Display extends \Zotlabs\Web\Controller {
|
||||
'$conv' => '0',
|
||||
'$spam' => '0',
|
||||
'$fh' => '0',
|
||||
'$dm' => '0',
|
||||
'$nouveau' => '0',
|
||||
'$wall' => '0',
|
||||
'$static' => $static,
|
||||
'$page' => ((\App::$pager['page'] != 1) ? \App::$pager['page'] : 1),
|
||||
'$list' => ((x($_REQUEST,'list')) ? intval($_REQUEST['list']) : 0),
|
||||
'$search' => '',
|
||||
@@ -269,9 +258,6 @@ class Display extends \Zotlabs\Web\Controller {
|
||||
intval(local_channel()),
|
||||
dbesc($target_item['parent_mid'])
|
||||
);
|
||||
if($r) {
|
||||
$updateable = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(! $r) {
|
||||
@@ -313,11 +299,7 @@ class Display extends \Zotlabs\Web\Controller {
|
||||
intval(local_channel()),
|
||||
dbesc($target_item['parent_mid'])
|
||||
);
|
||||
if($r) {
|
||||
$updateable = true;
|
||||
}
|
||||
}
|
||||
|
||||
if($r === null) {
|
||||
// in case somebody turned off public access to sys channel content using permissions
|
||||
// make that content unsearchable by ensuring the owner_xchan can't match
|
||||
@@ -337,7 +319,6 @@ class Display extends \Zotlabs\Web\Controller {
|
||||
intval($sysid)
|
||||
);
|
||||
}
|
||||
$_SESSION['loadtime'] = datetime_convert();
|
||||
}
|
||||
|
||||
else {
|
||||
@@ -427,13 +408,6 @@ class Display extends \Zotlabs\Web\Controller {
|
||||
killme();
|
||||
|
||||
}
|
||||
|
||||
if($updateable) {
|
||||
$x = q("UPDATE item SET item_unseen = 0 where item_unseen = 1 AND uid = %d and parent = %d ",
|
||||
intval(local_channel()),
|
||||
intval($r[0]['item_id'])
|
||||
);
|
||||
}
|
||||
|
||||
$o .= '<div id="content-complete"></div>';
|
||||
|
||||
@@ -457,6 +431,8 @@ class Display extends \Zotlabs\Web\Controller {
|
||||
|
||||
}
|
||||
|
||||
$_SESSION['loadtime'] = datetime_convert();
|
||||
|
||||
return $o;
|
||||
|
||||
}
|
||||
|
||||
@@ -68,6 +68,8 @@ class Embedphotos extends \Zotlabs\Web\Controller {
|
||||
$ext = '.png';
|
||||
elseif($r[0]['mimetype'] === 'image/gif')
|
||||
$ext = '.gif';
|
||||
elseif($r[0]['mimetype'] === 'image/webp')
|
||||
$exp = '.webp';
|
||||
else
|
||||
$ext = EMPTY_STR;
|
||||
|
||||
|
||||
76
Zotlabs/Module/Event.php
Normal file
76
Zotlabs/Module/Event.php
Normal file
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
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 {
|
||||
|
||||
function init() {
|
||||
|
||||
if(ActivityStreams::is_as_request()) {
|
||||
$item_id = argv(1);
|
||||
|
||||
if(! $item_id)
|
||||
return;
|
||||
|
||||
$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);
|
||||
|
||||
$r = q("select * from item where mid like '%s' $item_normal $sql_extra limit 1",
|
||||
dbesc(z_root() . '/activity/' . $item_id . '%')
|
||||
);
|
||||
|
||||
if(! $r) {
|
||||
$r = q("select * from item where mid like '%s' $item_normal limit 1",
|
||||
dbesc(z_root() . '/activity/' . $item_id . '%')
|
||||
);
|
||||
|
||||
if($r) {
|
||||
http_status_exit(403, 'Forbidden');
|
||||
}
|
||||
http_status_exit(404, 'Not found');
|
||||
}
|
||||
|
||||
xchan_query($r,true);
|
||||
$items = fetch_post_tags($r,true);
|
||||
|
||||
$channel = channelx_by_n($items[0]['uid']);
|
||||
|
||||
if(! is_array($items[0]['obj'])) {
|
||||
$obj = json_decode($items[0]['obj'],true);
|
||||
}
|
||||
else {
|
||||
$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();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -17,7 +17,7 @@ class Feed extends \Zotlabs\Web\Controller {
|
||||
$params['pages'] = ((x($_REQUEST,'pages')) ? intval($_REQUEST['pages']) : 0);
|
||||
$params['top'] = ((x($_REQUEST,'top')) ? intval($_REQUEST['top']) : 0);
|
||||
$params['start'] = ((x($_REQUEST,'start')) ? intval($_REQUEST['start']) : 0);
|
||||
$params['records'] = ((x($_REQUEST,'records')) ? intval($_REQUEST['records']) : 40);
|
||||
$params['records'] = ((x($_REQUEST,'records')) ? intval($_REQUEST['records']) : 10);
|
||||
$params['direction'] = ((x($_REQUEST,'direction')) ? dbesc($_REQUEST['direction']) : 'desc');
|
||||
$params['cat'] = ((x($_REQUEST,'cat')) ? escape_tags($_REQUEST['cat']) : '');
|
||||
$params['compat'] = ((x($_REQUEST,'compat')) ? intval($_REQUEST['compat']) : 0);
|
||||
|
||||
79
Zotlabs/Module/Fhubloc_id_url.php
Normal file
79
Zotlabs/Module/Fhubloc_id_url.php
Normal file
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
/* fix missing or hubloc_id_url entries */
|
||||
|
||||
class Fhubloc_id_url extends \Zotlabs\Web\Controller {
|
||||
|
||||
function get() {
|
||||
|
||||
if(! is_site_admin())
|
||||
return;
|
||||
|
||||
q("START TRANSACTION");
|
||||
|
||||
// remove broken xchan entries
|
||||
$r0 = dbq("DELETE FROM xchan WHERE xchan_hash = ''");
|
||||
|
||||
// remove broken hubloc entries
|
||||
$r1 = dbq("DELETE FROM hubloc WHERE hubloc_hash = ''");
|
||||
|
||||
// fix legacy zot hubloc_id_url
|
||||
$r2 = dbq("UPDATE hubloc
|
||||
SET hubloc_id_url = CONCAT(hubloc_url, '/channel/', SUBSTRING(hubloc_addr FROM 1 FOR POSITION('@' IN hubloc_addr) -1))
|
||||
WHERE hubloc_network = 'zot'
|
||||
AND hubloc_id_url = ''"
|
||||
);
|
||||
|
||||
// fix singleton networks hubloc_id_url
|
||||
if(ACTIVE_DBTYPE == DBTYPE_MYSQL) {
|
||||
// fix entries for activitypub which miss the xchan_url due to an earlier bug
|
||||
$r3 = dbq("UPDATE xchan
|
||||
SET xchan_url = xchan_hash
|
||||
WHERE xchan_network = 'activitypub'
|
||||
AND xchan_url = ''"
|
||||
);
|
||||
|
||||
$r4 = dbq("UPDATE hubloc
|
||||
LEFT JOIN xchan ON hubloc.hubloc_hash = xchan.xchan_hash
|
||||
SET hubloc.hubloc_id_url = xchan.xchan_url
|
||||
WHERE hubloc.hubloc_network IN ('activitypub', 'diaspora', 'friendica-over-diaspora', 'gnusoc')
|
||||
AND hubloc.hubloc_id_url = ''
|
||||
AND xchan.xchan_url IS NOT NULL"
|
||||
);
|
||||
|
||||
}
|
||||
if(ACTIVE_DBTYPE == DBTYPE_POSTGRES) {
|
||||
// fix entries for activitypub which miss the xchan_url due to an earlier bug
|
||||
$r3 = dbq("UPDATE xchan
|
||||
SET xchan_url = xchan_hash
|
||||
WHERE xchan_network = 'activitypub'
|
||||
AND xchan_url = ''"
|
||||
);
|
||||
|
||||
$r4 = dbq("UPDATE hubloc
|
||||
SET hubloc_id_url = xchan_url
|
||||
FROM xchan
|
||||
WHERE hubloc_hash = xchan_hash
|
||||
AND hubloc_network IN ('activitypub', 'diaspora', 'friendica-over-diaspora', 'gnusoc')
|
||||
AND hubloc_id_url = ''
|
||||
AND xchan_url IS NOT NULL"
|
||||
);
|
||||
|
||||
|
||||
}
|
||||
|
||||
if($r0 && $r1 && $r2 && $r3 && $r4) {
|
||||
// remove hubloc entries where hubloc_id_url could not be fixed
|
||||
$r5 = dbq("DELETE FROM hubloc WHERE hubloc_id_url = ''");
|
||||
}
|
||||
|
||||
if($r0 && $r1 && $r2 && $r3 && $r4 && $r5) {
|
||||
q("COMMIT");
|
||||
return 'Completed';
|
||||
}
|
||||
|
||||
q("ROLLBACK");
|
||||
return 'Failed';
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
<?php
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
use Zotlabs\Lib\Libzot;
|
||||
|
||||
require_once('include/zot.php');
|
||||
require_once('include/crypto.php');
|
||||
|
||||
@@ -10,7 +12,7 @@ require_once('include/crypto.php');
|
||||
class Fhublocs extends \Zotlabs\Web\Controller {
|
||||
|
||||
function get() {
|
||||
|
||||
|
||||
if(! is_site_admin())
|
||||
return;
|
||||
|
||||
@@ -21,9 +23,11 @@ class Fhublocs extends \Zotlabs\Web\Controller {
|
||||
|
||||
if($r) {
|
||||
foreach($r as $rr) {
|
||||
|
||||
$found = false;
|
||||
$primary_address = '';
|
||||
$x = zot_get_hublocs($rr['channel_hash']);
|
||||
$x = Libzot::get_hublocs($rr['channel_hash']);
|
||||
|
||||
if($x) {
|
||||
foreach($x as $xx) {
|
||||
if($xx['hubloc_url'] === z_root() && $xx['hubloc_sitekey'] === $sitekey) {
|
||||
@@ -42,13 +46,12 @@ class Fhublocs extends \Zotlabs\Web\Controller {
|
||||
if($y)
|
||||
$primary_address = $y[0]['xchan_addr'];
|
||||
|
||||
$hub_address = channel_reddress($rr['channel']);
|
||||
|
||||
|
||||
$hub_address = channel_reddress($rr);
|
||||
|
||||
$primary = (($hub_address === $primary_address) ? 1 : 0);
|
||||
if(! $y)
|
||||
$primary = 1;
|
||||
|
||||
|
||||
$m = q("delete from hubloc where hubloc_hash = '%s' and hubloc_url = '%s' ",
|
||||
dbesc($rr['channel_hash']),
|
||||
dbesc(z_root())
|
||||
@@ -56,7 +59,7 @@ class Fhublocs extends \Zotlabs\Web\Controller {
|
||||
|
||||
// Create a verified hub location pointing to this site.
|
||||
|
||||
|
||||
/*
|
||||
$h = hubloc_store_lowlevel(
|
||||
[
|
||||
'hubloc_guid' => $rr['channel_guid'],
|
||||
@@ -72,7 +75,26 @@ class Fhublocs extends \Zotlabs\Web\Controller {
|
||||
'hubloc_sitekey' => $sitekey
|
||||
]
|
||||
);
|
||||
|
||||
*/
|
||||
$h = hubloc_store_lowlevel(
|
||||
[
|
||||
'hubloc_guid' => $rr['channel_guid'],
|
||||
'hubloc_guid_sig' => $rr['channel_guid_sig'],
|
||||
'hubloc_hash' => $rr['channel_hash'],
|
||||
'hubloc_id_url' => channel_url($rr),
|
||||
'hubloc_addr' => channel_reddress($rr),
|
||||
'hubloc_primary' => intval($primary),
|
||||
'hubloc_url' => z_root(),
|
||||
'hubloc_url_sig' => Libzot::sign(z_root(), $rr['channel_prvkey']),
|
||||
'hubloc_site_id' => Libzot::make_xchan_hash(z_root(), $sitekey),
|
||||
'hubloc_host' => \App::get_hostname(),
|
||||
'hubloc_callback' => z_root() . '/zot',
|
||||
'hubloc_sitekey' => $sitekey,
|
||||
'hubloc_network' => 'zot6',
|
||||
'hubloc_updated' => datetime_convert()
|
||||
]
|
||||
);
|
||||
|
||||
if($h)
|
||||
$o . 'local hubloc created for ' . $rr['channel_name'] . EOL;
|
||||
else
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
<?php
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
use Zotlabs\Lib\Libsync;
|
||||
|
||||
require_once('include/attach.php');
|
||||
require_once('include/channel.php');
|
||||
require_once('include/photos.php');
|
||||
@@ -41,7 +43,7 @@ class File_upload extends \Zotlabs\Web\Controller {
|
||||
|
||||
$sync = attach_export_data($channel,$hash);
|
||||
if($sync) {
|
||||
build_sync_packet($channel['channel_id'],array('file' => array($sync)));
|
||||
Libsync::build_sync_packet($channel['channel_id'],array('file' => array($sync)));
|
||||
}
|
||||
goaway(z_root() . '/cloud/' . $channel['channel_address'] . '/' . $r['data']['display_path']);
|
||||
|
||||
@@ -97,7 +99,7 @@ class File_upload extends \Zotlabs\Web\Controller {
|
||||
if($r['success']) {
|
||||
$sync = attach_export_data($channel,$r['data']['hash']);
|
||||
if($sync)
|
||||
build_sync_packet($channel['channel_id'],array('file' => array($sync)));
|
||||
Libsync::build_sync_packet($channel['channel_id'],array('file' => array($sync)));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,8 @@ class Filer extends \Zotlabs\Web\Controller {
|
||||
intval(local_channel())
|
||||
);
|
||||
if($r) {
|
||||
$x = q("update item set item_retained = 1 where id = %d and uid = %d",
|
||||
$x = q("update item set item_retained = 1, changed = '%s' where id = %d and uid = %d",
|
||||
dbesc(datetime_convert()),
|
||||
intval($r[0]['parent']),
|
||||
intval(local_channel())
|
||||
);
|
||||
|
||||
@@ -28,10 +28,14 @@ class Filerm extends \Zotlabs\Web\Controller {
|
||||
intval($item_id),
|
||||
dbesc($term)
|
||||
);
|
||||
|
||||
$x = q("update item set item_retained = 0, changed = '%s' where id = %d and uid = %d",
|
||||
dbesc(datetime_convert()),
|
||||
intval($item_id),
|
||||
intval(local_channel())
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
if(x($_SESSION,'return_url'))
|
||||
goaway(z_root() . '/' . $_SESSION['return_url']);
|
||||
|
||||
killme();
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace Zotlabs\Module;
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
use Zotlabs\Lib\Libsync;
|
||||
|
||||
class Filestorage extends \Zotlabs\Web\Controller {
|
||||
|
||||
@@ -35,12 +35,12 @@ class Filestorage extends \Zotlabs\Web\Controller {
|
||||
|
||||
$url = get_cloud_url($channel_id, $channel['channel_address'], $resource);
|
||||
|
||||
//get the object before permissions change so we can catch eventual former allowed members
|
||||
$object = get_file_activity_object($channel_id, $resource, $url);
|
||||
|
||||
attach_change_permissions($channel_id, $resource, $x['allow_cid'], $x['allow_gid'], $x['deny_cid'], $x['deny_gid'], $recurse, true);
|
||||
|
||||
file_activity($channel_id, $object, $x['allow_cid'], $x['allow_gid'], $x['deny_cid'], $x['deny_gid'], 'post', $notify);
|
||||
if($notify) {
|
||||
$observer = \App::get_observer();
|
||||
attach_store_item($channel, $observer, $resource);
|
||||
}
|
||||
|
||||
goaway(dirname($url));
|
||||
}
|
||||
@@ -131,7 +131,7 @@ class Filestorage extends \Zotlabs\Web\Controller {
|
||||
if(! $admin_delete) {
|
||||
$sync = attach_export_data($channel, $f['hash'], true);
|
||||
if($sync) {
|
||||
build_sync_packet($channel['channel_id'], array('file' => array($sync)));
|
||||
Libsync::build_sync_packet($channel['channel_id'], array('file' => array($sync)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,31 +1,88 @@
|
||||
<?php
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
use App;
|
||||
use Zotlabs\Web\Controller;
|
||||
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;
|
||||
|
||||
require_once('include/follow.php');
|
||||
|
||||
|
||||
class Follow extends \Zotlabs\Web\Controller {
|
||||
class Follow extends Controller {
|
||||
|
||||
function init() {
|
||||
|
||||
if(! local_channel()) {
|
||||
if (ActivityStreams::is_as_request() && argc() == 2) {
|
||||
|
||||
$abook_id = intval(argv(1));
|
||||
if(! $abook_id)
|
||||
return;
|
||||
|
||||
$r = q("select * from abook left join xchan on abook_xchan = xchan_hash where abook_id = %d",
|
||||
intval($abook_id)
|
||||
);
|
||||
if (! $r) {
|
||||
return;
|
||||
}
|
||||
|
||||
$chan = channelx_by_n($r[0]['abook_channel']);
|
||||
|
||||
if (! $chan) {
|
||||
http_status_exit(404, 'Not found');
|
||||
}
|
||||
|
||||
$actor = Activity::encode_person($chan,true,true);
|
||||
if (! $actor) {
|
||||
http_status_exit(404, 'Not found');
|
||||
}
|
||||
|
||||
$x = array_merge(['@context' => [
|
||||
ACTIVITYSTREAMS_JSONLD_REV,
|
||||
'https://w3id.org/security/v1',
|
||||
z_root() . ZOT_APSCHEMA_REV
|
||||
]],
|
||||
[
|
||||
'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();
|
||||
|
||||
}
|
||||
|
||||
if (! local_channel()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
$uid = local_channel();
|
||||
$url = notags(trim(punify($_REQUEST['url'])));
|
||||
$return_url = $_SESSION['return_url'];
|
||||
$confirm = intval($_REQUEST['confirm']);
|
||||
$interactive = (($_REQUEST['interactive']) ? intval($_REQUEST['interactive']) : 1);
|
||||
$channel = \App::get_channel();
|
||||
$channel = App::get_channel();
|
||||
|
||||
$result = new_contact($uid,$url,$channel,$interactive,$confirm);
|
||||
$result = Connect::connect($channel,$url);
|
||||
|
||||
if($result['success'] == false) {
|
||||
if($result['message'])
|
||||
if ($result['success'] == false) {
|
||||
if ($result['message']) {
|
||||
notice($result['message']);
|
||||
if($interactive) {
|
||||
}
|
||||
if ($interactive) {
|
||||
goaway($return_url);
|
||||
}
|
||||
else {
|
||||
@@ -36,8 +93,8 @@ class Follow extends \Zotlabs\Web\Controller {
|
||||
info( t('Connection added.') . EOL);
|
||||
|
||||
$clone = array();
|
||||
foreach($result['abook'] as $k => $v) {
|
||||
if(strpos($k,'abook_') === 0) {
|
||||
foreach ($result['abook'] as $k => $v) {
|
||||
if (strpos($k,'abook_') === 0) {
|
||||
$clone[$k] = $v;
|
||||
}
|
||||
}
|
||||
@@ -46,20 +103,21 @@ class Follow extends \Zotlabs\Web\Controller {
|
||||
unset($clone['abook_channel']);
|
||||
|
||||
$abconfig = load_abconfig($channel['channel_id'],$clone['abook_xchan']);
|
||||
if($abconfig)
|
||||
if ($abconfig) {
|
||||
$clone['abconfig'] = $abconfig;
|
||||
}
|
||||
Libsync::build_sync_packet(0, [ 'abook' => [ $clone ] ], true);
|
||||
|
||||
build_sync_packet(0 /* use the current local_channel */, array('abook' => array($clone)), true);
|
||||
|
||||
$can_view_stream = intval(get_abconfig($channel['channel_id'],$clone['abook_xchan'],'their_perms','view_stream'));
|
||||
$can_view_stream = their_perms_contains($channel['channel_id'],$clone['abook_xchan'],'view_stream');
|
||||
|
||||
// If we can view their stream, pull in some posts
|
||||
|
||||
if(($can_view_stream) || ($result['abook']['xchan_network'] === 'rss'))
|
||||
\Zotlabs\Daemon\Master::Summon(array('Onepoll',$result['abook']['abook_id']));
|
||||
if (($can_view_stream) || ($result['abook']['xchan_network'] === 'rss')) {
|
||||
Master::Summon([ 'Onepoll', $result['abook']['abook_id'] ]);
|
||||
}
|
||||
|
||||
if($interactive) {
|
||||
goaway(z_root() . '/connedit/' . $result['abook']['abook_id'] . '?f=&follow=1');
|
||||
if ($interactive) {
|
||||
goaway(z_root() . '/connedit/' . $result['abook']['abook_id'] . '?follow=1');
|
||||
}
|
||||
else {
|
||||
json_return_and_die([ 'success' => true ]);
|
||||
@@ -68,7 +126,7 @@ class Follow extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
|
||||
function get() {
|
||||
if(! local_channel()) {
|
||||
if (! local_channel()) {
|
||||
return login();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
use Zotlabs\Web\HTTPSig;
|
||||
use Zotlabs\Lib\Libzot;
|
||||
|
||||
/**
|
||||
* module: getfile
|
||||
@@ -54,11 +55,11 @@ class Getfile extends \Zotlabs\Web\Controller {
|
||||
|
||||
if($keyId) {
|
||||
$r = q("select * from hubloc left join xchan on hubloc_hash = xchan_hash
|
||||
where hubloc_addr = '%s' limit 1",
|
||||
where hubloc_addr = '%s'",
|
||||
dbesc(str_replace('acct:','',$keyId))
|
||||
);
|
||||
if($r) {
|
||||
$hubloc = $r[0];
|
||||
$hubloc = Libzot::zot_record_preferred($r);
|
||||
$verified = HTTPSig::verify('',$hubloc['xchan_pubkey']);
|
||||
if($verified && $verified['header_signed'] && $verified['header_valid'] && $hash == $hubloc['hubloc_hash']) {
|
||||
$header_verified = true;
|
||||
|
||||
@@ -4,6 +4,7 @@ namespace Zotlabs\Module;
|
||||
use App;
|
||||
use Zotlabs\Web\Controller;
|
||||
use Zotlabs\Lib\Apps;
|
||||
use Zotlabs\Lib\Libsync;
|
||||
|
||||
require_once('include/group.php');
|
||||
|
||||
@@ -80,7 +81,7 @@ class Group extends Controller {
|
||||
info( t('Privacy group updated.') . EOL );
|
||||
|
||||
|
||||
build_sync_packet(local_channel(),null,true);
|
||||
Libsync::build_sync_packet(local_channel(),null,true);
|
||||
}
|
||||
|
||||
goaway(z_root() . '/group/' . argv(1) . '/' . argv(2));
|
||||
|
||||
@@ -66,7 +66,10 @@ class Help extends \Zotlabs\Web\Controller {
|
||||
case IMAGETYPE_PNG:
|
||||
header("Content-Type: image/png");
|
||||
break;
|
||||
default:
|
||||
case IMAGETYPE_WEBP:
|
||||
header("Content-Type: image/webp");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
header("Content-Length: " . filesize($realpath));
|
||||
|
||||
@@ -38,9 +38,6 @@ class Hq extends \Zotlabs\Web\Controller {
|
||||
if(!local_channel())
|
||||
return;
|
||||
|
||||
if($load)
|
||||
$_SESSION['loadtime'] = datetime_convert();
|
||||
|
||||
if(argc() > 1 && argv(1) !== 'load') {
|
||||
$item_hash = argv(1);
|
||||
}
|
||||
@@ -87,15 +84,9 @@ class Hq extends \Zotlabs\Web\Controller {
|
||||
goaway(z_root() . '/moderate/' . $target_item['id']);
|
||||
}
|
||||
|
||||
$static = ((array_key_exists('static',$_REQUEST)) ? intval($_REQUEST['static']) : 0);
|
||||
|
||||
$simple_update = (($update) ? " AND item_unseen = 1 " : '');
|
||||
|
||||
$simple_update = '';
|
||||
if($update && $_SESSION['loadtime'])
|
||||
$simple_update = " AND (( item_unseen = 1 AND item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' ) OR item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' ) ";
|
||||
|
||||
if($static && $simple_update)
|
||||
$simple_update .= " and item_thread_top = 0 and author_xchan = '" . protect_sprintf(get_observer_hash()) . "' ";
|
||||
|
||||
$sys = get_sys_channel();
|
||||
$sql_extra = item_permissions_sql($sys['channel_id']);
|
||||
@@ -148,12 +139,10 @@ class Hq extends \Zotlabs\Web\Controller {
|
||||
|
||||
nav_set_selected('HQ');
|
||||
|
||||
$static = ((local_channel()) ? channel_manual_conv_update(local_channel()) : 1);
|
||||
|
||||
if($target_item) {
|
||||
// if the target item is not a post (eg a like) we want to address its thread parent
|
||||
$mid = ((($target_item['verb'] == ACTIVITY_LIKE) || ($target_item['verb'] == ACTIVITY_DISLIKE)) ? $target_item['thr_parent'] : $target_item['mid']);
|
||||
|
||||
//$mid = ((($target_item['verb'] == ACTIVITY_LIKE) || ($target_item['verb'] == ACTIVITY_DISLIKE)) ? $target_item['thr_parent'] : $target_item['mid']);
|
||||
$mid = $target_item['mid'];
|
||||
// if we got a decoded hash we must encode it again before handing to javascript
|
||||
if($decoded)
|
||||
$mid = 'b64.' . base64url_encode($mid);
|
||||
@@ -179,10 +168,10 @@ class Hq extends \Zotlabs\Web\Controller {
|
||||
'$conv' => '0',
|
||||
'$spam' => '0',
|
||||
'$fh' => '0',
|
||||
'$dm' => '0',
|
||||
'$nouveau' => '0',
|
||||
'$wall' => '0',
|
||||
'$static' => $static,
|
||||
'$page' => 1,
|
||||
'$page' => '1',
|
||||
'$list' => ((x($_REQUEST,'list')) ? intval($_REQUEST['list']) : 0),
|
||||
'$search' => '',
|
||||
'$xchan' => '',
|
||||
@@ -198,8 +187,6 @@ class Hq extends \Zotlabs\Web\Controller {
|
||||
]);
|
||||
}
|
||||
|
||||
$updateable = false;
|
||||
|
||||
if($load && $target_item) {
|
||||
$r = null;
|
||||
|
||||
@@ -212,10 +199,6 @@ class Hq extends \Zotlabs\Web\Controller {
|
||||
dbesc($target_item['parent_mid'])
|
||||
);
|
||||
|
||||
if($r) {
|
||||
$updateable = true;
|
||||
}
|
||||
|
||||
if(!$r) {
|
||||
$sys_item = true;
|
||||
|
||||
@@ -242,10 +225,6 @@ class Hq extends \Zotlabs\Web\Controller {
|
||||
dbesc($target_item['parent_mid'])
|
||||
);
|
||||
|
||||
if($r) {
|
||||
$updateable = true;
|
||||
}
|
||||
|
||||
if(!$r) {
|
||||
$sys_item = true;
|
||||
|
||||
@@ -258,8 +237,6 @@ class Hq extends \Zotlabs\Web\Controller {
|
||||
intval($sys['channel_id'])
|
||||
);
|
||||
}
|
||||
|
||||
$_SESSION['loadtime'] = datetime_convert();
|
||||
}
|
||||
else {
|
||||
$r = [];
|
||||
@@ -282,15 +259,10 @@ class Hq extends \Zotlabs\Web\Controller {
|
||||
|
||||
$o .= conversation($items, 'hq', $update, 'client');
|
||||
|
||||
if($updateable) {
|
||||
$x = q("UPDATE item SET item_unseen = 0 WHERE item_unseen = 1 AND uid = %d AND parent = %d ",
|
||||
intval(local_channel()),
|
||||
intval($r[0]['item_id'])
|
||||
);
|
||||
}
|
||||
|
||||
$o .= '<div id="content-complete"></div>';
|
||||
|
||||
$_SESSION['loadtime'] = datetime_convert();
|
||||
|
||||
return $o;
|
||||
|
||||
}
|
||||
|
||||
@@ -137,6 +137,11 @@ class Import extends \Zotlabs\Web\Controller {
|
||||
return;
|
||||
}
|
||||
|
||||
if(version_compare($data['compatibility']['version'], '4.7.3', '<=')) {
|
||||
// zot6 transition: cloning is not compatible with older versions
|
||||
notice('Data export format is not compatible with this software (not a zot6 channel)');
|
||||
return;
|
||||
}
|
||||
|
||||
if($moving)
|
||||
$seize = 1;
|
||||
@@ -212,50 +217,21 @@ class Import extends \Zotlabs\Web\Controller {
|
||||
// create new hubloc for the new channel at this site
|
||||
|
||||
if(array_key_exists('channel',$data)) {
|
||||
$r = hubloc_store_lowlevel(
|
||||
[
|
||||
'hubloc_guid' => $channel['channel_guid'],
|
||||
'hubloc_guid_sig' => $channel['channel_guid_sig'],
|
||||
'hubloc_hash' => $channel['channel_hash'],
|
||||
'hubloc_addr' => channel_reddress($channel),
|
||||
'hubloc_network' => 'zot',
|
||||
'hubloc_primary' => (($seize) ? 1 : 0),
|
||||
'hubloc_url' => z_root(),
|
||||
'hubloc_url_sig' => base64url_encode(rsa_sign(z_root(),$channel['channel_prvkey'])),
|
||||
'hubloc_host' => \App::get_hostname(),
|
||||
'hubloc_callback' => z_root() . '/post',
|
||||
'hubloc_sitekey' => get_config('system','pubkey'),
|
||||
'hubloc_updated' => datetime_convert()
|
||||
]
|
||||
);
|
||||
|
||||
// reset the original primary hubloc if it is being seized
|
||||
if($seize) {
|
||||
$r = q("update hubloc set hubloc_primary = 0 where hubloc_primary = 1 and hubloc_hash = '%s' and hubloc_url != '%s' ",
|
||||
dbesc($channel['channel_hash']),
|
||||
dbesc(z_root())
|
||||
);
|
||||
}
|
||||
|
||||
// create a new zot6 hubloc if we have got a channel_portable_id
|
||||
if($channel['channel_portable_id']) {
|
||||
$r = hubloc_store_lowlevel(
|
||||
[
|
||||
'hubloc_guid' => $channel['channel_guid'],
|
||||
'hubloc_guid_sig' => 'sha256.' . $channel['channel_guid_sig'],
|
||||
'hubloc_guid_sig' => $channel['channel_guid_sig'],
|
||||
'hubloc_hash' => $channel['channel_portable_id'],
|
||||
'hubloc_addr' => channel_reddress($channel),
|
||||
'hubloc_network' => 'zot6',
|
||||
'hubloc_network' => 'zot',
|
||||
'hubloc_primary' => (($seize) ? 1 : 0),
|
||||
'hubloc_url' => z_root(),
|
||||
'hubloc_url_sig' => 'sha256.' . base64url_encode(rsa_sign(z_root(),$channel['channel_prvkey'])),
|
||||
'hubloc_url_sig' => base64url_encode(rsa_sign(z_root(),$channel['channel_prvkey'])),
|
||||
'hubloc_host' => \App::get_hostname(),
|
||||
'hubloc_callback' => z_root() . '/zot',
|
||||
'hubloc_callback' => z_root() . '/post',
|
||||
'hubloc_sitekey' => get_config('system','pubkey'),
|
||||
'hubloc_updated' => datetime_convert(),
|
||||
'hubloc_id_url' => channel_url($channel),
|
||||
'hubloc_site_id' => Libzot::make_xchan_hash(z_root(),get_config('system','pubkey'))
|
||||
|
||||
'hubloc_updated' => datetime_convert()
|
||||
]
|
||||
);
|
||||
|
||||
@@ -266,7 +242,35 @@ class Import extends \Zotlabs\Web\Controller {
|
||||
dbesc(z_root())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// create a new zot6 hubloc if we have got a channel_portable_id
|
||||
|
||||
$r = hubloc_store_lowlevel(
|
||||
[
|
||||
'hubloc_guid' => $channel['channel_guid'],
|
||||
'hubloc_guid_sig' => $channel['channel_guid_sig'],
|
||||
'hubloc_hash' => $channel['channel_hash'],
|
||||
'hubloc_addr' => channel_reddress($channel),
|
||||
'hubloc_network' => 'zot6',
|
||||
'hubloc_primary' => (($seize) ? 1 : 0),
|
||||
'hubloc_url' => z_root(),
|
||||
'hubloc_url_sig' => 'sha256.' . base64url_encode(rsa_sign(z_root(),$channel['channel_prvkey'])),
|
||||
'hubloc_host' => \App::get_hostname(),
|
||||
'hubloc_callback' => z_root() . '/zot',
|
||||
'hubloc_sitekey' => get_config('system','pubkey'),
|
||||
'hubloc_updated' => datetime_convert(),
|
||||
'hubloc_id_url' => channel_url($channel),
|
||||
'hubloc_site_id' => Libzot::make_xchan_hash(z_root(),get_config('system','pubkey'))
|
||||
]
|
||||
);
|
||||
|
||||
// reset the original primary hubloc if it is being seized
|
||||
if($seize) {
|
||||
$r = q("update hubloc set hubloc_primary = 0 where hubloc_primary = 1 and hubloc_hash = '%s' and hubloc_url != '%s' ",
|
||||
dbesc($channel['channel_hash']),
|
||||
dbesc(z_root())
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -285,6 +289,28 @@ class Import extends \Zotlabs\Web\Controller {
|
||||
dbesc($channel['channel_portable_id'])
|
||||
);
|
||||
|
||||
if($channel['channel_portable_id']) {
|
||||
$r = xchan_store_lowlevel(
|
||||
[
|
||||
'xchan_hash' => $channel['channel_portable_id'],
|
||||
'xchan_guid' => $channel['channel_guid'],
|
||||
'xchan_guid_sig' => $channel['channel_guid_sig'],
|
||||
'xchan_pubkey' => $channel['channel_pubkey'],
|
||||
'xchan_photo_l' => z_root() . "/photo/profile/l/" . $channel['channel_id'],
|
||||
'xchan_photo_m' => z_root() . "/photo/profile/m/" . $channel['channel_id'],
|
||||
'xchan_photo_s' => z_root() . "/photo/profile/s/" . $channel['channel_id'],
|
||||
'xchan_addr' => channel_reddress($channel),
|
||||
'xchan_url' => z_root() . '/channel/' . $channel['channel_address'],
|
||||
'xchan_connurl' => z_root() . '/poco/' . $channel['channel_address'],
|
||||
'xchan_follow' => z_root() . '/follow?f=&url=%s',
|
||||
'xchan_name' => $channel['channel_name'],
|
||||
'xchan_network' => 'zot',
|
||||
'xchan_photo_date' => datetime_convert(),
|
||||
'xchan_name_date' => datetime_convert()
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
$r = xchan_store_lowlevel(
|
||||
[
|
||||
'xchan_hash' => $channel['channel_hash'],
|
||||
@@ -299,35 +325,12 @@ class Import extends \Zotlabs\Web\Controller {
|
||||
'xchan_connurl' => z_root() . '/poco/' . $channel['channel_address'],
|
||||
'xchan_follow' => z_root() . '/follow?f=&url=%s',
|
||||
'xchan_name' => $channel['channel_name'],
|
||||
'xchan_network' => 'zot',
|
||||
'xchan_network' => 'zot6',
|
||||
'xchan_photo_date' => datetime_convert(),
|
||||
'xchan_name_date' => datetime_convert()
|
||||
]
|
||||
);
|
||||
|
||||
if($channel['channel_portable_id']) {
|
||||
$r = xchan_store_lowlevel(
|
||||
[
|
||||
'xchan_hash' => \Zotlabs\Lib\Libzot::make_xchan_hash($channel['channel_guid'],$channel['channel_pubkey']),
|
||||
'xchan_guid' => $channel['channel_guid'],
|
||||
'xchan_guid_sig' => 'sha256.' . $channel['channel_guid_sig'],
|
||||
'xchan_pubkey' => $channel['channel_pubkey'],
|
||||
'xchan_photo_l' => z_root() . "/photo/profile/l/" . $channel['channel_id'],
|
||||
'xchan_photo_m' => z_root() . "/photo/profile/m/" . $channel['channel_id'],
|
||||
'xchan_photo_s' => z_root() . "/photo/profile/s/" . $channel['channel_id'],
|
||||
'xchan_addr' => channel_reddress($channel),
|
||||
'xchan_url' => z_root() . '/channel/' . $channel['channel_address'],
|
||||
'xchan_connurl' => z_root() . '/poco/' . $channel['channel_address'],
|
||||
'xchan_follow' => z_root() . '/follow?f=&url=%s',
|
||||
'xchan_name' => $channel['channel_name'],
|
||||
'xchan_network' => 'zot6',
|
||||
'xchan_photo_date' => datetime_convert(),
|
||||
'xchan_name_date' => datetime_convert()
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
logger('import step 6');
|
||||
@@ -346,7 +349,7 @@ class Import extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
|
||||
if($xchan['xchan_network'] === 'zot6') {
|
||||
$zhash = \Zotlabs\Lib\Libzot::make_xchan_hash($xchan['xchan_guid'],$xchan['xchan_pubkey']);
|
||||
$zhash = Libzot::make_xchan_hash($xchan['xchan_guid'],$xchan['xchan_pubkey']);
|
||||
if($zhash !== $xchan['xchan_hash']) {
|
||||
logger('forged xchan: ' . print_r($xchan,true));
|
||||
continue;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
use Zotlabs\Lib\Config;
|
||||
use Zotlabs\Lib\IConfig;
|
||||
use Zotlabs\Lib\Enotify;
|
||||
use Zotlabs\Web\Controller;
|
||||
@@ -11,12 +12,15 @@ use Zotlabs\Lib\ActivityStreams;
|
||||
use Zotlabs\Lib\LDSignatures;
|
||||
use Zotlabs\Web\HTTPSig;
|
||||
use Zotlabs\Lib\Libzot;
|
||||
use Zotlabs\Lib\Libsync;
|
||||
use Zotlabs\Lib\ThreadListener;
|
||||
use Zotlabs\Access\PermissionRoles;
|
||||
use App;
|
||||
|
||||
require_once('include/crypto.php');
|
||||
require_once('include/items.php');
|
||||
require_once('include/security.php');
|
||||
require_once('include/conversation.php');
|
||||
|
||||
|
||||
/**
|
||||
@@ -46,7 +50,7 @@ class Item extends Controller {
|
||||
|
||||
$item_id = argv(1);
|
||||
|
||||
if (! $item_id)
|
||||
if(! $item_id)
|
||||
http_status_exit(404, 'Not found');
|
||||
|
||||
$portable_id = EMPTY_STR;
|
||||
@@ -67,32 +71,24 @@ class Item extends Controller {
|
||||
|
||||
// process an authenticated fetch
|
||||
|
||||
$sigdata = HTTPSig::verify(EMPTY_STR);
|
||||
if($sigdata['portable_id'] && $sigdata['header_valid']) {
|
||||
$sigdata = HTTPSig::verify(($_SERVER['REQUEST_METHOD'] === 'POST') ? file_get_contents('php://input') : EMPTY_STR);
|
||||
if ($sigdata['portable_id'] && $sigdata['header_valid']) {
|
||||
$portable_id = $sigdata['portable_id'];
|
||||
if (! check_channelallowed($portable_id)) {
|
||||
http_status_exit(403, 'Permission denied');
|
||||
}
|
||||
if (! check_siteallowed($sigdata['signer'])) {
|
||||
http_status_exit(403, 'Permission denied');
|
||||
}
|
||||
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'])
|
||||
$i = q("select id as item_id from item where mid = '%s' $item_normal and owner_xchan = '%s' limit 1",
|
||||
dbesc($r[0]['parent_mid']),
|
||||
dbesc($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
|
||||
@@ -112,7 +108,7 @@ class Item extends Controller {
|
||||
|
||||
$parents_str = ids_to_querystr($i,'item_id');
|
||||
|
||||
$items = q("SELECT item.*, item.id AS item_id FROM item WHERE item.parent IN ( %s ) $item_normal ",
|
||||
$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)
|
||||
);
|
||||
|
||||
@@ -123,43 +119,10 @@ class Item extends Controller {
|
||||
xchan_query($items,true);
|
||||
$items = fetch_post_tags($items,true);
|
||||
|
||||
$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)
|
||||
if(! $items)
|
||||
http_status_exit(404, 'Not found');
|
||||
|
||||
$chan = channelx_by_n($nitems[0]['uid']);
|
||||
$chan = channelx_by_n($items[0]['uid']);
|
||||
|
||||
if(! $chan)
|
||||
http_status_exit(404, 'Not found');
|
||||
@@ -167,7 +130,8 @@ class Item extends Controller {
|
||||
if(! perm_is_allowed($chan['channel_id'],get_observer_hash(),'view_stream'))
|
||||
http_status_exit(403, 'Forbidden');
|
||||
|
||||
$i = Activity::encode_item_collection($nitems,'conversation/' . $item_id,'OrderedCollection');
|
||||
|
||||
$i = Activity::encode_item_collection($items, 'conversation/' . $item_id, 'OrderedCollection');
|
||||
if($portable_id) {
|
||||
ThreadListener::store(z_root() . '/item/' . $item_id,$portable_id);
|
||||
}
|
||||
@@ -194,9 +158,110 @@ class Item extends Controller {
|
||||
|
||||
}
|
||||
|
||||
if(ActivityStreams::is_as_request()) {
|
||||
|
||||
$item_id = argv(1);
|
||||
if(! $item_id)
|
||||
http_status_exit(404, 'Not found');
|
||||
|
||||
$portable_id = EMPTY_STR;
|
||||
|
||||
$item_normal = " and item.item_hidden = 0 and item.item_type = 0 and item.item_unpublished = 0 and item.item_delayed = 0 and item.item_blocked = 0 ";
|
||||
|
||||
$i = null;
|
||||
|
||||
// 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),
|
||||
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'];
|
||||
if (! check_channelallowed($portable_id)) {
|
||||
http_status_exit(403, 'Permission denied');
|
||||
}
|
||||
if (! check_siteallowed($sigdata['signer'])) {
|
||||
http_status_exit(403, 'Permission denied');
|
||||
}
|
||||
observer_auth($portable_id);
|
||||
|
||||
$i = q("select id as item_id from item where mid = '%s' $item_normal and owner_xchan = '%s' limit 1 ",
|
||||
dbesc($r[0]['parent_mid']),
|
||||
dbesc($portable_id)
|
||||
);
|
||||
}
|
||||
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');
|
||||
}
|
||||
|
||||
// If we get to this point we have determined we can access the original in $r (fetched much further above), so use it.
|
||||
|
||||
xchan_query($r,true);
|
||||
$items = fetch_post_tags($r,false);
|
||||
|
||||
$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($items[0],true);
|
||||
|
||||
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/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();
|
||||
|
||||
}
|
||||
|
||||
|
||||
if(argc() > 1 && argv(1) !== 'drop') {
|
||||
$x = q("select uid, item_wall, llink, mid from item where mid = '%s' ",
|
||||
dbesc(z_root() . '/item/' . argv(1))
|
||||
$x = q("select uid, item_wall, llink, mid from item where mid = '%s' or mid = '%s' ",
|
||||
dbesc(z_root() . '/item/' . argv(1)),
|
||||
dbesc(z_root() . '/activity/' . argv(1))
|
||||
);
|
||||
if($x) {
|
||||
foreach($x as $xv) {
|
||||
@@ -236,6 +301,7 @@ class Item extends Controller {
|
||||
|
||||
$parent = ((x($_REQUEST,'parent')) ? intval($_REQUEST['parent']) : 0);
|
||||
$parent_mid = ((x($_REQUEST,'parent_mid')) ? trim($_REQUEST['parent_mid']) : '');
|
||||
$mode = (($_REQUEST['conv_mode'] === 'channel') ? 'channel' : 'network');
|
||||
|
||||
$remote_xchan = ((x($_REQUEST,'remote_xchan')) ? trim($_REQUEST['remote_xchan']) : false);
|
||||
$r = q("select * from xchan where xchan_hash = '%s' limit 1",
|
||||
@@ -273,7 +339,9 @@ class Item extends Controller {
|
||||
|
||||
$consensus = intval($_REQUEST['consensus']);
|
||||
$nocomment = intval($_REQUEST['nocomment']);
|
||||
|
||||
|
||||
$is_poll = ((trim($_REQUEST['poll_answers'][0]) != '' && trim($_REQUEST['poll_answers'][1]) != '') ? true : false);
|
||||
|
||||
// 'origin' (if non-zero) indicates that this network is where the message originated,
|
||||
// for the purpose of relaying comments to other conversation members.
|
||||
// If using the API from a device (leaf node) you must set origin to 1 (default) or leave unset.
|
||||
@@ -711,6 +779,27 @@ class Item extends Controller {
|
||||
$str_group_allow = $gacl['allow_gid'];
|
||||
$str_contact_deny = $gacl['deny_cid'];
|
||||
$str_group_deny = $gacl['deny_gid'];
|
||||
|
||||
|
||||
$groupww = false;
|
||||
|
||||
// if this is a wall-to-wall post to a group, turn it into a direct message
|
||||
|
||||
$role = get_pconfig($profile_uid,'system','permissions_role');
|
||||
|
||||
$rolesettings = PermissionRoles::role_perms($role);
|
||||
|
||||
$channel_type = isset($rolesettings['channel_type']) ? $rolesettings['channel_type'] : 'normal';
|
||||
|
||||
$is_group = (($channel_type === 'group') ? true : false);
|
||||
|
||||
if (($is_group) && ($walltowall) && (! $walltowall_comment)) {
|
||||
$groupww = true;
|
||||
$str_contact_allow = $owner_xchan['xchan_hash'];
|
||||
$str_group_allow = '';
|
||||
}
|
||||
|
||||
$post_tags = [];
|
||||
|
||||
if($mimetype === 'text/bbcode') {
|
||||
|
||||
@@ -720,19 +809,18 @@ class Item extends Controller {
|
||||
// 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
|
||||
|
||||
|
||||
if(strpos($body,'[/summary]') !== false) {
|
||||
$match = '';
|
||||
$cnt = preg_match("/\[summary\](.*?)\[\/summary\]/ism",$body,$match);
|
||||
if($cnt) {
|
||||
$summary .= $match[1];
|
||||
}
|
||||
$body_content = preg_replace("/^(.*?)\[summary\](.*?)\[\/summary\](.*?)$/ism", '',$body);
|
||||
$body = trim($body_content);
|
||||
}
|
||||
|
||||
$summary = cleanup_bbcode($summary);
|
||||
$match = '';
|
||||
$cnt = preg_match("/\[summary\](.*?)\[\/summary\]/ism",$body,$match);
|
||||
if($cnt) {
|
||||
$summary .= $match[1];
|
||||
}
|
||||
$body_content = preg_replace("/\[summary\](.*?)\[\/summary\]/ism", '',$body);
|
||||
$body = trim($body_content);
|
||||
}
|
||||
|
||||
$summary = cleanup_bbcode($summary);
|
||||
|
||||
$body = cleanup_bbcode($body);
|
||||
|
||||
@@ -746,7 +834,6 @@ class Item extends Controller {
|
||||
// Set permissions based on tag replacements
|
||||
set_linkified_perms($results, $str_contact_allow, $str_group_allow, $profile_uid, $parent_item, $private);
|
||||
|
||||
$post_tags = array();
|
||||
foreach($results as $result) {
|
||||
$success = $result['success'];
|
||||
if($success['replaced']) {
|
||||
@@ -759,6 +846,7 @@ class Item extends Controller {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(($str_contact_allow) && (! $str_group_allow)) {
|
||||
@@ -817,11 +905,6 @@ class Item extends Controller {
|
||||
'revision' => $r['data']['revision']
|
||||
);
|
||||
}
|
||||
$ext = substr($r['data']['filename'],strrpos($r['data']['filename'],'.'));
|
||||
if(strpos($r['data']['filetype'],'audio/') !== false)
|
||||
$attach_link = '[audio]' . z_root() . '/attach/' . $r['data']['hash'] . '/' . $r['data']['revision'] . (($ext) ? $ext : '') . '[/audio]';
|
||||
elseif(strpos($r['data']['filetype'],'video/') !== false)
|
||||
$attach_link = '[video]' . z_root() . '/attach/' . $r['data']['hash'] . '/' . $r['data']['revision'] . (($ext) ? $ext : '') . '[/video]';
|
||||
$body = str_replace($match[1][$i],$attach_link,$body);
|
||||
$i++;
|
||||
}
|
||||
@@ -835,8 +918,6 @@ class Item extends Controller {
|
||||
$i = 0;
|
||||
foreach($match[2] as $mtch) {
|
||||
$reshare = new \Zotlabs\Lib\Share($mtch);
|
||||
$datarray['obj'] = $reshare->obj();
|
||||
$datarray['obj_type'] = $datarray['obj']['type'];
|
||||
$body = str_replace($match[1][$i],$reshare->bbcode(),$body);
|
||||
$i++;
|
||||
}
|
||||
@@ -929,6 +1010,27 @@ class Item extends Controller {
|
||||
}
|
||||
|
||||
|
||||
if($is_poll) {
|
||||
$poll = [
|
||||
'question' => $body,
|
||||
'answers' => $_REQUEST['poll_answers'],
|
||||
'multiple_answers' => $_REQUEST['poll_multiple_answers'],
|
||||
'expire_value' => $_REQUEST['poll_expire_value'],
|
||||
'expire_unit' => $_REQUEST['poll_expire_unit']
|
||||
];
|
||||
$obj = $this->extract_poll_data($poll, [ 'item_private' => $private, 'allow_cid' => $str_contact_allow, 'allow_gid' => $str_contact_deny ]);
|
||||
}
|
||||
else {
|
||||
$obj = $this->extract_bb_poll_data($body,[ 'item_private' => $private, 'allow_cid' => $str_contact_allow, 'allow_gid' => $str_contact_deny ]);
|
||||
}
|
||||
|
||||
if ($obj) {
|
||||
$obj['url'] = $mid;
|
||||
$obj['attributedTo'] = channel_url($channel);
|
||||
$datarray['obj'] = $obj;
|
||||
$obj_type = 'Question';
|
||||
}
|
||||
|
||||
if(! $parent_mid) {
|
||||
$parent_mid = $mid;
|
||||
}
|
||||
@@ -974,10 +1076,15 @@ class Item extends Controller {
|
||||
}
|
||||
|
||||
if ((! $plink) && ($item_thread_top)) {
|
||||
$plink = z_root() . '/channel/' . $channel['channel_address'] . '/?f=&mid=' . gen_link_id($mid);
|
||||
$plink = substr($plink,0,190);
|
||||
// $plink = z_root() . '/channel/' . $channel['channel_address'] . '/?f=&mid=' . gen_link_id($mid);
|
||||
// $plink = substr($plink,0,190);
|
||||
$plink = $mid;
|
||||
}
|
||||
|
||||
|
||||
if ($datarray['obj']) {
|
||||
$datarray['obj']['id'] = $mid;
|
||||
}
|
||||
|
||||
$datarray['aid'] = $channel['channel_account_id'];
|
||||
$datarray['uid'] = $profile_uid;
|
||||
$datarray['uuid'] = $uuid;
|
||||
@@ -1035,10 +1142,9 @@ class Item extends Controller {
|
||||
$datarray['layout_mid'] = $layout_mid;
|
||||
$datarray['public_policy'] = $public_policy;
|
||||
$datarray['comment_policy'] = map_scope($comment_policy);
|
||||
$datarray['term'] = $post_tags;
|
||||
$datarray['term'] = array_unique($post_tags, SORT_REGULAR);
|
||||
$datarray['plink'] = $plink;
|
||||
$datarray['route'] = $route;
|
||||
|
||||
|
||||
// A specific ACL over-rides public_policy completely
|
||||
|
||||
@@ -1136,7 +1242,7 @@ class Item extends Controller {
|
||||
if($r) {
|
||||
xchan_query($r);
|
||||
$sync_item = fetch_post_tags($r);
|
||||
build_sync_packet($profile_uid,array('item' => array(encode_item($sync_item[0],true))));
|
||||
Libsync::build_sync_packet($profile_uid,array('item' => array(encode_item($sync_item[0],true))));
|
||||
}
|
||||
}
|
||||
if(! $nopush)
|
||||
@@ -1232,20 +1338,14 @@ class Item extends Controller {
|
||||
killme();
|
||||
}
|
||||
|
||||
if(($parent) && ($parent != $post_id)) {
|
||||
// Store the comment signature information in case we need to relay to Diaspora
|
||||
//$ditem = $datarray;
|
||||
//$ditem['author'] = $observer;
|
||||
//store_diaspora_comment_sig($ditem,$channel,$parent_item, $post_id, (($walltowall_comment) ? 1 : 0));
|
||||
}
|
||||
else {
|
||||
if(($parent == $post_id) || ($datarray['item_private'] == 1)) {
|
||||
$r = q("select * from item where id = %d",
|
||||
intval($post_id)
|
||||
);
|
||||
if($r) {
|
||||
xchan_query($r);
|
||||
$sync_item = fetch_post_tags($r);
|
||||
build_sync_packet($profile_uid,array('item' => array(encode_item($sync_item[0],true))));
|
||||
Libsync::build_sync_packet($profile_uid,array('item' => array(encode_item($sync_item[0],true))));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1253,7 +1353,11 @@ class Item extends Controller {
|
||||
$datarray['llink'] = z_root() . '/display/' . gen_link_id($datarray['mid']);
|
||||
|
||||
call_hooks('post_local_end', $datarray);
|
||||
|
||||
|
||||
if ($groupww) {
|
||||
$nopush = false;
|
||||
}
|
||||
|
||||
if(! $nopush)
|
||||
Master::Summon([ 'Notifier', $notify_type, $post_id ]);
|
||||
|
||||
@@ -1271,8 +1375,21 @@ class Item extends Controller {
|
||||
if($return_path) {
|
||||
goaway(z_root() . "/" . $return_path);
|
||||
}
|
||||
|
||||
$json = array('success' => 1);
|
||||
|
||||
if($mode === 'channel')
|
||||
profile_load($channel['channel_address']);
|
||||
|
||||
$item[] = $datarray;
|
||||
$item[0]['owner'] = $owner_xchan;
|
||||
$item[0]['author'] = $observer;
|
||||
$item[0]['attach'] = json_encode($datarray['attach']);
|
||||
|
||||
$json = [
|
||||
'success' => 1,
|
||||
'id' => $post_id,
|
||||
'html' => conversation($item,$mode,true,'r_preview'),
|
||||
];
|
||||
|
||||
if(x($_REQUEST,'jsreload') && strlen($_REQUEST['jsreload']))
|
||||
$json['reload'] = z_root() . '/' . $_REQUEST['jsreload'];
|
||||
|
||||
@@ -1347,7 +1464,7 @@ class Item extends Controller {
|
||||
if($r) {
|
||||
xchan_query($r);
|
||||
$sync_item = fetch_post_tags($r);
|
||||
build_sync_packet($i[0]['uid'],array('item' => array(encode_item($sync_item[0],true))));
|
||||
Libsync::build_sync_packet($i[0]['uid'],array('item' => array(encode_item($sync_item[0],true))));
|
||||
}
|
||||
|
||||
if($complex) {
|
||||
@@ -1400,5 +1517,104 @@ class Item extends Controller {
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
function extract_bb_poll_data(&$body,$item) {
|
||||
|
||||
$multiple = false;
|
||||
|
||||
if (strpos($body,'[/question]') === false && strpos($body,'[/answer]') === false) {
|
||||
return false;
|
||||
}
|
||||
if (strpos($body,'[nobb]') !== false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
$obj = [];
|
||||
$ptr = [];
|
||||
$matches = null;
|
||||
$obj['type'] = 'Question';
|
||||
|
||||
if (preg_match_all('/\[answer\](.*?)\[\/answer\]/ism',$body,$matches,PREG_SET_ORDER)) {
|
||||
foreach ($matches as $match) {
|
||||
$ptr[] = [ 'name' => $match[1], 'type' => 'Note', 'replies' => [ 'type' => 'Collection', 'totalItems' => 0 ]];
|
||||
$body = str_replace('[answer]' . $match[1] . '[/answer]', EMPTY_STR, $body);
|
||||
}
|
||||
}
|
||||
|
||||
$matches = null;
|
||||
|
||||
if (preg_match('/\[question\](.*?)\[\/question\]/ism',$body,$matches)) {
|
||||
$obj['content'] = bbcode($matches[1]);
|
||||
$body = str_replace('[question]' . $matches[1] . '[/question]', $matches[1], $body);
|
||||
$obj['oneOf'] = $ptr;
|
||||
}
|
||||
|
||||
$matches = null;
|
||||
|
||||
if (preg_match('/\[question=multiple\](.*?)\[\/question\]/ism',$body,$matches)) {
|
||||
$obj['content'] = bbcode($matches[1]);
|
||||
$body = str_replace('[question=multiple]' . $matches[1] . '[/question]', $matches[1], $body);
|
||||
$obj['anyOf'] = $ptr;
|
||||
}
|
||||
|
||||
$matches = null;
|
||||
|
||||
if (preg_match('/\[ends\](.*?)\[\/ends\]/ism',$body,$matches)) {
|
||||
$obj['endTime'] = datetime_convert(date_default_timezone_get(),'UTC', $matches[1],ATOM_TIME);
|
||||
$body = str_replace('[ends]' . $matches[1] . '[/ends]', EMPTY_STR, $body);
|
||||
}
|
||||
|
||||
|
||||
if ($item['item_private']) {
|
||||
$obj['to'] = Activity::map_acl($item);
|
||||
}
|
||||
else {
|
||||
$obj['to'] = [ ACTIVITY_PUBLIC_INBOX ];
|
||||
}
|
||||
|
||||
return $obj;
|
||||
|
||||
}
|
||||
|
||||
|
||||
function extract_poll_data($poll, $item) {
|
||||
|
||||
$multiple = intval($poll['multiple_answers']);
|
||||
$expire_value = intval($poll['expire_value']);
|
||||
$expire_unit = $poll['expire_unit'];
|
||||
$question = $poll['question'];
|
||||
$answers = $poll['answers'];
|
||||
|
||||
$obj = [];
|
||||
$ptr = [];
|
||||
$obj['type'] = 'Question';
|
||||
$obj['content'] = bbcode($question);
|
||||
|
||||
foreach($answers as $answer) {
|
||||
if(trim($answer))
|
||||
$ptr[] = [ 'name' => escape_tags($answer), 'type' => 'Note', 'replies' => [ 'type' => 'Collection', 'totalItems' => 0 ]];
|
||||
}
|
||||
|
||||
if($multiple) {
|
||||
$obj['anyOf'] = $ptr;
|
||||
}
|
||||
else {
|
||||
$obj['oneOf'] = $ptr;
|
||||
}
|
||||
|
||||
$obj['endTime'] = datetime_convert(date_default_timezone_get(), 'UTC', 'now + ' . $expire_value . ' ' . $expire_unit, ATOM_TIME);
|
||||
|
||||
if ($item['item_private']) {
|
||||
$obj['to'] = Activity::map_acl($item);
|
||||
}
|
||||
else {
|
||||
$obj['to'] = [ ACTIVITY_PUBLIC_INBOX ];
|
||||
}
|
||||
|
||||
return $obj;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -2,17 +2,15 @@
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
use Zotlabs\Lib\Activity;
|
||||
use Zotlabs\Lib\Libsync;
|
||||
|
||||
require_once('include/security.php');
|
||||
require_once('include/bbcode.php');
|
||||
require_once('include/items.php');
|
||||
|
||||
|
||||
require_once('include/conversation.php');
|
||||
|
||||
class Like extends \Zotlabs\Web\Controller {
|
||||
|
||||
|
||||
|
||||
private function reaction_to_activity($reaction) {
|
||||
|
||||
$acts = [
|
||||
@@ -41,7 +39,46 @@ class Like extends \Zotlabs\Web\Controller {
|
||||
|
||||
}
|
||||
|
||||
private function like_response($arr) {
|
||||
|
||||
if($arr['conv_mode'] === 'channel') {
|
||||
$parts = explode('@', $arr['owner_xchan']['xchan_addr']);
|
||||
profile_load($parts[0]);
|
||||
}
|
||||
|
||||
|
||||
$item_normal = item_normal();
|
||||
|
||||
$activities = q("SELECT item.*, item.id AS item_id FROM item
|
||||
WHERE uid = %d $item_normal
|
||||
AND thr_parent = '%s'
|
||||
AND verb IN ('%s', '%s', '%s', '%s', '%s')",
|
||||
intval($arr['item']['uid']),
|
||||
dbesc($arr['item']['mid']),
|
||||
dbesc(ACTIVITY_LIKE),
|
||||
dbesc(ACTIVITY_DISLIKE),
|
||||
dbesc(ACTIVITY_ATTEND),
|
||||
dbesc(ACTIVITY_ATTENDNO),
|
||||
dbesc(ACTIVITY_ATTENDMAYBE)
|
||||
);
|
||||
|
||||
xchan_query($activities,true);
|
||||
|
||||
$convitems[] = $arr['item'];
|
||||
$convitems = array_merge($convitems, $activities);
|
||||
|
||||
$convitems = fetch_post_tags($convitems,true);
|
||||
|
||||
$ret = [
|
||||
'success' => 1,
|
||||
'orig_id' => $arr['orig_item_id'], //this is required for pubstream items where $item_id != $item['id']
|
||||
'id' => $arr['item']['id'],
|
||||
'html' => conversation($convitems, $arr['conv_mode'], true, 'r_preview'),
|
||||
];
|
||||
|
||||
return $ret;
|
||||
|
||||
}
|
||||
|
||||
public function get() {
|
||||
|
||||
@@ -65,7 +102,8 @@ class Like extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
|
||||
$verb = notags(trim($_GET['verb']));
|
||||
|
||||
$mode = (($_GET['conv_mode'] === 'channel') ? 'channel' : 'network');
|
||||
|
||||
if(! $verb)
|
||||
$verb = 'like';
|
||||
|
||||
@@ -75,7 +113,12 @@ class Like extends \Zotlabs\Web\Controller {
|
||||
return EMPTY_STR;
|
||||
}
|
||||
|
||||
|
||||
$is_rsvp = false;
|
||||
if (in_array($activity, [ ACTIVITY_ATTEND, ACTIVITY_ATTENDNO, ACTIVITY_ATTENDMAYBE ])) {
|
||||
$is_rsvp = true;
|
||||
}
|
||||
|
||||
|
||||
$extended_like = false;
|
||||
$object = $target = null;
|
||||
$post_type = EMPTY_STR;
|
||||
@@ -204,20 +247,8 @@ class Like extends \Zotlabs\Web\Controller {
|
||||
if(! $plink)
|
||||
$plink = '[zrl=' . z_root() . '/profile/' . $ch[0]['channel_address'] . ']' . $post_type . '[/zrl]';
|
||||
|
||||
$links = array();
|
||||
$links[] = array('rel' => 'alternate', 'type' => 'text/html',
|
||||
'href' => z_root() . '/profile/' . $ch[0]['channel_address']);
|
||||
$links[] = array('rel' => 'photo', 'type' => $ch[0]['xchan_photo_mimetype'],
|
||||
'href' => $ch[0]['xchan_photo_l']);
|
||||
|
||||
$object = json_encode(array(
|
||||
'type' => ACTIVITY_OBJ_PROFILE,
|
||||
'title' => $ch[0]['channel_name'],
|
||||
'id' => $ch[0]['xchan_url'] . '/' . $ch[0]['xchan_hash'],
|
||||
'link' => $links
|
||||
));
|
||||
|
||||
|
||||
$object = json_encode(Activity::fetch_profile([ 'id' => channel_url($ch[0]) ]));
|
||||
|
||||
// second like of the same thing is "undo" for the first like
|
||||
|
||||
$z = q("select * from likes where channel_id = %d and liker = '%s' and verb = '%s' and target_type = '%s' and target_id = '%s' limit 1",
|
||||
@@ -230,7 +261,7 @@ class Like extends \Zotlabs\Web\Controller {
|
||||
|
||||
if($z) {
|
||||
$z[0]['deleted'] = 1;
|
||||
build_sync_packet($ch[0]['channel_id'],array('likes' => $z));
|
||||
Libsync::build_sync_packet($ch[0]['channel_id'],array('likes' => $z));
|
||||
|
||||
q("delete from likes where id = %d",
|
||||
intval($z[0]['id'])
|
||||
@@ -310,7 +341,7 @@ class Like extends \Zotlabs\Web\Controller {
|
||||
$thread_owner = $r[0];
|
||||
else
|
||||
killme();
|
||||
|
||||
|
||||
$r = q("select * from xchan where xchan_hash = '%s' limit 1",
|
||||
dbesc($item['author_xchan'])
|
||||
);
|
||||
@@ -318,8 +349,7 @@ class Like extends \Zotlabs\Web\Controller {
|
||||
$item_author = $r[0];
|
||||
else
|
||||
killme();
|
||||
|
||||
|
||||
|
||||
$verbs = " '".dbesc($activity)."' ";
|
||||
|
||||
$multi_undo = false;
|
||||
@@ -363,16 +393,27 @@ class Like extends \Zotlabs\Web\Controller {
|
||||
|
||||
// drop_item was not done interactively, so we need to invoke the notifier
|
||||
// in order to push the changes to connections
|
||||
|
||||
|
||||
\Zotlabs\Daemon\Master::Summon(array('Notifier','drop',$rr['id']));
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
if($interactive)
|
||||
return;
|
||||
|
||||
if(! $multi_undo)
|
||||
killme();
|
||||
if(! $multi_undo) {
|
||||
$ret = self::like_response([
|
||||
'item' => $item,
|
||||
'orig_item_id' => $item_id,
|
||||
'owner_xchan' => $thread_owner,
|
||||
'conv_mode' => $mode
|
||||
]);
|
||||
json_return_and_die($ret);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -381,7 +422,7 @@ class Like extends \Zotlabs\Web\Controller {
|
||||
$arr = array();
|
||||
|
||||
$arr['uuid'] = $uuid;
|
||||
$arr['mid'] = z_root() . '/item/' . $uuid;
|
||||
$arr['mid'] = z_root() . (($is_rsvp) ? '/activity/' : '/item/') . $uuid;
|
||||
|
||||
if($extended_like) {
|
||||
$arr['item_thread_top'] = 1;
|
||||
@@ -402,27 +443,8 @@ class Like extends \Zotlabs\Web\Controller {
|
||||
|
||||
$body = $item['body'];
|
||||
|
||||
$object = json_encode(array(
|
||||
'type' => $objtype,
|
||||
'id' => $item['mid'],
|
||||
'asld' => Activity::fetch_item( [ 'id' => $item['mid'] ] ),
|
||||
'parent' => (($item['thr_parent']) ? $item['thr_parent'] : $item['parent_mid']),
|
||||
'link' => $links,
|
||||
'title' => $item['title'],
|
||||
'content' => $item['body'],
|
||||
'created' => $item['created'],
|
||||
'edited' => $item['edited'],
|
||||
'author' => array(
|
||||
'name' => $item_author['xchan_name'],
|
||||
'address' => $item_author['xchan_addr'],
|
||||
'guid' => $item_author['xchan_guid'],
|
||||
'guid_sig' => $item_author['xchan_guid_sig'],
|
||||
'link' => array(
|
||||
array('rel' => 'alternate', 'type' => 'text/html', 'href' => $item_author['xchan_url']),
|
||||
array('rel' => 'photo', 'type' => $item_author['xchan_photo_mimetype'], 'href' => $item_author['xchan_photo_m'])),
|
||||
),
|
||||
));
|
||||
|
||||
$object = json_encode(Activity::fetch_item( [ 'id' => $item['mid'] ]));
|
||||
|
||||
if(! intval($item['item_thread_top']))
|
||||
$post_type = 'comment';
|
||||
|
||||
@@ -466,15 +488,15 @@ class Like extends \Zotlabs\Web\Controller {
|
||||
|
||||
|
||||
if($extended_like) {
|
||||
$ulink = '[zrl=' . $ch[0]['xchan_url'] . ']' . $ch[0]['xchan_name'] . '[/zrl]';
|
||||
$alink = '[zrl=' . $observer['xchan_url'] . ']' . $observer['xchan_name'] . '[/zrl]';
|
||||
$ulink = '[zrl=' . $ch[0]['xchan_url'] . '][bdi]' . $ch[0]['xchan_name'] . '[/bdi][/zrl]';
|
||||
$alink = '[zrl=' . $observer['xchan_url'] . '][bdi]' . $observer['xchan_name'] . '[/bdi][/zrl]';
|
||||
$private = (($public) ? 0 : 1);
|
||||
}
|
||||
else {
|
||||
$arr['parent'] = $item['id'];
|
||||
$arr['thr_parent'] = $item['mid'];
|
||||
$ulink = '[zrl=' . $item_author['xchan_url'] . ']' . $item_author['xchan_name'] . '[/zrl]';
|
||||
$alink = '[zrl=' . $observer['xchan_url'] . ']' . $observer['xchan_name'] . '[/zrl]';
|
||||
$ulink = '[zrl=' . $item_author['xchan_url'] . '][bdi]' . $item_author['xchan_name'] . '[/bdi][/zrl]';
|
||||
$alink = '[zrl=' . $observer['xchan_url'] . '][bdi]' . $observer['xchan_name'] . '[/bdi][/zrl]';
|
||||
$plink = '[zrl=' . z_root() . '/display/' . gen_link_id($item['mid']) . ']' . $post_type . '[/zrl]';
|
||||
$allow_cid = $item['allow_cid'];
|
||||
$allow_gid = $item['allow_gid'];
|
||||
@@ -526,7 +548,6 @@ class Like extends \Zotlabs\Web\Controller {
|
||||
|
||||
call_hooks('post_local',$arr);
|
||||
|
||||
|
||||
$post = item_store($arr);
|
||||
$post_id = $post['item_id'];
|
||||
|
||||
@@ -561,11 +582,10 @@ class Like extends \Zotlabs\Web\Controller {
|
||||
dbesc($obj_id)
|
||||
);
|
||||
if($r)
|
||||
build_sync_packet($ch[0]['channel_id'],array('likes' => $r));
|
||||
Libsync::build_sync_packet($ch[0]['channel_id'],array('likes' => $r));
|
||||
|
||||
}
|
||||
|
||||
|
||||
\Zotlabs\Daemon\Master::Summon(array('Notifier','like',$post_id));
|
||||
|
||||
if($interactive) {
|
||||
@@ -573,10 +593,15 @@ class Like extends \Zotlabs\Web\Controller {
|
||||
$o .= t('Thank you.');
|
||||
return $o;
|
||||
}
|
||||
|
||||
killme();
|
||||
|
||||
$ret = self::like_response([
|
||||
'item' => $item,
|
||||
'orig_item_id' => $item_id,
|
||||
'owner_xchan' => $thread_owner,
|
||||
'conv_mode' => $mode
|
||||
]);
|
||||
json_return_and_die($ret);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,59 +1,72 @@
|
||||
<?php
|
||||
namespace Zotlabs\Module; /** @file */
|
||||
|
||||
use App;
|
||||
use Zotlabs\Web\Controller;
|
||||
use Zotlabs\Daemon\Master;
|
||||
|
||||
|
||||
class Locs extends \Zotlabs\Web\Controller {
|
||||
class Locs extends Controller {
|
||||
|
||||
function post() {
|
||||
|
||||
|
||||
if(! local_channel())
|
||||
return;
|
||||
|
||||
$channel = \App::get_channel();
|
||||
|
||||
|
||||
$channel = App::get_channel();
|
||||
|
||||
if($_REQUEST['primary']) {
|
||||
$hubloc_id = intval($_REQUEST['primary']);
|
||||
if($hubloc_id) {
|
||||
|
||||
$r = q("select hubloc_id from hubloc where hubloc_id = %d and hubloc_hash = '%s' limit 1",
|
||||
|
||||
$r = q("select * from hubloc where hubloc_id = %d and hubloc_hash = '%s' limit 1",
|
||||
intval($hubloc_id),
|
||||
dbesc($channel['channel_hash'])
|
||||
);
|
||||
|
||||
|
||||
if(! $r) {
|
||||
notice( t('Location not found.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
$r = q("update hubloc set hubloc_primary = 0 where hubloc_primary = 1 and hubloc_hash = '%s' ",
|
||||
dbesc($channel['channel_hash'])
|
||||
|
||||
q("UPDATE hubloc SET hubloc_primary = 0 WHERE hubloc_primary = 1 AND (hubloc_hash = '%s' OR hubloc_hash = '%s')",
|
||||
dbesc($channel['channel_hash']),
|
||||
dbesc($channel['channel_portable_id'])
|
||||
);
|
||||
$r = q("update hubloc set hubloc_primary = 1 where hubloc_id = %d and hubloc_hash = '%s'",
|
||||
|
||||
q("UPDATE hubloc SET hubloc_primary = 1 WHERE hubloc_id = %d AND hubloc_hash = '%s'",
|
||||
intval($hubloc_id),
|
||||
dbesc($channel['channel_hash'])
|
||||
);
|
||||
|
||||
\Zotlabs\Daemon\Master::Summon(array('Notifier','location',$channel['channel_id']));
|
||||
|
||||
$x = q("select * from hubloc where hubloc_id = %d and hubloc_hash = '%s' ",
|
||||
intval($hubloc_id),
|
||||
dbesc($channel['channel_hash'])
|
||||
);
|
||||
|
||||
if ($x) {
|
||||
hubloc_change_primary($x[0]);
|
||||
}
|
||||
|
||||
Master::Summon( [ 'Notifier', 'refresh_all', $channel['channel_id'] ] );
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
if($_REQUEST['drop']) {
|
||||
$hubloc_id = intval($_REQUEST['drop']);
|
||||
|
||||
|
||||
if($hubloc_id) {
|
||||
$r = q("select * from hubloc where hubloc_id = %d and hubloc_url != '%s' and hubloc_hash = '%s' limit 1",
|
||||
intval($hubloc_id),
|
||||
dbesc(z_root()),
|
||||
dbesc($channel['channel_hash'])
|
||||
);
|
||||
|
||||
|
||||
if(! $r) {
|
||||
notice( t('Location not found.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
if(intval($r[0]['hubloc_primary'])) {
|
||||
$x = q("select hubloc_id from hubloc where hubloc_primary = 1 and hubloc_hash = '%s'",
|
||||
dbesc($channel['channel_hash'])
|
||||
@@ -67,51 +80,49 @@ class Locs extends \Zotlabs\Web\Controller {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$r = q("update hubloc set hubloc_deleted = 1 where hubloc_id = %d and hubloc_hash = '%s'",
|
||||
intval($hubloc_id),
|
||||
dbesc($channel['channel_hash'])
|
||||
|
||||
q("UPDATE hubloc SET hubloc_deleted = 1 WHERE hubloc_id_url = '%s' AND (hubloc_hash = '%s' OR hubloc_hash = '%s')",
|
||||
dbesc($r[0]['hubloc_id_url']),
|
||||
dbesc($channel['channel_hash']),
|
||||
dbesc($channel['channel_portable_id'])
|
||||
);
|
||||
\Zotlabs\Daemon\Master::Summon(array('Notifier','location',$channel['channel_id']));
|
||||
Master::Summon( [ 'Notifier', 'refresh_all', $channel['channel_id'] ] );
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
function get() {
|
||||
|
||||
|
||||
|
||||
if(! local_channel()) {
|
||||
notice( t('Permission denied.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
$channel = \App::get_channel();
|
||||
|
||||
|
||||
$channel = App::get_channel();
|
||||
|
||||
if($_REQUEST['sync']) {
|
||||
\Zotlabs\Daemon\Master::Summon(array('Notifier','location',$channel['channel_id']));
|
||||
Master::Summon( [ 'Notifier', 'refresh_all', $channel['channel_id'] ] );
|
||||
info( t('Syncing locations') . EOL);
|
||||
goaway(z_root() . '/locs');
|
||||
}
|
||||
|
||||
|
||||
|
||||
$r = q("select * from hubloc where hubloc_hash = '%s'",
|
||||
dbesc($channel['channel_hash'])
|
||||
);
|
||||
|
||||
|
||||
if(! $r) {
|
||||
notice( t('No locations found.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
for($x = 0; $x < count($r); $x ++) {
|
||||
$r[$x]['primary'] = (intval($r[$x]['hubloc_primary']) ? true : false);
|
||||
$r[$x]['deleted'] = (intval($r[$x]['hubloc_deleted']) ? true : false);
|
||||
}
|
||||
|
||||
|
||||
$o = replace_macros(get_markup_template('locmanage.tpl'), array(
|
||||
'$header' => t('Manage Channel Locations'),
|
||||
'$loc' => t('Location'),
|
||||
@@ -125,8 +136,8 @@ class Locs extends \Zotlabs\Web\Controller {
|
||||
'$last_resort' => t('Use this form to drop the location if the hub is no longer operating.'),
|
||||
'$hubs' => $r
|
||||
));
|
||||
|
||||
|
||||
return $o;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,214 +1,133 @@
|
||||
<?php
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
use App;
|
||||
use Zotlabs\Web\Controller;
|
||||
use Zotlabs\Web\HTTPSig;
|
||||
use Zotlabs\Lib\Libzot;
|
||||
use Zotlabs\Lib\SConfig;
|
||||
|
||||
@require_once('include/zot.php');
|
||||
|
||||
|
||||
class Magic extends \Zotlabs\Web\Controller {
|
||||
class Magic extends Controller {
|
||||
|
||||
function init() {
|
||||
|
||||
$ret = array('success' => false, 'url' => '', 'message' => '');
|
||||
logger('mod_magic: invoked', LOGGER_DEBUG);
|
||||
|
||||
logger('mod_magic: args: ' . print_r($_REQUEST,true),LOGGER_DATA);
|
||||
|
||||
$addr = ((x($_REQUEST,'addr')) ? $_REQUEST['addr'] : '');
|
||||
$bdest = ((x($_REQUEST,'bdest')) ? $_REQUEST['bdest'] : '');
|
||||
$dest = ((x($_REQUEST,'dest')) ? $_REQUEST['dest'] : '');
|
||||
$test = ((x($_REQUEST,'test')) ? intval($_REQUEST['test']) : 0);
|
||||
$rev = ((x($_REQUEST,'rev')) ? intval($_REQUEST['rev']) : 0);
|
||||
$owa = ((x($_REQUEST,'owa')) ? intval($_REQUEST['owa']) : 0);
|
||||
$delegate = ((x($_REQUEST,'delegate')) ? $_REQUEST['delegate'] : '');
|
||||
|
||||
if($bdest)
|
||||
$ret = [
|
||||
'success' => false,
|
||||
'url' => '',
|
||||
'message' => ''
|
||||
];
|
||||
|
||||
logger('mod_magic: invoked', LOGGER_DEBUG);
|
||||
|
||||
logger('args: ' . print_r($_REQUEST,true),LOGGER_DATA);
|
||||
|
||||
$addr = ((x($_REQUEST,'addr')) ? $_REQUEST['addr'] : '');
|
||||
$bdest = ((x($_REQUEST,'bdest')) ? $_REQUEST['bdest'] : '');
|
||||
$dest = ((x($_REQUEST,'dest')) ? $_REQUEST['dest'] : '');
|
||||
$rev = ((x($_REQUEST,'rev')) ? intval($_REQUEST['rev']) : 0);
|
||||
$owa = ((x($_REQUEST,'owa')) ? intval($_REQUEST['owa']) : 0);
|
||||
$delegate = ((x($_REQUEST,'delegate')) ? $_REQUEST['delegate'] : '');
|
||||
|
||||
// bdest is preferred as it is hex-encoded and can survive url rewrite and argument parsing
|
||||
|
||||
if ($bdest) {
|
||||
$dest = hex2bin($bdest);
|
||||
}
|
||||
|
||||
$parsed = parse_url($dest);
|
||||
if(! $parsed) {
|
||||
if($test) {
|
||||
$ret['message'] .= 'could not parse ' . $dest . EOL;
|
||||
return($ret);
|
||||
}
|
||||
|
||||
if (! $parsed) {
|
||||
goaway($dest);
|
||||
}
|
||||
|
||||
|
||||
$basepath = $parsed['scheme'] . '://' . $parsed['host'] . (($parsed['port']) ? ':' . $parsed['port'] : '');
|
||||
|
||||
$x = q("select * from hubloc where hubloc_url = '%s' order by hubloc_connected desc limit 1",
|
||||
dbesc($basepath)
|
||||
);
|
||||
|
||||
if(! $x) {
|
||||
|
||||
/*
|
||||
* We have no records for, or prior communications with this hub.
|
||||
* If an address was supplied, let's finger them to create a hub record.
|
||||
* Otherwise we'll use the special address '[system]' which will return
|
||||
* either a system channel or the first available normal channel. We don't
|
||||
* really care about what channel is returned - we need the hub information
|
||||
* from that response so that we can create signed auth packets destined
|
||||
* for that hub.
|
||||
*
|
||||
*/
|
||||
|
||||
$j = \Zotlabs\Zot\Finger::run((($addr) ? $addr : '[system]@' . $parsed['host']),null);
|
||||
if($j['success']) {
|
||||
import_xchan($j);
|
||||
|
||||
// Now try again
|
||||
|
||||
$x = q("select * from hubloc where hubloc_url = '%s' order by hubloc_connected desc limit 1",
|
||||
dbesc($basepath)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if(! $x) {
|
||||
if($rev)
|
||||
goaway($dest);
|
||||
else {
|
||||
logger('mod_magic: no channels found for requested hub.' . print_r($_REQUEST,true));
|
||||
if($test) {
|
||||
$ret['message'] .= 'This site has no previous connections with ' . $basepath . EOL;
|
||||
return $ret;
|
||||
}
|
||||
notice( t('Hub not found.') . EOL);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$owapath = SConfig::get($basepath,'system','openwebauth', $basepath . '/owa');
|
||||
|
||||
// This is ready-made for a plugin that provides a blacklist or "ask me" before blindly authenticating.
|
||||
// By default, we'll proceed without asking.
|
||||
|
||||
$arr = array(
|
||||
'channel_id' => local_channel(),
|
||||
'xchan' => $x[0],
|
||||
|
||||
$arr = [
|
||||
'channel_id' => local_channel(),
|
||||
'destination' => $dest,
|
||||
'proceed' => true
|
||||
);
|
||||
|
||||
'proceed' => true
|
||||
];
|
||||
|
||||
call_hooks('magic_auth',$arr);
|
||||
$dest = $arr['destination'];
|
||||
if(! $arr['proceed']) {
|
||||
if($test) {
|
||||
$ret['message'] .= 'cancelled by plugin.' . EOL;
|
||||
return $ret;
|
||||
}
|
||||
if (! $arr['proceed']) {
|
||||
goaway($dest);
|
||||
}
|
||||
|
||||
if((get_observer_hash()) && ($x[0]['hubloc_url'] === z_root())) {
|
||||
|
||||
if((get_observer_hash()) && (stripos($dest,z_root()) === 0)) {
|
||||
|
||||
// We are already authenticated on this site and a registered observer.
|
||||
// Just redirect.
|
||||
if($test) {
|
||||
$ret['success'] = true;
|
||||
$ret['message'] .= 'Local site - you are already authenticated.' . EOL;
|
||||
return $ret;
|
||||
}
|
||||
|
||||
$delegation_success = false;
|
||||
if($delegate) {
|
||||
// First check if this is a delegate request on the local system and process accordingly.
|
||||
// Otherwise redirect.
|
||||
|
||||
if ($delegate) {
|
||||
|
||||
$r = q("select * from channel left join hubloc on channel_hash = hubloc_hash where hubloc_addr = '%s' limit 1",
|
||||
dbesc($delegate)
|
||||
);
|
||||
|
||||
if($r && intval($r[0]['channel_id'])) {
|
||||
$allowed = perm_is_allowed($r[0]['channel_id'],get_observer_hash(),'delegate');
|
||||
if($allowed) {
|
||||
|
||||
if ($r) {
|
||||
$c = array_shift($r);
|
||||
if (perm_is_allowed($c['channel_id'],get_observer_hash(),'delegate')) {
|
||||
$tmp = $_SESSION;
|
||||
$_SESSION['delegate_push'] = $tmp;
|
||||
$_SESSION['delegate_channel'] = $r[0]['channel_id'];
|
||||
$_SESSION['delegate'] = get_observer_hash();
|
||||
$_SESSION['account_id'] = intval($r[0]['channel_account_id']);
|
||||
change_channel($r[0]['channel_id']);
|
||||
|
||||
$delegation_success = true;
|
||||
$_SESSION['delegate_push'] = $tmp;
|
||||
$_SESSION['delegate_channel'] = $c['channel_id'];
|
||||
$_SESSION['delegate'] = get_observer_hash();
|
||||
$_SESSION['account_id'] = intval($c['channel_account_id']);
|
||||
|
||||
change_channel($c['channel_id']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// FIXME: check and honour local delegation
|
||||
|
||||
|
||||
|
||||
goaway($dest);
|
||||
}
|
||||
|
||||
if(local_channel()) {
|
||||
$channel = \App::get_channel();
|
||||
|
||||
|
||||
if (local_channel()) {
|
||||
$channel = App::get_channel();
|
||||
|
||||
// OpenWebAuth
|
||||
|
||||
if($owa) {
|
||||
if ($owa) {
|
||||
|
||||
$dest = strip_zids($dest);
|
||||
$dest = strip_query_param($dest,'f');
|
||||
|
||||
// We now post to the OWA endpoint. This improves security by providing a signed digest
|
||||
|
||||
$data = json_encode([ 'OpenWebAuth' => random_string() ]);
|
||||
|
||||
$headers = [];
|
||||
$headers['Accept'] = 'application/x-zot+json' ;
|
||||
$headers['Content-Type'] = 'application/x-zot+json' ;
|
||||
$headers['X-Open-Web-Auth'] = random_string();
|
||||
$headers['Host'] = $parsed['host'];
|
||||
$headers['Digest'] = HTTPSig::generate_digest_header($data);
|
||||
$headers['Host'] = $parsed['host'];
|
||||
$headers['(request-target)'] = 'post ' . '/owa';
|
||||
|
||||
$headers = HTTPSig::create_sig($headers,$channel['channel_prvkey'], 'acct:' . channel_reddress($channel),true,'sha512');
|
||||
$x = z_post_url($basepath . '/owa',$data,$redirects,[ 'headers' => $headers ]);
|
||||
|
||||
if($x['success']) {
|
||||
$headers = HTTPSig::create_sig($headers,$channel['channel_prvkey'], channel_url($channel),true,'sha512');
|
||||
$x = z_post_url($owapath,$data,$redirects,[ 'headers' => $headers ]);
|
||||
logger('owa fetch returned: ' . print_r($x,true),LOGGER_DATA);
|
||||
if ($x['success']) {
|
||||
$j = json_decode($x['body'],true);
|
||||
if($j['success']) {
|
||||
if ($j['success'] && $j['encrypted_token']) {
|
||||
// decrypt the token using our private key
|
||||
$token = '';
|
||||
if($j['encrypted_token']) {
|
||||
openssl_private_decrypt(base64url_decode($j['encrypted_token']),$token,$channel['channel_prvkey']);
|
||||
}
|
||||
else {
|
||||
$token = $j['token'];
|
||||
}
|
||||
|
||||
$strp = strpbrk($dest,'?&');
|
||||
$args = (($strp) ? '&owt=' . $token : '?f=&owt=' . $token) . (($delegate) ? '&delegate=1' : '');
|
||||
openssl_private_decrypt(base64url_decode($j['encrypted_token']),$token,$channel['channel_prvkey']);
|
||||
$x = strpbrk($dest,'?&');
|
||||
// redirect using the encrypted token which will be exchanged for an authenticated session
|
||||
$args = (($x) ? '&owt=' . $token : '?f=&owt=' . $token) . (($delegate) ? '&delegate=1' : '');
|
||||
goaway($dest . $args);
|
||||
}
|
||||
}
|
||||
goaway($dest);
|
||||
}
|
||||
|
||||
|
||||
$token = random_string();
|
||||
|
||||
\Zotlabs\Lib\Verify::create('auth',$channel['channel_id'],$token,$x[0]['hubloc_url']);
|
||||
|
||||
$target_url = $x[0]['hubloc_callback'] . '/?f=&auth=' . urlencode(channel_reddress($channel))
|
||||
. '&sec=' . $token . '&dest=' . urlencode($dest) . '&version=' . ZOT_REVISION;
|
||||
|
||||
if($delegate)
|
||||
$target_url .= '&delegate=' . urlencode($delegate);
|
||||
|
||||
logger('mod_magic: redirecting to: ' . $target_url, LOGGER_DEBUG);
|
||||
|
||||
if($test) {
|
||||
$ret['success'] = true;
|
||||
$ret['url'] = $target_url;
|
||||
$ret['message'] = 'token ' . $token . ' created for channel ' . $channel['channel_id'] . ' for url ' . $x[0]['hubloc_url'] . EOL;
|
||||
return $ret;
|
||||
}
|
||||
|
||||
goaway($target_url);
|
||||
|
||||
}
|
||||
|
||||
if($test) {
|
||||
$ret['message'] = 'Not authenticated or invalid arguments to mod_magic' . EOL;
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
goaway($dest);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,449 +0,0 @@
|
||||
<?php
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
require_once('include/acl_selectors.php');
|
||||
require_once('include/message.php');
|
||||
require_once('include/zot.php');
|
||||
require_once("include/bbcode.php");
|
||||
|
||||
|
||||
|
||||
|
||||
class Mail extends \Zotlabs\Web\Controller {
|
||||
|
||||
function post() {
|
||||
|
||||
if(! local_channel())
|
||||
return;
|
||||
|
||||
$replyto = ((x($_REQUEST,'replyto')) ? notags(trim($_REQUEST['replyto'])) : '');
|
||||
$subject = ((x($_REQUEST,'subject')) ? notags(trim($_REQUEST['subject'])) : '');
|
||||
$body = ((x($_REQUEST,'body')) ? escape_tags(trim($_REQUEST['body'])) : '');
|
||||
$recipient = ((x($_REQUEST,'messageto')) ? notags(trim(urldecode($_REQUEST['messageto']))) : '');
|
||||
$rstr = ((x($_REQUEST,'messagerecip')) ? notags(trim($_REQUEST['messagerecip'])) : '');
|
||||
$preview = ((x($_REQUEST,'preview')) ? intval($_REQUEST['preview']) : 0);
|
||||
$expires = ((x($_REQUEST,'expires')) ? datetime_convert(date_default_timezone_get(),'UTC', $_REQUEST['expires']) : NULL_DATE);
|
||||
$raw = ((x($_REQUEST,'raw')) ? intval($_REQUEST['raw']) : 0);
|
||||
$mimetype = ((x($_REQUEST,'mimetype')) ? notags(trim($_REQUEST['mimetype'])) : 'text/bbcode');
|
||||
|
||||
$sig = ((x($_REQUEST,'signature')) ? trim($_REQUEST['signature']) : '');
|
||||
if(strpos($sig,'b64.') === 0)
|
||||
$sig = base64_decode(str_replace('b64.', '', $sig));
|
||||
|
||||
if($preview) {
|
||||
|
||||
if($raw) {
|
||||
$body = mail_prepare_binary(['id' => 'M0']);
|
||||
echo json_encode(['preview' => $body]);
|
||||
}
|
||||
else {
|
||||
$body = cleanup_bbcode($body);
|
||||
$results = linkify_tags($body, local_channel());
|
||||
|
||||
if(preg_match_all('/(\[attachment\](.*?)\[\/attachment\])/',$body,$match)) {
|
||||
$attachments = array();
|
||||
foreach($match[2] as $mtch) {
|
||||
$hash = substr($mtch,0,strpos($mtch,','));
|
||||
$rev = intval(substr($mtch,strpos($mtch,',')));
|
||||
$r = attach_by_hash_nodata($hash,get_observer_hash(),$rev);
|
||||
if($r['success']) {
|
||||
$attachments[] = array(
|
||||
'href' => z_root() . '/attach/' . $r['data']['hash'],
|
||||
'length' => $r['data']['filesize'],
|
||||
'type' => $r['data']['filetype'],
|
||||
'title' => urlencode($r['data']['filename']),
|
||||
'revision' => $r['data']['revision']
|
||||
);
|
||||
}
|
||||
$body = trim(str_replace($match[1],'',$body));
|
||||
}
|
||||
}
|
||||
echo json_encode(['preview' => zidify_links(smilies(bbcode($body)))]);
|
||||
}
|
||||
killme();
|
||||
}
|
||||
|
||||
// If we have a raw string for a recipient which hasn't been auto-filled,
|
||||
// it means they probably aren't in our address book, hence we don't know
|
||||
// if we have permission to send them private messages.
|
||||
// finger them and find out before we try and send it.
|
||||
|
||||
if(! $recipient) {
|
||||
$channel = \App::get_channel();
|
||||
|
||||
$j = \Zotlabs\Zot\Finger::run(punify($rstr),$channel);
|
||||
|
||||
if(! $j['success']) {
|
||||
notice( t('Unable to lookup recipient.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
logger('message_post: lookup: ' . $rstr . ' ' . print_r($j,true));
|
||||
|
||||
if(! $j['guid']) {
|
||||
notice( t('Unable to communicate with requested channel.'));
|
||||
return;
|
||||
}
|
||||
|
||||
$x = import_xchan($j);
|
||||
|
||||
if(! $x['success']) {
|
||||
notice( t('Cannot verify requested channel.'));
|
||||
return;
|
||||
}
|
||||
|
||||
$recipient = $x['hash'];
|
||||
|
||||
$their_perms = 0;
|
||||
|
||||
if($j['permissions']['data']) {
|
||||
$permissions = crypto_unencapsulate($j['permissions'],$channel['channel_prvkey']);
|
||||
if($permissions)
|
||||
$permissions = json_decode($permissions, true);
|
||||
logger('decrypted permissions: ' . print_r($permissions,true), LOGGER_DATA);
|
||||
}
|
||||
else
|
||||
$permissions = $j['permissions'];
|
||||
|
||||
if(! ($permissions['post_mail'])) {
|
||||
notice( t('Selected channel has private message restrictions. Send failed.'));
|
||||
// reported issue: let's still save the message and continue. We'll just tell them
|
||||
// that nothing useful is likely to happen. They might have spent hours on it.
|
||||
// return;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
require_once('include/text.php');
|
||||
linkify_tags($body, local_channel());
|
||||
|
||||
|
||||
if(! $recipient) {
|
||||
notice('No recipient found.');
|
||||
\App::$argc = 2;
|
||||
\App::$argv[1] = 'new';
|
||||
return;
|
||||
}
|
||||
|
||||
// We have a local_channel, let send_message use the session channel and save a lookup
|
||||
|
||||
$ret = send_message(0, $recipient, $body, $subject, $replyto, $expires, $mimetype, $raw, $sig);
|
||||
|
||||
if($ret['success']) {
|
||||
xchan_mail_query($ret['mail']);
|
||||
build_sync_packet(0,array('conv' => array($ret['conv']),'mail' => array(encode_mail($ret['mail'],true))));
|
||||
}
|
||||
else {
|
||||
notice($ret['message']);
|
||||
}
|
||||
|
||||
goaway(z_root() . '/mail/combined');
|
||||
|
||||
}
|
||||
|
||||
function get() {
|
||||
|
||||
$o = '';
|
||||
nav_set_selected('Mail');
|
||||
|
||||
if(! local_channel()) {
|
||||
notice( t('Permission denied.') . EOL);
|
||||
return login();
|
||||
}
|
||||
|
||||
$channel = \App::get_channel();
|
||||
|
||||
head_set_icon($channel['xchan_photo_s']);
|
||||
|
||||
$cipher = get_pconfig(local_channel(),'system','default_cipher');
|
||||
if(! $cipher)
|
||||
$cipher = 'aes256';
|
||||
|
||||
$tpl = get_markup_template('mail_head.tpl');
|
||||
$header = replace_macros($tpl, array(
|
||||
'$header' => t('Messages'),
|
||||
));
|
||||
|
||||
if(argc() == 3 && intval(argv(1)) && argv(2) === 'download') {
|
||||
|
||||
$r = q("select * from mail where id = %d and channel_id = %d",
|
||||
intval(argv(1)),
|
||||
intval(local_channel())
|
||||
);
|
||||
|
||||
if($r) {
|
||||
|
||||
header('Content-type: ' . $r[0]['mail_mimetype']);
|
||||
header('Content-disposition: attachment; filename="' . t('message') . '-' . $r[0]['id'] . '"' );
|
||||
$body = (($r[0]['mail_obscured']) ? base64url_decode(str_rot47($r[0]['body'])) : $r[0]['body']);
|
||||
echo $body;
|
||||
killme();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
if((argc() == 4) && (argv(2) === 'drop')) {
|
||||
if(! intval(argv(3)))
|
||||
return;
|
||||
$cmd = argv(2);
|
||||
$mailbox = argv(1);
|
||||
$r = private_messages_drop(local_channel(), argv(3));
|
||||
if($r) {
|
||||
//info( t('Message deleted.') . EOL );
|
||||
}
|
||||
goaway(z_root() . '/mail/' . $mailbox);
|
||||
}
|
||||
|
||||
if((argc() == 4) && (argv(2) === 'recall')) {
|
||||
if(! intval(argv(3)))
|
||||
return;
|
||||
$cmd = argv(2);
|
||||
$mailbox = argv(1);
|
||||
$r = q("update mail set mail_recalled = 1 where id = %d and channel_id = %d",
|
||||
intval(argv(3)),
|
||||
intval(local_channel())
|
||||
);
|
||||
$x = q("select * from mail where id = %d and channel_id = %d",
|
||||
intval(argv(3)),
|
||||
intval(local_channel())
|
||||
);
|
||||
if($x) {
|
||||
build_sync_packet(local_channel(),array('mail' => encode_mail($x[0],true)));
|
||||
}
|
||||
|
||||
\Zotlabs\Daemon\Master::Summon(array('Notifier','mail',intval(argv(3))));
|
||||
|
||||
if($r) {
|
||||
info( t('Message recalled.') . EOL );
|
||||
}
|
||||
goaway(z_root() . '/mail/' . $mailbox . '/' . argv(3));
|
||||
|
||||
}
|
||||
|
||||
if((argc() == 4) && (argv(2) === 'dropconv')) {
|
||||
if(! intval(argv(3)))
|
||||
return;
|
||||
$cmd = argv(2);
|
||||
$mailbox = argv(1);
|
||||
$r = private_messages_drop(local_channel(), argv(3), true);
|
||||
if($r)
|
||||
info( t('Conversation removed.') . EOL );
|
||||
goaway(z_root() . '/mail/' . $mailbox);
|
||||
}
|
||||
|
||||
if((argc() > 1) && (argv(1) === 'new')) {
|
||||
|
||||
$plaintext = true;
|
||||
|
||||
$tpl = get_markup_template('msg-header.tpl');
|
||||
|
||||
$header = replace_macros($tpl, array(
|
||||
'$baseurl' => z_root(),
|
||||
'$editselect' => (($plaintext) ? 'none' : '/(profile-jot-text|prvmail-text)/'),
|
||||
'$nickname' => $channel['channel_address'],
|
||||
'$linkurl' => t('Please enter a link URL:'),
|
||||
'$expireswhen' => t('Expires YYYY-MM-DD HH:MM')
|
||||
));
|
||||
|
||||
\App::$page['htmlhead'] .= $header;
|
||||
|
||||
$prename = '';
|
||||
$preid = '';
|
||||
|
||||
if(x($_REQUEST,'hash')) {
|
||||
|
||||
$r = q("select abook.*, xchan.* from abook left join xchan on abook_xchan = xchan_hash
|
||||
where abook_channel = %d and abook_xchan = '%s' limit 1",
|
||||
intval(local_channel()),
|
||||
dbesc($_REQUEST['hash'])
|
||||
);
|
||||
|
||||
if(!$r) {
|
||||
$r = q("select * from xchan where xchan_hash = '%s' and xchan_network = 'zot' limit 1",
|
||||
dbesc($_REQUEST['hash'])
|
||||
);
|
||||
}
|
||||
|
||||
if($r) {
|
||||
$prename = (($r[0]['abook_id']) ? $r[0]['xchan_name'] : $r[0]['xchan_addr']);
|
||||
$preurl = $r[0]['xchan_url'];
|
||||
$preid = (($r[0]['abook_id']) ? ($r[0]['xchan_hash']) : '');
|
||||
}
|
||||
else {
|
||||
notice( t('Requested channel is not in this network') . EOL );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$tpl = get_markup_template('prv_message.tpl');
|
||||
$o .= replace_macros($tpl,array(
|
||||
'$new' => true,
|
||||
'$header' => t('Send Private Message'),
|
||||
'$to' => t('To:'),
|
||||
'$prefill' => $prename,
|
||||
'$preid' => $preid,
|
||||
'$subject' => t('Subject:'),
|
||||
'$subjtxt' => ((x($_REQUEST,'subject')) ? strip_tags($_REQUEST['subject']) : ''),
|
||||
'$text' => ((x($_REQUEST,'body')) ? htmlspecialchars($_REQUEST['body'], ENT_COMPAT, 'UTF-8') : ''),
|
||||
'$yourmessage' => t('Your message:'),
|
||||
'$parent' => '',
|
||||
'$attach' => t('Attach file'),
|
||||
'$insert' => t('Insert web link'),
|
||||
'$submit' => t('Send'),
|
||||
'$defexpire' => '',
|
||||
'$feature_expire' => ((feature_enabled(local_channel(),'content_expire')) ? true : false),
|
||||
'$expires' => t('Set expiration date'),
|
||||
'$feature_encrypt' => ((feature_enabled(local_channel(),'content_encrypt')) ? true : false),
|
||||
'$encrypt' => t('Encrypt text'),
|
||||
'$cipher' => $cipher,
|
||||
));
|
||||
|
||||
return $o;
|
||||
}
|
||||
|
||||
$direct_mid = 0;
|
||||
|
||||
switch(argv(1)) {
|
||||
case 'combined':
|
||||
$mailbox = 'combined';
|
||||
break;
|
||||
case 'inbox':
|
||||
$mailbox = 'inbox';
|
||||
break;
|
||||
case 'outbox':
|
||||
$mailbox = 'outbox';
|
||||
break;
|
||||
default:
|
||||
$mailbox = 'combined';
|
||||
|
||||
// notifications direct to mail/nn
|
||||
|
||||
if(intval(argv(1)))
|
||||
$direct_mid = intval(argv(1));
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
$last_message = private_messages_list(local_channel(), $mailbox, 0, 1);
|
||||
|
||||
$mid = ((argc() > 2) && (intval(argv(2)))) ? argv(2) : $last_message[0]['id'];
|
||||
|
||||
if($direct_mid)
|
||||
$mid = $direct_mid;
|
||||
|
||||
|
||||
$plaintext = true;
|
||||
|
||||
// if( local_channel() && feature_enabled(local_channel(),'richtext') )
|
||||
// $plaintext = false;
|
||||
|
||||
|
||||
|
||||
if($mailbox == 'combined') {
|
||||
$messages = private_messages_fetch_conversation(local_channel(), $mid, true);
|
||||
}
|
||||
else {
|
||||
$messages = private_messages_fetch_message(local_channel(), $mid, true);
|
||||
}
|
||||
|
||||
if(! $messages) {
|
||||
//info( t('Message not found.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
if($messages[0]['to_xchan'] === $channel['channel_hash'])
|
||||
\App::$poi = $messages[0]['from'];
|
||||
else
|
||||
\App::$poi = $messages[0]['to'];
|
||||
|
||||
$tpl = get_markup_template('msg-header.tpl');
|
||||
|
||||
\App::$page['htmlhead'] .= replace_macros($tpl, array(
|
||||
'$nickname' => $channel['channel_address'],
|
||||
'$baseurl' => z_root(),
|
||||
'$editselect' => (($plaintext) ? 'none' : '/(profile-jot-text|prvmail-text)/'),
|
||||
'$linkurl' => t('Please enter a link URL:'),
|
||||
'$expireswhen' => t('Expires YYYY-MM-DD HH:MM')
|
||||
));
|
||||
|
||||
$mails = array();
|
||||
|
||||
$seen = 0;
|
||||
$unknown = false;
|
||||
|
||||
foreach($messages as $message) {
|
||||
|
||||
$s = theme_attachments($message);
|
||||
|
||||
if($message['mail_raw'])
|
||||
$message['body'] = mail_prepare_binary([ 'id' => $message['id'] ]);
|
||||
else
|
||||
$message['body'] = zidify_links(smilies(bbcode($message['body'])));
|
||||
|
||||
$mails[] = array(
|
||||
'mailbox' => $mailbox,
|
||||
'id' => $message['id'],
|
||||
'mid' => $message['mid'],
|
||||
'from_name' => $message['from']['xchan_name'],
|
||||
'from_url' => chanlink_hash($message['from_xchan']),
|
||||
'from_photo' => $message['from']['xchan_photo_s'],
|
||||
'to_name' => $message['to']['xchan_name'],
|
||||
'to_url' => chanlink_hash($message['to_xchan']),
|
||||
'to_photo' => $message['to']['xchan_photo_s'],
|
||||
'subject' => $message['title'],
|
||||
'body' => $message['body'],
|
||||
'attachments' => $s,
|
||||
'delete' => t('Delete message'),
|
||||
'dreport' => t('Delivery report'),
|
||||
'recall' => t('Recall message'),
|
||||
'can_recall' => ($channel['channel_hash'] == $message['from_xchan']),
|
||||
'is_recalled' => (intval($message['mail_recalled']) ? t('Message has been recalled.') : ''),
|
||||
'date' => datetime_convert('UTC',date_default_timezone_get(),$message['created'], 'c'),
|
||||
'sig' => base64_encode($message['sig'])
|
||||
);
|
||||
|
||||
$seen = $message['seen'];
|
||||
|
||||
}
|
||||
|
||||
$recp = (($message['from_xchan'] === $channel['channel_hash']) ? 'to' : 'from');
|
||||
|
||||
$tpl = get_markup_template('mail_display.tpl');
|
||||
$o = replace_macros($tpl, array(
|
||||
'$mailbox' => $mailbox,
|
||||
'$prvmsg_header' => $message['title'],
|
||||
'$thread_id' => $mid,
|
||||
'$thread_subject' => $message['title'],
|
||||
'$thread_seen' => $seen,
|
||||
'$delete' => t('Delete Conversation'),
|
||||
'$canreply' => (($unknown) ? false : '1'),
|
||||
'$unknown_text' => t("No secure communications available. You <strong>may</strong> be able to respond from the sender's profile page."),
|
||||
'$mails' => $mails,
|
||||
|
||||
// reply
|
||||
'$header' => t('Send Reply'),
|
||||
'$to' => t('To:'),
|
||||
'$reply' => true,
|
||||
'$subject' => t('Subject:'),
|
||||
'$subjtxt' => $message['title'],
|
||||
'$yourmessage' => sprintf(t('Your message for %s (%s):'), $message[$recp]['xchan_name'], $message[$recp]['xchan_addr']),
|
||||
'$text' => '',
|
||||
'$parent' => $message['parent_mid'],
|
||||
'$recphash' => $message[$recp]['xchan_hash'],
|
||||
'$attach' => t('Attach file'),
|
||||
'$insert' => t('Insert web link'),
|
||||
'$submit' => t('Submit'),
|
||||
'$defexpire' => '',
|
||||
'$feature_expire' => ((feature_enabled(local_channel(),'content_expire')) ? true : false),
|
||||
'$expires' => t('Set expiration date'),
|
||||
'$feature_encrypt' => ((feature_enabled(local_channel(),'content_encrypt')) ? true : false),
|
||||
'$encrypt' => t('Encrypt text'),
|
||||
'$cipher' => $cipher,
|
||||
));
|
||||
|
||||
return $o;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -54,9 +54,10 @@ class Menu extends \Zotlabs\Web\Controller {
|
||||
if($_REQUEST['menu_system'])
|
||||
$_REQUEST['menu_flags'] |= MENU_SYSTEM;
|
||||
|
||||
$menu_id = ((argc() > 1) ? intval(argv(1)) : 0);
|
||||
$menu_id = ((argc() > 2) ? intval(argv(2)) : 0);
|
||||
|
||||
if($menu_id) {
|
||||
$_REQUEST['menu_id'] = intval(argv(1));
|
||||
$_REQUEST['menu_id'] = $menu_id;
|
||||
$r = menu_edit($_REQUEST);
|
||||
if($r) {
|
||||
menu_sync_packet($uid,get_observer_hash(),$menu_id);
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
use Zotlabs\Lib\Libsync;
|
||||
|
||||
require_once('include/conversation.php');
|
||||
|
||||
|
||||
@@ -14,7 +16,7 @@ class Moderate extends \Zotlabs\Web\Controller {
|
||||
return;
|
||||
}
|
||||
|
||||
\App::set_pager_itemspage(60);
|
||||
\App::set_pager_itemspage(30);
|
||||
$pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(\App::$pager['itemspage']), intval(\App::$pager['start']));
|
||||
|
||||
//show all items
|
||||
@@ -77,7 +79,7 @@ class Moderate extends \Zotlabs\Web\Controller {
|
||||
if($r) {
|
||||
xchan_query($r);
|
||||
$sync_item = fetch_post_tags($r);
|
||||
build_sync_packet(local_channel(),array('item' => array(encode_item($sync_item[0],true))));
|
||||
Libsync::build_sync_packet(local_channel(),array('item' => array(encode_item($sync_item[0],true))));
|
||||
}
|
||||
if($action === 'approve') {
|
||||
\Zotlabs\Daemon\Master::Summon(array('Notifier', 'comment-new', $post_id));
|
||||
|
||||
@@ -44,10 +44,6 @@ class Network extends \Zotlabs\Web\Controller {
|
||||
|
||||
$o = '';
|
||||
|
||||
if($load) {
|
||||
$_SESSION['loadtime'] = datetime_convert();
|
||||
}
|
||||
|
||||
$arr = array('query' => App::$query_string);
|
||||
|
||||
call_hooks('network_content_init', $arr);
|
||||
@@ -64,11 +60,11 @@ class Network extends \Zotlabs\Web\Controller {
|
||||
|
||||
$datequery = ((x($_GET,'dend') && is_a_date_arg($_GET['dend'])) ? notags($_GET['dend']) : '');
|
||||
$datequery2 = ((x($_GET,'dbegin') && is_a_date_arg($_GET['dbegin'])) ? notags($_GET['dbegin']) : '');
|
||||
$static = ((x($_GET,'static')) ? intval($_GET['static']) : 0);
|
||||
$gid = ((x($_GET,'gid')) ? intval($_GET['gid']) : 0);
|
||||
$category = ((x($_REQUEST,'cat')) ? $_REQUEST['cat'] : '');
|
||||
$hashtags = ((x($_REQUEST,'tag')) ? $_REQUEST['tag'] : '');
|
||||
$verb = ((x($_REQUEST,'verb')) ? $_REQUEST['verb'] : '');
|
||||
$dm = ((x($_REQUEST,'dm')) ? $_REQUEST['dm'] : 0);
|
||||
|
||||
|
||||
$order = get_pconfig(local_channel(), 'mod_network', 'order', 0);
|
||||
@@ -132,8 +128,6 @@ class Network extends \Zotlabs\Web\Controller {
|
||||
$pf = ((x($_GET,'pf')) ? $_GET['pf'] : '');
|
||||
$unseen = ((x($_GET,'unseen')) ? $_GET['unseen'] : '');
|
||||
|
||||
$deftag = '';
|
||||
|
||||
if (Apps::system_app_installed(local_channel(),'Affinity Tool')) {
|
||||
$affinity_locked = intval(get_pconfig(local_channel(),'affinity','lock',1));
|
||||
if ($affinity_locked) {
|
||||
@@ -159,10 +153,7 @@ class Network extends \Zotlabs\Web\Controller {
|
||||
goaway(z_root() . '/network');
|
||||
// NOTREACHED
|
||||
}
|
||||
if($pf)
|
||||
$deftag = '!{' . (($cid_r[0]['xchan_addr']) ? $cid_r[0]['xchan_addr'] : $cid_r[0]['xchan_url']) . '}';
|
||||
else
|
||||
$def_acl = [ 'allow_cid' => '<' . $cid_r[0]['abook_xchan'] . '>', 'allow_gid' => '', 'deny_cid' => '', 'deny_gid' => '' ];
|
||||
$def_acl = [ 'allow_cid' => '<' . $cid_r[0]['abook_xchan'] . '>', 'allow_gid' => '', 'deny_cid' => '', 'deny_gid' => '' ];
|
||||
}
|
||||
|
||||
if(! $update) {
|
||||
@@ -176,6 +167,17 @@ class Network extends \Zotlabs\Web\Controller {
|
||||
|
||||
nav_set_selected('Network');
|
||||
|
||||
$bang = '!';
|
||||
|
||||
if($cid_r) {
|
||||
$forums = get_forum_channels($channel['channel_id']);
|
||||
if($forums) {
|
||||
$forum_xchans = ids_to_array($forums, 'xchan_hash');
|
||||
if(in_array($cid_r[0]['abook_xchan'], $forum_xchans))
|
||||
$bang = $cid_r[0]['abook_xchan'];
|
||||
}
|
||||
}
|
||||
|
||||
$channel_acl = array(
|
||||
'allow_cid' => $channel['channel_allow_cid'],
|
||||
'allow_gid' => $channel['channel_allow_gid'],
|
||||
@@ -183,7 +185,7 @@ class Network extends \Zotlabs\Web\Controller {
|
||||
'deny_gid' => $channel['channel_deny_gid']
|
||||
);
|
||||
|
||||
$private_editing = ((($group || $cid) && (! intval($_GET['pf']))) ? true : false);
|
||||
$private_editing = (($group || $cid) ? true : false);
|
||||
|
||||
$x = array(
|
||||
'is_owner' => true,
|
||||
@@ -193,7 +195,7 @@ class Network extends \Zotlabs\Web\Controller {
|
||||
'lockstate' => (($private_editing || $channel['channel_allow_cid'] || $channel['channel_allow_gid'] || $channel['channel_deny_cid'] || $channel['channel_deny_gid']) ? 'lock' : 'unlock'),
|
||||
'acl' => populate_acl((($private_editing) ? $def_acl : $channel_acl), true, \Zotlabs\Lib\PermissionDescription::fromGlobalPermission('view_stream'), get_post_aclDialogDescription(), 'acl_dialog_post'),
|
||||
'permissions' => (($private_editing) ? $def_acl : $channel_acl),
|
||||
'bang' => (($private_editing) ? '!' : ''),
|
||||
'bang' => (($private_editing) ? $bang : ''),
|
||||
'visitor' => true,
|
||||
'profile_uid' => local_channel(),
|
||||
'editor_autocomplete' => true,
|
||||
@@ -202,15 +204,10 @@ class Network extends \Zotlabs\Web\Controller {
|
||||
'jotnets' => true,
|
||||
'reset' => t('Reset form')
|
||||
);
|
||||
if($deftag)
|
||||
$x['pretext'] = $deftag;
|
||||
|
||||
|
||||
$status_editor = status_editor($a,$x,false,'Network');
|
||||
$o .= $status_editor;
|
||||
|
||||
$static = channel_manual_conv_update(local_channel());
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -339,7 +336,7 @@ class Network extends \Zotlabs\Web\Controller {
|
||||
// The special div is needed for liveUpdate to kick in for this page.
|
||||
// We only launch liveUpdate if you aren't filtering in some incompatible
|
||||
// way and also you aren't writing a comment (discovered in javascript).
|
||||
|
||||
|
||||
$maxheight = get_pconfig(local_channel(),'system','network_divmore_height');
|
||||
if(! $maxheight)
|
||||
$maxheight = 400;
|
||||
@@ -363,9 +360,9 @@ class Network extends \Zotlabs\Web\Controller {
|
||||
'$conv' => (($conv) ? $conv : '0'),
|
||||
'$spam' => (($spam) ? $spam : '0'),
|
||||
'$fh' => '0',
|
||||
'$dm' => (($dm) ? $dm : '0'),
|
||||
'$nouveau' => (($nouveau) ? $nouveau : '0'),
|
||||
'$wall' => '0',
|
||||
'$static' => $static,
|
||||
'$list' => ((x($_REQUEST,'list')) ? intval($_REQUEST['list']) : 0),
|
||||
'$page' => ((App::$pager['page'] != 1) ? App::$pager['page'] : 1),
|
||||
'$search' => (($search) ? urlencode($search) : ''),
|
||||
@@ -409,15 +406,33 @@ class Network extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
}
|
||||
|
||||
if($verb) {
|
||||
$sql_extra .= sprintf(" AND item.verb like '%s' ",
|
||||
dbesc(protect_sprintf('%' . $verb . '%'))
|
||||
);
|
||||
if ($verb) {
|
||||
|
||||
// the presence of a leading dot in the verb determines
|
||||
// whether to match the type of activity or the child object.
|
||||
// The name 'verb' is a holdover from the earlier XML
|
||||
// ActivityStreams specification.
|
||||
|
||||
if (substr($verb,0,1) === '.') {
|
||||
$verb = substr($verb,1);
|
||||
$sql_extra .= sprintf(" AND item.obj_type like '%s' ",
|
||||
dbesc(protect_sprintf('%' . $verb . '%'))
|
||||
);
|
||||
}
|
||||
else {
|
||||
$sql_extra .= sprintf(" AND item.verb like '%s' ",
|
||||
dbesc(protect_sprintf('%' . $verb . '%'))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if(strlen($file)) {
|
||||
$sql_extra .= term_query('item',$file,TERM_FILE);
|
||||
}
|
||||
|
||||
if ($dm) {
|
||||
$sql_extra .= " AND item_private = 2 ";
|
||||
}
|
||||
|
||||
if($conv) {
|
||||
$item_thread_top = '';
|
||||
@@ -432,7 +447,7 @@ class Network extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
else {
|
||||
$itemspage = get_pconfig(local_channel(),'system','itemspage');
|
||||
App::set_pager_itemspage(((intval($itemspage)) ? $itemspage : 20));
|
||||
App::set_pager_itemspage(((intval($itemspage)) ? $itemspage : 10));
|
||||
$pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(App::$pager['itemspage']), intval(App::$pager['start']));
|
||||
}
|
||||
|
||||
@@ -470,9 +485,6 @@ class Network extends \Zotlabs\Web\Controller {
|
||||
$page_mode = 'client';
|
||||
|
||||
$parents_str = '';
|
||||
$update_unseen = '';
|
||||
|
||||
$simple_update = (($update) ? " and item_unseen = 1 " : '');
|
||||
|
||||
// This fixes a very subtle bug so I'd better explain it. You wake up in the morning or return after a day
|
||||
// or three and look at your matrix page - after opening up your browser. The first page loads just as it
|
||||
@@ -485,16 +497,11 @@ class Network extends \Zotlabs\Web\Controller {
|
||||
// which "arrived as you were reading page 1". We're going to do this
|
||||
// by storing in your session the current UTC time whenever you LOAD a network page, and only UPDATE items
|
||||
// which are both ITEM_UNSEEN and have "changed" since that time. Cross fingers...
|
||||
|
||||
|
||||
$simple_update = '';
|
||||
if($update && $_SESSION['loadtime'])
|
||||
$simple_update = " AND (( item_unseen = 1 AND item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' ) OR item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' ) ";
|
||||
|
||||
if($load)
|
||||
$simple_update = '';
|
||||
|
||||
if($static && $simple_update)
|
||||
$simple_update .= " and item_thread_top = 0 and author_xchan = '" . protect_sprintf(get_observer_hash()) . "' ";
|
||||
|
||||
if($nouveau && $load) {
|
||||
// "New Item View" - show all items unthreaded in reverse created date order
|
||||
$items = q("SELECT item.*, item.id AS item_id, created FROM item
|
||||
@@ -502,16 +509,12 @@ class Network extends \Zotlabs\Web\Controller {
|
||||
$net_query
|
||||
WHERE true $uids $item_normal
|
||||
and (abook.abook_blocked = 0 or abook.abook_flags is null)
|
||||
$simple_update
|
||||
$sql_extra $sql_options $sql_nets
|
||||
$net_query2
|
||||
ORDER BY item.created DESC $pager_sql "
|
||||
);
|
||||
|
||||
$parents_str = ids_to_querystr($items,'item_id');
|
||||
if($parents_str) {
|
||||
$update_unseen = " AND id IN ( " . dbesc($parents_str) . " )";
|
||||
}
|
||||
|
||||
require_once('include/items.php');
|
||||
|
||||
@@ -551,7 +554,6 @@ class Network extends \Zotlabs\Web\Controller {
|
||||
and (abook.abook_blocked = 0 or abook.abook_flags is null)
|
||||
$sql_extra3 $sql_extra $sql_options $sql_nets $net_query2"
|
||||
);
|
||||
$_SESSION['loadtime'] = datetime_convert();
|
||||
}
|
||||
|
||||
// Then fetch all the children of the parents that are on this page
|
||||
@@ -575,35 +577,6 @@ class Network extends \Zotlabs\Web\Controller {
|
||||
$items = array();
|
||||
}
|
||||
|
||||
if($page_mode === 'list') {
|
||||
|
||||
/**
|
||||
* in "list mode", only mark the parent item and any like activities as "seen".
|
||||
* We won't distinguish between comment likes and post likes. The important thing
|
||||
* is that the number of unseen comments will be accurate. The SQL to separate the
|
||||
* comment likes could also get somewhat hairy.
|
||||
*/
|
||||
|
||||
if($parents_str) {
|
||||
$update_unseen = " AND ( id IN ( " . dbesc($parents_str) . " )";
|
||||
$update_unseen .= " OR ( parent IN ( " . dbesc($parents_str) . " ) AND verb in ( '" . dbesc(ACTIVITY_LIKE) . "','" . dbesc(ACTIVITY_DISLIKE) . "' ))) ";
|
||||
}
|
||||
}
|
||||
else {
|
||||
if($parents_str) {
|
||||
$update_unseen = " AND parent IN ( " . dbesc($parents_str) . " )";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if($update_unseen) {
|
||||
$x = [ 'channel_id' => local_channel(), 'update' => 'unset' ];
|
||||
call_hooks('update_unseen',$x);
|
||||
if($x['update'] === 'unset' || intval($x['update'])) {
|
||||
$r = q("UPDATE item SET item_unseen = 0 WHERE item_unseen = 1 AND uid = %d $update_unseen ",
|
||||
intval(local_channel())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$mode = (($nouveau) ? 'network-new' : 'network');
|
||||
@@ -615,6 +588,8 @@ class Network extends \Zotlabs\Web\Controller {
|
||||
|
||||
if(($items) && (! $update))
|
||||
$o .= alt_pager(count($items));
|
||||
|
||||
$_SESSION['loadtime'] = datetime_convert();
|
||||
|
||||
return $o;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ namespace Zotlabs\Module;
|
||||
use App;
|
||||
use Zotlabs\Web\Controller;
|
||||
use Zotlabs\Lib\Apps;
|
||||
use Zotlabs\Lib\Libsync;
|
||||
|
||||
/**
|
||||
* @brief Notes Module controller.
|
||||
@@ -38,7 +39,7 @@ class Notes extends Controller {
|
||||
|
||||
if((argc() > 1) && (argv(1) === 'sync')) {
|
||||
require_once('include/zot.php');
|
||||
build_sync_packet();
|
||||
Libsync::build_sync_packet();
|
||||
}
|
||||
|
||||
logger('notes saved.', LOGGER_DEBUG);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user