mirror of
https://framagit.org/hubzilla/core.git
synced 2026-06-22 09:17:57 -04:00
Compare commits
1279 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e8f3b7f853 | ||
|
|
e28341ca4b | ||
|
|
6c11a020ee | ||
|
|
7200c2ac0c | ||
|
|
732ca49b02 | ||
|
|
ee976ed460 | ||
|
|
06ac3e896a | ||
|
|
6ce0f6e806 | ||
|
|
e006586275 | ||
|
|
e9d6b17a00 | ||
|
|
bf2f199f37 | ||
|
|
718ca548be | ||
|
|
51c0dc070a | ||
|
|
d5e0d52bc4 | ||
|
|
f6b99db738 | ||
|
|
ef69294072 | ||
|
|
c56d395c90 | ||
|
|
778e9141d8 | ||
|
|
c70a4662b4 | ||
|
|
e441a31051 | ||
|
|
9f5ec5cc50 | ||
|
|
825ded2e08 | ||
|
|
a7c3776557 | ||
|
|
1e7cfc2644 | ||
|
|
c6fd32ffde | ||
|
|
5f551a8b47 | ||
|
|
f73ff57148 | ||
|
|
c538d7372e | ||
|
|
4e7804ca75 | ||
|
|
8fe715983a | ||
|
|
4a3fb07d5f | ||
|
|
f5062c0507 | ||
|
|
f0d7a17b72 | ||
|
|
b89d2d7580 | ||
|
|
7a7f57fa45 | ||
|
|
047dd31724 | ||
|
|
0ce1a200f7 | ||
|
|
0e0024218f | ||
|
|
4886d088e9 | ||
|
|
6eec6e2d65 | ||
|
|
6c12880f5b | ||
|
|
eb472111a8 | ||
|
|
8d8b7ed567 | ||
|
|
681dc70205 | ||
|
|
130cfbf231 | ||
|
|
940e4a6152 | ||
|
|
38f7d9ad37 | ||
|
|
e896d316f2 | ||
|
|
af690b64d6 | ||
|
|
699aad8626 | ||
|
|
4382e53acb | ||
|
|
832adf92a6 | ||
|
|
33e2582918 | ||
|
|
1c2f413211 | ||
|
|
2300581c93 | ||
|
|
03c4fba730 | ||
|
|
75a8b209f5 | ||
|
|
d554b41fea | ||
|
|
b0db1f827e | ||
|
|
3070baf04e | ||
|
|
72629ca511 | ||
|
|
1c39fc71d9 | ||
|
|
0bb59b66be | ||
|
|
31b177f8ad | ||
|
|
8ee5ced08d | ||
|
|
c96a1632f5 | ||
|
|
b3b2649814 | ||
|
|
95805d2e7c | ||
|
|
d4b92141fd | ||
|
|
829e915c90 | ||
|
|
aaffc7485d | ||
|
|
9ea1d6e8af | ||
|
|
17661b4b5f | ||
|
|
32874b89ca | ||
|
|
d4a038c437 | ||
|
|
59fed33797 | ||
|
|
feea137dbf | ||
|
|
70e4a2c4fa | ||
|
|
696359daba | ||
|
|
5695350e98 | ||
|
|
4e3a0720c3 | ||
|
|
dc56d8560d | ||
|
|
81ecea29c8 | ||
|
|
ad58697521 | ||
|
|
6ca7527ec9 | ||
|
|
8ced3699c2 | ||
|
|
c4de5b45df | ||
|
|
71056e1db1 | ||
|
|
f94faeeace | ||
|
|
80f56a1315 | ||
|
|
485f5a07ed | ||
|
|
821af482f0 | ||
|
|
b2d1fadf66 | ||
|
|
3b73e5223e | ||
|
|
6a964e7caf | ||
|
|
a6f06c2d94 | ||
|
|
a85f0a93c6 | ||
|
|
250387c7e5 | ||
|
|
dde7144f5a | ||
|
|
68733a2bc0 | ||
|
|
b2d3a11de8 | ||
|
|
a024e4c10a | ||
|
|
db6e4d1c32 | ||
|
|
8393c382c3 | ||
|
|
5c0e3688fe | ||
|
|
1e6c07246e | ||
|
|
e5370971d6 | ||
|
|
090d921006 | ||
|
|
39c0a7525b | ||
|
|
407b02bde8 | ||
|
|
da7912b879 | ||
|
|
02c08aed12 | ||
|
|
87668f7fa8 | ||
|
|
001734a725 | ||
|
|
276ab3eae3 | ||
|
|
1b976f30f3 | ||
|
|
019afe2a1a | ||
|
|
37ebcd3b4f | ||
|
|
5ad6eeccdf | ||
|
|
65cd33cb15 | ||
|
|
4aa59226d7 | ||
|
|
d53c98860d | ||
|
|
d022e1acce | ||
|
|
98100520eb | ||
|
|
42526fc2dc | ||
|
|
9c76afa2a3 | ||
|
|
943db4496b | ||
|
|
4a77b6673b | ||
|
|
62b31b1e4a | ||
|
|
ddde4e1965 | ||
|
|
96a99935ef | ||
|
|
60c003733e | ||
|
|
9def9a5cb7 | ||
|
|
145295302d | ||
|
|
302d2dbd51 | ||
|
|
49ba3ffee6 | ||
|
|
d83ce0863a | ||
|
|
cf844cb27c | ||
|
|
5ccef18d4e | ||
|
|
40bbdfdf6a | ||
|
|
ad8ad0ccd7 | ||
|
|
1cf012650b | ||
|
|
4f280b5497 | ||
|
|
5ee7009271 | ||
|
|
07f850ed15 | ||
|
|
1b6fbe3a2e | ||
|
|
b1b415ec5b | ||
|
|
8730bbac2f | ||
|
|
e8918ca149 | ||
|
|
82478eef09 | ||
|
|
892e9cd835 | ||
|
|
3dd6499ac4 | ||
|
|
109c66aea3 | ||
|
|
24b0f8e27e | ||
|
|
1a76e83fa4 | ||
|
|
2fa788b01b | ||
|
|
028cbdcffa | ||
|
|
8aefbd911b | ||
|
|
f37387de80 | ||
|
|
4f705fc3f8 | ||
|
|
5b727065cf | ||
|
|
952e466d91 | ||
|
|
c1cc76119c | ||
|
|
9d156141b1 | ||
|
|
8c92b0cd3a | ||
|
|
dd515da889 | ||
|
|
2862b69d56 | ||
|
|
db8e46184b | ||
|
|
99a7cd3cfb | ||
|
|
75746d714a | ||
|
|
983d6d3b42 | ||
|
|
060dd8b020 | ||
|
|
b5be0a2e3e | ||
|
|
46a687b0a6 | ||
|
|
4ff7aa4352 | ||
|
|
750d1f820d | ||
|
|
f046a34d34 | ||
|
|
0d165920bb | ||
|
|
9e3a4402e0 | ||
|
|
34d7aea1be | ||
|
|
e2abc0b727 | ||
|
|
a677a68ab7 | ||
|
|
df228237de | ||
|
|
fc2a038ee1 | ||
|
|
619b39f955 | ||
|
|
becaa3b920 | ||
|
|
c0b9ab930d | ||
|
|
f106b1db15 | ||
|
|
958217dd55 | ||
|
|
2f80fdae97 | ||
|
|
9507f191b0 | ||
|
|
92f5d8c8be | ||
|
|
8535eb7bf5 | ||
|
|
c9604eaabf | ||
|
|
3bc214e544 | ||
|
|
43cec4398d | ||
|
|
335394aaa1 | ||
|
|
c9615cc19c | ||
|
|
5315d8fe3f | ||
|
|
75dedb3345 | ||
|
|
134dfb8804 | ||
|
|
86f4a8d33a | ||
|
|
abeb924554 | ||
|
|
4da3933f24 | ||
|
|
c5703306ef | ||
|
|
a26774b99e | ||
|
|
9258593776 | ||
|
|
48604041e8 | ||
|
|
57ed9ec8e2 | ||
|
|
801ab611ed | ||
|
|
bc34167c84 | ||
|
|
decd0dc035 | ||
|
|
9ac9c693ad | ||
|
|
9b2cd69c0f | ||
|
|
b3f1a19db6 | ||
|
|
f3b6708a92 | ||
|
|
8848885d9a | ||
|
|
c1cab6789e | ||
|
|
907777eeb0 | ||
|
|
7889612edc | ||
|
|
e81e264988 | ||
|
|
eacc29ded0 | ||
|
|
ea04c93bfd | ||
|
|
8692977585 | ||
|
|
6a40f3ed60 | ||
|
|
dd1f631d9d | ||
|
|
15874ac45c | ||
|
|
761fc74a67 | ||
|
|
0e2239e50b | ||
|
|
e9a17517d3 | ||
|
|
94254e61c1 | ||
|
|
9f403a4d6b | ||
|
|
55792d5528 | ||
|
|
a3f726baa8 | ||
|
|
ebc2b23c3a | ||
|
|
e4ca3609d9 | ||
|
|
bc092d8d78 | ||
|
|
dd5933b048 | ||
|
|
5d6128b25c | ||
|
|
24cb04c346 | ||
|
|
f1b54cf0a4 | ||
|
|
e64a7b87a8 | ||
|
|
2b452ea3e8 | ||
|
|
66c6c6c7d1 | ||
|
|
5b4aa1afc2 | ||
|
|
89205276ab | ||
|
|
6d2ab6a7d6 | ||
|
|
e6da910ee2 | ||
|
|
2100ac3cfc | ||
|
|
c7476a1d96 | ||
|
|
d8c3033941 | ||
|
|
7e26ee5a73 | ||
|
|
a8e25ccfe6 | ||
|
|
b6267ec7c2 | ||
|
|
b6bd2884d5 | ||
|
|
767a235611 | ||
|
|
620fc06b6c | ||
|
|
0fa4c89a1b | ||
|
|
1bf046c142 | ||
|
|
52f8429218 | ||
|
|
932b414063 | ||
|
|
097b2390db | ||
|
|
ca8d252ad7 | ||
|
|
23a0dbe3cc | ||
|
|
545ece82b3 | ||
|
|
eaea947b74 | ||
|
|
f1b61d5882 | ||
|
|
e466d72058 | ||
|
|
385be35ed5 | ||
|
|
528b9b6a60 | ||
|
|
dd374eaebf | ||
|
|
9ea483d1dc | ||
|
|
b1813df61a | ||
|
|
8715f74d29 | ||
|
|
152224944b | ||
|
|
f86d12c8f4 | ||
|
|
94d4bc4bac | ||
|
|
c95488549d | ||
|
|
39613aa2d9 | ||
|
|
7c2aafd4ee | ||
|
|
e834c7fe3e | ||
|
|
f96958adf8 | ||
|
|
776074b24f | ||
|
|
c9d64d75f3 | ||
|
|
9651689bb8 | ||
|
|
75be0475ba | ||
|
|
e130b58b20 | ||
|
|
e44f0c497f | ||
|
|
2d0f96d28b | ||
|
|
34d1f79777 | ||
|
|
2185ccd4ea | ||
|
|
125634759d | ||
|
|
350e636e3d | ||
|
|
429140df97 | ||
|
|
a921deafd1 | ||
|
|
071fba2f71 | ||
|
|
9de729e3e7 | ||
|
|
7cf5bd30f2 | ||
|
|
e6cee2965a | ||
|
|
af2b263bc7 | ||
|
|
aa120e0478 | ||
|
|
b07c55a0d9 | ||
|
|
e7f1f496c5 | ||
|
|
823c0434eb | ||
|
|
22162635e7 | ||
|
|
8be0031602 | ||
|
|
29c5e74d31 | ||
|
|
3c8867a1e8 | ||
|
|
c439fe0437 | ||
|
|
b21db670b4 | ||
|
|
1f84aa9809 | ||
|
|
4ac249c26c | ||
|
|
85a29fce94 | ||
|
|
71ecb470b6 | ||
|
|
15a000bb45 | ||
|
|
18e4a7ac6e | ||
|
|
d0322f5fbd | ||
|
|
c1f01b7e35 | ||
|
|
71064f481b | ||
|
|
436293713b | ||
|
|
fc726bfb4b | ||
|
|
b0c3780667 | ||
|
|
3e431c65be | ||
|
|
5b0b90d1f5 | ||
|
|
d16714e84b | ||
|
|
1d5fff9f58 | ||
|
|
fbe8d6144a | ||
|
|
d5f59a57bf | ||
|
|
7465c79884 | ||
|
|
769195fcff | ||
|
|
dc786bd1cc | ||
|
|
960f4ed649 | ||
|
|
91ad3bf1b6 | ||
|
|
91b495d526 | ||
|
|
973d91d120 | ||
|
|
bf5deace8e | ||
|
|
0e4acf6299 | ||
|
|
a5cd0061c5 | ||
|
|
630e3903fa | ||
|
|
0b6a5fad70 | ||
|
|
67ca1b82cc | ||
|
|
9866053f0c | ||
|
|
89a2c1a09c | ||
|
|
70220d8b9c | ||
|
|
274f69526f | ||
|
|
d7026fe36b | ||
|
|
b9b65d7dfb | ||
|
|
1545c78d05 | ||
|
|
f0c292e77b | ||
|
|
62336127e3 | ||
|
|
5beaf8ac98 | ||
|
|
9efd484e27 | ||
|
|
44d5cf980a | ||
|
|
e53650d6c6 | ||
|
|
5bf9a9828c | ||
|
|
24f3bc9f0c | ||
|
|
c200e55f95 | ||
|
|
ea19d59fca | ||
|
|
d34d14c1f4 | ||
|
|
7b17306dbd | ||
|
|
6731564c2d | ||
|
|
194ba0cf8d | ||
|
|
6fc2429540 | ||
|
|
bdcbe61273 | ||
|
|
de5d7bfbd3 | ||
|
|
242878c45c | ||
|
|
c0911da887 | ||
|
|
6e0bf04276 | ||
|
|
56c460d932 | ||
|
|
f0933b66a9 | ||
|
|
422d633f89 | ||
|
|
0537be129c | ||
|
|
9b947c8370 | ||
|
|
14eb4326e7 | ||
|
|
89a3e8fcc7 | ||
|
|
6fd5133bed | ||
|
|
e010877490 | ||
|
|
f56371c79b | ||
|
|
c98f3c5d29 | ||
|
|
5c8de9d82f | ||
|
|
b9c8b6ba23 | ||
|
|
6cd968b53b | ||
|
|
2aa76d257c | ||
|
|
32c0be8bde | ||
|
|
88d283a89d | ||
|
|
66b370c421 | ||
|
|
20bf139b3f | ||
|
|
1da4602567 | ||
|
|
e7ef69e6e7 | ||
|
|
d55904d4db | ||
|
|
740dc59255 | ||
|
|
98b6362c07 | ||
|
|
cd829c096b | ||
|
|
f127c55802 | ||
|
|
13247a0e00 | ||
|
|
609752d331 | ||
|
|
413410d02d | ||
|
|
3528610a51 | ||
|
|
59ee045c24 | ||
|
|
b1dec12893 | ||
|
|
319b0acdd8 | ||
|
|
c605c46f83 | ||
|
|
9ef692b48c | ||
|
|
6da4dfe605 | ||
|
|
7b4cb31a10 | ||
|
|
03ce4d7e2b | ||
|
|
f55f5fa92a | ||
|
|
76757ad1f2 | ||
|
|
347e88dc65 | ||
|
|
746d032e58 | ||
|
|
b6d598a001 | ||
|
|
b35961c53c | ||
|
|
47fba5827b | ||
|
|
47f75ad8bf | ||
|
|
516167c0f8 | ||
|
|
238b3a97a8 | ||
|
|
d4ab8a5a5d | ||
|
|
6672299f8a | ||
|
|
ea5f515f18 | ||
|
|
ea6293544d | ||
|
|
cbe35281b9 | ||
|
|
51a0fc45e2 | ||
|
|
1e7e2bd34f | ||
|
|
fa2f3d136f | ||
|
|
92b6026695 | ||
|
|
c9a5f21344 | ||
|
|
0174bf3722 | ||
|
|
0d003e7450 | ||
|
|
8847838c43 | ||
|
|
9594ce9a8a | ||
|
|
4a91d09c86 | ||
|
|
06837bd32b | ||
|
|
b8d8887d5a | ||
|
|
256f8dd41b | ||
|
|
e0fdafc7e5 | ||
|
|
9a55df245f | ||
|
|
9800d95c50 | ||
|
|
c340416c94 | ||
|
|
9af8a1d30c | ||
|
|
4da96ee980 | ||
|
|
21637e033c | ||
|
|
9ebf2dc97b | ||
|
|
a04689b784 | ||
|
|
5066945adc | ||
|
|
e945c12856 | ||
|
|
0b062d0b8a | ||
|
|
9cc1eff15c | ||
|
|
327e5d06e1 | ||
|
|
a2dd0aea92 | ||
|
|
39da3459c7 | ||
|
|
c0be4c36e1 | ||
|
|
31e04378cd | ||
|
|
e80c99ad74 | ||
|
|
d9be443e53 | ||
|
|
6db323b15e | ||
|
|
5abbfd3f19 | ||
|
|
674215e9e6 | ||
|
|
dce6a5763d | ||
|
|
d89d6e8a01 | ||
|
|
6230dbed2d | ||
|
|
9641254443 | ||
|
|
95871fe13c | ||
|
|
0cecfceb14 | ||
|
|
13970280d9 | ||
|
|
55ce80aabe | ||
|
|
9536a490b3 | ||
|
|
405e07f0a2 | ||
|
|
d3ce91bd89 | ||
|
|
eb44201c5f | ||
|
|
73248aadd5 | ||
|
|
f6a4084f81 | ||
|
|
d5f89c165a | ||
|
|
a518471a27 | ||
|
|
dce5080e53 | ||
|
|
2221d4d612 | ||
|
|
5f73a46c05 | ||
|
|
b782c6bd16 | ||
|
|
ab8d8aa552 | ||
|
|
f955276694 | ||
|
|
77cc60faf2 | ||
|
|
a6f50b8c85 | ||
|
|
e2dfa1d72f | ||
|
|
9a61c0a6fc | ||
|
|
e10b25a12c | ||
|
|
0c1e803208 | ||
|
|
b57dcc74d1 | ||
|
|
f8c583636c | ||
|
|
e6521d1cf3 | ||
|
|
96785e8df1 | ||
|
|
d689778465 | ||
|
|
3c8f8b76aa | ||
|
|
c123fa5422 | ||
|
|
0ade8be7f7 | ||
|
|
a60c2f38c6 | ||
|
|
f1c0797780 | ||
|
|
701167bc12 | ||
|
|
a39e63e324 | ||
|
|
8401e9c2b4 | ||
|
|
c5fca0a1e7 | ||
|
|
e779335d06 | ||
|
|
26039adf5b | ||
|
|
c88286556a | ||
|
|
831b9d4433 | ||
|
|
e937e8fff9 | ||
|
|
f616b2d49a | ||
|
|
fe84dae313 | ||
|
|
9104933b18 | ||
|
|
79654635d3 | ||
|
|
f0edfca75c | ||
|
|
e845da2edc | ||
|
|
7a3050f2c0 | ||
|
|
9a6531e2a2 | ||
|
|
a6a17a85f3 | ||
|
|
9275fd16c2 | ||
|
|
904ae05810 | ||
|
|
54f95389a8 | ||
|
|
a8fc70a5b9 | ||
|
|
c374072822 | ||
|
|
0212de68a4 | ||
|
|
2ea9b6d409 | ||
|
|
823d71df28 | ||
|
|
7560918b32 | ||
|
|
fd87faa7a6 | ||
|
|
cb2d706fa1 | ||
|
|
6b638ac896 | ||
|
|
2bd5ae3617 | ||
|
|
39a5311315 | ||
|
|
9b6e46dc6b | ||
|
|
7311d1182d | ||
|
|
ea1d8b8104 | ||
|
|
fb03e3f00e | ||
|
|
c9c35255e7 | ||
|
|
99a578dbad | ||
|
|
e56c0a6251 | ||
|
|
66479e2aa7 | ||
|
|
6feddcbced | ||
|
|
db020ca1a3 | ||
|
|
6c93518ef7 | ||
|
|
eb02d01eed | ||
|
|
7a9093f634 | ||
|
|
1732b2dfe3 | ||
|
|
a62f891a60 | ||
|
|
a22ecd42ed | ||
|
|
b7cb2a2951 | ||
|
|
c490970324 | ||
|
|
5a9c8a9343 | ||
|
|
5ba7e5d7d7 | ||
|
|
f7b281a65f | ||
|
|
df5a1c59e6 | ||
|
|
0615709a7a | ||
|
|
d85a0130b7 | ||
|
|
71f17a233e | ||
|
|
25c35cbbe4 | ||
|
|
257ba570ee | ||
|
|
91e96b2314 | ||
|
|
c2ee7cbff5 | ||
|
|
27f813e043 | ||
|
|
00ed91f12e | ||
|
|
4cb5efc277 | ||
|
|
65a453d21b | ||
|
|
9c8cb4dea3 | ||
|
|
ed902fdb70 | ||
|
|
509067391b | ||
|
|
04b261057d | ||
|
|
852343f254 | ||
|
|
26e35344d0 | ||
|
|
d3a619659f | ||
|
|
979f2415fb | ||
|
|
28c1d219f6 | ||
|
|
5792f4bf07 | ||
|
|
3a0fa5cb29 | ||
|
|
074ee656f0 | ||
|
|
064f93185c | ||
|
|
4b5922f652 | ||
|
|
85be906b68 | ||
|
|
775285cdf8 | ||
|
|
42f96dc7a6 | ||
|
|
e96fa64625 | ||
|
|
8dc495c9bc | ||
|
|
5d70d889e9 | ||
|
|
999ae6eb49 | ||
|
|
ae1450bbcf | ||
|
|
dcd8a05809 | ||
|
|
62e466f774 | ||
|
|
70777a047d | ||
|
|
47fd95db9d | ||
|
|
7602d9e54b | ||
|
|
1ed0079882 | ||
|
|
b026be410c | ||
|
|
767a1711ff | ||
|
|
a93bd8d944 | ||
|
|
4e12f86e90 | ||
|
|
3007009fab | ||
|
|
2d886b65ce | ||
|
|
8700b87030 | ||
|
|
5a46f1229d | ||
|
|
9d5f8883a7 | ||
|
|
8e0b9b82e9 | ||
|
|
ea4b4ddce4 | ||
|
|
bd95c7b82a | ||
|
|
e20c5cf9cf | ||
|
|
6adb489cb3 | ||
|
|
0c2db1cea5 | ||
|
|
e33604887b | ||
|
|
410f37df1b | ||
|
|
c9f3883c8c | ||
|
|
4346d7605d | ||
|
|
a0a2c27973 | ||
|
|
3fb87ee76e | ||
|
|
242aeea24c | ||
|
|
c305dc8d22 | ||
|
|
f61b898633 | ||
|
|
2bdcd436bb | ||
|
|
a1bea7d7cc | ||
|
|
b2bdc73164 | ||
|
|
cbaf0a3864 | ||
|
|
103563b375 | ||
|
|
595429fdde | ||
|
|
b384b27546 | ||
|
|
0b996245d5 | ||
|
|
1ee91dd690 | ||
|
|
f9e602c44c | ||
|
|
4fa827ddfd | ||
|
|
1b3c73618c | ||
|
|
7b08f1cc8c | ||
|
|
7d392e5adb | ||
|
|
f44cc2b60c | ||
|
|
31680898e3 | ||
|
|
318fd7c9e3 | ||
|
|
b10b8ca3f4 | ||
|
|
b0c33308be | ||
|
|
1421c4e9d3 | ||
|
|
f55dfc9025 | ||
|
|
c218970890 | ||
|
|
bd27ce2520 | ||
|
|
44795b65f9 | ||
|
|
af84c4e6bd | ||
|
|
0a28207200 | ||
|
|
8ca2a5832c | ||
|
|
333534dfe7 | ||
|
|
d8ce0d0df0 | ||
|
|
28c3259449 | ||
|
|
0d0ede7b14 | ||
|
|
9ebf6bcc92 | ||
|
|
9d186e9ba3 | ||
|
|
3c3a4526bf | ||
|
|
3094c2ce17 | ||
|
|
393494a728 | ||
|
|
d2725c3f49 | ||
|
|
4d4425a5bf | ||
|
|
c11fbe0868 | ||
|
|
c676689df0 | ||
|
|
0f5625d721 | ||
|
|
6f5e6bd0f1 | ||
|
|
a0af092ecb | ||
|
|
3a07a194ab | ||
|
|
682ffa7cf5 | ||
|
|
dc4a4ca9d3 | ||
|
|
33ac85f637 | ||
|
|
efd9421dc9 | ||
|
|
9b696a872b | ||
|
|
aab515b16c | ||
|
|
f220628354 | ||
|
|
322bc5dc87 | ||
|
|
75c3bda866 | ||
|
|
b2b776169b | ||
|
|
8e8d7ae614 | ||
|
|
fa1af5a2cb | ||
|
|
a27e4072b4 | ||
|
|
fad26a49be | ||
|
|
1742159345 | ||
|
|
ed8d2cb482 | ||
|
|
8e1f022810 | ||
|
|
4c25072c18 | ||
|
|
564ec32520 | ||
|
|
a743feb040 | ||
|
|
b028667de1 | ||
|
|
41888f84bc | ||
|
|
6a918dbde9 | ||
|
|
578230e32c | ||
|
|
d486b03089 | ||
|
|
8559334339 | ||
|
|
968c6ed8be | ||
|
|
8893d9edc4 | ||
|
|
43753ec113 | ||
|
|
2ec3e4a912 | ||
|
|
a086745ec0 | ||
|
|
51156d0582 | ||
|
|
ea9925f489 | ||
|
|
026b96b8f2 | ||
|
|
136b2ae37f | ||
|
|
97009a2748 | ||
|
|
e123f7c743 | ||
|
|
e28bde6ccd | ||
|
|
a976f418e3 | ||
|
|
3c701e780c | ||
|
|
769dd174bd | ||
|
|
e92514ee63 | ||
|
|
8ebc517b41 | ||
|
|
91b03e52f1 | ||
|
|
a22406c9f8 | ||
|
|
ebc3666c6f | ||
|
|
f1fee1239b | ||
|
|
8769fa0156 | ||
|
|
f4d7338687 | ||
|
|
6a8c3f82ef | ||
|
|
05bcbfa28c | ||
|
|
6a55500c1b | ||
|
|
a5a5ac60ba | ||
|
|
6ed7f47b3f | ||
|
|
a3e94855f9 | ||
|
|
503da97a79 | ||
|
|
088a93e023 | ||
|
|
30f71ad632 | ||
|
|
0026849821 | ||
|
|
cf5a310286 | ||
|
|
72384ff2cb | ||
|
|
c33ef01af8 | ||
|
|
11116bdcb7 | ||
|
|
09a5cf4e68 | ||
|
|
a9172129d2 | ||
|
|
3ec06705ca | ||
|
|
5fb0d38ad8 | ||
|
|
9ed5cddb89 | ||
|
|
4e97fb0e58 | ||
|
|
1688e373bc | ||
|
|
cada0b6df1 | ||
|
|
91358010a0 | ||
|
|
51024d3821 | ||
|
|
220d6ed494 | ||
|
|
b5ed3edc8f | ||
|
|
9772726065 | ||
|
|
8ecdde6cb5 | ||
|
|
73c96f35c1 | ||
|
|
5b3824917d | ||
|
|
ca4f10dc5e | ||
|
|
853fb33913 | ||
|
|
e352cfc861 | ||
|
|
b8d79d9132 | ||
|
|
507c71f64c | ||
|
|
ce0067d8eb | ||
|
|
c0b238b19a | ||
|
|
d961cf21fb | ||
|
|
1f7622e4c4 | ||
|
|
b019ca0746 | ||
|
|
04fe7e61de | ||
|
|
beb4e00afb | ||
|
|
3e6607585f | ||
|
|
0b2213dd41 | ||
|
|
9450305568 | ||
|
|
08725c44c6 | ||
|
|
e18c64c9d9 | ||
|
|
7b018c60cb | ||
|
|
a81286c795 | ||
|
|
75a66b716e | ||
|
|
0c05e6593e | ||
|
|
571e9bf26a | ||
|
|
c4714e95b6 | ||
|
|
c43ab50d66 | ||
|
|
26e7da0b96 | ||
|
|
98b1c7a38c | ||
|
|
d407e5556e | ||
|
|
6a3cfe54af | ||
|
|
a0bffe4a78 | ||
|
|
336c716a44 | ||
|
|
ccdbec619c | ||
|
|
47001c3303 | ||
|
|
8e50fecccc | ||
|
|
938fcdd1a6 | ||
|
|
9ede57b228 | ||
|
|
8810658858 | ||
|
|
e074d02714 | ||
|
|
e26de9c1d1 | ||
|
|
7dc3835a54 | ||
|
|
117a8cafca | ||
|
|
337dfd5ee4 | ||
|
|
e37c9ed0a1 | ||
|
|
aa6a31eba5 | ||
|
|
8a0a0aef5c | ||
|
|
4750e15c20 | ||
|
|
747ce9b1f1 | ||
|
|
7fa874d9ef | ||
|
|
5febc3e07d | ||
|
|
2244bf2ba2 | ||
|
|
29cb62af3d | ||
|
|
6aa041b193 | ||
|
|
0fdc0a01d0 | ||
|
|
de7f2eef47 | ||
|
|
a449ffe49d | ||
|
|
08cacc4943 | ||
|
|
04b9216758 | ||
|
|
1ff97754af | ||
|
|
20e43311db | ||
|
|
89bcb1de42 | ||
|
|
7a1a44f802 | ||
|
|
06aa32db22 | ||
|
|
6f8593cf47 | ||
|
|
3b2efb1000 | ||
|
|
87482e3746 | ||
|
|
ef6a280019 | ||
|
|
326ae05b06 | ||
|
|
3f13c85b64 | ||
|
|
1ae7bd6477 | ||
|
|
c91641aa83 | ||
|
|
f92d2e3f7c | ||
|
|
3e2489465f | ||
|
|
a5bf32a97d | ||
|
|
8bb2d29a8d | ||
|
|
a9b75d059b | ||
|
|
938e8110ca | ||
|
|
93039081d5 | ||
|
|
3d253309b7 | ||
|
|
301c1861f3 | ||
|
|
a3a90ea09b | ||
|
|
e6f289deb6 | ||
|
|
0e22618d93 | ||
|
|
a0ad110cff | ||
|
|
89ee28f858 | ||
|
|
5917786296 | ||
|
|
7f1e0313a0 | ||
|
|
c89be96209 | ||
|
|
fcd6c3065e | ||
|
|
a700ef5e24 | ||
|
|
3a6ea57d2c | ||
|
|
e960bcfd1c | ||
|
|
65e8ed6871 | ||
|
|
a77d7b8442 | ||
|
|
51e9f302b0 | ||
|
|
72fd1cc5a6 | ||
|
|
1a77bdd1d0 | ||
|
|
1ea9002fe8 | ||
|
|
7d1c3920fd | ||
|
|
c5bb074573 | ||
|
|
cead10b9af | ||
|
|
382e94e282 | ||
|
|
7e8434404f | ||
|
|
cfcbaf33af | ||
|
|
175f78fa84 | ||
|
|
c8ab2bec5e | ||
|
|
136d50a7c5 | ||
|
|
0fa653d580 | ||
|
|
48f2c85791 | ||
|
|
13ca56d380 | ||
|
|
b5109d2a1a | ||
|
|
8ab532efb5 | ||
|
|
f11c17063c | ||
|
|
72eb44aebc | ||
|
|
b070503e77 | ||
|
|
f48e1ee0ac | ||
|
|
a5b7590d3a | ||
|
|
f0955f1620 | ||
|
|
4769254978 | ||
|
|
ca917f7b9a | ||
|
|
b9df4c99cf | ||
|
|
e6dadb215e | ||
|
|
d70bba2806 | ||
|
|
3217452b02 | ||
|
|
ff0494b180 | ||
|
|
8be15c1b5b | ||
|
|
0207b5ba8b | ||
|
|
5ab917f606 | ||
|
|
ea541ca21b | ||
|
|
fc223f5924 | ||
|
|
7b8eb84cb8 | ||
|
|
c3e2b463e4 | ||
|
|
5b3ea012ab | ||
|
|
07df43aa2a | ||
|
|
6e3bc77369 | ||
|
|
24ddefe3ad | ||
|
|
7db645587b | ||
|
|
cbf6d53e84 | ||
|
|
f52a532771 | ||
|
|
efc4c53b44 | ||
|
|
4837f9cdad | ||
|
|
317c53acf6 | ||
|
|
f02af5fe6e | ||
|
|
92e6c21210 | ||
|
|
beb26e84f3 | ||
|
|
2b7a605223 | ||
|
|
d70f0092f7 | ||
|
|
7f6e4a9744 | ||
|
|
96a4fc7ca2 | ||
|
|
29c1797493 | ||
|
|
860dead985 | ||
|
|
518ceb53a8 | ||
|
|
4bcddca1f0 | ||
|
|
cf80f03084 | ||
|
|
47f31eed37 | ||
|
|
8ff9a9ff08 | ||
|
|
8dcf27ba29 | ||
|
|
d97043725d | ||
|
|
90fd323ac5 | ||
|
|
b6c384a0f7 | ||
|
|
cda8a7be38 | ||
|
|
c657d766cf | ||
|
|
4706ff6938 | ||
|
|
c444af007f | ||
|
|
6e80bb49fb | ||
|
|
bf3d0c1274 | ||
|
|
0ded1d326c | ||
|
|
708d288121 | ||
|
|
6462c83f69 | ||
|
|
f30bb452cc | ||
|
|
ad4dd2def5 | ||
|
|
76582a60b5 | ||
|
|
004246163d | ||
|
|
a2cae45f00 | ||
|
|
c1159337da | ||
|
|
71adbd7c39 | ||
|
|
a56bc0e1e0 | ||
|
|
519db2aace | ||
|
|
e64c5661da | ||
|
|
b15421826d | ||
|
|
3b31dbaa16 | ||
|
|
318957cb81 | ||
|
|
4b516fdb09 | ||
|
|
913b620c66 | ||
|
|
cd4d90c647 | ||
|
|
456207b4e7 | ||
|
|
39604d2fdc | ||
|
|
27e415e664 | ||
|
|
c57a4cf926 | ||
|
|
0a868b5c27 | ||
|
|
753f137575 | ||
|
|
728788e3b9 | ||
|
|
ec6e130eb3 | ||
|
|
8972ca8134 | ||
|
|
671b6d2eda | ||
|
|
043f7bf2ab | ||
|
|
625cdde9a4 | ||
|
|
e3d39fbf3f | ||
|
|
94cbc8bd31 | ||
|
|
e262de9b2d | ||
|
|
17d9e30be5 | ||
|
|
37b7dc8e7c | ||
|
|
5c2f7a744a | ||
|
|
535f0f45c9 | ||
|
|
b9cef2f38f | ||
|
|
793d78fba6 | ||
|
|
5ad055efb4 | ||
|
|
3277595366 | ||
|
|
b11be32063 | ||
|
|
725652006d | ||
|
|
10587e3a84 | ||
|
|
073115e7ab | ||
|
|
45dcd987c5 | ||
|
|
960246fbb9 | ||
|
|
2fa274de1e | ||
|
|
4cc98874a0 | ||
|
|
fafd05afb2 | ||
|
|
7a3ad30bfa | ||
|
|
32acf9cb72 | ||
|
|
ddbc35181c | ||
|
|
0946ac2ff9 | ||
|
|
1d314834a4 | ||
|
|
13e0151cd2 | ||
|
|
51a7be29f5 | ||
|
|
ef46738384 | ||
|
|
54806f6ee8 | ||
|
|
ae538a2259 | ||
|
|
66f443fd00 | ||
|
|
ca9c29e2b6 | ||
|
|
273beb016b | ||
|
|
cd8a0f33b5 | ||
|
|
b1e05b4832 | ||
|
|
4c0378eeae | ||
|
|
ea14398929 | ||
|
|
1b5dd8bbd7 | ||
|
|
4e8fc6d198 | ||
|
|
39128c34cc | ||
|
|
542d21c4e1 | ||
|
|
90a62405ca | ||
|
|
bba20c27fe | ||
|
|
d355e57fa6 | ||
|
|
f2d7c4091a | ||
|
|
bf879ce742 | ||
|
|
e89a3b05ec | ||
|
|
52305ca91b | ||
|
|
d6167636fa | ||
|
|
cc1e1a525f | ||
|
|
96deae43fa | ||
|
|
5aa0267936 | ||
|
|
b1b1e0eba4 | ||
|
|
07f6465872 | ||
|
|
eda7c5369c | ||
|
|
e9f709301c | ||
|
|
7e29bd10b6 | ||
|
|
20eea2184b | ||
|
|
eaa375936f | ||
|
|
de8582ec07 | ||
|
|
e6ccdc2378 | ||
|
|
4450a01014 | ||
|
|
a1ac507a94 | ||
|
|
ad6eb15eac | ||
|
|
2e94e4cd67 | ||
|
|
c26e112bee | ||
|
|
7daf18b077 | ||
|
|
a8a5d2fc4e | ||
|
|
90f6abfa7c | ||
|
|
65f2d7fd66 | ||
|
|
f3554804bf | ||
|
|
f5e571ba40 | ||
|
|
e43331b7a2 | ||
|
|
e78fd09e07 | ||
|
|
b4c1ca88f3 | ||
|
|
dba9c2fbb0 | ||
|
|
ab074f52fe | ||
|
|
121fa834d5 | ||
|
|
598cbf2210 | ||
|
|
9e42dfd094 | ||
|
|
8aa117e4ae | ||
|
|
f6f4e40a64 | ||
|
|
caf2c0a6c4 | ||
|
|
57dde3e980 | ||
|
|
dc8da4717f | ||
|
|
7b30fc4b82 | ||
|
|
6791b05a40 | ||
|
|
b54ddccd7b | ||
|
|
d32360cb3e | ||
|
|
3eba0c2297 | ||
|
|
01f4ce96f1 | ||
|
|
90b6afe06b | ||
|
|
b22caef65f | ||
|
|
db4281164c | ||
|
|
217c2cacaf | ||
|
|
df4b6f0376 | ||
|
|
6ec1bfebec | ||
|
|
5d88326915 | ||
|
|
24354b9dcc | ||
|
|
39de8e28da | ||
|
|
06beb59628 | ||
|
|
563a5088be | ||
|
|
c10c59db4b | ||
|
|
463f084b3e | ||
|
|
312e0dcbc8 | ||
|
|
6f93001658 | ||
|
|
48821a6da5 | ||
|
|
b93bc142d3 | ||
|
|
ab9b8b8b0a | ||
|
|
1c4a90626a | ||
|
|
3bf1866f4a | ||
|
|
1a652b555f | ||
|
|
3f61d24d0a | ||
|
|
16064d5614 | ||
|
|
d9f21db623 | ||
|
|
8ac541e634 | ||
|
|
da2688403e | ||
|
|
dbd230da74 | ||
|
|
f660530ef5 | ||
|
|
a19563e139 | ||
|
|
c4400cf72a | ||
|
|
aae4943e64 | ||
|
|
b0339b848f | ||
|
|
f3f106c21f | ||
|
|
a50433dd95 | ||
|
|
37d7d18bb7 | ||
|
|
cdb85f1309 | ||
|
|
6d7fba6758 | ||
|
|
fac3579fb0 | ||
|
|
458b023204 | ||
|
|
4bad4ec632 | ||
|
|
e34853e19e | ||
|
|
6cbdb1b4c3 | ||
|
|
60f890ce0d | ||
|
|
c82c0a9812 | ||
|
|
123b1d4002 | ||
|
|
e4958d5bb9 | ||
|
|
89e734dcca | ||
|
|
090fe394e4 | ||
|
|
389b4beba4 | ||
|
|
ec769bc9f9 | ||
|
|
6b259070f0 | ||
|
|
7a55dd512a | ||
|
|
774dd6d5e3 | ||
|
|
4cbaddf4c4 | ||
|
|
10f1da2736 | ||
|
|
0e5d76e735 | ||
|
|
339c9cceec | ||
|
|
2354bb5427 | ||
|
|
fe80f8179c | ||
|
|
b97143e9db | ||
|
|
aaab905e72 | ||
|
|
bc6d384ca9 | ||
|
|
6fc8c174f9 | ||
|
|
63b205c601 | ||
|
|
15ce8bc79b | ||
|
|
8d70b91955 | ||
|
|
a33ed05bec | ||
|
|
aace8a14ce | ||
|
|
d80b8ff30f | ||
|
|
3a66255576 | ||
|
|
1541f67eab | ||
|
|
a2959c6e9e | ||
|
|
70a7661711 | ||
|
|
d190b1995b | ||
|
|
a6f8230063 | ||
|
|
e4c60d70b0 | ||
|
|
4d8a815932 | ||
|
|
b0e5f5973a | ||
|
|
05cb4fd897 | ||
|
|
72dc6ea77c | ||
|
|
1b0a6fe9eb | ||
|
|
363ad01bce | ||
|
|
04a45a407e | ||
|
|
14735e0a48 | ||
|
|
1c07428f89 | ||
|
|
e0d68664c4 | ||
|
|
6c72c3d4a5 | ||
|
|
5bcc379530 | ||
|
|
c854ec0686 | ||
|
|
6a825cc504 | ||
|
|
3ed6763da9 | ||
|
|
dbeabb8ff0 | ||
|
|
cc66e1d966 | ||
|
|
919ea9f750 | ||
|
|
09b2cdd618 | ||
|
|
1e526e68ab | ||
|
|
4ff3c57976 | ||
|
|
3416190e4b | ||
|
|
de7cb6d6ad | ||
|
|
eb297104de | ||
|
|
03a214c8b9 | ||
|
|
3f06a857c2 | ||
|
|
f81a3ba45d | ||
|
|
c771d2809f | ||
|
|
fc78206049 | ||
|
|
618d673947 | ||
|
|
6464099364 | ||
|
|
6bea3d6bfc | ||
|
|
993db01400 | ||
|
|
4cb4f17500 | ||
|
|
15a689c6f5 | ||
|
|
7894fed741 | ||
|
|
61f7c1e7d7 | ||
|
|
30efeb5bec | ||
|
|
18caf0273f | ||
|
|
214b81e491 | ||
|
|
e60fb17524 | ||
|
|
7f65d82a74 | ||
|
|
8ab1f31058 | ||
|
|
4cd5529027 | ||
|
|
d12744011a | ||
|
|
c0e4c92d47 | ||
|
|
cc3e910194 | ||
|
|
5d9f993352 | ||
|
|
eaa52c19a8 | ||
|
|
42aeb19562 | ||
|
|
ffc3dba682 | ||
|
|
1acc5ceb5f | ||
|
|
7d694dca07 | ||
|
|
7a693500c4 | ||
|
|
1c44912aff | ||
|
|
5e14da67e1 | ||
|
|
b586fcebab | ||
|
|
244c0d828a | ||
|
|
57ebd7e170 | ||
|
|
5776471547 | ||
|
|
c50e3a702a | ||
|
|
2173ef5fb6 | ||
|
|
1f6da1c653 | ||
|
|
c165894ce9 | ||
|
|
19903ea3c1 | ||
|
|
0b38ab259c | ||
|
|
237c6eed50 | ||
|
|
f13b1e8604 | ||
|
|
2a57e00cb4 | ||
|
|
52424b0f9c | ||
|
|
132547a9d9 | ||
|
|
fdb0459288 | ||
|
|
df84352385 | ||
|
|
8d4f6a7865 | ||
|
|
6f22e47feb | ||
|
|
c6acb6191c | ||
|
|
6cade7d935 | ||
|
|
c857ecab46 | ||
|
|
53d9cbc69c | ||
|
|
0ee403eab3 | ||
|
|
6f2d09eb20 | ||
|
|
d6442ec991 | ||
|
|
f3831fa77f | ||
|
|
3265c2e543 | ||
|
|
1a9ea64523 | ||
|
|
9de650e175 | ||
|
|
d8b5f383f5 | ||
|
|
6aa99a903f | ||
|
|
d9faf6c4bb | ||
|
|
48cd5855fe | ||
|
|
bd0fc8a2d7 | ||
|
|
476bd7400d | ||
|
|
bd10d48338 | ||
|
|
bb91064416 | ||
|
|
72d2fe2fd4 | ||
|
|
92a5b9ac41 | ||
|
|
cded6b1136 | ||
|
|
19f0ce7e37 | ||
|
|
a88a515fa0 | ||
|
|
a4b2eac0f0 | ||
|
|
0bd38290e6 | ||
|
|
19e4f3c2f0 | ||
|
|
8bede7b81f | ||
|
|
37d563c30e | ||
|
|
3775be4ce9 | ||
|
|
5ac08ec3aa | ||
|
|
e5883dd605 | ||
|
|
6b02c664fb | ||
|
|
c7ae3fdc9a | ||
|
|
c667572d3e | ||
|
|
9bbd6ff67d | ||
|
|
ca98a566ee | ||
|
|
f865d6e5da | ||
|
|
bc9f2922e0 | ||
|
|
c5a9b00eae | ||
|
|
f408ff982c | ||
|
|
9a8d1200ec | ||
|
|
16c7aa2813 | ||
|
|
85f52d2aed | ||
|
|
8e71324514 | ||
|
|
ea235c0c67 | ||
|
|
e30be643c9 | ||
|
|
07fd2dbc99 | ||
|
|
6481c9dca1 | ||
|
|
7aaa1973f4 | ||
|
|
4dea1b5a0d | ||
|
|
da44ab0529 | ||
|
|
73b836c73d | ||
|
|
af0c2f59cc | ||
|
|
dffc0a4ed8 | ||
|
|
0525eb2d29 | ||
|
|
f34af496ec | ||
|
|
3787c490d4 | ||
|
|
c3f1aae570 | ||
|
|
0c94747ab1 | ||
|
|
783cca1e13 | ||
|
|
238a616292 | ||
|
|
6010b5c619 | ||
|
|
4812c5486d | ||
|
|
23b30fdd10 | ||
|
|
c69556f2ff | ||
|
|
b0689614bf | ||
|
|
e42a401987 | ||
|
|
5162459e4a | ||
|
|
39d914c9df | ||
|
|
8d2f4d9dfd | ||
|
|
a7d2f9b530 | ||
|
|
ca4e7f9b4f | ||
|
|
b11858bcac | ||
|
|
034f23b47e | ||
|
|
9c25f300cf | ||
|
|
db4ff56f0b | ||
|
|
830c2472cb | ||
|
|
079e2af0c0 | ||
|
|
5f166158c3 | ||
|
|
4a06378d67 | ||
|
|
d0f0a74df8 | ||
|
|
65a8965e85 | ||
|
|
ab2376f8d8 | ||
|
|
48717dff00 | ||
|
|
b64dd7ab57 | ||
|
|
bf013ecf00 | ||
|
|
22b744fa23 | ||
|
|
71cc2d7d5d | ||
|
|
62b367fa81 | ||
|
|
cfc43f6dea | ||
|
|
ee85784be1 | ||
|
|
1a2df9c51c | ||
|
|
770fdb2b7d | ||
|
|
171ff54ea4 | ||
|
|
da452decf6 | ||
|
|
c80ac58eff | ||
|
|
d56e1f6285 | ||
|
|
22b3ddab66 | ||
|
|
3fe2491b73 | ||
|
|
4e6758e31d | ||
|
|
d2aa2c080f | ||
|
|
a5483a03c9 | ||
|
|
bb8b3b9291 | ||
|
|
e7f1d350c9 | ||
|
|
3b9aedec5f | ||
|
|
fabcf841c9 |
137
.gitlab-ci.yml
137
.gitlab-ci.yml
@@ -1,36 +1,147 @@
|
||||
# Select image from https://hub.docker.com/_/php/
|
||||
image: php:7.1
|
||||
#image: php:7.2
|
||||
# Use a prepared Hubzilla image to optimise pipeline duration
|
||||
image: registry.gitlab.com/dawnbreak/hubzilla/core:php7.2
|
||||
|
||||
|
||||
stages:
|
||||
- test
|
||||
- deploy
|
||||
|
||||
|
||||
# Select what we should cache
|
||||
cache:
|
||||
paths:
|
||||
- vendor/
|
||||
- .cache/
|
||||
|
||||
|
||||
# global variables for all jobs, if no job specific variables
|
||||
variables:
|
||||
# Configure mysql service (https://hub.docker.com/_/mysql/)
|
||||
# Tell composer to use the project workspace .cache folder
|
||||
COMPOSER_CACHE_DIR: "$CI_PROJECT_DIR/.cache/composer"
|
||||
# Ignore a Composer warning
|
||||
COMPOSER_ALLOW_SUPERUSER: 1
|
||||
# Configure MySQL/MariaDB service (https://hub.docker.com/_/mysql/, https://hub.docker.com/_/mariadb/)
|
||||
MYSQL_DATABASE: hello_world_test
|
||||
MYSQL_ROOT_PASSWORD: mysql
|
||||
# Configure PostgreSQL service (https://hub.docker.com/_/postgres/)
|
||||
POSTGRES_DB: ci-db
|
||||
POSTGRES_USER: ci-user
|
||||
POSTGRES_PASSWORD: ci-pass
|
||||
|
||||
|
||||
services:
|
||||
- mysql:5.7
|
||||
|
||||
before_script:
|
||||
- apt-get update -yqq
|
||||
- apt-get install -yqq git mysql-server mysql-client libmcrypt-dev libpq-dev libcurl4-gnutls-dev libicu-dev libvpx-dev libjpeg-dev libpng-dev libxpm-dev zlib1g-dev libfreetype6-dev libxml2-dev libexpat1-dev libbz2-dev libgmp3-dev libldap2-dev unixodbc-dev libsqlite3-dev libaspell-dev libsnmp-dev libpcre3-dev libtidy-dev
|
||||
# Install PHP extensions
|
||||
- docker-php-ext-install mbstring mcrypt pdo_mysql pdo_pgsql curl json intl gd xml zip bz2 opcache
|
||||
# pecl and composer do not work with PHP production restrictions (from Hubzilla Docker image)
|
||||
- if [ -f /usr/local/etc/php/conf.d/z_prod.ini ]; then mv /usr/local/etc/php/conf.d/z_prod.ini /usr/local/etc/php/conf.d/z_prod.ini.off; fi
|
||||
# Install & enable Xdebug for code coverage reports
|
||||
- pecl install xdebug
|
||||
- docker-php-ext-enable xdebug
|
||||
# Install and run Composer
|
||||
# Install composer
|
||||
- curl -sS https://getcomposer.org/installer | php
|
||||
- php composer.phar install
|
||||
# Install dev libraries from composer
|
||||
- php ./composer.phar install --no-progress
|
||||
|
||||
# We test PHP7 with MySQL, but we allow it to fail
|
||||
test:php:mysql:
|
||||
|
||||
# hidden job definition with template for MySQL/MariaDB
|
||||
.job_template_mysql: &job_definition_mysql
|
||||
stage: test
|
||||
script:
|
||||
- echo "USE $MYSQL_DATABASE; $(cat ./install/schema_mysql.sql)" | mysql --user=root --password="$MYSQL_ROOT_PASSWORD" --host=mysql "$MYSQL_DATABASE"
|
||||
- echo "SHOW DATABASES;" | mysql --user=root --password="$MYSQL_ROOT_PASSWORD" --host=mysql "$MYSQL_DATABASE"
|
||||
- echo "USE $MYSQL_DATABASE; SHOW TABLES;" | mysql --user=root --password="$MYSQL_ROOT_PASSWORD" --host=mysql "$MYSQL_DATABASE"
|
||||
- vendor/bin/phpunit --configuration tests/phpunit.xml --coverage-text
|
||||
|
||||
# hidden job definition with template for PostgreSQL
|
||||
.job_template_postgres: &job_definition_postgres
|
||||
stage: test
|
||||
services:
|
||||
- postgres:latest
|
||||
script:
|
||||
- export PGPASSWORD=$POSTGRES_PASSWORD
|
||||
- psql --version
|
||||
- psql -h "postgres" -U "$POSTGRES_USER" -d "$POSTGRES_DB" -c "SELECT VERSION();"
|
||||
# Import hubzilla's DB schema
|
||||
- psql -h "postgres" -U "$POSTGRES_USER" -v ON_ERROR_STOP=1 --quiet "$POSTGRES_DB" < ./install/schema_postgres.sql
|
||||
# Show databases and relations/tables of hubzilla's database
|
||||
#- psql -h "postgres" -U "$POSTGRES_USER" -l
|
||||
#- psql -h "postgres" -U "$POSTGRES_USER" -d "$POSTGRES_DB" -c "\dt;"
|
||||
# Run the actual tests
|
||||
- vendor/bin/phpunit --configuration tests/phpunit-pgsql.xml --testdox
|
||||
|
||||
# hidden job definition with artifacts config template
|
||||
.artifacts_template:
|
||||
artifacts: &artifacts_template
|
||||
expire_in: 1 week
|
||||
# Gitlab should show the results, but has problems parsing PHPUnit's junit file.
|
||||
reports:
|
||||
junit: tests/results/junit.xml
|
||||
# Archive test results (coverage, testdox, junit)
|
||||
name: "$CI_COMMIT_REF_SLUG-$CI_JOB_NAME"
|
||||
paths:
|
||||
- tests/results/
|
||||
|
||||
|
||||
# PHP7.2 with MySQL 5.7
|
||||
php7.2_mysql5.7:
|
||||
<<: *job_definition_mysql
|
||||
services:
|
||||
- mysql:5.7
|
||||
|
||||
|
||||
# PHP7.2 with MySQL 8 (latest)
|
||||
php7.2_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:
|
||||
<<: *job_definition_mysql
|
||||
services:
|
||||
- name: mariadb:10.2
|
||||
alias: mysql
|
||||
|
||||
|
||||
# PHP7.3 with MariaDB 10.3 (latest)
|
||||
php7.3_mariadb10.3:
|
||||
<<: *job_definition_mysql
|
||||
image: registry.gitlab.com/dawnbreak/hubzilla/core:php7.3
|
||||
services:
|
||||
- name: mariadb:10.3
|
||||
alias: mysql
|
||||
|
||||
|
||||
# PHP7.2 with PostgreSQL latest (11)
|
||||
php7.2_postgres11:
|
||||
<<: *job_definition_postgres
|
||||
artifacts: *artifacts_template
|
||||
|
||||
|
||||
# PHP7.3 with PostgreSQL latest (11)
|
||||
php7.3_postgres11:
|
||||
<<: *job_definition_postgres
|
||||
image: registry.gitlab.com/dawnbreak/hubzilla/core:php7.3
|
||||
artifacts: *artifacts_template
|
||||
|
||||
|
||||
# Generate Doxygen API Documentation and deploy it as GitLab pages
|
||||
pages:
|
||||
stage: deploy
|
||||
cache: {}
|
||||
image: php:7-cli-alpine
|
||||
before_script:
|
||||
- apk update
|
||||
- apk add doxygen ttf-freefont graphviz
|
||||
script:
|
||||
- doxygen util/Doxyfile
|
||||
- mv doc/html/ public/
|
||||
- echo "API documentation should be accessible at https://hubzilla.frama.io/core/ soon"
|
||||
artifacts:
|
||||
paths:
|
||||
- public
|
||||
only:
|
||||
# Only generate it on main repo's master branch
|
||||
- master@hubzilla/core
|
||||
|
||||
@@ -1,19 +1,46 @@
|
||||
# Hubzilla at Home next to your Router
|
||||
|
||||
Run hubzilla-setup.sh for an unattended installation of hubzilla.
|
||||
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-9.2-amd64, or
|
||||
- Rapberry 3 with Raspbian, Debian-9.3
|
||||
- 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)
|
||||
|
||||
## Disclaimers
|
||||
|
||||
- This script does work with Debian 9 only.
|
||||
- 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
|
||||
@@ -28,8 +55,8 @@ Hardware
|
||||
|
||||
Software
|
||||
|
||||
+ Fresh installation of Debian 9 (Stretch)
|
||||
+ Router with open ports 80 and 443 for your Hub
|
||||
+ Fresh installation of Debian 10 (Stretch)
|
||||
+ Router with open ports 80 and 443 for your web server
|
||||
|
||||
## The basic steps (quick overview)
|
||||
|
||||
@@ -38,16 +65,15 @@ Software
|
||||
- apt-get install git
|
||||
- mkdir -p /var/www
|
||||
- cd /var/www
|
||||
- git clone https://github.com/redmatrix/hubzilla.git html
|
||||
- git clone https://framagit.org/hubzilla/core.git html
|
||||
- cd html/.homeinstall
|
||||
- cp hubzilla-config.txt.template hubzilla-config.txt
|
||||
- nano hubzilla-config.txt
|
||||
- Read the comments carefully
|
||||
- Enter your values: db pass, domain, values for dyn DNS
|
||||
- Make sure your external drive (for backups) is mounted
|
||||
- Prepare your external disk for backups
|
||||
- hubzilla-setup.sh as root
|
||||
- ... wait, wait, wait until the script is finised
|
||||
- reboot
|
||||
+ Open your domain with a browser and step throught the initial configuration of hubzilla.
|
||||
|
||||
## Troubleshooting
|
||||
@@ -66,58 +92,28 @@ In Admin settings of hubzilla or via terminal
|
||||
|
||||
# Step-by-Step in Detail
|
||||
|
||||
## Preparations Hardware
|
||||
|
||||
### Mini-PC
|
||||
|
||||
### Recommended: USB Drive for Backups
|
||||
|
||||
The installation will create a daily backup written to an external drive.
|
||||
|
||||
The USB drive must be compatible with the filesystems
|
||||
|
||||
- ext4 (if you do not want to encrypt the USB)
|
||||
- LUKS + ext4 (if you want to encrypt the USB)
|
||||
|
||||
The backup includes
|
||||
|
||||
- Hubzilla DB
|
||||
- Hubzilla installation /var/www/html
|
||||
- Certificates for letsencrypt
|
||||
|
||||
## Preparations Software
|
||||
|
||||
### Install Debian Linux on the Mini-PC
|
||||
## Install Debian 9
|
||||
|
||||
Download the stable Debian at https://www.debian.org/
|
||||
(Debian 8 is no longer supported.)
|
||||
Provided you use a Raspberry Pi 3...
|
||||
|
||||
Create bootable USB drive with Debian on it.You could use
|
||||
Download the OS Raspbian from https://www.raspberrypi.org/downloads/raspbian/
|
||||
|
||||
- unetbootin, https://en.wikipedia.org/wiki/UNetbootin
|
||||
- or simply the linux command "dd"
|
||||
Follow the installation instruction there.
|
||||
|
||||
Example for command dd...
|
||||
## Configure your Router
|
||||
|
||||
su -
|
||||
dd if=2017-11-29-raspbian-stretch.img of=/dev/mmcblk0
|
||||
Your web has to be visible in the internet.
|
||||
|
||||
Do not forget to unmount the SD card before and check if unmounted like in this example...
|
||||
|
||||
su -
|
||||
umount /dev/mmcblk0*
|
||||
df -h
|
||||
|
||||
|
||||
Switch off your mini pc, plug in your USB drive and start the mini pc from the
|
||||
stick. Install Debian. Follow the instructions of the installation.
|
||||
|
||||
### Configure your Router
|
||||
|
||||
Open the ports 80 and 443 on your router for your Debian
|
||||
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.
|
||||
|
||||
In short...
|
||||
|
||||
Your Hubzilla must be reachable by a domain that you can type in your browser
|
||||
|
||||
cooldomain.org
|
||||
@@ -132,99 +128,15 @@ There are two ways to get a domain...
|
||||
|
||||
...for example buy at selfHOST.de
|
||||
|
||||
The cost are around 10,- € once and 1,50 € per month (2017).
|
||||
The cost is 1,50 € per month (2019).
|
||||
|
||||
### Method 2: Register a free subdomain
|
||||
|
||||
...for example register at freedns.afraid.org
|
||||
|
||||
Follow the instructions in .homeinstall/hubzilla-config.txt.
|
||||
## Note on Rasperry
|
||||
|
||||
|
||||
## Install Hubzilla on your Debian
|
||||
|
||||
Login to your debian
|
||||
(Provided your username is "you" and the name of the mini pc is "debian". You
|
||||
could take the IP address instead of "debian")
|
||||
|
||||
ssh -X you@debian
|
||||
|
||||
Change to root user
|
||||
|
||||
su -l
|
||||
|
||||
Install git
|
||||
|
||||
apt-get install git
|
||||
|
||||
Make the directory for apache and change diretory to it
|
||||
|
||||
mkdir /var/www
|
||||
cd /var/www/
|
||||
|
||||
Clone hubzilla from git ("git pull" will update it later)
|
||||
|
||||
git clone https://framagit.org/hubzilla/core html
|
||||
|
||||
Change to the install script
|
||||
|
||||
cd html/.homeinstall/
|
||||
|
||||
Copy the template file
|
||||
|
||||
cp hubzilla-config.txt.template hubzilla-config.txt
|
||||
|
||||
Modify the file "hubzilla-config.txt". Read the instructions there carefully and enter your values.
|
||||
|
||||
nano hubzilla-config.txt
|
||||
|
||||
Make sure your external drive (for backups) is plugged in and can be mounted as configured in "hubzilla-config.txt". Otherwise the daily backups will not work.
|
||||
|
||||
Run the script
|
||||
|
||||
./hubzilla-setup.sh
|
||||
|
||||
Wait... The script should not finish with an error message.
|
||||
|
||||
In a webbrowser open your domain.
|
||||
Expected: A test page of hubzilla is shown. All checks there should be
|
||||
successfull. Go on...
|
||||
Expected: A page for the Hubzilla server configuration shows up.
|
||||
|
||||
Leave db server name "127.0.0.1" and port "0" untouched.
|
||||
|
||||
Enter
|
||||
|
||||
- DB user name = hubzilla
|
||||
- DB pass word = This is the password you entered in "hubzilla-config.txt"
|
||||
- DB name = hubzilla
|
||||
|
||||
Leave db type "MySQL" untouched.
|
||||
|
||||
Follow the instructions in the next pages.
|
||||
|
||||
Recommended: Set path to imagemagick
|
||||
|
||||
- in admin settings of hubzilla or
|
||||
- via terminal
|
||||
|
||||
util/config system.imagick_convert_path /usr/bin/convert
|
||||
|
||||
After the daily script was executed at 05:30 (am)
|
||||
|
||||
- look at /var/www/html/hubzilla-daily.log
|
||||
- check your backup on the external drive
|
||||
- optionally view the daily log under yourdomain.org/admin/logs/
|
||||
- set the logfile to var/www/html/hubzilla-daily.log
|
||||
|
||||
## Note for the Rasperry
|
||||
|
||||
The script was tested with an Raspberry 3 under Raspian (Debian 9.3, 2017-11-29-raspbian-stretch.img).
|
||||
|
||||
It is recommended to deinstall these programms to avoid endless updates. Use...
|
||||
|
||||
sudo apt-get purge wolfram-engine sonic-pi
|
||||
sudo apt-get autoremove
|
||||
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...
|
||||
|
||||
@@ -234,7 +146,7 @@ to boot the Rapsi to the client console.
|
||||
|
||||
DO NOT FORGET TO CHANGE THE DEFAULT PASSWORD FOR USER PI!
|
||||
|
||||
On a Raspian Stretch (Debian 9) the validation of the mail address fails for the very first user.
|
||||
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
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
### MANDATORY - database password #############
|
||||
#
|
||||
# Please give your database password
|
||||
# It is better to not use blanks inside the password.
|
||||
# Example: db_pass=pass_word_with_no_blanks_in_it
|
||||
# Example: db_pass="this password has blanks in it"
|
||||
db_pass=
|
||||
|
||||
###############################################
|
||||
@@ -18,7 +18,12 @@ db_pass=
|
||||
# Example: my.cooldomain.org
|
||||
# Example: cooldomain.org
|
||||
#
|
||||
# Email is optional
|
||||
# You might use "localhost" for a LOCAL TEST installation.
|
||||
# This is usefull if you want to debug the server inside a VM.
|
||||
#
|
||||
# Example: localhost
|
||||
#
|
||||
# Email is optional if you use "localhost".
|
||||
#
|
||||
#
|
||||
le_domain=
|
||||
@@ -28,7 +33,7 @@ le_email=
|
||||
### OPTIONAL - selfHOST - dynamic IP address ##
|
||||
#
|
||||
# 1. Register a domain at selfhost.de
|
||||
# - choose offer "DOMAIN dynamisch" 1,50€/mon at 08.01.2016
|
||||
# - choose offer "DOMAIN dynamisch" 1,50€/mon at 04/2019
|
||||
# 2. Get your configuration for dynamic IP update
|
||||
# - Log in at selfhost.de
|
||||
# - go to "DynDNS Accounte"
|
||||
|
||||
@@ -3,7 +3,10 @@
|
||||
# How to use
|
||||
# ----------
|
||||
#
|
||||
# This file automates the installation of hubzilla under Debian Linux
|
||||
# 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
|
||||
@@ -23,18 +26,16 @@
|
||||
# - install
|
||||
# * apache webserer,
|
||||
# * php,
|
||||
# * mysql - the database for hubzilla,
|
||||
# * phpmyadmin,
|
||||
# * git to download and update hubzilla itself
|
||||
# * mariadb - the database for hubzilla,
|
||||
# * adminer,
|
||||
# * git to download and update hubzilla addon
|
||||
# - download hubzilla core and addons
|
||||
# - configure cron
|
||||
# * "poller.php" for regular background prozesses of hubzilla
|
||||
# * to_do "apt-get update" and "apt-get dist-upgrade" to keep linux
|
||||
# up-to-date
|
||||
# * to_do backup hubzillas database and files (rsnapshot)
|
||||
# - configure dynamic ip with cron
|
||||
# - to_do letsencrypt
|
||||
# - to_do redirection to https
|
||||
# * "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
|
||||
@@ -44,26 +45,6 @@
|
||||
# - The script runs into installation errors for phpmyadmin if it uses
|
||||
# different passwords. For the sake of simplicity one singel password.
|
||||
#
|
||||
# Security - suhosin for PHP
|
||||
# - The script does not install suhosin.
|
||||
# - Is the security package suhosin usefull or not usefull?
|
||||
#
|
||||
# Hubzilla - email verification
|
||||
# - The script switches off email verification off in all htconfig.tpl.
|
||||
# Example: /var/www/html/view/en/htconfig.tpl
|
||||
# - Is this a silly idea or not?
|
||||
#
|
||||
#
|
||||
# Remove Hubzilla (for a fresh start using the script)
|
||||
# ----------------------------------------------------
|
||||
#
|
||||
# You could use /var/www/hubzilla-remove.sh
|
||||
# that is created by hubzilla-setup.sh.
|
||||
#
|
||||
# The script will remove (almost everything) what was installed by the script.
|
||||
# After the removal you could run the script again to have a fresh install
|
||||
# of all applications including hubzilla and its database.
|
||||
#
|
||||
# How to restore from backup
|
||||
# --------------------------
|
||||
#
|
||||
@@ -76,18 +57,10 @@
|
||||
#
|
||||
# hubzilla-daily.sh makes a (daily) backup of all relevant files
|
||||
# - /var/lib/mysql/ > hubzilla database
|
||||
# - /var/www/html/ > hubzilla from github
|
||||
# - /var/www/letsencrypt/ > certificates
|
||||
# - /var/www/ > hubzilla/zap from github
|
||||
# - /etc/letsencrypt/ > certificates
|
||||
#
|
||||
# hubzilla-daily.sh writes the backup
|
||||
# - either to an external disk compatible to LUKS+ext4 (see hubzilla-config.txt)
|
||||
# - or to /var/cache/rsnapshot in case the external disk is not plugged in
|
||||
#
|
||||
# Restore backup
|
||||
# - - - - - - -
|
||||
#
|
||||
# This was not tested yet.
|
||||
# Bacically you can copy the files from the backup to the server.
|
||||
# hubzilla-daily.sh writes the backup to an external disk compatible to LUKS+ext4 (see hubzilla-config.txt)
|
||||
#
|
||||
# Credits
|
||||
# -------
|
||||
@@ -95,8 +68,6 @@
|
||||
# The script is based on Thomas Willinghams script "debian-setup.sh"
|
||||
# which he used to install the red#matrix.
|
||||
#
|
||||
# The script uses another script from https://github.com/lukas2511/letsencrypt.sh
|
||||
#
|
||||
# The documentation for bash is here
|
||||
# https://www.gnu.org/software/bash/manual/bash.html
|
||||
#
|
||||
@@ -116,9 +87,9 @@ function check_sanity {
|
||||
then
|
||||
die "Debian is supported only"
|
||||
fi
|
||||
if ! grep -q 'Linux 9' /etc/issue
|
||||
if ! grep -q 'Linux 10' /etc/issue
|
||||
then
|
||||
die "Linux 9 (stretch) is supported only"x
|
||||
die "Linux 10 (buster) is supported only"x
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -136,11 +107,11 @@ function check_config {
|
||||
# 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 [ ! -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"
|
||||
@@ -229,21 +200,17 @@ function print_warn {
|
||||
}
|
||||
|
||||
function stop_hubzilla {
|
||||
if [ -d /etc/apache2 ]
|
||||
then
|
||||
print_info "stopping apache webserver..."
|
||||
service apache2 stop
|
||||
fi
|
||||
if [ -f /etc/init.d/mysql ]
|
||||
then
|
||||
print_info "stopping mysql db..."
|
||||
/etc/init.d/mysql stop
|
||||
fi
|
||||
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 {
|
||||
@@ -264,78 +231,46 @@ function install_sendmail {
|
||||
function install_php {
|
||||
# openssl and mbstring are included in libapache2-mod-php
|
||||
print_info "installing php..."
|
||||
nocheck_install "libapache2-mod-php php php-pear php-curl php-mcrypt php-gd"
|
||||
sed -i "s/^upload_max_filesize =.*/upload_max_filesize = 100M/g" /etc/php/7.0/apache2/php.ini
|
||||
sed -i "s/^post_max_size =.*/post_max_size = 100M/g" /etc/php/7.0/apache2/php.ini
|
||||
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 {
|
||||
# http://www.microhowto.info/howto/perform_an_unattended_installation_of_a_debian_package.html
|
||||
#
|
||||
# To determine the required package name, key and type you can perform
|
||||
# a trial installation then search the configuration database.
|
||||
#
|
||||
# debconf-get-selections | grep mysql-server
|
||||
#
|
||||
# The command debconf-get-selections is provided by the package
|
||||
# debconf-utils, which you may need to install.
|
||||
#
|
||||
# apt-get install debconf-utils
|
||||
#
|
||||
# If you want to supply an answer to a configuration question but do not
|
||||
# want to be prompted for it then this can be arranged by preseeding the
|
||||
# DebConf database with the required information.
|
||||
#
|
||||
# echo mysql-server mysql-server/root_password password xyzzy | debconf-set-selections
|
||||
# echo mysql-server mysql-server/root_password_again password xyzzy | debconf-set-selections
|
||||
#
|
||||
print_info "installing mysql..."
|
||||
if [ -z "$mysqlpass" ]
|
||||
then
|
||||
die "mysqlpass not set in $configfile"
|
||||
fi
|
||||
echo mysql-server mysql-server/root_password password $mysqlpass | debconf-set-selections
|
||||
echo mysql-server mysql-server/root_password_again password $mysqlpass | debconf-set-selections
|
||||
nocheck_install "php-mysql mysql-server mysql-client"
|
||||
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_phpmyadmin {
|
||||
print_info "installing phpmyadmin..."
|
||||
if [ -z "$phpmyadminpass" ]
|
||||
function install_adminer {
|
||||
print_info "installing adminer..."
|
||||
nocheck_install "adminer"
|
||||
if [ ! -f /etc/adminer/adminer.conf ]
|
||||
then
|
||||
die "phpmyadminpass not set in $configfile"
|
||||
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
|
||||
echo phpmyadmin phpmyadmin/setup-password password $phpmyadminpass | debconf-set-selections
|
||||
echo phpmyadmin phpmyadmin/mysql/app-pass password $phpmyadminpass | debconf-set-selections
|
||||
echo phpmyadmin phpmyadmin/app-password-confirm password $phpmyadminpass | debconf-set-selections
|
||||
echo phpmyadmin phpmyadmin/mysql/admin-pass password $phpmyadminpass | debconf-set-selections
|
||||
echo phpmyadmin phpmyadmin/password-confirm password $phpmyadminpass | debconf-set-selections
|
||||
echo phpmyadmin phpmyadmin/reconfigure-webserver multiselect apache2 | debconf-set-selections
|
||||
nocheck_install "phpmyadmin"
|
||||
|
||||
# It seems to be not neccessary to check rewrite.load because it comes
|
||||
# with the installation. To be sure you could check this manually by:
|
||||
#
|
||||
# nano /etc/apache2/mods-available/rewrite.load
|
||||
#
|
||||
# You should find the content:
|
||||
#
|
||||
# LoadModule rewrite_module /usr/lib/apache2/modules/mod_rewrite.so
|
||||
|
||||
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
|
||||
if [ -z "`grep 'Include /etc/phpmyadmin/apache.conf' /etc/apache2/apache2.conf`" ]
|
||||
then
|
||||
echo "Include /etc/phpmyadmin/apache.conf" >> /etc/apache2/apache2.conf
|
||||
fi
|
||||
service apache2 restart
|
||||
/etc/init.d/mysql start
|
||||
a2enconf adminer
|
||||
systemctl reload apache2
|
||||
}
|
||||
|
||||
function create_hubzilla_db {
|
||||
@@ -352,6 +287,7 @@ function create_hubzilla_db {
|
||||
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';"
|
||||
@@ -449,11 +385,11 @@ function configure_cron_selfhost {
|
||||
print_info "configure cron for selfhost..."
|
||||
if [ -z "$selfhost_user" ]
|
||||
then
|
||||
print_info "freedns is not configured because freedns_key is empty in $configfile"
|
||||
print_info "selfhost is not configured because selfhost_key is empty in $configfile"
|
||||
else
|
||||
# Use cron for dynamich ip update
|
||||
# - at reboot
|
||||
# - every 30 minutes
|
||||
# - 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
|
||||
@@ -471,89 +407,14 @@ function install_letsencrypt {
|
||||
then
|
||||
die "Failed to install let's encrypt: 'le_domain' is empty in $configfile"
|
||||
fi
|
||||
# configure apache
|
||||
apache_le_conf=/etc/apache2/sites-available/le-default.conf
|
||||
if [ -f $apache_le_conf ]
|
||||
# check if user gave mail address
|
||||
if [ -z "$le_email" ]
|
||||
then
|
||||
print_info "$apache_le_conf exist already"
|
||||
else
|
||||
cat > $apache_le_conf <<END
|
||||
# letsencrypt default Apache configuration
|
||||
Alias /.well-known/acme-challenge /var/www/letsencrypt
|
||||
|
||||
<Directory /var/www/letsencrypt>
|
||||
Options FollowSymLinks
|
||||
Allow from all
|
||||
</Directory>
|
||||
END
|
||||
a2ensite le-default.conf
|
||||
service apache2 restart
|
||||
die "Failed to install let's encrypt: 'le_domain' is empty in $configfile"
|
||||
fi
|
||||
# download the shell script
|
||||
if [ -d $le_dir ]
|
||||
then
|
||||
print_info "letsenrypt exists already (nothing downloaded > no certificate created and registered)"
|
||||
return 0
|
||||
fi
|
||||
git clone https://github.com/lukas2511/dehydrated $le_dir
|
||||
cd $le_dir
|
||||
# create config file for letsencrypt.sh
|
||||
echo "WELLKNOWN=$le_dir" > $le_dir/config.sh
|
||||
if [ -n "$le_email" ]
|
||||
then
|
||||
echo "CONTACT_EMAIL=$le_email" >> $le_dir/config.sh
|
||||
fi
|
||||
# create domain file for letsencrypt.sh
|
||||
# WATCH THIS:
|
||||
# - It did not work wit "sub.domain.org www.sub.domain.org".
|
||||
# - So just use "sub.domain.org" only!
|
||||
echo "$le_domain" > $le_dir/domains.txt
|
||||
# test apache config for letsencrpyt
|
||||
url_http=http://$le_domain/.well-known/acme-challenge/domains.txt
|
||||
wget_output=$(wget -nv --spider --max-redirect 0 $url_http)
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
die "Failed to load $url_http"
|
||||
fi
|
||||
# accept terms of service of letsencrypt
|
||||
./dehydrated --register --accept-terms
|
||||
# run script dehydrated
|
||||
#
|
||||
./dehydrated --cron --config $le_dir/config.sh
|
||||
}
|
||||
|
||||
function configure_apache_for_https {
|
||||
print_info "configuring apache to use httpS ..."
|
||||
# letsencrypt.sh
|
||||
#
|
||||
# "${BASEDIR}/certs/${domain}/privkey.pem"
|
||||
# "${BASEDIR}/certs/${domain}/cert.pem"
|
||||
# "${BASEDIR}/certs/${domain}/fullchain.pem"
|
||||
#
|
||||
SSLCertificateFile=${le_dir}/certs/${le_domain}/cert.pem
|
||||
SSLCertificateKeyFile=${le_dir}/certs/${le_domain}/privkey.pem
|
||||
SSLCertificateChainFile=${le_dir}/certs/${le_domain}/fullchain.pem
|
||||
if [ ! -f $SSLCertificateFile ]
|
||||
then
|
||||
print_warn "Failed to configure apache for httpS: Missing certificate file $SSLCertificateFile"
|
||||
return 0
|
||||
fi
|
||||
# make sure that the ssl mode is enabled
|
||||
print_info "...configuring apache to use httpS - a2enmod ssl ..."
|
||||
a2enmod ssl
|
||||
# modify apach' ssl conf file
|
||||
if grep -i "ServerName" $sslconf
|
||||
then
|
||||
print_info "seems that apache was already configered to use httpS with $sslconf"
|
||||
else
|
||||
sed -i "s/ServerAdmin.*$/ServerAdmin webmaster@localhost\\n ServerName ${le_domain}/" $sslconf
|
||||
fi
|
||||
sed -i s#/etc/ssl/certs/ssl-cert-snakeoil.pem#$SSLCertificateFile# $sslconf
|
||||
sed -i s#/etc/ssl/private/ssl-cert-snakeoil.key#$SSLCertificateKeyFile# $sslconf
|
||||
sed -i s#/etc/apache2/ssl.crt/server-ca.crt#$SSLCertificateChainFile# $sslconf
|
||||
sed -i s/#SSLCertificateChainFile/SSLCertificateChainFile/ $sslconf
|
||||
# apply changes
|
||||
a2ensite default-ssl.conf
|
||||
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
|
||||
}
|
||||
|
||||
@@ -572,7 +433,10 @@ function check_https {
|
||||
function install_hubzilla {
|
||||
print_info "installing hubzilla addons..."
|
||||
cd /var/www/html/
|
||||
util/add_addon_repo https://framagit.org/hubzilla/addons.git hzaddons
|
||||
# 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
|
||||
@@ -582,58 +446,12 @@ function install_hubzilla {
|
||||
chown root:www-data /var/www/html/
|
||||
chown root:www-data /var/www/html/.htaccess
|
||||
chmod 0644 /var/www/html/.htaccess
|
||||
# try to switch off email registration
|
||||
sed -i "s/verify_email.*1/verify_email'] = 0/" /var/www/html/view/*/ht*
|
||||
if [ -n "`grep -r 'verify_email.*1' /var/www/html/view/`" ]
|
||||
then
|
||||
print_warn "Hubzillas registration prozess might have email verification switched on."
|
||||
fi
|
||||
print_info "installed hubzilla"
|
||||
}
|
||||
|
||||
function rewrite_to_https {
|
||||
print_info "configuring apache to redirect http to httpS ..."
|
||||
htaccessfile=/var/www/html/.htaccess
|
||||
if grep -i "https" $htaccessfile
|
||||
then
|
||||
print_info "...configuring apache to redirect http to httpS was already done in $htaccessfile"
|
||||
else
|
||||
sed -i "s#QSA]#QSA]\\n RewriteCond %{SERVER_PORT} !^443$\\n RewriteRule (.*) https://%{HTTP_HOST}/$1 [R=301,L]#" $htaccessfile
|
||||
fi
|
||||
service apache2 restart
|
||||
}
|
||||
|
||||
# This will allways overwrite both config files
|
||||
# - internal disk
|
||||
# - external disk (LUKS + ext4)
|
||||
# of rsnapshot for hubzilla
|
||||
function install_rsnapshot {
|
||||
print_info "installing rsnapshot..."
|
||||
nocheck_install "rsnapshot"
|
||||
# internal disk
|
||||
cp -f /etc/rsnapshot.conf $snapshotconfig
|
||||
sed -i "s/^cmd_cp/#cmd_cp/" $snapshotconfig
|
||||
sed -i "s/^backup/#backup/" $snapshotconfig
|
||||
echo "backup /var/lib/mysql/ localhost/" >> $snapshotconfig
|
||||
echo "backup /var/www/html/ localhost/" >> $snapshotconfig
|
||||
echo "backup /var/www/letsencrypt/ localhost/" >> $snapshotconfig
|
||||
# external disk
|
||||
if [ -n "$backup_device_name" ]
|
||||
then
|
||||
cp -f /etc/rsnapshot.conf $snapshotconfig_external_device
|
||||
sed -i "s#snapshot_root.*#snapshot_root $backup_mount_point#" $snapshotconfig_external_device
|
||||
sed -i "/alpha/s/6/30/" $snapshotconfig_external_device
|
||||
sed -i "s/^cmd_cp/#cmd_cp/" $snapshotconfig_external_device
|
||||
sed -i "s/^backup/#backup/" $snapshotconfig_external_device
|
||||
if [ -z "`grep 'letsencrypt' $snapshotconfig_external_device`" ]
|
||||
then
|
||||
echo "backup /var/lib/mysql/ localhost/" >> $snapshotconfig_external_device
|
||||
echo "backup /var/www/html/ localhost/" >> $snapshotconfig_external_device
|
||||
echo "backup /var/www/letsencrypt/ localhost/" >> $snapshotconfig_external_device
|
||||
fi
|
||||
else
|
||||
print_info "No backup configuration (rsnapshot) for external device configured. Reason: backup_device_name and/or backup_device_pass not given in $configfile"
|
||||
fi
|
||||
function install_rsync {
|
||||
print_info "installing rsync..."
|
||||
nocheck_install "rsync"
|
||||
}
|
||||
|
||||
function install_cryptosetup {
|
||||
@@ -644,28 +462,28 @@ function install_cryptosetup {
|
||||
function configure_cron_daily {
|
||||
print_info "configuring cron..."
|
||||
# every 10 min for poller.php
|
||||
if [ -z "`grep 'poller.php' /etc/crontab`" ]
|
||||
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
|
||||
# - backup hubzilla
|
||||
# - renew the certificate of letsencrypt
|
||||
# - backup db, files (/var/www/html), certificates if letsencrypt
|
||||
# - update hubzilla core and addon
|
||||
# - update and upgrade linux
|
||||
# - reboot
|
||||
# - 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 "bash $le_dir/dehydrated --cron --config $le_dir/config.sh" >> /var/www/$hubzilladaily
|
||||
echo "certbot renew --noninteractive" >> /var/www/$hubzilladaily
|
||||
echo "#" >> /var/www/$hubzilladaily
|
||||
echo "# stop hubzilla" >> /var/www/$hubzilladaily
|
||||
echo "echo \"\$(date) - stoping apache and mysql...\"" >> /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 inconsistancies" >> /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
|
||||
@@ -696,11 +514,13 @@ echo " if mount $backup_device_name $backup_mount_point" >> /var/www/$hub
|
||||
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 " rsnapshot -c $snapshotconfig_external_device alpha" >> /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 " 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
|
||||
@@ -722,18 +542,16 @@ 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 dehydrated...\"" >> /var/www/$hubzilladaily
|
||||
echo "git -C /var/www/letsencrypt/ pull" >> /var/www/$hubzilladaily
|
||||
echo "echo \"\$(date) - updating hubhilla core...\"" >> /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 hubzilla and update linux finished. Rebooting...\"" >> /var/www/$hubzilladaily
|
||||
echo "echo \"\$(date) - Backup and update finished. Rebooting...\"" >> /var/www/$hubzilladaily
|
||||
echo "#" >> /var/www/$hubzilladaily
|
||||
echo "reboot" >> /var/www/$hubzilladaily
|
||||
echo "shutdown -r now" >> /var/www/$hubzilladaily
|
||||
|
||||
if [ -z "`grep 'hubzilla-daily.sh' /etc/crontab`" ]
|
||||
then
|
||||
@@ -745,38 +563,6 @@ echo "reboot" >> /var/www/$hubzilladaily
|
||||
print_info "configured cron for updates/upgrades"
|
||||
}
|
||||
|
||||
function write_uninstall_script {
|
||||
print_info "writing uninstall script..."
|
||||
|
||||
cat > /var/www/hubzilla-remove.sh <<END
|
||||
#!/bin/sh
|
||||
#
|
||||
# This script removes Hubzilla.
|
||||
# You might do this for a fresh start using the script.
|
||||
# The script will remove (almost everything) what was installed by the script,
|
||||
# all applications including hubzilla and its database.
|
||||
#
|
||||
# Backup the certificates of letsencrypt (you never know)
|
||||
cp -a /var/www/letsencrypt/ ~/backup_le_certificats
|
||||
#
|
||||
# Removal
|
||||
apt-get remove apache2 apache2-utils libapache2-mod-php5 php5 php-pear php5-xcache php5-curl php5-mcrypt php5-gd php5-mysql mysql-server mysql-client phpmyadmin
|
||||
apt-get purge apache2 apache2-utils libapache2-mod-php5 php5 php-pear php5-xcache php5-curl php5-mcrypt php5-gd php5-mysql mysql-server mysql-client phpmyadmin
|
||||
apt-get autoremove
|
||||
apt-get clean
|
||||
rm /etc/rsnapshot_hubzilla.conf
|
||||
rm /etc/rsnapshot_hubzilla_external_device.conf
|
||||
rm -R /etc/apache2/
|
||||
rm -R /var/lib/mysql/
|
||||
rm -R /var/www
|
||||
rm -R /etc/selfhost/
|
||||
# uncomment the next line if you want to remove the backups
|
||||
# rm -R /var/cache/rsnapshot
|
||||
nano /etc/crontab # remove entries there manually
|
||||
END
|
||||
chmod -x /var/www/hubzilla-remove.sh
|
||||
}
|
||||
|
||||
########################################################################
|
||||
# START OF PROGRAM
|
||||
########################################################################
|
||||
@@ -791,12 +577,7 @@ source $configfile
|
||||
selfhostdir=/etc/selfhost
|
||||
selfhostscript=selfhost-updater.sh
|
||||
hubzilladaily=hubzilla-daily.sh
|
||||
plugins_update=.homeinstall/plugins_update.sh
|
||||
snapshotconfig=/etc/rsnapshot_hubzilla.conf
|
||||
snapshotconfig_external_device=/etc/rsnapshot_hubzilla_external_device.conf
|
||||
backup_mount_point=/media/hubzilla_backup
|
||||
le_dir=/var/www/letsencrypt
|
||||
sslconf=/etc/apache2/sites-available/default-ssl.conf
|
||||
|
||||
#set -x # activate debugging from here
|
||||
|
||||
@@ -809,22 +590,33 @@ install_apache
|
||||
install_imagemagick
|
||||
install_php
|
||||
install_mysql
|
||||
install_phpmyadmin
|
||||
install_adminer
|
||||
create_hubzilla_db
|
||||
run_freedns
|
||||
install_run_selfhost
|
||||
ping_domain
|
||||
configure_cron_freedns
|
||||
configure_cron_selfhost
|
||||
install_letsencrypt
|
||||
configure_apache_for_https
|
||||
check_https
|
||||
|
||||
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
|
||||
rewrite_to_https
|
||||
install_rsnapshot
|
||||
|
||||
configure_cron_daily
|
||||
install_cryptosetup
|
||||
write_uninstall_script
|
||||
|
||||
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
|
||||
|
||||
|
||||
310
CHANGELOG
310
CHANGELOG
@@ -1,3 +1,313 @@
|
||||
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
|
||||
- Replace plink URL with share tag if possible
|
||||
- Catch and exclude trailing punctuation while URL embedding
|
||||
- Do not limit channel if service class property value is set to zero
|
||||
- Streamline keyId and creator/actor
|
||||
- Add daemon_master_summon hook
|
||||
- Serve static files directly if not caught by web server
|
||||
- Update cacert.pem
|
||||
- Calendar: allow different date/time format inputs
|
||||
- Calendar: hide timezone select for allday events
|
||||
⁻ Add opengraph meta info to channel page
|
||||
- Begin directory migration to zot6
|
||||
- Support zot and zot6 in social graph operations
|
||||
- Lowlevel support for zot6 direct messages
|
||||
- Consolidate HTTP signatures
|
||||
- Allow api login by address or url
|
||||
- Provide auto redirect from zot6 /item permalinks
|
||||
- Export all items except photos in channel_export_items_date()
|
||||
- Calendar: clicking a day or week number will now open the day or week view
|
||||
- Remove cached photo location directory on delete if empty
|
||||
- Include zot6 hubs in the Grid scope
|
||||
- Fix os_path replace for thumbnails
|
||||
- Avoid to process original images using storeThumbnail()
|
||||
|
||||
Bugfixes
|
||||
- Fix URLs on imported item taxonomy
|
||||
- Fix admin not allowed to delete any item
|
||||
- Fix webfiunger issue with URLs containing an @
|
||||
- Fix missing object in emoji reactions
|
||||
- Fix appschema to include diaspora:guid
|
||||
- Fix zotfinger in update_directory_entry()
|
||||
- Fix incorrect media type on links for photo objects
|
||||
- Fix mid not dbesc'd in item_store()
|
||||
- Fix calendar encoding issues
|
||||
|
||||
Addons
|
||||
- twitter: various rendering improvements
|
||||
- cavatar: fix wrong image mimetype
|
||||
- gravatar: fix wrong image mimetype
|
||||
- Add license file
|
||||
- pubcrawl: make repeats render like wall to wall posts
|
||||
- pubcrawl: fix pubcrawl_import_author() sometimes returning a non activitypub xchan
|
||||
- pubcrawl: use Lib/Activity for taxonomy en/decoding
|
||||
- pubcrawl: fix wrong uuid in like activity
|
||||
- pubcrawl: fix issue with encoding hashtags
|
||||
- openstreetmap: use https URLs by default
|
||||
- queueworker: refactor and efficiency improvements
|
||||
- pubcrawl: use unique IDs for follow and accept activities
|
||||
- pubcrawl: implement thread completion
|
||||
- pubcrawl: implement delete activity
|
||||
- photocache: reduce the size of the photo cache subdirectories tree
|
||||
- photocache: use html_entity_decode() for cached photo URL
|
||||
- diaspora: fix possible issue with diaspora relay not initializing
|
||||
|
||||
|
||||
Hubzilla 4.2.1 (2019-06-17)
|
||||
- Deprecate mod events
|
||||
- Revisit mod cal
|
||||
- Fix issues with deletion of linked items and resources
|
||||
- Fix zot6 delete issue
|
||||
- Fix attach sync issue
|
||||
- Remove sizeRangeSuffixes in justified gallery wrapper
|
||||
- Fix storageconv issue with postgres
|
||||
- Fix embedphotos image size
|
||||
- pubcrawl: use URI instead of object for actor url
|
||||
- diaspora: adjust loglevel
|
||||
- gallery: remove workaround for margin issue which has been fixed upstream
|
||||
- cart: warn about unsaved changes
|
||||
|
||||
|
||||
Hubzilla 4.2 (2019-06-04)
|
||||
- Introduce Calendar app which deprecates Events and CalDAV apps and streamlines the featuresets
|
||||
- Update mod cal to reflect changes in the calendar app
|
||||
- Improve timezone detection for CalDAV calendars
|
||||
- Add mention support to event description in channel calendar
|
||||
- Update jgrowl library
|
||||
- Do not try to oembed URLs without embed tags
|
||||
- Optimise pdf oembed processing
|
||||
- Add form security token to mod register
|
||||
- Replace URLs for mod gallery, mod photos and mod photo on cloned channel post sync
|
||||
- Update justified gallery library
|
||||
- Update bootstrap libraries
|
||||
- Use "cache" flag for bbcode() on content destined for zot6
|
||||
- Improve DB indexing
|
||||
- Drop deprecated columns from channel the table
|
||||
- Replace own image URL in clonned channel posts
|
||||
- Improve DB update handling
|
||||
- Improve item deletion when a contact was removed
|
||||
- Zot6 compatibility for emoji reactions
|
||||
- Add threaded comments support (disabled by default)
|
||||
- Improve xmlify()/unxmlify() performance
|
||||
- Update blueimp/jquery-file-uplad library
|
||||
- Update sabre/vobject library
|
||||
- Various doco updates
|
||||
- Implement remove profile photo button (reset to default photo)
|
||||
- Implement remove cover photo button
|
||||
- Update the homeinstall script
|
||||
- Add command line tool for photo thumbnails storage conversion
|
||||
- Implement option to store photo thumbnails in filesystem instead of DB
|
||||
|
||||
Bugfixes
|
||||
- Fix category widget when using articles
|
||||
- Fix live update not triggering in mod search
|
||||
- Fix encoded URLs in code blocks
|
||||
- Fix wiki headers not escaped
|
||||
- Fix possible xchan protocol confusion in new_contact()
|
||||
- Fix xchan_url not displayed if xchan_addr not available
|
||||
- Fix suggestion ordering in mod directory
|
||||
- Fix event attachment delivery to zot6
|
||||
|
||||
Addons
|
||||
- pubcrawl: improve friendica compatibility by adding the nonstandard diaspora:guid field
|
||||
- pubcrawl: initial suport for events
|
||||
- pubcrawl: improve permalink detection
|
||||
- flashcards: fix moving learn buttons if viewport sizes changes
|
||||
- flashcards: Move card details to the bottom of a card
|
||||
- upgrade_info: provide links to changelog
|
||||
- photocache: do not save filename for cached photos
|
||||
- pubcrawl: save local comment activitypub payload in iconfig to be used for relay
|
||||
- flashcards: UI improvements in box settings
|
||||
- pubcrawl: implement profile update messages
|
||||
- pubcrawl: use URI instead of object for actor
|
||||
- flashcards: fix jumping sync button
|
||||
- pubcrawl: add threaded comments support
|
||||
- pubcrawl: ignore target encoding errors
|
||||
- pubcrawl: format photo items for activitypub
|
||||
|
||||
|
||||
Hubzilla 4.0.3 (2019-04-26)
|
||||
- Add attachments to zot6 event objects
|
||||
- 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
|
||||
- Fix magic auth in combination with zot6
|
||||
- Fix check for required PHP version
|
||||
- Diaspora: favour diaspora protocol identities over others with same hubloc or xchan address
|
||||
|
||||
|
||||
Hubzilla 4.0.2 (2019-04-08)
|
||||
- Port cdav calendar to fullcalendar version 4
|
||||
- Fix perms_pending not evaluated correctly
|
||||
- Fix return wrong profile photo modification date by plugin
|
||||
- Fix suggestion widget using feature_enabled still
|
||||
- Fix check service class limits when syncing files
|
||||
- Remove xchan_instance_url from notifier query - it is not used anymore
|
||||
- Implement remove cover photo functionality
|
||||
- Fix z6_discover() and create a zot6 hubloc on import if applicable
|
||||
- Add backend support for connections ordering
|
||||
- Deduplicate items in item_store() by uuid if we got one otherwise by mid
|
||||
- Add ITEM_TYPE_CUSTOM support to mod display
|
||||
- Fix mod subthread on sys channel items
|
||||
- Fix "recipient not found" dreport spaming with own xchan
|
||||
- Fix wrong variables in dirsearch
|
||||
- Fix 48 hours timeframe check in mod changeaddr
|
||||
- Fix wrong variable in Libsync
|
||||
- Pubcrawl: revert adding additional receivers to comments
|
||||
- Diaspora: fix intro received when being banned
|
||||
- Pubcrawl: add diaspora:guid from friendica AP posts for deduplication
|
||||
- Diaspora: fix friendica plink
|
||||
- Photocache: fix issue with spaces and quotes in original filenames
|
||||
|
||||
|
||||
Hubzilla 4.0.1 (2019-03-21)
|
||||
- Fix permissions not getting decrypted on follow
|
||||
- Add option to add a poster to the video bbcode
|
||||
- Fix SQL performance issue with queries including thr_parent
|
||||
- Fix share encoding issue between hz and zap
|
||||
- Fix edge case in unsupported advisory privacy
|
||||
- Messagefilter enhancements
|
||||
- Fix XSS issues
|
||||
- Clone systems apps to the extent possible
|
||||
- Auto-configure imagick thumbnail binary during setup if possible
|
||||
- Fix array not unserialized in util/service_class
|
||||
- Add phpmd and phpcs to composer require-dev for code linting
|
||||
- Fix issue with email encoding
|
||||
- Fix signature issue for zot6 content imported from zotfeeds to hubzilla
|
||||
- Find unregistered z6 clones on hubzilla sites
|
||||
- Add zot6 to clonable networks
|
||||
- Add owner permission checks to AS item fetch
|
||||
- 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()
|
||||
- Deliverynotice: do not save empty postopts
|
||||
- Gravatar: fix URL and use z_fetch_url()
|
||||
- Pubcrawl: improve SQL queries in pubcrawl_item_mod_init()
|
||||
- Pubcrawl: fix authenticated item fetch
|
||||
|
||||
|
||||
Hubzilla 4.0 (2019-03-08)
|
||||
- Add CURLOPT_CONNECTTIMEOUT option
|
||||
- Allow parameters as final path argument in API router
|
||||
- Remove clones from delivery recipients for top-level posts in favor of clone sync
|
||||
- Mention php-zip module dependency in administrator guide
|
||||
- Iron out some kinks with scrollToItem() in combination with collapsed content and images
|
||||
- Zot API changes to support combined content (items+files) import addon
|
||||
- Update PHP Version check during setup - min version is now 7.1
|
||||
- Urlencode links in category widget
|
||||
- Implement ability for channel visitors to be able to delete their own content
|
||||
- Support zot location independent urls
|
||||
- MySQL 8 admin summary compatibility
|
||||
- Improved gitlab-ci environment
|
||||
- Deprecate and remove addon settings in favour of per app settings
|
||||
- Refactor PhotoDriver class and add tests
|
||||
- Convert affinity tool to app
|
||||
- Refactor linkify_tags() so it works with xchans across multiple protocols
|
||||
- Add the actual mid to viewsrc for debuging reasons
|
||||
- Add filter hooks and the ability to add buttons to the default status editor
|
||||
- Prevent Hubzilla usage for SEO backlinks
|
||||
- Implement privacy warning for forum posts via !-tag
|
||||
- Set document title when title changes on a page update
|
||||
- Cache embeds in the background on initial storage rather than on first access
|
||||
- Custom sessionhandler support
|
||||
- Update nginx and lighttpd sample server configs to explicit disallow access to util
|
||||
- Introduce command line tool for managing site admins
|
||||
- Various doxygen improvements
|
||||
- Add privacygroup_extras_post/drop hooks
|
||||
- Add collect_public_recipients hook
|
||||
- Prevent memory exhaustion on zot message pickup with large message queue
|
||||
- Remove experimental worker queue from core
|
||||
- Add get_base_apps hook
|
||||
- Improve handling of notification updates while commenting
|
||||
- Add warning if upload_filesize < 4MB
|
||||
- Add ITEM_TYPE_CUSTOM and hooks for processing custom item types
|
||||
- Set min/maxversion for plugins to STD_VERSION unless otherwise specified
|
||||
- Add option to make affinity slider 'sticky' across page loads
|
||||
- Add photo_view_filter hook
|
||||
- Reset page title if article has no title
|
||||
- Implement the zot6 protocol
|
||||
- Add PHOTO_CACHE photo type
|
||||
- Basic support for HTTP3
|
||||
- Add native summary support
|
||||
- Disable image caching if personal or group permissions enabled
|
||||
|
||||
Bugfixes
|
||||
- Fix guest access token xchan record not created on URL login
|
||||
- Fix regression where mod oep was still using hex2bin/bin2hex instead of album hash
|
||||
- Fix regression when selecting multiple images in embed images
|
||||
- Fix broken sync_an_item()
|
||||
- Fix page jumping on like if comments are expanded (show all x comments)
|
||||
- Fix regression in mod display where an page update could display items from multiple channels
|
||||
- Fix starring and filing allowed for other unsupported item types
|
||||
- Fix wrong variable in z_get_temp_dir()
|
||||
- Fix page jumping when liking a collapsed/expanded post
|
||||
- Fix tags detection in URL
|
||||
- Fix warnings in mod embedphotos
|
||||
- Fix wrong variable in can_comment_on_post()
|
||||
- Fix mod new_channel counting removed channels
|
||||
- Fix regression where not all content variables were sslified
|
||||
- Fix default values for affinity tool and other information which could be lost when approving a connection
|
||||
- Fix regression in linkdropper()
|
||||
- Fix issue with unset auto_save_draft variable which resultet in a javascript error
|
||||
- Fix home notifications won't expand if there are more than 300 unseen network notifications ahead of them
|
||||
- Fix total_identities count
|
||||
- Fix delayed items propagate before publication on cloned channels
|
||||
|
||||
Addons
|
||||
- twitter_api: fedilab needs profile_image_url_https
|
||||
- New addon: content_import - imports items and files to cloned channels (this obsoletes hzfiles)
|
||||
- Diaspora: prevent processing of incomplete messages in various places
|
||||
- hzfiles: fix add missing load/unload functions
|
||||
- chess: do not look for games if we have no game_id - improves initial pageload performance
|
||||
- chess: convert to app
|
||||
- channelreputation: convert to app
|
||||
- irc: convert to per app
|
||||
- Provide the addon_common directory for common addon libraries
|
||||
- fuzzloc: convert to app
|
||||
- flattrwidget: convert to app
|
||||
- jappixmini: convert to app
|
||||
- xmpp: convert to app
|
||||
- visage: convert to app
|
||||
- diaspora: reflect linkify_tags() rewrite
|
||||
- twitter: convert to app
|
||||
- smileybutton: convert to app
|
||||
- skeleton: convert to app
|
||||
- planets: convert to app
|
||||
- pumpio: convert to app
|
||||
- pageheader: convert to app
|
||||
- nsabait: convert to app
|
||||
- dwpost: convert to app
|
||||
- diaspora: set the preserve_lf option in various places
|
||||
- diaspora: fix comments from unknown persons are not accpted
|
||||
- nofed: convert to app
|
||||
- ljpost: convert to app
|
||||
- diaspora: call update_queue_item() if delivery failed
|
||||
- pubcrawl: call update_queue_item() if delivery failed
|
||||
- libertree: convert to app
|
||||
- New addon: queueworker advanced - queue handling (experimental)
|
||||
- gallery: extended functionality: implements stream image viewer, converts images at the beginning of a post to a gallery
|
||||
- authchoose: correction to query, add affinity setting
|
||||
- New addon: photocache - local caching for public photos
|
||||
- New addon: totp - two factor authentication using time-based one-time passwords
|
||||
|
||||
|
||||
Hubzilla 3.8.9 (2018-02-03)
|
||||
- Fix typos in mod oep
|
||||
- Fix page jumping when liking collapsed/expanded post
|
||||
- Fix failure to import mail in mod import
|
||||
- Fix wrong channel count in mod new_channel
|
||||
- Fix diaspora addon regression
|
||||
- Remove deprecated diaspora addon endpoint
|
||||
- Fix wrong function call in gallery addon
|
||||
|
||||
|
||||
Hubzilla 3.8.8 (2018-12-22)
|
||||
- Fix issue with linkinfo
|
||||
- Fix cURL with HTTP/2
|
||||
|
||||
11
LICENSE
11
LICENSE
@@ -1,4 +1,5 @@
|
||||
Copyright (c) 2010-2018 the Hubzilla Community
|
||||
Copyright (c) 2019 Hubzilla Community
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
@@ -8,13 +9,13 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
27
Zotlabs/Daemon/Cache_embeds.php
Normal file
27
Zotlabs/Daemon/Cache_embeds.php
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php /** @file */
|
||||
|
||||
namespace Zotlabs\Daemon;
|
||||
|
||||
|
||||
class Cache_embeds {
|
||||
|
||||
static public function run($argc,$argv) {
|
||||
|
||||
if(! $argc == 2)
|
||||
return;
|
||||
|
||||
$c = q("select body from item where id = %d ",
|
||||
dbesc(intval($argv[1]))
|
||||
);
|
||||
|
||||
if(! $c)
|
||||
return;
|
||||
|
||||
$item = $c[0];
|
||||
|
||||
// bbcode conversion by default processes embeds that aren't already cached.
|
||||
// Ignore the returned html output.
|
||||
|
||||
bbcode($item['body']);
|
||||
}
|
||||
}
|
||||
@@ -94,6 +94,30 @@ class Cron {
|
||||
@time_sleep_until(microtime(true) + (float) $interval);
|
||||
}
|
||||
}
|
||||
|
||||
// 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')
|
||||
);
|
||||
if($r) {
|
||||
foreach($r as $rr) {
|
||||
$file = dbunescbin($rr['content']);
|
||||
if(is_file($file)) {
|
||||
@unlink($file);
|
||||
@rmdir(dirname($file));
|
||||
logger('info: deleted cached photo file ' . $file, LOGGER_DEBUG);
|
||||
}
|
||||
}
|
||||
}
|
||||
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
|
||||
@@ -164,7 +188,7 @@ class Cron {
|
||||
if($r) {
|
||||
require_once('include/photo/photo_driver.php');
|
||||
foreach($r as $rr) {
|
||||
$photos = import_xchan_photo($rr['xchan_photo_l'],$rr['xchan_hash']);
|
||||
$photos = import_xchan_photo($rr['xchan_photo_l'], $rr['xchan_hash'], false, true);
|
||||
$x = q("update xchan set xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s'
|
||||
where xchan_hash = '%s'",
|
||||
dbesc($photos[0]),
|
||||
|
||||
@@ -85,6 +85,7 @@ class Cron_daily {
|
||||
Master::Summon(array('Cli_suggest'));
|
||||
|
||||
remove_obsolete_hublocs();
|
||||
z6_discover();
|
||||
|
||||
call_hooks('cron_daily',datetime_convert());
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
namespace Zotlabs\Daemon;
|
||||
|
||||
use Zotlabs\Lib\DReport;
|
||||
|
||||
require_once('include/zot.php');
|
||||
require_once('include/queue_fn.php');
|
||||
|
||||
@@ -58,11 +60,12 @@ class Deliver {
|
||||
|
||||
foreach($dresult as $xx) {
|
||||
if(is_array($xx) && array_key_exists('message_id',$xx)) {
|
||||
if(delivery_report_is_storable($xx)) {
|
||||
q("insert into dreport ( dreport_mid, dreport_site, dreport_recip, dreport_result, dreport_time, dreport_xchan ) values ( '%s', '%s','%s','%s','%s','%s' ) ",
|
||||
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'])
|
||||
|
||||
@@ -16,135 +16,44 @@ if(array_search( __file__ , get_included_files()) === 0) {
|
||||
|
||||
class Master {
|
||||
|
||||
static public $queueworker = null;
|
||||
|
||||
static public function Summon($arr) {
|
||||
proc_run('php','Zotlabs/Daemon/Master.php',$arr);
|
||||
$hookinfo = [
|
||||
'argv'=>$arr
|
||||
];
|
||||
|
||||
call_hooks ('daemon_master_summon',$hookinfo);
|
||||
|
||||
$arr = $hookinfo['argv'];
|
||||
$argc = count($arr);
|
||||
|
||||
if ((!is_array($arr) || (count($arr) < 1))) {
|
||||
logger("Summon handled by hook.",LOGGER_DEBUG);
|
||||
return;
|
||||
}
|
||||
|
||||
$phpbin = get_config('system','phpbin','php');
|
||||
proc_run($phpbin,'Zotlabs/Daemon/Master.php',$arr);
|
||||
}
|
||||
|
||||
static public function Release($argc,$argv) {
|
||||
cli_startup();
|
||||
|
||||
$maxworkers = get_config('system','max_queue_workers');
|
||||
$hookinfo = [
|
||||
'argv'=>$argv
|
||||
];
|
||||
|
||||
if (!$maxworkers || $maxworkers == 0) {
|
||||
logger('Master: release: ' . print_r($argv,true), LOGGER_ALL,LOG_DEBUG);
|
||||
$cls = '\\Zotlabs\\Daemon\\' . $argv[0];
|
||||
$cls::run($argc,$argv);
|
||||
self::ClearQueue();
|
||||
} else {
|
||||
logger('Master: enqueue: ' . print_r($argv,true), LOGGER_ALL,LOG_DEBUG);
|
||||
$workinfo = ['argc'=>$argc,'argv'=>$argv];
|
||||
q("insert into config (cat,k,v) values ('queuework','%s','%s')",
|
||||
dbesc(uniqid('workitem:',true)),
|
||||
dbesc(serialize($workinfo)));
|
||||
self::Process();
|
||||
call_hooks ('daemon_master_release',$hookinfo);
|
||||
|
||||
$argv = $hookinfo['argv'];
|
||||
$argc = count($argv);
|
||||
|
||||
if ((!is_array($argv) || (count($argv) < 1))) {
|
||||
logger("Release handled by hook.",LOGGER_DEBUG);
|
||||
return;
|
||||
}
|
||||
|
||||
logger('Master: release: ' . json_encode($argv), LOGGER_ALL,LOG_DEBUG);
|
||||
$cls = '\\Zotlabs\\Daemon\\' . $argv[0];
|
||||
$cls::run($argc,$argv);
|
||||
}
|
||||
|
||||
static public function GetWorkerID() {
|
||||
$maxworkers = get_config('system','max_queue_workers');
|
||||
$maxworkers = ($maxworkers) ? $maxworkers : 3;
|
||||
|
||||
$workermaxage = get_config('system','max_queue_worker_age');
|
||||
$workermaxage = ($workermaxage) ? $workermaxage : 300;
|
||||
|
||||
$workers = q("select * from config where cat='queueworkers' and k like '%s'", 'workerstarted_%');
|
||||
|
||||
if (count($workers) > $maxworkers) {
|
||||
foreach ($workers as $idx => $worker) {
|
||||
$curtime = time();
|
||||
$age = (intval($curtime) - intval($worker['v']));
|
||||
if ( $age > $workermaxage) {
|
||||
logger("Prune worker: ".$worker['k'], LOGGER_ALL, LOGGER_DEBUG);
|
||||
$k = explode('_',$worker['k']);
|
||||
q("delete from config where cat='queueworkers' and k='%s'",
|
||||
'workerstarted_'.$k[1]);
|
||||
q("update config set k='%s' where cat='queuework' and k='%s'",
|
||||
dbesc(uniqid('workitem:',true)),
|
||||
'workitem_'.$k[1]);
|
||||
unset($workers[$idx]);
|
||||
}
|
||||
}
|
||||
if (count($workers) > $maxworkers) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return uniqid('',true);
|
||||
|
||||
}
|
||||
|
||||
static public function Process() {
|
||||
|
||||
self::$queueworker = self::GetWorkerID();
|
||||
|
||||
if (!self::$queueworker) {
|
||||
logger('Master: unable to obtain worker ID.');
|
||||
killme();
|
||||
}
|
||||
|
||||
set_config('queueworkers','workerstarted_'.self::$queueworker,time());
|
||||
|
||||
$workersleep = get_config('system','queue_worker_sleep');
|
||||
$workersleep = ($workersleep) ? $workersleep : 5;
|
||||
cli_startup();
|
||||
|
||||
$work = q("update config set k='%s' where cat='queuework' and k like '%s' limit 1",
|
||||
'workitem_'.self::$queueworker,
|
||||
dbesc('workitem:%'));
|
||||
$jobs = 0;
|
||||
while ($work) {
|
||||
$workitem = q("select * from config where cat='queuework' and k='%s'",
|
||||
'workitem_'.self::$queueworker);
|
||||
|
||||
if (isset($workitem[0])) {
|
||||
$jobs++;
|
||||
$workinfo = unserialize($workitem[0]['v']);
|
||||
$argc = $workinfo['argc'];
|
||||
$argv = $workinfo['argv'];
|
||||
logger('Master: process: ' . print_r($argv,true), LOGGER_ALL,LOG_DEBUG);
|
||||
|
||||
//Delete unclaimed duplicate workitems.
|
||||
q("delete from config where cat='queuework' and k='workitem' and v='%s'",
|
||||
serialize($argv));
|
||||
|
||||
$cls = '\\Zotlabs\\Daemon\\' . $argv[0];
|
||||
$cls::run($argc,$argv);
|
||||
|
||||
//Right now we assume that if we get a return, everything is OK.
|
||||
//At some point we may want to test whether the run returns true/false
|
||||
// and requeue the work to be tried again. But we probably want
|
||||
// to implement some sort of "retry interval" first.
|
||||
|
||||
q("delete from config where cat='queuework' and k='%s'",
|
||||
'workitem_'.self::$queueworker);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
sleep ($workersleep);
|
||||
$work = q("update config set k='%s' where cat='queuework' and k like '%s' limit 1",
|
||||
'workitem_'.self::$queueworker,
|
||||
dbesc('workitem:%'));
|
||||
|
||||
}
|
||||
logger('Master: Worker Thread: queue items processed:' . $jobs);
|
||||
q("delete from config where cat='queueworkers' and k='%s'",
|
||||
'workerstarted_'.self::$queueworker);
|
||||
}
|
||||
|
||||
static public function ClearQueue() {
|
||||
$work = q("select * from config where cat='queuework' and k like '%s'",
|
||||
dbesc('workitem%'));
|
||||
foreach ($work as $workitem) {
|
||||
$workinfo = unserialize($workitem['v']);
|
||||
$argc = $workinfo['argc'];
|
||||
$argv = $workinfo['argv'];
|
||||
logger('Master: process: ' . print_r($argv,true), LOGGER_ALL,LOG_DEBUG);
|
||||
$cls = '\\Zotlabs\\Daemon\\' . $argv[0];
|
||||
$cls::run($argc,$argv);
|
||||
}
|
||||
$work = q("delete from config where cat='queuework' and k like '%s'",
|
||||
dbesc('workitem%'));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
namespace Zotlabs\Daemon;
|
||||
|
||||
use Zotlabs\Lib\Libzot;
|
||||
|
||||
require_once('include/queue_fn.php');
|
||||
require_once('include/html2plain.php');
|
||||
require_once('include/conversation.php');
|
||||
@@ -344,7 +346,16 @@ class Notifier {
|
||||
return;
|
||||
|
||||
$encoded_item = encode_item($target_item);
|
||||
|
||||
|
||||
// activitystreams version
|
||||
$m = get_iconfig($target_item,'activitystreams','signed_data');
|
||||
if($m) {
|
||||
$activity = json_decode($m,true);
|
||||
}
|
||||
else {
|
||||
$activity = \Zotlabs\Lib\Activity::encode_activity($target_item);
|
||||
}
|
||||
|
||||
// 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.
|
||||
@@ -401,6 +412,12 @@ class Notifier {
|
||||
$private = false;
|
||||
$recipients = collect_recipients($parent_item,$private);
|
||||
|
||||
|
||||
if ($top_level_post) {
|
||||
// remove clones who will receive the post via sync
|
||||
$recipients = array_diff($recipients, [ $target_item['owner_xchan'] ]);
|
||||
}
|
||||
|
||||
// FIXME add any additional recipients such as mentions, etc.
|
||||
|
||||
// don't send deletions onward for other people's stuff
|
||||
@@ -423,6 +440,8 @@ class Notifier {
|
||||
$x['body'] = 'private';
|
||||
logger('notifier: encoded item: ' . print_r($x,true), LOGGER_DATA, LOG_DEBUG);
|
||||
|
||||
//logger('notifier: encoded activity: ' . print_r($activity,true), LOGGER_DATA, LOG_DEBUG);
|
||||
|
||||
stringify_array_elms($recipients);
|
||||
if(! $recipients) {
|
||||
logger('no recipients');
|
||||
@@ -433,7 +452,7 @@ class Notifier {
|
||||
|
||||
$env_recips = (($private) ? array() : null);
|
||||
|
||||
$details = q("select xchan_hash, xchan_instance_url, xchan_network, xchan_addr, xchan_guid, xchan_guid_sig from xchan where xchan_hash in (" . protect_sprintf(implode(',',$recipients)) . ")");
|
||||
$details = q("select xchan_hash, xchan_network, xchan_addr, xchan_guid, xchan_guid_sig from xchan where xchan_hash in (" . protect_sprintf(implode(',',$recipients)) . ")");
|
||||
|
||||
|
||||
$recip_list = array();
|
||||
@@ -561,7 +580,7 @@ class Notifier {
|
||||
|
||||
logger('notifier_hub: ' . $hub['hubloc_url'],LOGGER_DEBUG);
|
||||
|
||||
if($hub['hubloc_network'] !== 'zot') {
|
||||
if(! in_array($hub['hubloc_network'], [ 'zot','zot6' ])) {
|
||||
$narr = [
|
||||
'channel' => $channel,
|
||||
'upstream' => $upstream,
|
||||
@@ -610,20 +629,32 @@ class Notifier {
|
||||
continue;
|
||||
}
|
||||
|
||||
// default: zot protocol
|
||||
if(! in_array($hub['hubloc_network'], [ 'zot','zot6' ])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Do not change this to a uuid as long as we have traditional zot servers
|
||||
// in the loop. The signature verification step can't handle dashes in the
|
||||
// hashes.
|
||||
|
||||
$hash = random_string(48);
|
||||
|
||||
$hash = random_string();
|
||||
$packet = null;
|
||||
$pmsg = '';
|
||||
|
||||
if($packet_type === 'refresh' || $packet_type === 'purge') {
|
||||
$packet = zot_build_packet($channel,$packet_type,(($packet_recips) ? $packet_recips : null));
|
||||
if($hub['hubloc_network'] === 'zot6') {
|
||||
$packet = Libzot::build_packet($channel, $packet_type, ids_to_array($packet_recips,'hash'));
|
||||
}
|
||||
else {
|
||||
$packet = zot_build_packet($channel,$packet_type,(($packet_recips) ? $packet_recips : null));
|
||||
}
|
||||
}
|
||||
if($packet_type === 'keychange') {
|
||||
if($packet_type === 'keychange' && $hub['hubloc_network'] === 'zot') {
|
||||
$pmsg = get_pconfig($channel['channel_id'],'system','keychange');
|
||||
$packet = zot_build_packet($channel,$packet_type,(($packet_recips) ? $packet_recips : null));
|
||||
}
|
||||
elseif($packet_type === 'request') {
|
||||
elseif($packet_type === 'request' && $hub['hubloc_network'] === 'zot') {
|
||||
$env = (($hub_env && $hub_env[$hub['hubloc_host'] . $hub['hubloc_sitekey']]) ? $hub_env[$hub['hubloc_host'] . $hub['hubloc_sitekey']] : '');
|
||||
$packet = zot_build_packet($channel,$packet_type,$env,$hub['hubloc_sitekey'],$hub['site_crypto'],
|
||||
$hash, array('message_id' => $request_message_id)
|
||||
@@ -636,6 +667,7 @@ class Notifier {
|
||||
'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) : '')
|
||||
));
|
||||
@@ -643,18 +675,43 @@ class Notifier {
|
||||
else {
|
||||
$env = (($hub_env && $hub_env[$hub['hubloc_host'] . $hub['hubloc_sitekey']]) ? $hub_env[$hub['hubloc_host'] . $hub['hubloc_sitekey']] : '');
|
||||
|
||||
// currently zot6 delivery is only performed on normal items and not sync items or mail or anything else
|
||||
// Eventually we will do this for all deliveries, but for now ensure this is precisely what we are dealing
|
||||
// with before switching to zot6 as the primary zot6 handler checks for the existence of a message delivery report
|
||||
// to trigger dequeue'ing
|
||||
|
||||
$z6 = (($encoded_item && $encoded_item['type'] === 'activity' && (! array_key_exists('allow_cid',$encoded_item))) ? true : false);
|
||||
if($z6) {
|
||||
$packet = zot6_build_packet($channel,'notify',$env, json_encode($encoded_item), (($private) ? $hub['hubloc_sitekey'] : null), $hub['site_crypto'],$hash);
|
||||
if($hub['hubloc_network'] === 'zot6') {
|
||||
$zenv = [];
|
||||
if($env) {
|
||||
foreach($env as $e) {
|
||||
$zenv[] = $e['hash'];
|
||||
}
|
||||
}
|
||||
|
||||
$packet_type = (($upstream || $uplink) ? 'response' : 'activity');
|
||||
|
||||
// block zot private reshares from zot6, as this could cause a number of privacy issues
|
||||
// due to parenting differences between the reshare implementations. In zot a reshare is
|
||||
// a standalone parent activity and in zot6 it is a followup/child of the original activity.
|
||||
// For public reshares, some comments to the reshare on the zot fork will not make it to zot6
|
||||
// due to these different message models. This cannot be prevented at this time.
|
||||
|
||||
if($packet_type === 'activity' && $activity['type'] === 'Announce' && intval($target_item['item_private'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$packet = Libzot::build_packet($channel,$packet_type,$zenv,$activity,'activitystreams',(($private) ? $hub['hubloc_sitekey'] : null),$hub['site_crypto']);
|
||||
}
|
||||
else {
|
||||
$packet = zot_build_packet($channel,'notify',$env, (($private) ? $hub['hubloc_sitekey'] : null), $hub['site_crypto'],$hash);
|
||||
// currently zot6 delivery is only performed on normal items and not sync items or mail or anything else
|
||||
// Eventually we will do this for all deliveries, but for now ensure this is precisely what we are dealing
|
||||
// with before switching to zot6 as the primary zot6 handler checks for the existence of a message delivery report
|
||||
// to trigger dequeue'ing
|
||||
|
||||
$z6 = (($encoded_item && $encoded_item['type'] === 'activity' && (! array_key_exists('allow_cid',$encoded_item))) ? true : false);
|
||||
if($z6) {
|
||||
$packet = zot6_build_packet($channel,'notify',$env, json_encode($encoded_item), (($private) ? $hub['hubloc_sitekey'] : null), $hub['site_crypto'],$hash);
|
||||
}
|
||||
else {
|
||||
$packet = zot_build_packet($channel,'notify',$env, (($private) ? $hub['hubloc_sitekey'] : null), $hub['site_crypto'],$hash);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
queue_insert(
|
||||
@@ -663,6 +720,7 @@ class Notifier {
|
||||
'account_id' => $target_item['aid'],
|
||||
'channel_id' => $target_item['uid'],
|
||||
'posturl' => $hub['hubloc_callback'],
|
||||
'driver' => $hub['hubloc_network'],
|
||||
'notify' => $packet,
|
||||
'msg' => json_encode($encoded_item)
|
||||
]
|
||||
|
||||
@@ -69,7 +69,7 @@ class Onepoll {
|
||||
return;
|
||||
}
|
||||
|
||||
if($contact['xchan_network'] !== 'zot')
|
||||
if(! in_array($contact['xchan_network'],['zot','zot6']))
|
||||
return;
|
||||
|
||||
// update permissions
|
||||
|
||||
@@ -110,7 +110,7 @@ class Poller {
|
||||
}
|
||||
|
||||
|
||||
if($contact['xchan_network'] !== 'zot')
|
||||
if(! in_array($contact['xchan_network'],['zot','zot6']))
|
||||
continue;
|
||||
|
||||
if($c == $t) {
|
||||
@@ -199,6 +199,7 @@ class Poller {
|
||||
set_config('system','lastpoll',datetime_convert());
|
||||
|
||||
//All done - clear the lockfile
|
||||
|
||||
@unlink($lockfile);
|
||||
|
||||
return;
|
||||
|
||||
@@ -12,7 +12,6 @@ class Queue {
|
||||
require_once('include/items.php');
|
||||
require_once('include/bbcode.php');
|
||||
|
||||
|
||||
if($argc > 1)
|
||||
$queue_id = $argv[1];
|
||||
else
|
||||
@@ -61,10 +60,20 @@ class Queue {
|
||||
// or just prior to this query based on recent and long-term delivery history. If we have good reason to believe
|
||||
// the site is permanently down, there's no reason to attempt delivery at all, or at most not more than once
|
||||
// or twice a day.
|
||||
|
||||
$r = q("SELECT * FROM outq WHERE outq_delivered = 0 and outq_scheduled < %s ",
|
||||
|
||||
$sqlrandfunc = db_getfunc('rand');
|
||||
|
||||
$r = q("SELECT *,$sqlrandfunc as rn FROM outq WHERE outq_delivered = 0 and outq_scheduled < %s order by rn limit 1",
|
||||
db_utcnow()
|
||||
);
|
||||
while ($r) {
|
||||
foreach($r as $rv) {
|
||||
queue_deliver($rv);
|
||||
}
|
||||
$r = q("SELECT *,$sqlrandfunc as rn FROM outq WHERE outq_delivered = 0 and outq_scheduled < %s order by rn limit 1",
|
||||
db_utcnow()
|
||||
);
|
||||
}
|
||||
}
|
||||
if(! $r)
|
||||
return;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -7,22 +7,25 @@ namespace Zotlabs\Lib;
|
||||
*
|
||||
* Parses an ActivityStream JSON string.
|
||||
*/
|
||||
|
||||
class ActivityStreams {
|
||||
|
||||
public $raw = null;
|
||||
public $data;
|
||||
public $valid = false;
|
||||
public $id = '';
|
||||
public $type = '';
|
||||
public $actor = null;
|
||||
public $obj = null;
|
||||
public $tgt = null;
|
||||
public $origin = null;
|
||||
public $owner = null;
|
||||
public $signer = null;
|
||||
public $ldsig = null;
|
||||
public $sigok = false;
|
||||
public $recips = null;
|
||||
public $raw = null;
|
||||
public $data = null;
|
||||
public $valid = false;
|
||||
public $deleted = false;
|
||||
public $id = '';
|
||||
public $parent_id = '';
|
||||
public $type = '';
|
||||
public $actor = null;
|
||||
public $obj = null;
|
||||
public $tgt = null;
|
||||
public $origin = null;
|
||||
public $owner = null;
|
||||
public $signer = null;
|
||||
public $ldsig = null;
|
||||
public $sigok = false;
|
||||
public $recips = null;
|
||||
public $raw_recips = null;
|
||||
|
||||
/**
|
||||
@@ -35,16 +38,49 @@ class ActivityStreams {
|
||||
function __construct($string) {
|
||||
|
||||
$this->raw = $string;
|
||||
$this->data = json_decode($string, true);
|
||||
|
||||
if(is_array($string)) {
|
||||
$this->data = $string;
|
||||
}
|
||||
else {
|
||||
$this->data = json_decode($string, true);
|
||||
}
|
||||
|
||||
if($this->data) {
|
||||
|
||||
// verify and unpack JSalmon signature if present
|
||||
|
||||
if(is_array($this->data) && array_key_exists('signed',$this->data)) {
|
||||
$ret = JSalmon::verify($this->data);
|
||||
$tmp = JSalmon::unpack($this->data['data']);
|
||||
if($ret && $ret['success']) {
|
||||
if($ret['signer']) {
|
||||
$saved = json_encode($this->data,JSON_UNESCAPED_SLASHES);
|
||||
$this->data = $tmp;
|
||||
$this->data['signer'] = $ret['signer'];
|
||||
$this->data['signed_data'] = $saved;
|
||||
if($ret['hubloc']) {
|
||||
$this->data['hubloc'] = $ret['hubloc'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->valid = true;
|
||||
|
||||
if(array_key_exists('type',$this->data) && array_key_exists('actor',$this->data) && array_key_exists('object',$this->data)) {
|
||||
if($this->data['type'] === 'Delete' && $this->data['actor'] === $this->data['object']) {
|
||||
$this->deleted = $this->data['actor'];
|
||||
$this->valid = false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if($this->is_valid()) {
|
||||
$this->id = $this->get_property_obj('id');
|
||||
$this->type = $this->get_primary_type();
|
||||
$this->actor = $this->get_compound_property('actor');
|
||||
$this->actor = $this->get_actor('actor','','');
|
||||
$this->obj = $this->get_compound_property('object');
|
||||
$this->tgt = $this->get_compound_property('target');
|
||||
$this->origin = $this->get_compound_property('origin');
|
||||
@@ -53,14 +89,31 @@ class ActivityStreams {
|
||||
$this->ldsig = $this->get_compound_property('signature');
|
||||
if($this->ldsig) {
|
||||
$this->signer = $this->get_compound_property('creator',$this->ldsig);
|
||||
if($this->signer && $this->signer['publicKey'] && $this->signer['publicKey']['publicKeyPem']) {
|
||||
$this->sigok = \Zotlabs\Lib\LDSignatures::verify($this->data,$this->signer['publicKey']['publicKeyPem']);
|
||||
if($this->signer && is_array($this->signer) && array_key_exists('publicKey',$this->signer) && is_array($this->signer['publicKey']) && $this->signer['publicKey']['publicKeyPem']) {
|
||||
$this->sigok = LDSignatures::verify($this->data,$this->signer['publicKey']['publicKeyPem']);
|
||||
}
|
||||
}
|
||||
|
||||
if(($this->type === 'Note') && (! $this->obj)) {
|
||||
if(! $this->obj) {
|
||||
$this->obj = $this->data;
|
||||
$this->type = 'Create';
|
||||
if(! $this->actor) {
|
||||
$this->actor = $this->get_actor('attributedTo',$this->obj);
|
||||
}
|
||||
}
|
||||
|
||||
if($this->obj && is_array($this->obj) && $this->obj['actor'])
|
||||
$this->obj['actor'] = $this->get_actor('actor',$this->obj);
|
||||
if($this->tgt && is_array($this->tgt) && $this->tgt['actor'])
|
||||
$this->tgt['actor'] = $this->get_actor('actor',$this->tgt);
|
||||
|
||||
$this->parent_id = $this->get_property_obj('inReplyTo');
|
||||
|
||||
if((! $this->parent_id) && is_array($this->obj)) {
|
||||
$this->parent_id = $this->obj['inReplyTo'];
|
||||
}
|
||||
if((! $this->parent_id) && is_array($this->obj)) {
|
||||
$this->parent_id = $this->obj['id'];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -190,28 +243,32 @@ class ActivityStreams {
|
||||
$base = (($base) ? $base : $this->data);
|
||||
$propname = (($prefix) ? $prefix . ':' : '') . $property;
|
||||
|
||||
if(! is_array($base)) {
|
||||
btlogger('not an array: ' . print_r($base,true));
|
||||
return null;
|
||||
}
|
||||
|
||||
return ((array_key_exists($propname, $base)) ? $base[$propname] : null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Fetches a property from an URL.
|
||||
*
|
||||
* @param string $url
|
||||
* @return NULL|mixed
|
||||
*/
|
||||
|
||||
function fetch_property($url) {
|
||||
$redirects = 0;
|
||||
if(! check_siteallowed($url)) {
|
||||
logger('blacklisted: ' . $url);
|
||||
return null;
|
||||
}
|
||||
return self::fetch($url);
|
||||
}
|
||||
|
||||
$x = z_fetch_url($url, true, $redirects,
|
||||
['headers' => [ 'Accept: application/activity+json, application/ld+json; profile="https://www.w3.org/ns/activitystreams"' ]]);
|
||||
if($x['success'])
|
||||
return json_decode($x['body'], true);
|
||||
static function fetch($url,$channel = null) {
|
||||
return Activity::fetch($url,$channel);
|
||||
}
|
||||
|
||||
return null;
|
||||
static function is_an_actor($s) {
|
||||
return(in_array($s,[ 'Application','Group','Organization','Person','Service' ]));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -222,10 +279,71 @@ class ActivityStreams {
|
||||
* @param string $namespace (optional) default empty
|
||||
* @return NULL|mixed
|
||||
*/
|
||||
function get_compound_property($property, $base = '', $namespace = '') {
|
||||
|
||||
function get_actor($property,$base='',$namespace = '') {
|
||||
$x = $this->get_property_obj($property, $base, $namespace);
|
||||
if($this->is_url($x)) {
|
||||
$x = $this->fetch_property($x);
|
||||
|
||||
// SECURITY: If we have already stored the actor profile, re-generate it
|
||||
// from cached data - don't refetch it from the network
|
||||
|
||||
$r = q("select * from xchan left join hubloc on xchan_hash = hubloc_hash where hubloc_id_url = '%s' limit 1",
|
||||
dbesc($x)
|
||||
);
|
||||
if($r) {
|
||||
$y = Activity::encode_person($r[0]);
|
||||
$y['cached'] = true;
|
||||
return $y;
|
||||
}
|
||||
}
|
||||
$actor = $this->get_compound_property($property,$base,$namespace,true);
|
||||
if(is_array($actor) && self::is_an_actor($actor['type'])) {
|
||||
if(array_key_exists('id',$actor) && (! array_key_exists('inbox',$actor))) {
|
||||
$actor = $this->fetch_property($actor['id']);
|
||||
}
|
||||
return $actor;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @param string $property
|
||||
* @param array $base
|
||||
* @param string $namespace (optional) default empty
|
||||
* @param boolean $first (optional) default false, if true and result is a sequential array return only the first element
|
||||
* @return NULL|mixed
|
||||
*/
|
||||
function get_compound_property($property, $base = '', $namespace = '', $first = false) {
|
||||
$x = $this->get_property_obj($property, $base, $namespace);
|
||||
if($this->is_url($x)) {
|
||||
$y = $this->fetch_property($x);
|
||||
if (is_array($y)) {
|
||||
$x = $y;
|
||||
}
|
||||
}
|
||||
|
||||
// verify and unpack JSalmon signature if present
|
||||
|
||||
if(is_array($x) && array_key_exists('signed',$x)) {
|
||||
$ret = JSalmon::verify($x);
|
||||
$tmp = JSalmon::unpack($x['data']);
|
||||
if($ret && $ret['success']) {
|
||||
if($ret['signer']) {
|
||||
$saved = json_encode($x,JSON_UNESCAPED_SLASHES);
|
||||
$x = $tmp;
|
||||
$x['signer'] = $ret['signer'];
|
||||
$x['signed_data'] = $saved;
|
||||
if($ret['hubloc']) {
|
||||
$x['hubloc'] = $ret['hubloc'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if($first && is_array($x) && array_key_exists(0,$x)) {
|
||||
return $x[0];
|
||||
}
|
||||
|
||||
return $x;
|
||||
@@ -273,4 +391,18 @@ class ActivityStreams {
|
||||
return $x;
|
||||
}
|
||||
|
||||
|
||||
static function is_as_request() {
|
||||
|
||||
$x = getBestSupportedMimeType([
|
||||
'application/ld+json;profile="https://www.w3.org/ns/activitystreams"',
|
||||
'application/activity+json',
|
||||
'application/ld+json;profile="http://www.w3.org/ns/activitystreams"'
|
||||
]);
|
||||
|
||||
return(($x) ? true : false);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -12,8 +12,16 @@ class Api_router {
|
||||
}
|
||||
|
||||
static function find($path) {
|
||||
if(array_key_exists($path,self::$routes))
|
||||
if (array_key_exists($path,self::$routes)) {
|
||||
return self::$routes[$path];
|
||||
}
|
||||
|
||||
$with_params = dirname($path) . '/[id]';
|
||||
|
||||
if (array_key_exists($with_params,self::$routes)) {
|
||||
return self::$routes[$with_params];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,32 +1,34 @@
|
||||
<?php /** @file */
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
/**
|
||||
* Apps
|
||||
*
|
||||
*/
|
||||
|
||||
require_once('include/plugin.php');
|
||||
require_once('include/channel.php');
|
||||
|
||||
|
||||
/**
|
||||
* @brief Apps class.
|
||||
*
|
||||
*/
|
||||
class Apps {
|
||||
|
||||
static public $available_apps = null;
|
||||
static public $installed_apps = null;
|
||||
|
||||
static public $base_apps = null;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @param boolean $translate (optional) default true
|
||||
* @return array
|
||||
*/
|
||||
static public function get_system_apps($translate = true) {
|
||||
$ret = [];
|
||||
|
||||
$ret = array();
|
||||
if(is_dir('apps'))
|
||||
$files = glob('apps/*.apd');
|
||||
else
|
||||
$files = glob('app/*.apd');
|
||||
|
||||
if($files) {
|
||||
foreach($files as $f) {
|
||||
$x = self::parse_app_description($f,$translate);
|
||||
@@ -50,14 +52,17 @@ class Apps {
|
||||
}
|
||||
}
|
||||
|
||||
call_hooks('get_system_apps',$ret);
|
||||
/**
|
||||
* @hooks get_system_apps
|
||||
* Hook to manipulate the system apps array.
|
||||
*/
|
||||
call_hooks('get_system_apps', $ret);
|
||||
|
||||
return $ret;
|
||||
|
||||
}
|
||||
|
||||
static public function get_base_apps() {
|
||||
return get_config('system','base_apps',[
|
||||
$x = get_config('system','base_apps',[
|
||||
'Connections',
|
||||
'Network',
|
||||
'Settings',
|
||||
@@ -65,13 +70,21 @@ class Apps {
|
||||
'Channel Home',
|
||||
'View Profile',
|
||||
'Photos',
|
||||
'Events',
|
||||
'Calendar',
|
||||
'Directory',
|
||||
'Search',
|
||||
'Help',
|
||||
'Mail',
|
||||
'Profile Photo'
|
||||
]);
|
||||
|
||||
/**
|
||||
* @hooks get_base_apps
|
||||
* Hook to manipulate the base apps array.
|
||||
*/
|
||||
call_hooks('get_base_apps', $x);
|
||||
|
||||
return $x;
|
||||
}
|
||||
|
||||
static public function import_system_apps() {
|
||||
@@ -79,7 +92,7 @@ class Apps {
|
||||
return;
|
||||
|
||||
self::$base_apps = self::get_base_apps();
|
||||
|
||||
|
||||
$apps = self::get_system_apps(false);
|
||||
|
||||
self::$available_apps = q("select * from app where app_channel = 0");
|
||||
@@ -104,6 +117,7 @@ class Apps {
|
||||
// $id will be boolean true or false to install an app, or an integer id to update an existing app
|
||||
if($id === false)
|
||||
continue;
|
||||
|
||||
if($id !== true) {
|
||||
// if we already installed this app, but it changed, preserve any categories we created
|
||||
$s = EMPTY_STR;
|
||||
@@ -124,16 +138,17 @@ class Apps {
|
||||
$app['guid'] = hash('whirlpool',$app['name']);
|
||||
$app['system'] = 1;
|
||||
self::app_install(local_channel(),$app);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Install the system app if no system apps have been installed, or if a new system app
|
||||
* Install the system app if no system apps have been installed, or if a new system app
|
||||
* is discovered, or if the version of a system app changes.
|
||||
*
|
||||
* @param array $app
|
||||
* @return boolean|int
|
||||
*/
|
||||
|
||||
static public function check_install_system_app($app) {
|
||||
if((! is_array(self::$available_apps)) || (! count(self::$available_apps))) {
|
||||
return true;
|
||||
@@ -157,17 +172,16 @@ class Apps {
|
||||
return $notfound;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Install the system app if no system apps have been installed, or if a new system app
|
||||
* is discovered, or if the version of a system app changes.
|
||||
* Install the personal app if no personal apps have been installed, or if a new personal app
|
||||
* is discovered, or if the version of a personal app changes.
|
||||
*
|
||||
* @param array $app
|
||||
* @return boolean|int
|
||||
*/
|
||||
|
||||
|
||||
|
||||
static public function check_install_personal_app($app) {
|
||||
$installed = false;
|
||||
foreach(self::$installed_apps as $iapp) {
|
||||
foreach(self::$installed_apps as $iapp) {
|
||||
if($iapp['app_id'] == hash('whirlpool',$app['name'])) {
|
||||
$installed = true;
|
||||
if(($iapp['app_version'] != $app['version'])
|
||||
@@ -187,19 +201,24 @@ class Apps {
|
||||
return strcasecmp($a['name'],$b['name']);
|
||||
}
|
||||
|
||||
|
||||
static public function parse_app_description($f,$translate = true) {
|
||||
|
||||
$ret = array();
|
||||
/**
|
||||
* @brief Parse app description.
|
||||
*
|
||||
* @param string $f filename
|
||||
* @param boolean $translate (optional) default true
|
||||
* @return boolean|array
|
||||
*/
|
||||
static public function parse_app_description($f, $translate = true) {
|
||||
$ret = [];
|
||||
$matches = [];
|
||||
|
||||
$baseurl = z_root();
|
||||
$channel = \App::get_channel();
|
||||
$address = (($channel) ? $channel['channel_address'] : '');
|
||||
|
||||
//$channel = \App::get_channel();
|
||||
//$address = (($channel) ? $channel['channel_address'] : '');
|
||||
|
||||
//future expansion
|
||||
|
||||
$observer = \App::get_observer();
|
||||
|
||||
|
||||
$lines = @file($f);
|
||||
if($lines) {
|
||||
@@ -208,7 +227,7 @@ class Apps {
|
||||
$ret[$matches[1]] = trim($matches[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(! $ret['photo'])
|
||||
$ret['photo'] = $baseurl . '/' . get_default_profile_photo(80);
|
||||
@@ -290,36 +309,41 @@ class Apps {
|
||||
if($ret) {
|
||||
if($translate)
|
||||
self::translate_system_apps($ret);
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static public function translate_system_apps(&$arr) {
|
||||
$apps = array(
|
||||
'Apps' => t('Apps'),
|
||||
'Affinity Tool' => t('Affinity Tool'),
|
||||
'Articles' => t('Articles'),
|
||||
'Cards' => t('Cards'),
|
||||
'Admin' => t('Site Admin'),
|
||||
'Report Bug' => t('Report Bug'),
|
||||
'Bookmarks' => t('Bookmarks'),
|
||||
'Chatrooms' => t('Chatrooms'),
|
||||
'Content Filter' => t('Content Filter'),
|
||||
'Content Import' => t('Content Import'),
|
||||
'Connections' => t('Connections'),
|
||||
'Remote Diagnostics' => t('Remote Diagnostics'),
|
||||
'Suggest Channels' => t('Suggest Channels'),
|
||||
'Login' => t('Login'),
|
||||
'Channel Manager' => t('Channel Manager'),
|
||||
'Channel Manager' => t('Channel Manager'),
|
||||
'Network' => t('Stream'),
|
||||
'Settings' => t('Settings'),
|
||||
'Files' => t('Files'),
|
||||
'Webpages' => t('Webpages'),
|
||||
'Wiki' => t('Wiki'),
|
||||
'Channel Home' => t('Channel Home'),
|
||||
'Channel Home' => t('Channel Home'),
|
||||
'View Profile' => t('View Profile'),
|
||||
'Photos' => t('Photos'),
|
||||
'Events' => t('Events'),
|
||||
'Directory' => t('Directory'),
|
||||
'Photos' => t('Photos'),
|
||||
'Calendar' => t('Calendar'),
|
||||
'Directory' => t('Directory'),
|
||||
'Help' => t('Help'),
|
||||
'Mail' => t('Mail'),
|
||||
'Mood' => t('Mood'),
|
||||
@@ -339,7 +363,6 @@ class Apps {
|
||||
'Privacy Groups' => t('Privacy Groups'),
|
||||
'Notifications' => t('Notifications'),
|
||||
'Order Apps' => t('Order Apps'),
|
||||
'CalDAV' => t('CalDAV'),
|
||||
'CardDAV' => t('CardDAV'),
|
||||
'Channel Sources' => t('Channel Sources'),
|
||||
'Guest Access' => t('Guest Access'),
|
||||
@@ -364,30 +387,31 @@ class Apps {
|
||||
if(array_key_exists($arr[$x]['name'],$apps)) {
|
||||
$arr[$x]['name'] = $apps[$arr[$x]['name']];
|
||||
} else {
|
||||
// Try to guess by app name if not in list
|
||||
$arr[$x]['name'] = t(trim($arr[$x]['name']));
|
||||
// Try to guess by app name if not in list
|
||||
$arr[$x]['name'] = t(trim($arr[$x]['name']));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// papp is a portable app
|
||||
|
||||
static public function app_render($papp,$mode = 'view') {
|
||||
|
||||
/**
|
||||
* modes:
|
||||
* view: normal mode for viewing an app via bbcode from a conversation or page
|
||||
* provides install/update button if you're logged in locally
|
||||
* install: like view but does not display app-bin options if they are present
|
||||
* list: normal mode for viewing an app on the app page
|
||||
* no buttons are shown
|
||||
* edit: viewing the app page in editing mode provides a delete button
|
||||
* nav: render apps for app-bin
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @param array $papp
|
||||
* papp is a portable app
|
||||
* @param string $mode (optional) default 'view'
|
||||
* Render modes:
|
||||
* * \b view: normal mode for viewing an app via bbcode from a conversation or page
|
||||
* provides install/update button if you're logged in locally
|
||||
* * \b install: like view but does not display app-bin options if they are present
|
||||
* * \b list: normal mode for viewing an app on the app page
|
||||
* no buttons are shown
|
||||
* * \b edit: viewing the app page in editing mode provides a delete button
|
||||
* * \b nav: render apps for app-bin
|
||||
*
|
||||
* @return void|string Parsed HTML
|
||||
*/
|
||||
static public function app_render($papp, $mode = 'view') {
|
||||
$installed = false;
|
||||
|
||||
if(! $papp)
|
||||
@@ -412,7 +436,7 @@ class Apps {
|
||||
$sys = get_sys_channel();
|
||||
$view_channel = $sys['channel_id'];
|
||||
}
|
||||
self::app_macros($view_channel,$papp);
|
||||
self::app_macros($view_channel,$papp);
|
||||
}
|
||||
|
||||
if(strpos($papp['url'], ',')) {
|
||||
@@ -425,7 +449,6 @@ class Apps {
|
||||
$papp['url'] = z_root() . ((strpos($papp['url'],'/') === 0) ? '' : '/') . $papp['url'];
|
||||
|
||||
|
||||
|
||||
foreach($papp as $k => $v) {
|
||||
if(strpos($v,'http') === 0 && $k != 'papp') {
|
||||
if(! (local_channel() && strpos($v,z_root()) === 0)) {
|
||||
@@ -507,7 +530,7 @@ class Apps {
|
||||
if($x) {
|
||||
$hosturl = $x['scheme'] . '://' . $x['host'] . '/';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$install_action = (($installed) ? t('Update') : t('Install'));
|
||||
@@ -590,8 +613,14 @@ class Apps {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static public function can_delete($uid,$app) {
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @param mixed $uid If not set return false, otherwise no influence
|
||||
* @param array $app
|
||||
* @return boolean
|
||||
*/
|
||||
static public function can_delete($uid, $app) {
|
||||
if(! $uid) {
|
||||
return false;
|
||||
}
|
||||
@@ -599,7 +628,7 @@ class Apps {
|
||||
$base_apps = self::get_base_apps();
|
||||
if($base_apps) {
|
||||
foreach($base_apps as $b) {
|
||||
if($app['guid'] === hash('whirlpool',$b)) {
|
||||
if($app['guid'] === hash('whirlpool', $b)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -611,7 +640,6 @@ class Apps {
|
||||
static public function app_destroy($uid,$app) {
|
||||
|
||||
if($uid && $app['guid']) {
|
||||
|
||||
$x = q("select * from app where app_id = '%s' and app_channel = %d limit 1",
|
||||
dbesc($app['guid']),
|
||||
intval($uid)
|
||||
@@ -620,7 +648,7 @@ class Apps {
|
||||
if(! intval($x[0]['app_deleted'])) {
|
||||
$x[0]['app_deleted'] = 1;
|
||||
if(self::can_delete($uid,$app)) {
|
||||
$r = q("delete from app where app_id = '%s' and app_channel = %d",
|
||||
q("delete from app where app_id = '%s' and app_channel = %d",
|
||||
dbesc($app['guid']),
|
||||
intval($uid)
|
||||
);
|
||||
@@ -628,10 +656,15 @@ class Apps {
|
||||
intval(TERM_OBJ_APP),
|
||||
intval($x[0]['id'])
|
||||
);
|
||||
/**
|
||||
* @hooks app_destroy
|
||||
* Called after app entry got removed from database
|
||||
* and provide app array from database.
|
||||
*/
|
||||
call_hooks('app_destroy', $x[0]);
|
||||
}
|
||||
else {
|
||||
$r = q("update app set app_deleted = 1 where app_id = '%s' and app_channel = %d",
|
||||
q("update app set app_deleted = 1 where app_id = '%s' and app_channel = %d",
|
||||
dbesc($app['guid']),
|
||||
intval($uid)
|
||||
);
|
||||
@@ -645,22 +678,23 @@ class Apps {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static public function app_undestroy($uid,$app) {
|
||||
|
||||
// undelete a system app
|
||||
|
||||
/**
|
||||
* @brief Undelete a system app.
|
||||
*
|
||||
* @param int $uid
|
||||
* @param array $app
|
||||
*/
|
||||
static public function app_undestroy($uid, $app) {
|
||||
if($uid && $app['guid']) {
|
||||
|
||||
$x = q("select * from app where app_id = '%s' and app_channel = %d limit 1",
|
||||
dbesc($app['guid']),
|
||||
intval($uid)
|
||||
);
|
||||
if($x) {
|
||||
if($x[0]['app_system']) {
|
||||
$r = q("update app set app_deleted = 0 where app_id = '%s' and app_channel = %d",
|
||||
q("update app set app_deleted = 0 where app_id = '%s' and app_channel = %d",
|
||||
dbesc($app['guid']),
|
||||
intval($uid)
|
||||
);
|
||||
@@ -669,7 +703,15 @@ class Apps {
|
||||
}
|
||||
}
|
||||
|
||||
static public function app_feature($uid,$app,$term) {
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @param int $uid
|
||||
* @param array $app
|
||||
* @param string $term
|
||||
* @return void
|
||||
*/
|
||||
static public function app_feature($uid, $app, $term) {
|
||||
$r = q("select id from app where app_id = '%s' and app_channel = %d limit 1",
|
||||
dbesc($app['guid']),
|
||||
intval($uid)
|
||||
@@ -693,23 +735,37 @@ class Apps {
|
||||
}
|
||||
}
|
||||
|
||||
static public function app_installed($uid,$app,$bypass_filter=false) {
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @param int $uid
|
||||
* @param array $app
|
||||
* @param boolean $bypass_filter (optional) default false
|
||||
* @return boolean
|
||||
*/
|
||||
static public function app_installed($uid, $app, $bypass_filter = false) {
|
||||
|
||||
$r = q("select id from app where app_id = '%s' and app_channel = %d limit 1",
|
||||
dbesc((array_key_exists('guid',$app)) ? $app['guid'] : ''),
|
||||
dbesc((array_key_exists('guid', $app)) ? $app['guid'] : ''),
|
||||
intval($uid)
|
||||
);
|
||||
if (!$bypass_filter) {
|
||||
if(!$bypass_filter) {
|
||||
$filter_arr = [
|
||||
'uid'=>$uid,
|
||||
'app'=>$app,
|
||||
'installed'=>$r
|
||||
'uid' => $uid,
|
||||
'app' => $app,
|
||||
'installed' => $r
|
||||
];
|
||||
call_hooks('app_installed_filter',$filter_arr);
|
||||
/**
|
||||
* @hooks app_installed_filter
|
||||
* * \e int \b uid
|
||||
* * \e array \b app
|
||||
* * \e mixed \b installed - return value
|
||||
*/
|
||||
call_hooks('app_installed_filter', $filter_arr);
|
||||
$r = $filter_arr['installed'];
|
||||
}
|
||||
return(($r) ? true : false);
|
||||
|
||||
return(($r) ? true : false);
|
||||
}
|
||||
|
||||
|
||||
@@ -725,11 +781,17 @@ class Apps {
|
||||
'app'=>$app,
|
||||
'installed'=>$r
|
||||
];
|
||||
call_hooks('addon_app_installed_filter',$filter_arr);
|
||||
/**
|
||||
* @hooks addon_app_installed_filter
|
||||
* * \e int \b uid
|
||||
* * \e array \b app
|
||||
* * \e mixed \b installed - return value
|
||||
*/
|
||||
call_hooks('addon_app_installed_filter', $filter_arr);
|
||||
$r = $filter_arr['installed'];
|
||||
}
|
||||
return(($r) ? true : false);
|
||||
|
||||
return(($r) ? true : false);
|
||||
}
|
||||
|
||||
static public function system_app_installed($uid,$app,$bypass_filter=false) {
|
||||
@@ -744,28 +806,39 @@ class Apps {
|
||||
'app'=>$app,
|
||||
'installed'=>$r
|
||||
];
|
||||
call_hooks('system_app_installed_filter',$filter_arr);
|
||||
/**
|
||||
* @hooks system_app_installed_filter
|
||||
* * \e int \b uid
|
||||
* * \e array \b app
|
||||
* * \e mixed \b installed - return value
|
||||
*/
|
||||
call_hooks('system_app_installed_filter', $filter_arr);
|
||||
$r = $filter_arr['installed'];
|
||||
}
|
||||
return(($r) ? true : false);
|
||||
|
||||
return(($r) ? true : false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @param int $uid
|
||||
* @param boolean $deleted
|
||||
* @param array $cats
|
||||
* @return boolean|array
|
||||
*/
|
||||
static public function app_list($uid, $deleted = false, $cats = []) {
|
||||
if($deleted)
|
||||
$sql_extra = "";
|
||||
if($deleted)
|
||||
$sql_extra = '';
|
||||
else
|
||||
$sql_extra = " and app_deleted = 0 ";
|
||||
$sql_extra = ' and app_deleted = 0 ';
|
||||
|
||||
if($cats) {
|
||||
|
||||
$cat_sql_extra = " and ( ";
|
||||
$cat_sql_extra = ' and ( ';
|
||||
|
||||
foreach($cats as $cat) {
|
||||
if(strpos($cat_sql_extra, 'term'))
|
||||
$cat_sql_extra .= "or ";
|
||||
$cat_sql_extra .= 'or ';
|
||||
|
||||
$cat_sql_extra .= "term = '" . dbesc($cat) . "' ";
|
||||
}
|
||||
@@ -777,11 +850,13 @@ class Apps {
|
||||
);
|
||||
if(! $r)
|
||||
return $r;
|
||||
$sql_extra .= " and app.id in ( ";
|
||||
|
||||
$sql_extra .= ' and app.id in ( ';
|
||||
$s = '';
|
||||
foreach($r as $rr) {
|
||||
if($s)
|
||||
$s .= ',';
|
||||
|
||||
$s .= intval($rr['oid']);
|
||||
}
|
||||
$sql_extra .= $s . ') ';
|
||||
@@ -792,12 +867,26 @@ class Apps {
|
||||
);
|
||||
|
||||
if($r) {
|
||||
$hookinfo = Array('uid'=>$uid,'deleted'=>$deleted,'cats'=>$cats,'apps'=>$r);
|
||||
call_hooks('app_list',$hookinfo);
|
||||
$hookinfo = [
|
||||
'uid' => $uid,
|
||||
'deleted' => $deleted,
|
||||
'cats' => $cats,
|
||||
'apps' => $r,
|
||||
];
|
||||
/**
|
||||
* @hooks app_list
|
||||
* * \e int \b uid
|
||||
* * \e boolean \b deleted
|
||||
* * \e array \b cats
|
||||
* * \e array \b apps - return value
|
||||
*/
|
||||
call_hooks('app_list', $hookinfo);
|
||||
$r = $hookinfo['apps'];
|
||||
for($x = 0; $x < count($r); $x ++) {
|
||||
|
||||
for($x = 0; $x < count($r); $x++) {
|
||||
if(! $r[$x]['app_system'])
|
||||
$r[$x]['type'] = 'personal';
|
||||
|
||||
$r[$x]['term'] = q("select * from term where otype = %d and oid = %d",
|
||||
intval(TERM_OBJ_APP),
|
||||
intval($r[$x]['id'])
|
||||
@@ -805,7 +894,7 @@ class Apps {
|
||||
}
|
||||
}
|
||||
|
||||
return($r);
|
||||
return $r;
|
||||
}
|
||||
|
||||
static public function app_order($uid,$apps,$menu) {
|
||||
@@ -837,13 +926,14 @@ class Apps {
|
||||
$ret[] = $ap;
|
||||
}
|
||||
}
|
||||
return $ret;
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
static function find_app_in_array($name,$arr) {
|
||||
if(! $arr)
|
||||
return false;
|
||||
|
||||
foreach($arr as $x) {
|
||||
if($x['name'] === $name) {
|
||||
return $x;
|
||||
@@ -852,8 +942,16 @@ class Apps {
|
||||
return false;
|
||||
}
|
||||
|
||||
static function moveup($uid,$guid,$menu) {
|
||||
$syslist = array();
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @param int $uid
|
||||
* @param int $guid
|
||||
* @param string $menu
|
||||
* @return void
|
||||
*/
|
||||
static function moveup($uid, $guid, $menu) {
|
||||
$syslist = [];
|
||||
|
||||
$conf = (($menu === 'nav_featured_app') ? 'app_order' : 'app_pin_order');
|
||||
|
||||
@@ -863,6 +961,7 @@ class Apps {
|
||||
$papp = self::app_encode($li);
|
||||
if($menu !== 'nav_pinned_app' && strpos($papp['categories'],'nav_pinned_app') !== false)
|
||||
continue;
|
||||
|
||||
$syslist[] = $papp;
|
||||
}
|
||||
}
|
||||
@@ -875,8 +974,6 @@ class Apps {
|
||||
if(! $syslist)
|
||||
return;
|
||||
|
||||
$newlist = [];
|
||||
|
||||
foreach($syslist as $k => $li) {
|
||||
if($li['guid'] === $guid) {
|
||||
$position = $k;
|
||||
@@ -885,6 +982,7 @@ class Apps {
|
||||
}
|
||||
if(! $position)
|
||||
return;
|
||||
|
||||
$dest_position = $position - 1;
|
||||
$saved = $syslist[$dest_position];
|
||||
$syslist[$dest_position] = $syslist[$position];
|
||||
@@ -896,11 +994,18 @@ class Apps {
|
||||
}
|
||||
|
||||
set_pconfig($uid,'system',$conf,implode(',',$narr));
|
||||
|
||||
}
|
||||
|
||||
static function movedown($uid,$guid,$menu) {
|
||||
$syslist = array();
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @param int $uid
|
||||
* @param int $guid
|
||||
* @param string $menu
|
||||
* @return void
|
||||
*/
|
||||
static function movedown($uid, $guid, $menu) {
|
||||
$syslist = [];
|
||||
|
||||
$conf = (($menu === 'nav_featured_app') ? 'app_order' : 'app_pin_order');
|
||||
|
||||
@@ -910,6 +1015,7 @@ class Apps {
|
||||
$papp = self::app_encode($li);
|
||||
if($menu !== 'nav_pinned_app' && strpos($papp['categories'],'nav_pinned_app') !== false)
|
||||
continue;
|
||||
|
||||
$syslist[] = $papp;
|
||||
}
|
||||
}
|
||||
@@ -922,8 +1028,6 @@ class Apps {
|
||||
if(! $syslist)
|
||||
return;
|
||||
|
||||
$newlist = [];
|
||||
|
||||
foreach($syslist as $k => $li) {
|
||||
if($li['guid'] === $guid) {
|
||||
$position = $k;
|
||||
@@ -932,6 +1036,7 @@ class Apps {
|
||||
}
|
||||
if($position >= count($syslist) - 1)
|
||||
return;
|
||||
|
||||
$dest_position = $position + 1;
|
||||
$saved = $syslist[$dest_position];
|
||||
$syslist[$dest_position] = $syslist[$position];
|
||||
@@ -943,7 +1048,6 @@ class Apps {
|
||||
}
|
||||
|
||||
set_pconfig($uid,'system',$conf,implode(',',$narr));
|
||||
|
||||
}
|
||||
|
||||
static public function app_decode($s) {
|
||||
@@ -951,8 +1055,14 @@ class Apps {
|
||||
return json_decode($x,true);
|
||||
}
|
||||
|
||||
|
||||
static public function app_macros($uid,&$arr) {
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @param int $uid
|
||||
* @param[in,out] array $arr
|
||||
* @return void
|
||||
*/
|
||||
static public function app_macros($uid, &$arr) {
|
||||
|
||||
if(! intval($uid))
|
||||
return;
|
||||
@@ -960,21 +1070,17 @@ class Apps {
|
||||
$baseurl = z_root();
|
||||
$channel = channelx_by_n($uid);
|
||||
$address = (($channel) ? $channel['channel_address'] : '');
|
||||
|
||||
|
||||
//future expansion
|
||||
|
||||
$observer = \App::get_observer();
|
||||
|
||||
//$observer = \App::get_observer();
|
||||
|
||||
$arr['url'] = str_replace(array('$baseurl','$nick'),array($baseurl,$address),$arr['url']);
|
||||
$arr['photo'] = str_replace(array('$baseurl','$nick'),array($baseurl,$address),$arr['photo']);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static public function app_store($arr) {
|
||||
|
||||
//logger('app_store: ' . print_r($arr,true));
|
||||
@@ -1158,16 +1264,20 @@ class Apps {
|
||||
}
|
||||
|
||||
return $ret;
|
||||
|
||||
}
|
||||
|
||||
|
||||
static public function app_encode($app,$embed = false) {
|
||||
|
||||
$ret = array();
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @param array $app
|
||||
* @param boolean $embed (optional) default false
|
||||
* @return array|string
|
||||
*/
|
||||
static public function app_encode($app, $embed = false) {
|
||||
$ret = [];
|
||||
|
||||
$ret['type'] = 'personal';
|
||||
|
||||
|
||||
if($app['app_id'])
|
||||
$ret['guid'] = $app['app_id'];
|
||||
|
||||
@@ -1200,7 +1310,7 @@ class Apps {
|
||||
|
||||
if($app['app_price'])
|
||||
$ret['price'] = $app['app_price'];
|
||||
|
||||
|
||||
if($app['app_page'])
|
||||
$ret['page'] = $app['app_page'];
|
||||
|
||||
@@ -1224,12 +1334,12 @@ class Apps {
|
||||
foreach($app['term'] as $t) {
|
||||
if($s)
|
||||
$s .= ',';
|
||||
|
||||
$s .= $t['term'];
|
||||
}
|
||||
$ret['categories'] = $s;
|
||||
}
|
||||
|
||||
|
||||
if(! $embed)
|
||||
return $ret;
|
||||
|
||||
@@ -1237,18 +1347,15 @@ class Apps {
|
||||
|
||||
if(array_key_exists('categories',$ret))
|
||||
unset($ret['categories']);
|
||||
|
||||
$j = json_encode($ret);
|
||||
return '[app]' . chunk_split(base64_encode($j),72,"\n") . '[/app]';
|
||||
|
||||
$j = json_encode($ret);
|
||||
|
||||
return '[app]' . chunk_split(base64_encode($j),72,"\n") . '[/app]';
|
||||
}
|
||||
|
||||
|
||||
static public function papp_encode($papp) {
|
||||
return chunk_split(base64_encode(json_encode($papp)),72,"\n");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -58,10 +58,15 @@ class DB_Upgrade {
|
||||
|
||||
|
||||
$c = new $cls();
|
||||
|
||||
$retval = $c->run();
|
||||
|
||||
if($retval != UPDATE_SUCCESS) {
|
||||
|
||||
|
||||
$source = t('Source code of failed update: ') . "\n\n" . @file_get_contents('Zotlabs/Update/' . $s . '.php');
|
||||
|
||||
|
||||
// Prevent sending hundreds of thousands of emails by creating
|
||||
// a lockfile.
|
||||
|
||||
@@ -86,7 +91,9 @@ class DB_Upgrade {
|
||||
'$sitename' => \App::$config['system']['sitename'],
|
||||
'$siteurl' => z_root(),
|
||||
'$update' => $x,
|
||||
'$error' => sprintf( t('Update %s failed. See error logs.'), $x)
|
||||
'$error' => sprintf( t('Update %s failed. See error logs.'), $x),
|
||||
'$baseurl' => z_root(),
|
||||
'$source' => $source
|
||||
]
|
||||
)
|
||||
]
|
||||
|
||||
@@ -14,6 +14,7 @@ class DReport {
|
||||
$this->location = $location;
|
||||
$this->sender = $sender;
|
||||
$this->recipient = $recipient;
|
||||
$this->name = EMPTY_STR;
|
||||
$this->message_id = $message_id;
|
||||
$this->status = $status;
|
||||
$this->date = datetime_convert();
|
||||
@@ -24,8 +25,8 @@ class DReport {
|
||||
$this->date = datetime_convert();
|
||||
}
|
||||
|
||||
function addto_recipient($name) {
|
||||
$this->recipient = $this->recipient . ' ' . $name;
|
||||
function set_name($name) {
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
function addto_update($status) {
|
||||
@@ -37,6 +38,7 @@ class DReport {
|
||||
$this->location = $arr['location'];
|
||||
$this->sender = $arr['sender'];
|
||||
$this->recipient = $arr['recipient'];
|
||||
$this->name = $arr['name'];
|
||||
$this->message_id = $arr['message_id'];
|
||||
$this->status = $arr['status'];
|
||||
$this->date = $arr['date'];
|
||||
@@ -47,9 +49,99 @@ class DReport {
|
||||
'location' => $this->location,
|
||||
'sender' => $this->sender,
|
||||
'recipient' => $this->recipient,
|
||||
'name' => $this->name,
|
||||
'message_id' => $this->message_id,
|
||||
'status' => $this->status,
|
||||
'date' => $this->date
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief decide whether to store a returned delivery report
|
||||
*
|
||||
* @param array $dr
|
||||
* @return boolean
|
||||
*/
|
||||
|
||||
static function is_storable($dr) {
|
||||
|
||||
if(get_config('system', 'disable_dreport'))
|
||||
return false;
|
||||
|
||||
/**
|
||||
* @hooks dreport_is_storable
|
||||
* Called before storing a dreport record to determine whether to store it.
|
||||
* * \e array
|
||||
*/
|
||||
|
||||
call_hooks('dreport_is_storable', $dr);
|
||||
|
||||
// let plugins accept or reject - if neither, continue on
|
||||
if(array_key_exists('accept',$dr) && intval($dr['accept']))
|
||||
return true;
|
||||
if(array_key_exists('reject',$dr) && intval($dr['reject']))
|
||||
return false;
|
||||
|
||||
if(! ($dr['sender']))
|
||||
return false;
|
||||
|
||||
// Is the sender one of our channels?
|
||||
|
||||
$c = q("select channel_id from channel where channel_hash = '%s' or channel_portable_id = '%s' limit 1",
|
||||
dbesc($dr['sender']),
|
||||
dbesc($dr['sender'])
|
||||
);
|
||||
|
||||
if(! $c)
|
||||
return false;
|
||||
|
||||
// legacy zot recipients add a space and their name to the xchan. remove it if true.
|
||||
|
||||
$legacy_recipient = strpos($dr['recipient'], ' ');
|
||||
if($legacy_recipient !== false) {
|
||||
$legacy_recipient_parts = explode(' ', $dr['recipient'], 2);
|
||||
$rxchan = $legacy_recipient_parts[0];
|
||||
}
|
||||
else {
|
||||
$rxchan = $dr['recipient'];
|
||||
}
|
||||
|
||||
|
||||
|
||||
// is the recipient one of our connections, or do we want to store every report?
|
||||
|
||||
$pcf = get_pconfig($c[0]['channel_id'],'system','dreport_store_all');
|
||||
if($pcf)
|
||||
return true;
|
||||
|
||||
// We always add ourself as a recipient to private and relayed posts
|
||||
// So if a remote site says they can't find us, that's no big surprise
|
||||
// and just creates a lot of extra report noise
|
||||
|
||||
if(($dr['location'] !== z_root()) && ($dr['sender'] === $rxchan) && ($dr['status'] === 'recipient not found'))
|
||||
return false;
|
||||
|
||||
// If you have a private post with a recipient list, every single site is going to report
|
||||
// back a failed delivery for anybody on that list that isn't local to them. We're only
|
||||
// concerned about this if we have a local hubloc record which says we expected them to
|
||||
// have a channel on that site.
|
||||
|
||||
$r = q("select hubloc_id from hubloc where hubloc_hash = '%s' and hubloc_url = '%s'",
|
||||
dbesc($rxchan),
|
||||
dbesc($dr['location'])
|
||||
);
|
||||
if((! $r) && ($dr['status'] === 'recipient_not_found'))
|
||||
return false;
|
||||
|
||||
$r = q("select abook_id from abook where abook_xchan = '%s' and abook_channel = %d limit 1",
|
||||
dbesc($rxchan),
|
||||
intval($c[0]['channel_id'])
|
||||
);
|
||||
if($r)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -754,9 +754,9 @@ class Enotify {
|
||||
// generate a multipart/alternative message header
|
||||
$messageHeader =
|
||||
$params['additionalMailHeader'] .
|
||||
"From: $fromName <{$params['fromEmail']}>\n" .
|
||||
"Reply-To: $fromName <{$params['replyTo']}>\n" .
|
||||
"MIME-Version: 1.0\n" .
|
||||
"From: $fromName <{$params['fromEmail']}>" . PHP_EOL .
|
||||
"Reply-To: $fromName <{$params['replyTo']}>" . PHP_EOL .
|
||||
"MIME-Version: 1.0" . PHP_EOL .
|
||||
"Content-Type: multipart/alternative; boundary=\"{$mimeBoundary}\"";
|
||||
|
||||
// assemble the final multipart message body with the text and html types included
|
||||
@@ -764,15 +764,15 @@ class Enotify {
|
||||
$htmlBody = chunk_split(base64_encode($params['htmlVersion']));
|
||||
|
||||
$multipartMessageBody =
|
||||
"--" . $mimeBoundary . "\n" . // plain text section
|
||||
"Content-Type: text/plain; charset=UTF-8\n" .
|
||||
"Content-Transfer-Encoding: base64\n\n" .
|
||||
$textBody . "\n" .
|
||||
"--" . $mimeBoundary . "\n" . // text/html section
|
||||
"Content-Type: text/html; charset=UTF-8\n" .
|
||||
"Content-Transfer-Encoding: base64\n\n" .
|
||||
$htmlBody . "\n" .
|
||||
"--" . $mimeBoundary . "--\n"; // message ending
|
||||
"--" . $mimeBoundary . PHP_EOL . // plain text section
|
||||
"Content-Type: text/plain; charset=UTF-8" . PHP_EOL .
|
||||
"Content-Transfer-Encoding: base64" . PHP_EOL . PHP_EOL .
|
||||
$textBody . PHP_EOL .
|
||||
"--" . $mimeBoundary . PHP_EOL . // text/html section
|
||||
"Content-Type: text/html; charset=UTF-8" . PHP_EOL .
|
||||
"Content-Transfer-Encoding: base64" . PHP_EOL . PHP_EOL .
|
||||
$htmlBody . PHP_EOL .
|
||||
"--" . $mimeBoundary . "--" . PHP_EOL; // message ending
|
||||
|
||||
// send the message
|
||||
$res = mail(
|
||||
@@ -807,6 +807,11 @@ class Enotify {
|
||||
$itemem_text = (($item['item_thread_top'])
|
||||
? t('created a new post')
|
||||
: sprintf( t('commented on %s\'s post'), $item['owner']['xchan_name']));
|
||||
|
||||
if($item['verb'] === ACTIVITY_SHARE) {
|
||||
$itemem_text = sprintf( t('repeated %s\'s post'), $item['author']['xchan_name']);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$edit = false;
|
||||
@@ -825,12 +830,14 @@ class Enotify {
|
||||
|
||||
// convert this logic into a json array just like the system notifications
|
||||
|
||||
$who = (($item['verb'] === ACTIVITY_SHARE) ? 'owner' : 'author');
|
||||
|
||||
$x = array(
|
||||
'notify_link' => $item['llink'],
|
||||
'name' => $item['author']['xchan_name'],
|
||||
'addr' => (($item['author']['xchan_addr']) ? $item['author']['xchan_addr'] : $item['author']['xchan_url']),
|
||||
'url' => $item['author']['xchan_url'],
|
||||
'photo' => $item['author']['xchan_photo_s'],
|
||||
'name' => $item[$who]['xchan_name'],
|
||||
'addr' => (($item[$who]['xchan_addr']) ? $item[$who]['xchan_addr'] : $item[$who]['xchan_url']),
|
||||
'url' => $item[$who]['xchan_url'],
|
||||
'photo' => $item[$who]['xchan_photo_s'],
|
||||
'when' => relative_date(($edit)? $item['edited'] : $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'])),
|
||||
@@ -838,7 +845,7 @@ class Enotify {
|
||||
'thread_top' => (($item['item_thread_top']) ? true : false),
|
||||
'message' => strip_tags(bbcode($itemem_text)),
|
||||
// these are for the superblock addon
|
||||
'hash' => $item['author']['xchan_hash'],
|
||||
'hash' => $item[$who]['xchan_hash'],
|
||||
'uid' => local_channel(),
|
||||
'display' => true
|
||||
);
|
||||
|
||||
@@ -2,15 +2,13 @@
|
||||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
use Zotlabs\Web\HTTPSig;
|
||||
|
||||
class JSalmon {
|
||||
|
||||
static function sign($data,$key_id,$key) {
|
||||
static function sign($data,$key_id,$key,$data_type = 'application/x-zot+json') {
|
||||
|
||||
$arr = $data;
|
||||
$data = json_encode($data,JSON_UNESCAPED_SLASHES);
|
||||
$data = base64url_encode($data, false); // do not strip padding
|
||||
$data_type = 'application/x-zot+json';
|
||||
$data = base64url_encode(json_encode($data,true),true); // strip padding
|
||||
$encoding = 'base64url';
|
||||
$algorithm = 'RSA-SHA256';
|
||||
|
||||
@@ -18,9 +16,9 @@ class JSalmon {
|
||||
|
||||
// precomputed base64url encoding of data_type, encoding, algorithm concatenated with periods
|
||||
|
||||
$precomputed = '.' . base64url_encode($data_type,false) . '.YmFzZTY0dXJs.UlNBLVNIQTI1Ng==';
|
||||
$precomputed = '.' . base64url_encode($data_type,true) . '.YmFzZTY0dXJs.UlNBLVNIQTI1Ng';
|
||||
|
||||
$signature = base64url_encode(rsa_sign($data . $precomputed, $key), false);
|
||||
$signature = base64url_encode(rsa_sign($data . $precomputed, $key), true);
|
||||
|
||||
return ([
|
||||
'signed' => true,
|
||||
@@ -30,9 +28,45 @@ class JSalmon {
|
||||
'alg' => $algorithm,
|
||||
'sigs' => [
|
||||
'value' => $signature,
|
||||
'key_id' => base64url_encode($key_id)
|
||||
'key_id' => base64url_encode($key_id, true)
|
||||
]
|
||||
]);
|
||||
|
||||
}
|
||||
|
||||
static function verify($x) {
|
||||
|
||||
logger('verify');
|
||||
$ret = [ 'results' => [] ];
|
||||
|
||||
if(! is_array($x)) {
|
||||
return $false;
|
||||
}
|
||||
if(! ( array_key_exists('signed',$x) && $x['signed'])) {
|
||||
return $false;
|
||||
}
|
||||
|
||||
$signed_data = preg_replace('/\s+/','',$x['data']) . '.'
|
||||
. base64url_encode($x['data_type'],true) . '.'
|
||||
. base64url_encode($x['encoding'],true) . '.'
|
||||
. base64url_encode($x['alg'],true);
|
||||
|
||||
$key = HTTPSig::get_key(EMPTY_STR,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'])) {
|
||||
logger('verified');
|
||||
$ret = [ 'success' => true, 'signer' => $key['portable_id'], 'hubloc' => $key['hubloc'] ];
|
||||
}
|
||||
}
|
||||
|
||||
return $ret;
|
||||
|
||||
}
|
||||
|
||||
static function unpack($data) {
|
||||
return json_decode(base64url_decode($data),true);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -29,7 +29,7 @@ class LDSignatures {
|
||||
$options = [
|
||||
'type' => 'RsaSignature2017',
|
||||
'nonce' => random_string(64),
|
||||
'creator' => z_root() . '/channel/' . $channel['channel_address'] . '/public_key_pem',
|
||||
'creator' => z_root() . '/channel/' . $channel['channel_address'],
|
||||
'created' => datetime_convert('UTC','UTC', 'now', 'Y-m-d\Th:i:s\Z')
|
||||
];
|
||||
|
||||
@@ -124,7 +124,7 @@ class LDSignatures {
|
||||
'meDataType' => $data_type,
|
||||
'meEncoding' => $encoding,
|
||||
'meAlgorithm' => $algorithm,
|
||||
'meCreator' => z_root() . '/channel/' . $channel['channel_address'] . '/public_key_pem',
|
||||
'meCreator' => z_root() . '/channel/' . $channel['channel_address'],
|
||||
'meSignatureValue' => $signature
|
||||
]);
|
||||
|
||||
@@ -132,4 +132,4 @@ class LDSignatures {
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -336,7 +336,7 @@ class Libsync {
|
||||
|
||||
$disallowed = array('abook_id','abook_account','abook_channel','abook_rating','abook_rating_text','abook_not_here');
|
||||
|
||||
$fields = db_columns($abook);
|
||||
$fields = db_columns('abook');
|
||||
|
||||
foreach($arr['abook'] as $abook) {
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -307,7 +307,7 @@ class Libzotdir {
|
||||
if ($ud['ud_addr'] && (! ($ud['ud_flags'] & UPDATE_FLAGS_DELETED))) {
|
||||
$success = false;
|
||||
|
||||
$href = \Zotlabs\Lib\Webfinger::zot_url(punify($url));
|
||||
$href = \Zotlabs\Lib\Webfinger::zot_url(punify($ud['ud_addr']));
|
||||
if($href) {
|
||||
$zf = \Zotlabs\Lib\Zotfinger::exec($href);
|
||||
}
|
||||
@@ -651,4 +651,4 @@ class Libzotdir {
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ class MessageFilter {
|
||||
|
||||
$lang = null;
|
||||
|
||||
if((strpos($incl,'lang=') !== false) || (strpos($excl,'lang=') !== false)) {
|
||||
if((strpos($incl,'lang=') !== false) || (strpos($excl,'lang=') !== false) || (strpos($incl,'lang!=') !== false) || (strpos($excl,'lang!=') !== false)) {
|
||||
$lang = detect_language($text);
|
||||
}
|
||||
|
||||
@@ -39,10 +39,17 @@ class MessageFilter {
|
||||
if((($t['ttype'] == TERM_HASHTAG) || ($t['ttype'] == TERM_COMMUNITYTAG)) && (($t['term'] === substr($word,1)) || (substr($word,1) === '*')))
|
||||
return false;
|
||||
}
|
||||
elseif(substr($word,0,1) === '$' && $tags) {
|
||||
foreach($tags as $t)
|
||||
if(($t['ttype'] == TERM_CATEGORY) && (($t['term'] === substr($word,1)) || (substr($word,1) === '*')))
|
||||
return false;
|
||||
}
|
||||
elseif((strpos($word,'/') === 0) && preg_match($word,$text))
|
||||
return false;
|
||||
elseif((strpos($word,'lang=') === 0) && ($lang) && (strcasecmp($lang,trim(substr($word,5))) == 0))
|
||||
return false;
|
||||
elseif((strpos($word,'lang!=') === 0) && ($lang) && (strcasecmp($lang,trim(substr($word,6))) != 0))
|
||||
return false;
|
||||
elseif(stristr($text,$word) !== false)
|
||||
return false;
|
||||
}
|
||||
@@ -60,10 +67,17 @@ class MessageFilter {
|
||||
if((($t['ttype'] == TERM_HASHTAG) || ($t['ttype'] == TERM_COMMUNITYTAG)) && (($t['term'] === substr($word,1)) || (substr($word,1) === '*')))
|
||||
return true;
|
||||
}
|
||||
elseif(substr($word,0,1) === '$' && $tags) {
|
||||
foreach($tags as $t)
|
||||
if(($t['ttype'] == TERM_CATEGORY) && (($t['term'] === substr($word,1)) || (substr($word,1) === '*')))
|
||||
return true;
|
||||
}
|
||||
elseif((strpos($word,'/') === 0) && preg_match($word,$text))
|
||||
return true;
|
||||
elseif((strpos($word,'lang=') === 0) && ($lang) && (strcasecmp($lang,trim(substr($word,5))) == 0))
|
||||
return true;
|
||||
elseif((strpos($word,'lang!=') === 0) && ($lang) && (strcasecmp($lang,trim(substr($word,6))) != 0))
|
||||
return true;
|
||||
elseif(stristr($text,$word) !== false)
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -40,26 +40,17 @@ class NativeWiki {
|
||||
|
||||
function create_wiki($channel, $observer_hash, $wiki, $acl) {
|
||||
|
||||
// Generate unique resource_id using the same method as item_message_id()
|
||||
do {
|
||||
$dups = false;
|
||||
$resource_id = random_string();
|
||||
$r = q("SELECT mid FROM item WHERE resource_id = '%s' AND resource_type = '%s' AND uid = %d LIMIT 1",
|
||||
dbesc($resource_id),
|
||||
dbesc(NWIKI_ITEM_RESOURCE_TYPE),
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
if($r)
|
||||
$dups = true;
|
||||
} while($dups == true);
|
||||
$resource_id = new_uuid();
|
||||
$uuid = new_uuid();
|
||||
|
||||
$ac = $acl->get();
|
||||
$mid = item_message_id();
|
||||
$mid = z_root() . '/item/' . $uuid;
|
||||
|
||||
$arr = array(); // Initialize the array of parameters for the post
|
||||
$item_hidden = ((intval($wiki['postVisible']) === 0) ? 1 : 0);
|
||||
$wiki_url = z_root() . '/wiki/' . $channel['channel_address'] . '/' . $wiki['urlName'];
|
||||
$arr['aid'] = $channel['channel_account_id'];
|
||||
$arr['uuid'] = $uuid;
|
||||
$arr['uid'] = $channel['channel_id'];
|
||||
$arr['mid'] = $mid;
|
||||
$arr['parent_mid'] = $mid;
|
||||
@@ -200,7 +191,7 @@ class NativeWiki {
|
||||
return array('item' => null, 'success' => false);
|
||||
}
|
||||
else {
|
||||
$drop = drop_item($item['id'], false, DROPITEM_NORMAL, true);
|
||||
$drop = drop_item($item['id'], false, DROPITEM_NORMAL);
|
||||
}
|
||||
|
||||
info( t('Wiki files deleted successfully'));
|
||||
|
||||
@@ -112,9 +112,11 @@ class PConfig {
|
||||
* The configuration key to set
|
||||
* @param string $value
|
||||
* The value to store
|
||||
* @param string $updated (optional)
|
||||
* The datetime to store
|
||||
* @return mixed Stored $value or false
|
||||
*/
|
||||
static public function Set($uid, $family, $key, $value, $updated=NULL) {
|
||||
static public function Set($uid, $family, $key, $value, $updated = NULL) {
|
||||
|
||||
// this catches subtle errors where this function has been called
|
||||
// with local_channel() when not logged in (which returns false)
|
||||
@@ -131,14 +133,19 @@ class PConfig {
|
||||
$dbvalue = ((is_array($value)) ? serialize($value) : $value);
|
||||
$dbvalue = ((is_bool($dbvalue)) ? intval($dbvalue) : $dbvalue);
|
||||
|
||||
$now = datetime_convert();
|
||||
if (! $updated) {
|
||||
$updated = datetime_convert();
|
||||
//Sometimes things happen fast... very fast.
|
||||
//To make sure legitimate updates aren't rejected
|
||||
//because not enough time has passed. We say our updates
|
||||
//happened just a short time in the past rather than right now.
|
||||
$updated = datetime_convert('UTC','UTC','-2 seconds');
|
||||
}
|
||||
|
||||
$hash = hash('sha256',$family.':'.$key);
|
||||
|
||||
if (self::Get($uid, 'hz_delpconfig', $hash) !== false) {
|
||||
if (self::Get($uid, 'hz_delpconfig', $hash) > $updated) {
|
||||
if (self::Get($uid, 'hz_delpconfig', $hash) > $now) {
|
||||
logger('Refusing to update pconfig with outdated info (Item deleted more recently).', LOGGER_NORMAL, LOG_ERR);
|
||||
return self::Get($uid,$family,$key);
|
||||
} else {
|
||||
@@ -173,7 +180,7 @@ class PConfig {
|
||||
|
||||
}
|
||||
else {
|
||||
$new = (\App::$config[$uid][$family]['pcfgud:'.$key] < $updated);
|
||||
$new = (\App::$config[$uid][$family]['pcfgud:'.$key] < $now);
|
||||
|
||||
if ($new) {
|
||||
|
||||
@@ -234,16 +241,18 @@ class PConfig {
|
||||
* The category of the configuration value
|
||||
* @param string $key
|
||||
* The configuration key to delete
|
||||
* @return mixed
|
||||
* @param string $updated (optional)
|
||||
* The datetime to store
|
||||
* @return boolean
|
||||
*/
|
||||
static public function Delete($uid, $family, $key, $updated = NULL) {
|
||||
|
||||
if(is_null($uid) || $uid === false)
|
||||
return false;
|
||||
|
||||
$updated = ($updated) ? $updated : datetime_convert();
|
||||
|
||||
$newer = (\App::$config[$uid][$family]['pcfgud:'.$key] < $updated);
|
||||
$updated = ($updated) ? $updated : datetime_convert('UTC','UTC','-2 seconds');
|
||||
$now = datetime_convert();
|
||||
$newer = (\App::$config[$uid][$family]['pcfgud:'.$key] < $now);
|
||||
|
||||
if (! $newer) {
|
||||
logger('Refusing to delete pconfig with outdated delete request.', LOGGER_NORMAL, LOG_ERR);
|
||||
@@ -266,22 +275,13 @@ class PConfig {
|
||||
dbesc($key)
|
||||
);
|
||||
|
||||
// Synchronize delete with clones.
|
||||
|
||||
if ($family != 'hz_delpconfig') {
|
||||
$hash = hash('sha256',$family.':'.$key);
|
||||
set_pconfig($uid,'hz_delpconfig',$hash,$updated);
|
||||
}
|
||||
|
||||
// Synchronize delete with clones.
|
||||
|
||||
if(! array_key_exists('transient', \App::$config[$uid]))
|
||||
\App::$config[$uid]['transient'] = array();
|
||||
if(! array_key_exists($family, \App::$config[$uid]['transient']))
|
||||
\App::$config[$uid]['transient'][$family] = array();
|
||||
|
||||
if ($new) {
|
||||
\App::$config[$uid]['transient'][$family]['pcfgdel:'.$key] = $updated;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -54,6 +54,7 @@ class Share {
|
||||
if(! $this->item)
|
||||
return $obj;
|
||||
|
||||
$obj['asld'] = $this->item['mid'];
|
||||
$obj['type'] = $this->item['obj_type'];
|
||||
$obj['id'] = $this->item['mid'];
|
||||
$obj['content'] = $this->item['body'];
|
||||
|
||||
@@ -38,6 +38,9 @@ class ThreadItem {
|
||||
|
||||
$this->data = $data;
|
||||
$this->toplevel = ($this->get_id() == $this->get_data_value('parent'));
|
||||
$this->threaded = get_config('system','thread_allow');
|
||||
|
||||
$observer = \App::get_observer();
|
||||
|
||||
// Prepare the children
|
||||
if($data['children']) {
|
||||
@@ -51,6 +54,7 @@ class ThreadItem {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
$child = new ThreadItem($item);
|
||||
$this->add_child($child);
|
||||
}
|
||||
@@ -73,7 +77,7 @@ class ThreadItem {
|
||||
* _ false on failure
|
||||
*/
|
||||
|
||||
public function get_template_data($conv_responses, $thread_level=1) {
|
||||
public function get_template_data($conv_responses, $thread_level=1, $conv_flags = []) {
|
||||
|
||||
$result = array();
|
||||
|
||||
@@ -94,10 +98,11 @@ class ThreadItem {
|
||||
$conv = $this->get_conversation();
|
||||
$observer = $conv->get_observer();
|
||||
|
||||
$lock = ((($item['item_private'] == 1) || (($item['uid'] == local_channel()) && (strlen($item['allow_cid']) || strlen($item['allow_gid'])
|
||||
$lock = (((intval($item['item_private'])) || (($item['uid'] == local_channel()) && (strlen($item['allow_cid']) || strlen($item['allow_gid'])
|
||||
|| strlen($item['deny_cid']) || strlen($item['deny_gid']))))
|
||||
? t('Private Message')
|
||||
: false);
|
||||
|
||||
$shareable = ((($conv->get_profile_owner() == local_channel() && local_channel()) && ($item['item_private'] != 1)) ? true : false);
|
||||
|
||||
// allow an exemption for sharing stuff from your private feeds
|
||||
@@ -105,13 +110,26 @@ class ThreadItem {
|
||||
$shareable = true;
|
||||
|
||||
$privacy_warning = false;
|
||||
if(($item['item_private'] == 1) && ($item['owner']['xchan_network'] === 'activitypub')) {
|
||||
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']))
|
||||
$privacy_warning = true;
|
||||
}
|
||||
|
||||
if ($lock) {
|
||||
if (($item['mid'] == $item['parent_mid']) && count(get_terms_oftype($item['term'],TERM_FORUM))) {
|
||||
$privacy_warning = true;
|
||||
$conv_flags['parent_privacy_warning'] = true;
|
||||
}
|
||||
}
|
||||
|
||||
$privacy_warning = (isset($conv_flags['parent_privacy_warning'])) ? $conv_flags['parent_privacy_warning'] : $privacy_warning;
|
||||
|
||||
if ($lock && $privacy_warning) {
|
||||
$lock = t('Privacy conflict. Discretion advised.');
|
||||
}
|
||||
|
||||
$mode = $conv->get_mode();
|
||||
|
||||
switch($item['item_type']) {
|
||||
@@ -288,10 +306,18 @@ class ThreadItem {
|
||||
if($this->is_commentable() && $observer) {
|
||||
$like = array( t("I like this \x28toggle\x29"), t("like"));
|
||||
$dislike = array( t("I don't like this \x28toggle\x29"), t("dislike"));
|
||||
$reply_to = array( t("Reply on this comment"), t("reply"), t("Reply to"));
|
||||
}
|
||||
|
||||
if ($shareable)
|
||||
$share = array( t('Share This'), t('share'));
|
||||
if ($shareable) {
|
||||
// This actually turns out not to be possible in some protocol stacks without opening up hundreds of new issues.
|
||||
// Will allow it only for uri resolvable sources.
|
||||
if(strpos($item['mid'],'http') === 0) {
|
||||
$share = []; //Not yet ready for primetime
|
||||
//$share = array( t('Repeat This'), t('repeat'));
|
||||
}
|
||||
$embed = array( t('Share This'), t('share'));
|
||||
}
|
||||
|
||||
$dreport = '';
|
||||
|
||||
@@ -299,13 +325,14 @@ class ThreadItem {
|
||||
if($keep_reports === 0)
|
||||
$keep_reports = 10;
|
||||
|
||||
if((! get_config('system','disable_dreport')) && strcmp(datetime_convert('UTC','UTC',$item['created']),datetime_convert('UTC','UTC',"now - $keep_reports days")) > 0)
|
||||
if((! get_config('system','disable_dreport')) && strcmp(datetime_convert('UTC','UTC',$item['created']),datetime_convert('UTC','UTC',"now - $keep_reports days")) > 0) {
|
||||
$dreport = t('Delivery Report');
|
||||
$dreport_link = gen_link_id($item['mid']);
|
||||
}
|
||||
|
||||
if(strcmp(datetime_convert('UTC','UTC',$item['created']),datetime_convert('UTC','UTC','now - 12 hours')) > 0)
|
||||
$is_new = true;
|
||||
|
||||
|
||||
localize_item($item);
|
||||
|
||||
$body = prepare_body($item,true);
|
||||
@@ -316,15 +343,11 @@ class ThreadItem {
|
||||
$owner_address = substr($item['owner']['xchan_addr'],0,strpos($item['owner']['xchan_addr'],'@'));
|
||||
$viewthread = $item['llink'];
|
||||
if($conv->get_mode() === 'channel')
|
||||
$viewthread = z_root() . '/channel/' . $owner_address . '?f=&mid=' . urlencode($item['mid']);
|
||||
$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) : '');
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
$children = $this->get_children();
|
||||
|
||||
$has_tags = (($body['tags'] || $body['categories'] || $body['mentions'] || $body['attachments'] || $body['folders']) ? true : false);
|
||||
@@ -347,13 +370,15 @@ class ThreadItem {
|
||||
'text' => strip_tags($body['html']),
|
||||
'id' => $this->get_id(),
|
||||
'mid' => $item['mid'],
|
||||
'parent' => $item['parent'],
|
||||
'author_id' => (($item['author']['xchan_addr']) ? $item['author']['xchan_addr'] : $item['author']['xchan_url']),
|
||||
'isevent' => $isevent,
|
||||
'attend' => $attend,
|
||||
'consensus' => $consensus,
|
||||
'conlabels' => $conlabels,
|
||||
'canvote' => $canvote,
|
||||
'linktitle' => sprintf( t('View %s\'s profile - %s'), $profile_name, $item['author']['xchan_addr']),
|
||||
'olinktitle' => sprintf( t('View %s\'s profile - %s'), $this->get_owner_name(), $item['owner']['xchan_addr']),
|
||||
'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'])),
|
||||
'llink' => $item['llink'],
|
||||
'viewthread' => $viewthread,
|
||||
'to' => t('to'),
|
||||
@@ -364,6 +389,7 @@ class ThreadItem {
|
||||
'thread_action_menu' => thread_action_menu($item,$conv->get_mode()),
|
||||
'thread_author_menu' => thread_author_menu($item,$conv->get_mode()),
|
||||
'dreport' => $dreport,
|
||||
'dreport_link' => $dreport_link,
|
||||
'name' => $profile_name,
|
||||
'thumb' => $profile_avatar,
|
||||
'osparkle' => $osparkle,
|
||||
@@ -398,23 +424,25 @@ class ThreadItem {
|
||||
'has_tags' => $has_tags,
|
||||
'reactions' => $this->reactions,
|
||||
// Item toolbar buttons
|
||||
'emojis' => (($this->is_toplevel() && $this->is_commentable() && $observer && feature_enabled($conv->get_profile_owner(),'emojis')) ? '1' : ''),
|
||||
'emojis' => (($this->is_toplevel() && $this->is_commentable() && $observer && feature_enabled($conv->get_profile_owner(),'emojis')) ? '1' : ''),
|
||||
'like' => $like,
|
||||
'dislike' => ((feature_enabled($conv->get_profile_owner(),'dislike')) ? $dislike : ''),
|
||||
'reply_to' => (((! $this->is_toplevel()) && feature_enabled($conv->get_profile_owner(),'reply_to')) ? $reply_to : ''),
|
||||
'top_hint' => t("Go to previous comment"),
|
||||
'share' => $share,
|
||||
'embed' => $embed,
|
||||
'rawmid' => $item['mid'],
|
||||
'plink' => get_plink($item),
|
||||
'edpost' => $edpost, // ((feature_enabled($conv->get_profile_owner(),'edit_posts')) ? $edpost : ''),
|
||||
'star' => ((feature_enabled($conv->get_profile_owner(),'star_posts')) ? $star : ''),
|
||||
'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')) ? $filer : ''),
|
||||
'filer' => ((feature_enabled($conv->get_profile_owner(),'filing') && ($item['item_type'] == ITEM_TYPE_POST)) ? $filer : ''),
|
||||
'bookmark' => (($conv->get_profile_owner() == local_channel() && local_channel() && $has_bookmarks) ? t('Save Bookmarks') : ''),
|
||||
'addtocal' => (($has_event) ? t('Add to Calendar') : ''),
|
||||
'drop' => $drop,
|
||||
'multidrop' => ((feature_enabled($conv->get_profile_owner(),'multi_delete')) ? $multidrop : ''),
|
||||
'dropdown_extras' => $dropdown_extras,
|
||||
'dropdown_extras' => $dropdown_extras,
|
||||
// end toolbar buttons
|
||||
|
||||
'unseen_comments' => $unseen_comments,
|
||||
'comment_count' => $total_children,
|
||||
'comment_count_txt' => $comment_count_txt,
|
||||
@@ -441,7 +469,8 @@ class ThreadItem {
|
||||
'wait' => t('Please wait'),
|
||||
'submid' => str_replace(['+','='], ['',''], base64_encode($item['mid'])),
|
||||
'thread_level' => $thread_level,
|
||||
'settings' => $settings
|
||||
'settings' => $settings,
|
||||
'thr_parent' => (($item['parent_mid'] != $item['thr_parent']) ? $item['thr_parent'] : '')
|
||||
);
|
||||
|
||||
$arr = array('item' => $item, 'output' => $tmp_item);
|
||||
@@ -464,7 +493,7 @@ class ThreadItem {
|
||||
|
||||
if(($this->get_display_mode() === 'normal') && ($nb_children > 0)) {
|
||||
foreach($children as $child) {
|
||||
$result['children'][] = $child->get_template_data($conv_responses, $thread_level + 1);
|
||||
$result['children'][] = $child->get_template_data($conv_responses, $thread_level + 1,$conv_flags);
|
||||
}
|
||||
// Collapse
|
||||
if(($nb_children > $visible_comments) || ($thread_level > 1)) {
|
||||
@@ -786,7 +815,7 @@ class ThreadItem {
|
||||
'$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,
|
||||
'$auto_save_draft' => $feature_auto_save_draft
|
||||
));
|
||||
|
||||
return $comment_box;
|
||||
@@ -841,4 +870,3 @@ class ThreadItem {
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
53
Zotlabs/Lib/ThreadListener.php
Normal file
53
Zotlabs/Lib/ThreadListener.php
Normal file
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
class ThreadListener {
|
||||
|
||||
static public function store($target_id,$portable_id,$ltype = 0) {
|
||||
$x = self::fetch($target_id,$portable_id,$ltype = 0);
|
||||
if(! $x) {
|
||||
$r = q("insert into listeners ( target_id, portable_id, ltype ) values ( '%s', '%s' , %d ) ",
|
||||
dbesc($target_id),
|
||||
dbesc($portable_id),
|
||||
intval($ltype)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
static public function fetch($target_id,$portable_id,$ltype = 0) {
|
||||
$x = q("select * from listeners where target_id = '%s' and portable_id = '%s' and ltype = %d limit 1",
|
||||
dbesc($target_id),
|
||||
dbesc($portable_id),
|
||||
intval($ltype)
|
||||
);
|
||||
if($x) {
|
||||
return $x[0];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static public function fetch_by_target($target_id,$ltype = 0) {
|
||||
$x = q("select * from listeners where target_id = '%s' and ltype = %d",
|
||||
dbesc($target_id),
|
||||
intval($ltype)
|
||||
);
|
||||
|
||||
return $x;
|
||||
}
|
||||
|
||||
static public function delete_by_target($target_id, $ltype = 0) {
|
||||
return q("delete from listeners where target_id = '%s' and ltype = %d",
|
||||
dbesc($target_id),
|
||||
intval($ltype)
|
||||
);
|
||||
}
|
||||
|
||||
static public function delete_by_pid($portable_id, $ltype = 0) {
|
||||
return q("delete from listeners where portable_id = '%s' and ltype = %d",
|
||||
dbesc($portable_id),
|
||||
intval($ltype)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
91
Zotlabs/Lib/ZotURL.php
Normal file
91
Zotlabs/Lib/ZotURL.php
Normal file
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
use Zotlabs\Web\HTTPSig;
|
||||
|
||||
|
||||
class ZotURL {
|
||||
|
||||
static public function fetch($url,$channel) {
|
||||
|
||||
$ret = [ 'success' => false ];
|
||||
|
||||
if(strpos($url,'x-zot:') !== 0) {
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
if(! $url) {
|
||||
return $ret;
|
||||
}
|
||||
|
||||
$portable_url = substr($url,6);
|
||||
$u = explode('/',$portable_url);
|
||||
$portable_id = $u[0];
|
||||
|
||||
$hosts = self::lookup($portable_id);
|
||||
|
||||
if(! $hosts) {
|
||||
return $ret;
|
||||
}
|
||||
|
||||
foreach($hosts as $h) {
|
||||
$newurl = $h . '/id/' . $portable_url;
|
||||
|
||||
$m = parse_url($newurl);
|
||||
|
||||
$data = json_encode([ 'zot_token' => random_string() ]);
|
||||
|
||||
if($channel && $m) {
|
||||
|
||||
$headers = [
|
||||
'Accept' => 'application/x-zot+json',
|
||||
'Content-Type' => 'application/x-zot+json',
|
||||
'X-Zot-Token' => random_string(),
|
||||
'Digest' => HTTPSig::generate_digest_header($data),
|
||||
'Host' => $m['host'],
|
||||
'(request-target)' => 'post ' . get_request_string($newurl)
|
||||
];
|
||||
$h = HTTPSig::create_sig($headers,$channel['channel_prvkey'],channel_url($channel),false);
|
||||
}
|
||||
else {
|
||||
$h = [ 'Accept: application/x-zot+json' ];
|
||||
}
|
||||
|
||||
$result = [];
|
||||
|
||||
$redirects = 0;
|
||||
$x = z_post_url($newurl,$data,$redirects, [ 'headers' => $h ] );
|
||||
if($x['success']) {
|
||||
return $x;
|
||||
}
|
||||
}
|
||||
|
||||
return $ret;
|
||||
|
||||
}
|
||||
|
||||
static public function is_zoturl($url) {
|
||||
|
||||
if(strpos($url,'x-zot:') === 0) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static public function lookup($portable_id) {
|
||||
|
||||
$r = q("select * from hubloc left join site on hubloc_url = site_url where hubloc_hash = '%s' and site_dead = 0 order by hubloc_primary desc",
|
||||
dbesc($portable_id)
|
||||
);
|
||||
|
||||
if(! $r) {
|
||||
// extend to network lookup
|
||||
return false;
|
||||
}
|
||||
return ids_to_array($r,'hubloc_url');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -12,10 +12,19 @@ class Zotfinger {
|
||||
return false;
|
||||
}
|
||||
|
||||
if($channel) {
|
||||
$m = parse_url($resource);
|
||||
|
||||
$data = json_encode([ 'zot_token' => random_string() ]);
|
||||
|
||||
if($channel && $m) {
|
||||
|
||||
$headers = [
|
||||
'Accept' => 'application/x-zot+json',
|
||||
'X-Zot-Token' => random_string(),
|
||||
'Accept' => 'application/x-zot+json',
|
||||
'Content-Type' => 'application/x-zot+json',
|
||||
'X-Zot-Token' => random_string(),
|
||||
'Digest' => HTTPSig::generate_digest_header($data),
|
||||
'Host' => $m['host'],
|
||||
'(request-target)' => 'post ' . get_request_string($resource)
|
||||
];
|
||||
$h = HTTPSig::create_sig($headers,$channel['channel_prvkey'],channel_url($channel),false);
|
||||
}
|
||||
@@ -27,7 +36,9 @@ class Zotfinger {
|
||||
|
||||
|
||||
$redirects = 0;
|
||||
$x = z_fetch_url($resource,false,$redirects, [ 'headers' => $h ] );
|
||||
$x = z_post_url($resource,$data,$redirects, [ 'headers' => $h ] );
|
||||
|
||||
logger('fetch: ' . print_r($x,true));
|
||||
|
||||
if($x['success']) {
|
||||
|
||||
@@ -39,6 +50,8 @@ class Zotfinger {
|
||||
$result['data'] = json_decode(crypto_unencapsulate($result['data'],get_config('system','prvkey')),true);
|
||||
}
|
||||
|
||||
logger('decrypted: ' . print_r($result,true));
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
@@ -166,7 +166,7 @@ class Acl extends \Zotlabs\Web\Controller {
|
||||
if($extra_channels) {
|
||||
foreach($extra_channels as $channel) {
|
||||
if(perm_is_allowed(intval($channel), get_observer_hash(),'view_contacts')) {
|
||||
if($extra_channel_sql)
|
||||
if($extra_channels_sql)
|
||||
$extra_channels_sql .= ',';
|
||||
$extra_channels_sql .= intval($channel);
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@ class Admin extends \Zotlabs\Web\Controller {
|
||||
|
||||
// list total user accounts, expirations etc.
|
||||
$accounts = array();
|
||||
$r = q("SELECT COUNT(*) AS total, COUNT(CASE WHEN account_expires > %s THEN 1 ELSE NULL END) AS expiring, COUNT(CASE WHEN account_expires < %s AND account_expires > '%s' THEN 1 ELSE NULL END) AS expired, COUNT(CASE WHEN (account_flags & %d)>0 THEN 1 ELSE NULL END) AS blocked FROM account",
|
||||
$r = q("SELECT COUNT(CASE WHEN account_id > 0 THEN 1 ELSE NULL END) AS total, COUNT(CASE WHEN account_expires > %s THEN 1 ELSE NULL END) AS expiring, COUNT(CASE WHEN account_expires < %s AND account_expires > '%s' THEN 1 ELSE NULL END) AS expired, COUNT(CASE WHEN (account_flags & %d)>0 THEN 1 ELSE NULL END) AS blocked FROM account",
|
||||
db_utcnow(),
|
||||
db_utcnow(),
|
||||
dbesc(NULL_DATE),
|
||||
|
||||
@@ -375,6 +375,9 @@ class Addons {
|
||||
if($files) {
|
||||
foreach($files as $file) {
|
||||
if (is_dir($file)){
|
||||
if($file == 'addon/addon_common/')
|
||||
continue;
|
||||
|
||||
list($tmp, $id) = array_map('trim', explode('/', $file));
|
||||
$info = get_plugin_info($id);
|
||||
$enabled = in_array($id,\App::$plugins);
|
||||
@@ -476,4 +479,4 @@ class Addons {
|
||||
return(strcmp(strtolower($a[2]['name']),strtolower($b[2]['name'])));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,47 @@ class Dbsync {
|
||||
info( t('Update has been marked successful') . EOL);
|
||||
goaway(z_root() . '/admin/dbsync');
|
||||
}
|
||||
|
||||
if(argc() > 3 && intval(argv(3)) && argv(2) === 'verify') {
|
||||
|
||||
$s = '_' . intval(argv(3));
|
||||
$cls = '\\Zotlabs\Update\\' . $s ;
|
||||
if(class_exists($cls)) {
|
||||
$c = new $cls();
|
||||
if(method_exists($c,'verify')) {
|
||||
$retval = $c->verify();
|
||||
if($retval === UPDATE_FAILED) {
|
||||
$o .= sprintf( t('Verification of update %s failed. Check system logs.'), $s);
|
||||
}
|
||||
elseif($retval === UPDATE_SUCCESS) {
|
||||
$o .= sprintf( t('Update %s was successfully applied.'), $s);
|
||||
set_config('database',$s, 'success');
|
||||
}
|
||||
else
|
||||
$o .= sprintf( t('Verifying update %s did not return a status. Unknown if it succeeded.'), $s);
|
||||
}
|
||||
else {
|
||||
$o .= sprintf( t('Update %s does not contain a verification function.'), $s );
|
||||
}
|
||||
}
|
||||
else
|
||||
$o .= sprintf( t('Update function %s could not be found.'), $s);
|
||||
|
||||
return $o;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// remove the old style config if it exists
|
||||
del_config('database', 'update_r' . intval(argv(3)));
|
||||
set_config('database', '_' . intval(argv(3)), 'success');
|
||||
if(intval(get_config('system','db_version')) < intval(argv(3)))
|
||||
set_config('system','db_version',intval(argv(3)));
|
||||
info( t('Update has been marked successful') . EOL);
|
||||
goaway(z_root() . '/admin/dbsync');
|
||||
}
|
||||
|
||||
if(argc() > 2 && intval(argv(2))) {
|
||||
$x = intval(argv(2));
|
||||
$s = '_' . $x;
|
||||
@@ -28,14 +68,14 @@ class Dbsync {
|
||||
$c = new $cls();
|
||||
$retval = $c->run();
|
||||
if($retval === UPDATE_FAILED) {
|
||||
$o .= sprintf( t('Executing %s failed. Check system logs.'), $s);
|
||||
$o .= sprintf( t('Executing update procedure %s failed. Check system logs.'), $s);
|
||||
}
|
||||
elseif($retval === UPDATE_SUCCESS) {
|
||||
$o .= sprintf( t('Update %s was successfully applied.'), $s);
|
||||
set_config('database',$s, 'success');
|
||||
}
|
||||
else
|
||||
$o .= sprintf( t('Update %s did not return a status. Unknown if it succeeded.'), $s);
|
||||
$o .= sprintf( t('Update %s did not return a status. It cannot be determined if it was successful.'), $s);
|
||||
}
|
||||
else
|
||||
$o .= sprintf( t('Update function %s could not be found.'), $s);
|
||||
@@ -59,6 +99,7 @@ class Dbsync {
|
||||
'$banner' => t('Failed Updates'),
|
||||
'$desc' => '',
|
||||
'$mark' => t('Mark success (if update was manually applied)'),
|
||||
'$verify' => t('Attempt to verify this update if a verification procedure exists'),
|
||||
'$apply' => t('Attempt to execute this update step automatically'),
|
||||
'$failed' => $failed
|
||||
));
|
||||
|
||||
@@ -119,7 +119,7 @@ class Site {
|
||||
del_config('system', 'admininfo');
|
||||
} else {
|
||||
require_once('include/text.php');
|
||||
linkify_tags($a, $admininfo, local_channel());
|
||||
linkify_tags($admininfo, local_channel());
|
||||
set_config('system', 'admininfo', $admininfo);
|
||||
}
|
||||
set_config('system','siteinfo',$siteinfo);
|
||||
|
||||
94
Zotlabs/Module/Affinity.php
Normal file
94
Zotlabs/Module/Affinity.php
Normal file
@@ -0,0 +1,94 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
use App;
|
||||
use Zotlabs\Lib\Apps;
|
||||
use Zotlabs\Lib\Libsync;
|
||||
|
||||
class Affinity extends \Zotlabs\Web\Controller {
|
||||
|
||||
function post() {
|
||||
|
||||
if(! local_channel())
|
||||
return;
|
||||
|
||||
if(! Apps::system_app_installed(local_channel(),'Affinity Tool'))
|
||||
return;
|
||||
|
||||
check_form_security_token_redirectOnErr('affinity', 'affinity');
|
||||
|
||||
$cmax = intval($_POST['affinity_cmax']);
|
||||
if($cmax < 0 || $cmax > 99)
|
||||
$cmax = 99;
|
||||
|
||||
$cmin = intval($_POST['affinity_cmin']);
|
||||
if($cmin < 0 || $cmin > 99)
|
||||
$cmin = 0;
|
||||
|
||||
$lock = intval($_POST['affinity_lock']);
|
||||
|
||||
set_pconfig(local_channel(),'affinity','cmin',$cmin);
|
||||
set_pconfig(local_channel(),'affinity','cmax',$cmax);
|
||||
set_pconfig(local_channel(),'affinity','lock',$lock);
|
||||
|
||||
info( t('Affinity Tool settings updated.') . EOL);
|
||||
|
||||
Libsync::build_sync_packet();
|
||||
|
||||
}
|
||||
|
||||
|
||||
function get() {
|
||||
|
||||
if(! local_channel())
|
||||
return;
|
||||
|
||||
$desc = t('This app presents a slider control in your connection editor and also on your network page. The slider represents your degree of friendship (affinity) with each connection. It allows you to zoom in or out and display conversations from only your closest friends or everybody in your stream.');
|
||||
if(! Apps::system_app_installed(local_channel(),'Affinity Tool')) {
|
||||
//Do not display any associated widgets at this point
|
||||
App::$pdl = '';
|
||||
|
||||
$o = '<b>' . t('Affinity Tool App') . ' (' . t('Not Installed') . '):</b><br>';
|
||||
$o .= $desc;
|
||||
return $o;
|
||||
}
|
||||
|
||||
$text = t('The numbers below represent the minimum and maximum slider default positions for your network/stream page as a percentage.');
|
||||
|
||||
$content = '<div class="section-content-info-wrapper">' . $text . '</div>';
|
||||
|
||||
$cmax = intval(get_pconfig(local_channel(),'affinity','cmax'));
|
||||
$cmax = (($cmax) ? $cmax : 99);
|
||||
$content .= replace_macros(get_markup_template('field_input.tpl'), array(
|
||||
'$field' => array('affinity_cmax', t('Default maximum affinity level'), $cmax, t('0-99 default 99'))
|
||||
));
|
||||
|
||||
$cmin = intval(get_pconfig(local_channel(),'affinity','cmin'));
|
||||
$cmin = (($cmin) ? $cmin : 0);
|
||||
$content .= replace_macros(get_markup_template('field_input.tpl'), array(
|
||||
'$field' => array('affinity_cmin', t('Default minimum affinity level'), $cmin, t('0-99 - default 0'))
|
||||
));
|
||||
|
||||
$lock = intval(get_pconfig(local_channel(),'affinity','lock',1));
|
||||
|
||||
$content .= replace_macros(get_markup_template('field_checkbox.tpl'), array(
|
||||
'$field' => array('affinity_lock', t('Persistent affinity levels'), $lock, t('If disabled the max and min levels will be reset to default after page reload'), ['No','Yes'])
|
||||
));
|
||||
|
||||
$tpl = get_markup_template("settings_addon.tpl");
|
||||
|
||||
$o = replace_macros($tpl, array(
|
||||
'$action_url' => 'affinity',
|
||||
'$form_security_token' => get_form_security_token("affinity"),
|
||||
'$title' => t('Affinity Tool Settings'),
|
||||
'$content' => $content,
|
||||
'$baseurl' => z_root(),
|
||||
'$submit' => t('Submit'),
|
||||
));
|
||||
|
||||
return $o;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
63
Zotlabs/Module/Apschema.php
Normal file
63
Zotlabs/Module/Apschema.php
Normal file
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
|
||||
class Apschema extends \Zotlabs\Web\Controller {
|
||||
|
||||
function init() {
|
||||
|
||||
$base = z_root();
|
||||
|
||||
$arr = [
|
||||
'@context' => [
|
||||
'zot' => z_root() . '/apschema#',
|
||||
'id' => '@id',
|
||||
'type' => '@type',
|
||||
'commentPolicy' => 'as:commentPolicy',
|
||||
'meData' => 'zot:meData',
|
||||
'meDataType' => 'zot:meDataType',
|
||||
'meEncoding' => 'zot:meEncoding',
|
||||
'meAlgorithm' => 'zot:meAlgorithm',
|
||||
'meCreator' => 'zot:meCreator',
|
||||
'meSignatureValue' => 'zot:meSignatureValue',
|
||||
'locationAddress' => 'zot:locationAddress',
|
||||
'locationPrimary' => 'zot:locationPrimary',
|
||||
'locationDeleted' => 'zot:locationDeleted',
|
||||
'nomadicLocation' => 'zot:nomadicLocation',
|
||||
'nomadicHubs' => 'zot:nomadicHubs',
|
||||
'emojiReaction' => 'zot:emojiReaction',
|
||||
'expires' => 'zot:expires',
|
||||
'directMessage' => 'zot:directMessage',
|
||||
|
||||
'magicEnv' => [
|
||||
'@id' => 'zot:magicEnv',
|
||||
'@type' => '@id'
|
||||
],
|
||||
|
||||
'nomadicLocations' => [
|
||||
'@id' => 'zot:nomadicLocations',
|
||||
'@type' => '@id'
|
||||
],
|
||||
|
||||
'ostatus' => 'http://ostatus.org#',
|
||||
'conversation' => 'ostatus:conversation',
|
||||
|
||||
'diaspora' => 'https://diasporafoundation.org/ns/',
|
||||
'guid' => 'diaspora:guid',
|
||||
|
||||
'Hashtag' => 'as:Hashtag'
|
||||
|
||||
]
|
||||
];
|
||||
|
||||
header('Content-Type: application/ld+json');
|
||||
echo json_encode($arr,JSON_UNESCAPED_SLASHES);
|
||||
killme();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -1,6 +1,10 @@
|
||||
<?php
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
|
||||
use App;
|
||||
use Zotlabs\Web\Controller;
|
||||
|
||||
require_once('include/conversation.php');
|
||||
require_once('include/bbcode.php');
|
||||
require_once('include/datetime.php');
|
||||
@@ -9,15 +13,13 @@ require_once('include/items.php');
|
||||
require_once('include/html2plain.php');
|
||||
|
||||
|
||||
class Cal extends \Zotlabs\Web\Controller {
|
||||
class Cal extends Controller {
|
||||
|
||||
function init() {
|
||||
if(observer_prohibited()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$o = '';
|
||||
|
||||
if(argc() > 1) {
|
||||
$nick = argv(1);
|
||||
|
||||
@@ -25,19 +27,21 @@ class Cal extends \Zotlabs\Web\Controller {
|
||||
|
||||
$channelx = channelx_by_nick($nick);
|
||||
|
||||
if(! $channelx)
|
||||
if(! $channelx) {
|
||||
notice( t('Channel not found.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
\App::$data['channel'] = $channelx;
|
||||
App::$data['channel'] = $channelx;
|
||||
|
||||
$observer = \App::get_observer();
|
||||
\App::$data['observer'] = $observer;
|
||||
$observer = App::get_observer();
|
||||
App::$data['observer'] = $observer;
|
||||
|
||||
$observer_xchan = (($observer) ? $observer['xchan_hash'] : '');
|
||||
|
||||
head_set_icon(\App::$data['channel']['xchan_photo_s']);
|
||||
head_set_icon(App::$data['channel']['xchan_photo_s']);
|
||||
|
||||
\App::$page['htmlhead'] .= "<script> var profile_uid = " . ((\App::$data['channel']) ? \App::$data['channel']['channel_id'] : 0) . "; </script>" ;
|
||||
App::$page['htmlhead'] .= "<script> var profile_uid = " . ((App::$data['channel']) ? App::$data['channel']['channel_id'] : 0) . "; </script>" ;
|
||||
|
||||
}
|
||||
|
||||
@@ -52,18 +56,8 @@ class Cal extends \Zotlabs\Web\Controller {
|
||||
return;
|
||||
}
|
||||
|
||||
$channel = null;
|
||||
|
||||
if(argc() > 1) {
|
||||
$channel = channelx_by_nick(argv(1));
|
||||
}
|
||||
|
||||
|
||||
if(! $channel) {
|
||||
notice( t('Channel not found.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
$channel = App::$data['channel'];
|
||||
|
||||
// since we don't currently have an event permission - use the stream permission
|
||||
|
||||
if(! perm_is_allowed($channel['channel_id'], get_observer_hash(), 'view_stream')) {
|
||||
@@ -72,287 +66,152 @@ class Cal extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
|
||||
nav_set_selected('Calendar');
|
||||
|
||||
head_add_css('/library/fullcalendar/packages/core/main.min.css');
|
||||
head_add_css('/library/fullcalendar/packages/daygrid/main.min.css');
|
||||
head_add_css('cdav_calendar.css');
|
||||
|
||||
head_add_js('/library/fullcalendar/packages/core/main.min.js');
|
||||
head_add_js('/library/fullcalendar/packages/daygrid/main.min.js');
|
||||
|
||||
$sql_extra = permissions_sql($channel['channel_id'], get_observer_hash(), 'event');
|
||||
|
||||
if(! perm_is_allowed($channel['channel_id'], get_observer_hash(), 'view_contacts') || App::$profile['hide_friends'])
|
||||
$sql_extra .= " and etype != 'birthday' ";
|
||||
|
||||
$sql_extra = permissions_sql($channel['channel_id'],get_observer_hash(),'event');
|
||||
|
||||
$first_day = feature_enabled($channel['channel_id'], 'events_cal_first_day');
|
||||
$first_day = feature_enabled($channel['channel_id'], 'cal_first_day');
|
||||
$first_day = (($first_day) ? $first_day : 0);
|
||||
|
||||
$htpl = get_markup_template('event_head.tpl');
|
||||
\App::$page['htmlhead'] .= replace_macros($htpl,array(
|
||||
'$baseurl' => z_root(),
|
||||
'$module_url' => '/cal/' . $channel['channel_address'],
|
||||
'$modparams' => 2,
|
||||
'$lang' => \App::$language,
|
||||
'$first_day' => $first_day
|
||||
));
|
||||
|
||||
$o = '';
|
||||
|
||||
$mode = 'view';
|
||||
$y = 0;
|
||||
$m = 0;
|
||||
$ignored = ((x($_REQUEST,'ignored')) ? " and dismissed = " . intval($_REQUEST['ignored']) . " " : '');
|
||||
|
||||
// logger('args: ' . print_r(\App::$argv,true));
|
||||
|
||||
if(argc() > 3 && intval(argv(2)) && intval(argv(3))) {
|
||||
$mode = 'view';
|
||||
$y = intval(argv(2));
|
||||
$m = intval(argv(3));
|
||||
}
|
||||
if(argc() <= 3) {
|
||||
$mode = 'view';
|
||||
$event_id = argv(2);
|
||||
$start = '';
|
||||
$finish = '';
|
||||
|
||||
if (argv(2) === 'json') {
|
||||
if (x($_GET,'start')) $start = $_GET['start'];
|
||||
if (x($_GET,'end')) $finish = $_GET['end'];
|
||||
}
|
||||
|
||||
if($mode == 'view') {
|
||||
|
||||
/* edit/create form */
|
||||
if($event_id) {
|
||||
$r = q("SELECT * FROM event WHERE event_hash = '%s' AND uid = %d LIMIT 1",
|
||||
dbesc($event_id),
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
if(count($r))
|
||||
$orig_event = $r[0];
|
||||
}
|
||||
|
||||
|
||||
// Passed parameters overrides anything found in the DB
|
||||
if(!x($orig_event))
|
||||
$orig_event = array();
|
||||
|
||||
|
||||
|
||||
$tz = date_default_timezone_get();
|
||||
if(x($orig_event))
|
||||
$tz = (($orig_event['adjust']) ? date_default_timezone_get() : 'UTC');
|
||||
|
||||
$syear = datetime_convert('UTC', $tz, $sdt, 'Y');
|
||||
$smonth = datetime_convert('UTC', $tz, $sdt, 'm');
|
||||
$sday = datetime_convert('UTC', $tz, $sdt, 'd');
|
||||
$shour = datetime_convert('UTC', $tz, $sdt, 'H');
|
||||
$sminute = datetime_convert('UTC', $tz, $sdt, 'i');
|
||||
|
||||
$stext = datetime_convert('UTC',$tz,$sdt);
|
||||
$stext = substr($stext,0,14) . "00:00";
|
||||
|
||||
$fyear = datetime_convert('UTC', $tz, $fdt, 'Y');
|
||||
$fmonth = datetime_convert('UTC', $tz, $fdt, 'm');
|
||||
$fday = datetime_convert('UTC', $tz, $fdt, 'd');
|
||||
$fhour = datetime_convert('UTC', $tz, $fdt, 'H');
|
||||
$fminute = datetime_convert('UTC', $tz, $fdt, 'i');
|
||||
|
||||
$ftext = datetime_convert('UTC',$tz,$fdt);
|
||||
$ftext = substr($ftext,0,14) . "00:00";
|
||||
|
||||
$type = ((x($orig_event)) ? $orig_event['etype'] : 'event');
|
||||
|
||||
$f = get_config('system','event_input_format');
|
||||
if(! $f)
|
||||
$f = 'ymd';
|
||||
|
||||
$catsenabled = feature_enabled($channel['channel_id'],'categories');
|
||||
|
||||
|
||||
$show_bd = perm_is_allowed($channel['channel_id'], get_observer_hash(), 'view_contacts');
|
||||
if(! $show_bd) {
|
||||
$sql_extra .= " and event.etype != 'birthday' ";
|
||||
}
|
||||
|
||||
|
||||
$category = '';
|
||||
|
||||
$thisyear = datetime_convert('UTC',date_default_timezone_get(),'now','Y');
|
||||
$thismonth = datetime_convert('UTC',date_default_timezone_get(),'now','m');
|
||||
if(! $y)
|
||||
$y = intval($thisyear);
|
||||
if(! $m)
|
||||
$m = intval($thismonth);
|
||||
|
||||
// Put some limits on dates. The PHP date functions don't seem to do so well before 1900.
|
||||
// An upper limit was chosen to keep search engines from exploring links millions of years in the future.
|
||||
|
||||
if($y < 1901)
|
||||
$y = 1900;
|
||||
if($y > 2099)
|
||||
$y = 2100;
|
||||
|
||||
$nextyear = $y;
|
||||
$nextmonth = $m + 1;
|
||||
if($nextmonth > 12) {
|
||||
$nextmonth = 1;
|
||||
$nextyear ++;
|
||||
}
|
||||
|
||||
$prevyear = $y;
|
||||
if($m > 1)
|
||||
$prevmonth = $m - 1;
|
||||
else {
|
||||
$prevmonth = 12;
|
||||
$prevyear --;
|
||||
}
|
||||
|
||||
$dim = get_dim($y,$m);
|
||||
$start = sprintf('%d-%d-%d %d:%d:%d',$y,$m,1,0,0,0);
|
||||
$finish = sprintf('%d-%d-%d %d:%d:%d',$y,$m,$dim,23,59,59);
|
||||
|
||||
|
||||
if (argv(2) === 'json'){
|
||||
if (x($_GET,'start')) $start = $_GET['start'];
|
||||
if (x($_GET,'end')) $finish = $_GET['end'];
|
||||
}
|
||||
|
||||
$start = datetime_convert('UTC','UTC',$start);
|
||||
$finish = datetime_convert('UTC','UTC',$finish);
|
||||
|
||||
$adjust_start = datetime_convert('UTC', date_default_timezone_get(), $start);
|
||||
$adjust_finish = datetime_convert('UTC', date_default_timezone_get(), $finish);
|
||||
|
||||
$start = datetime_convert('UTC','UTC',$start);
|
||||
$finish = datetime_convert('UTC','UTC',$finish);
|
||||
$adjust_start = datetime_convert('UTC', date_default_timezone_get(), $start);
|
||||
$adjust_finish = datetime_convert('UTC', date_default_timezone_get(), $finish);
|
||||
|
||||
if(! perm_is_allowed(\App::$profile['uid'],get_observer_hash(),'view_contacts'))
|
||||
$sql_extra .= " and etype != 'birthday' ";
|
||||
if (x($_GET, 'id')) {
|
||||
$r = q("SELECT event.*, item.plink, item.item_flags, item.author_xchan, item.owner_xchan, item.id as item_id
|
||||
from event left join item on item.resource_id = event.event_hash
|
||||
where item.resource_type = 'event' and event.uid = %d and event.id = %d $sql_extra limit 1",
|
||||
intval($channel['channel_id']),
|
||||
intval($_GET['id'])
|
||||
);
|
||||
}
|
||||
else {
|
||||
// fixed an issue with "nofinish" events not showing up in the calendar.
|
||||
// There's still an issue if the finish date crosses the end of month.
|
||||
// Noting this for now - it will need to be fixed here and in Friendica.
|
||||
// Ultimately the finish date shouldn't be involved in the query.
|
||||
$r = q("SELECT event.*, item.plink, item.item_flags, item.author_xchan, item.owner_xchan, item.id as item_id
|
||||
from event left join item on event.event_hash = item.resource_id
|
||||
where item.resource_type = 'event' and event.uid = %d and event.uid = item.uid
|
||||
AND (( event.adjust = 0 AND ( event.dtend >= '%s' or event.nofinish = 1 ) AND event.dtstart <= '%s' )
|
||||
OR ( event.adjust = 1 AND ( event.dtend >= '%s' or event.nofinish = 1 ) AND event.dtstart <= '%s' ))
|
||||
$sql_extra",
|
||||
intval($channel['channel_id']),
|
||||
dbesc($start),
|
||||
dbesc($finish),
|
||||
dbesc($adjust_start),
|
||||
dbesc($adjust_finish)
|
||||
);
|
||||
}
|
||||
|
||||
if($r) {
|
||||
xchan_query($r);
|
||||
$r = fetch_post_tags($r,true);
|
||||
$r = sort_by_date($r);
|
||||
}
|
||||
|
||||
if (x($_GET,'id')){
|
||||
$r = q("SELECT event.*, item.plink, item.item_flags, item.author_xchan, item.owner_xchan
|
||||
from event left join item on resource_id = event_hash where resource_type = 'event' and event.uid = %d and event.id = %d $sql_extra limit 1",
|
||||
intval($channel['channel_id']),
|
||||
intval($_GET['id'])
|
||||
);
|
||||
}
|
||||
else {
|
||||
// fixed an issue with "nofinish" events not showing up in the calendar.
|
||||
// There's still an issue if the finish date crosses the end of month.
|
||||
// Noting this for now - it will need to be fixed here and in Friendica.
|
||||
// Ultimately the finish date shouldn't be involved in the query.
|
||||
$events = [];
|
||||
|
||||
$r = q("SELECT event.*, item.plink, item.item_flags, item.author_xchan, item.owner_xchan
|
||||
from event left join item on event_hash = resource_id
|
||||
where resource_type = 'event' and event.uid = %d and event.uid = item.uid $ignored
|
||||
AND (( adjust = 0 AND ( dtend >= '%s' or nofinish = 1 ) AND dtstart <= '%s' )
|
||||
OR ( adjust = 1 AND ( dtend >= '%s' or nofinish = 1 ) AND dtstart <= '%s' )) $sql_extra ",
|
||||
intval($channel['channel_id']),
|
||||
dbesc($start),
|
||||
dbesc($finish),
|
||||
dbesc($adjust_start),
|
||||
dbesc($adjust_finish)
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
$links = array();
|
||||
|
||||
if($r) {
|
||||
xchan_query($r);
|
||||
$r = fetch_post_tags($r,true);
|
||||
|
||||
$r = sort_by_date($r);
|
||||
}
|
||||
|
||||
if($r) {
|
||||
foreach($r as $rr) {
|
||||
$j = (($rr['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$rr['dtstart'], 'j') : datetime_convert('UTC','UTC',$rr['dtstart'],'j'));
|
||||
if(! x($links,$j))
|
||||
$links[$j] = z_root() . '/' . \App::$cmd . '#link-' . $j;
|
||||
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'));
|
||||
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'));
|
||||
}
|
||||
}
|
||||
|
||||
$events=array();
|
||||
|
||||
$last_date = '';
|
||||
$fmt = t('l, F j');
|
||||
|
||||
if($r) {
|
||||
|
||||
foreach($r as $rr) {
|
||||
|
||||
$j = (($rr['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$rr['dtstart'], 'j') : datetime_convert('UTC','UTC',$rr['dtstart'],'j'));
|
||||
$d = (($rr['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$rr['dtstart'], $fmt) : datetime_convert('UTC','UTC',$rr['dtstart'],$fmt));
|
||||
$d = day_translate($d);
|
||||
|
||||
$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('UTC',date_default_timezone_get(),$rr['dtend'], 'c') : datetime_convert('UTC','UTC',$rr['dtend'],'c'));
|
||||
}
|
||||
|
||||
|
||||
$is_first = ($d !== $last_date);
|
||||
|
||||
$last_date = $d;
|
||||
|
||||
$edit = false;
|
||||
|
||||
$drop = false;
|
||||
|
||||
$title = strip_tags(html_entity_decode(bbcode($rr['summary']),ENT_QUOTES,'UTF-8'));
|
||||
if(! $title) {
|
||||
list($title, $_trash) = explode("<br",bbcode($rr['desc']),2);
|
||||
$title = strip_tags(html_entity_decode($title,ENT_QUOTES,'UTF-8'));
|
||||
}
|
||||
|
||||
$html = '';
|
||||
if (x($_GET,'id')) {
|
||||
$rr['timezone'] = $tz;
|
||||
$html = format_event_html($rr);
|
||||
$rr['desc'] = zidify_links(smilies(bbcode($rr['desc'])));
|
||||
$rr['description'] = htmlentities(html2plain(bbcode($rr['description'])),ENT_COMPAT,'UTF-8',false);
|
||||
$rr['location'] = zidify_links(smilies(bbcode($rr['location'])));
|
||||
$events[] = array(
|
||||
'id'=>$rr['id'],
|
||||
'hash' => $rr['event_hash'],
|
||||
'start'=> $start,
|
||||
'end' => $end,
|
||||
'drop' => $drop,
|
||||
'allDay' => false,
|
||||
'title' => $title,
|
||||
|
||||
'j' => $j,
|
||||
'd' => $d,
|
||||
'edit' => $edit,
|
||||
'is_first'=>$is_first,
|
||||
'item'=>$rr,
|
||||
'html'=>$html,
|
||||
'plink' => array($rr['plink'],t('Link to Source'),'',''),
|
||||
);
|
||||
|
||||
|
||||
}
|
||||
|
||||
$events[] = array(
|
||||
'calendar_id' => 'channel_calendar',
|
||||
'rw' => true,
|
||||
'id'=>$rr['id'],
|
||||
'uri' => $rr['event_hash'],
|
||||
'timezone' => $tz,
|
||||
'start'=> $start,
|
||||
'end' => $end,
|
||||
'drop' => $drop,
|
||||
'allDay' => (($rr['adjust']) ? 0 : 1),
|
||||
'title' => html_entity_decode($rr['summary'], ENT_COMPAT, 'UTF-8'),
|
||||
'editable' => $edit ? true : false,
|
||||
'item' => $rr,
|
||||
'plink' => [$rr['plink'], t('Link to source')],
|
||||
'description' => html_entity_decode($rr['description'], ENT_COMPAT, 'UTF-8'),
|
||||
'location' => html_entity_decode($rr['location'], ENT_COMPAT, 'UTF-8'),
|
||||
'allow_cid' => expand_acl($rr['allow_cid']),
|
||||
'allow_gid' => expand_acl($rr['allow_gid']),
|
||||
'deny_cid' => expand_acl($rr['deny_cid']),
|
||||
'deny_gid' => expand_acl($rr['deny_gid']),
|
||||
'html' => $html
|
||||
);
|
||||
}
|
||||
|
||||
if (argv(2) === 'json'){
|
||||
echo json_encode($events); killme();
|
||||
}
|
||||
|
||||
// links: array('href', 'text', 'extra css classes', 'title')
|
||||
if (x($_GET,'id')){
|
||||
$tpl = get_markup_template("event_cal.tpl");
|
||||
}
|
||||
else {
|
||||
$tpl = get_markup_template("events_cal-js.tpl");
|
||||
}
|
||||
|
||||
$nick = $channel['channel_address'];
|
||||
|
||||
$o = replace_macros($tpl, array(
|
||||
'$baseurl' => z_root(),
|
||||
'$new_event' => array(z_root().'/cal',(($event_id) ? t('Edit Event') : t('Create Event')),'',''),
|
||||
'$previus' => array(z_root()."/cal/$nick/$prevyear/$prevmonth",t('Previous'),'',''),
|
||||
'$next' => array(z_root()."/cal/$nick/$nextyear/$nextmonth",t('Next'),'',''),
|
||||
'$export' => array(z_root()."/cal/$nick/$y/$m/export",t('Export'),'',''),
|
||||
'$calendar' => cal($y,$m,$links, ' eventcal'),
|
||||
'$events' => $events,
|
||||
'$upload' => t('Import'),
|
||||
'$submit' => t('Submit'),
|
||||
'$prev' => t('Previous'),
|
||||
'$next' => t('Next'),
|
||||
'$today' => t('Today'),
|
||||
'$form' => $form,
|
||||
'$expandform' => ((x($_GET,'expandform')) ? true : false)
|
||||
));
|
||||
|
||||
if (x($_GET,'id')){ echo $o; killme(); }
|
||||
|
||||
return $o;
|
||||
}
|
||||
|
||||
if (argv(2) === 'json') {
|
||||
echo json_encode($events);
|
||||
killme();
|
||||
}
|
||||
|
||||
if (x($_GET,'id')) {
|
||||
$o = replace_macros(get_markup_template("cal_event.tpl"), [
|
||||
'$events' => $events
|
||||
]);
|
||||
echo $o;
|
||||
killme();
|
||||
}
|
||||
|
||||
$nick = $channel['channel_address'];
|
||||
|
||||
$sources = '{
|
||||
id: \'channel_calendar\',
|
||||
url: \'/cal/' . $nick . '/json/\',
|
||||
color: \'#3a87ad\'
|
||||
}';
|
||||
|
||||
$o = replace_macros(get_markup_template("cal_calendar.tpl"), [
|
||||
'$sources' => $sources,
|
||||
'$lang' => App::$language,
|
||||
'$timezone' => date_default_timezone_get(),
|
||||
'$first_day' => $first_day,
|
||||
'$prev' => t('Previous'),
|
||||
'$next' => t('Next'),
|
||||
'$today' => t('Today'),
|
||||
'$title' => $title,
|
||||
'$dtstart' => $dtstart,
|
||||
'$dtend' => $dtend,
|
||||
'$nick' => $nick
|
||||
]);
|
||||
|
||||
return $o;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -10,9 +10,13 @@ require_once('include/channel.php');
|
||||
require_once('include/conversation.php');
|
||||
require_once('include/acl_selectors.php');
|
||||
|
||||
/**
|
||||
* @brief Provides the Cards module.
|
||||
*
|
||||
*/
|
||||
class Cards extends Controller {
|
||||
|
||||
function init() {
|
||||
public function init() {
|
||||
|
||||
if(argc() > 1)
|
||||
$which = argv(1);
|
||||
@@ -20,14 +24,15 @@ class Cards extends Controller {
|
||||
return;
|
||||
|
||||
profile_load($which);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see \Zotlabs\Web\Controller::get()
|
||||
* @see \\Zotlabs\\Web\\Controller::get()
|
||||
*
|
||||
* @return string Parsed HTML from template 'cards.tpl'
|
||||
*/
|
||||
function get($update = 0, $load = false) {
|
||||
public function get($update = 0, $load = false) {
|
||||
|
||||
if(observer_prohibited(true)) {
|
||||
return login();
|
||||
@@ -99,7 +104,6 @@ class Cards extends Controller {
|
||||
}
|
||||
|
||||
|
||||
|
||||
if(perm_is_allowed($owner, $ob_hash, 'write_pages')) {
|
||||
|
||||
$x = [
|
||||
@@ -110,7 +114,7 @@ class Cards extends Controller {
|
||||
'nickname' => $channel['channel_address'],
|
||||
'lockstate' => (($channel['channel_allow_cid'] || $channel['channel_allow_gid']
|
||||
|| $channel['channel_deny_cid'] || $channel['channel_deny_gid']) ? 'lock' : 'unlock'),
|
||||
'acl' => (($is_owner) ? populate_acl($channel_acl, false,
|
||||
'acl' => (($is_owner) ? populate_acl($channel_acl, false,
|
||||
PermissionDescription::fromGlobalPermission('view_pages')) : ''),
|
||||
'permissions' => $channel_acl,
|
||||
'showacl' => (($is_owner) ? true : false),
|
||||
|
||||
@@ -4,6 +4,7 @@ namespace Zotlabs\Module;
|
||||
use App;
|
||||
use Zotlabs\Lib\Apps;
|
||||
use Zotlabs\Web\Controller;
|
||||
use Zotlabs\Web\HTTPSig;
|
||||
|
||||
require_once('include/event.php');
|
||||
|
||||
@@ -41,7 +42,7 @@ class Cdav extends Controller {
|
||||
continue;
|
||||
}
|
||||
|
||||
$sigblock = \Zotlabs\Web\HTTPSig::parse_sigheader($_SERVER[$head]);
|
||||
$sigblock = HTTPSig::parse_sigheader($_SERVER[$head]);
|
||||
if($sigblock) {
|
||||
$keyId = str_replace('acct:','',$sigblock['keyId']);
|
||||
if($keyId) {
|
||||
@@ -64,7 +65,7 @@ class Cdav extends Controller {
|
||||
continue;
|
||||
|
||||
if($record) {
|
||||
$verified = \Zotlabs\Web\HTTPSig::verify('',$record['channel']['channel_pubkey']);
|
||||
$verified = HTTPSig::verify('',$record['channel']['channel_pubkey']);
|
||||
if(! ($verified && $verified['header_signed'] && $verified['header_valid'])) {
|
||||
$record = null;
|
||||
}
|
||||
@@ -133,10 +134,6 @@ class Cdav extends Controller {
|
||||
|
||||
logger('loggedin');
|
||||
|
||||
if((argv(1) == 'calendars') && (!Apps::system_app_installed(local_channel(), 'CalDAV'))) {
|
||||
killme();
|
||||
}
|
||||
|
||||
if((argv(1) == 'addressbooks') && (!Apps::system_app_installed(local_channel(), 'CardDAV'))) {
|
||||
killme();
|
||||
}
|
||||
@@ -221,10 +218,6 @@ class Cdav extends Controller {
|
||||
if(! local_channel())
|
||||
return;
|
||||
|
||||
if((argv(1) === 'calendar') && (! Apps::system_app_installed(local_channel(), 'CalDAV'))) {
|
||||
return;
|
||||
}
|
||||
|
||||
if((argv(1) === 'addressbook') && (! Apps::system_app_installed(local_channel(), 'CardDAV'))) {
|
||||
return;
|
||||
}
|
||||
@@ -279,10 +272,19 @@ class Cdav extends Controller {
|
||||
if(!cdav_perms($id[0],$calendars,true))
|
||||
return;
|
||||
|
||||
$timezone = ((x($_POST,'timezone_select')) ? escape_tags(trim($_POST['timezone_select'])) : '');
|
||||
$tz = (($timezone) ? $timezone : date_default_timezone_get());
|
||||
|
||||
$allday = $_REQUEST['allday'];
|
||||
|
||||
$title = $_REQUEST['title'];
|
||||
$dtstart = new \DateTime($_REQUEST['dtstart']);
|
||||
if($_REQUEST['dtend'])
|
||||
$dtend = new \DateTime($_REQUEST['dtend']);
|
||||
$start = datetime_convert('UTC', 'UTC', $_REQUEST['dtstart']);
|
||||
$dtstart = new \DateTime($start);
|
||||
|
||||
if($_REQUEST['dtend']) {
|
||||
$end = datetime_convert('UTC', 'UTC', $_REQUEST['dtend']);
|
||||
$dtend = new \DateTime($end);
|
||||
}
|
||||
$description = $_REQUEST['description'];
|
||||
$location = $_REQUEST['location'];
|
||||
|
||||
@@ -306,13 +308,24 @@ class Cdav extends Controller {
|
||||
'DTSTART' => $dtstart
|
||||
]
|
||||
]);
|
||||
if($dtend)
|
||||
|
||||
if($dtend) {
|
||||
$vcalendar->VEVENT->add('DTEND', $dtend);
|
||||
if($allday)
|
||||
$vcalendar->VEVENT->DTEND['VALUE'] = 'DATE';
|
||||
else
|
||||
$vcalendar->VEVENT->DTEND['TZID'] = $tz;
|
||||
}
|
||||
if($description)
|
||||
$vcalendar->VEVENT->add('DESCRIPTION', $description);
|
||||
if($location)
|
||||
$vcalendar->VEVENT->add('LOCATION', $location);
|
||||
|
||||
if($allday)
|
||||
$vcalendar->VEVENT->DTSTART['VALUE'] = 'DATE';
|
||||
else
|
||||
$vcalendar->VEVENT->DTSTART['TZID'] = $tz;
|
||||
|
||||
$calendarData = $vcalendar->serialize();
|
||||
|
||||
$caldavBackend->createCalendarObject($id, $objectUri, $calendarData);
|
||||
@@ -349,10 +362,19 @@ class Cdav extends Controller {
|
||||
if(!cdav_perms($id[0],$calendars,true))
|
||||
return;
|
||||
|
||||
$timezone = ((x($_POST,'timezone_select')) ? escape_tags(trim($_POST['timezone_select'])) : '');
|
||||
$tz = (($timezone) ? $timezone : date_default_timezone_get());
|
||||
|
||||
$allday = $_REQUEST['allday'];
|
||||
|
||||
$uri = $_REQUEST['uri'];
|
||||
$title = $_REQUEST['title'];
|
||||
$dtstart = new \DateTime($_REQUEST['dtstart']);
|
||||
$dtend = $_REQUEST['dtend'] ? new \DateTime($_REQUEST['dtend']) : '';
|
||||
$start = datetime_convert('UTC', 'UTC', $_REQUEST['dtstart']);
|
||||
$dtstart = new \DateTime($start);
|
||||
if($_REQUEST['dtend']) {
|
||||
$end = datetime_convert('UTC', 'UTC', $_REQUEST['dtend']);
|
||||
$dtend = new \DateTime($end);
|
||||
}
|
||||
$description = $_REQUEST['description'];
|
||||
$location = $_REQUEST['location'];
|
||||
|
||||
@@ -362,12 +384,23 @@ class Cdav extends Controller {
|
||||
|
||||
if($title)
|
||||
$vcalendar->VEVENT->SUMMARY = $title;
|
||||
if($dtstart)
|
||||
if($dtstart) {
|
||||
$vcalendar->VEVENT->DTSTART = $dtstart;
|
||||
if($dtend)
|
||||
if($allday)
|
||||
$vcalendar->VEVENT->DTSTART['VALUE'] = 'DATE';
|
||||
else
|
||||
$vcalendar->VEVENT->DTSTART['TZID'] = $tz;
|
||||
}
|
||||
if($dtend) {
|
||||
$vcalendar->VEVENT->DTEND = $dtend;
|
||||
if($allday)
|
||||
$vcalendar->VEVENT->DTEND['VALUE'] = 'DATE';
|
||||
else
|
||||
$vcalendar->VEVENT->DTEND['TZID'] = $tz;
|
||||
}
|
||||
else
|
||||
unset($vcalendar->VEVENT->DTEND);
|
||||
|
||||
if($description)
|
||||
$vcalendar->VEVENT->DESCRIPTION = $description;
|
||||
if($location)
|
||||
@@ -403,9 +436,18 @@ class Cdav extends Controller {
|
||||
if(!cdav_perms($id[0],$calendars,true))
|
||||
return;
|
||||
|
||||
$timezone = ((x($_POST,'timezone_select')) ? escape_tags(trim($_POST['timezone_select'])) : '');
|
||||
$tz = (($timezone) ? $timezone : date_default_timezone_get());
|
||||
|
||||
$allday = $_REQUEST['allday'];
|
||||
|
||||
$uri = $_REQUEST['uri'];
|
||||
$dtstart = new \DateTime($_REQUEST['dtstart']);
|
||||
$dtend = $_REQUEST['dtend'] ? new \DateTime($_REQUEST['dtend']) : '';
|
||||
$start = datetime_convert('UTC', 'UTC', $_REQUEST['dtstart']);
|
||||
$dtstart = new \DateTime($start);
|
||||
if($_REQUEST['dtend']) {
|
||||
$end = datetime_convert('UTC', 'UTC', $_REQUEST['dtend']);
|
||||
$dtend = new \DateTime($end);
|
||||
}
|
||||
|
||||
$object = $caldavBackend->getCalendarObject($id, $uri);
|
||||
|
||||
@@ -413,13 +455,20 @@ class Cdav extends Controller {
|
||||
|
||||
if($dtstart) {
|
||||
$vcalendar->VEVENT->DTSTART = $dtstart;
|
||||
if($allday)
|
||||
$vcalendar->VEVENT->DTSTART['VALUE'] = 'DATE';
|
||||
else
|
||||
$vcalendar->VEVENT->DTSTART['TZID'] = $tz;
|
||||
}
|
||||
if($dtend) {
|
||||
$vcalendar->VEVENT->DTEND = $dtend;
|
||||
if($allday)
|
||||
$vcalendar->VEVENT->DTEND['VALUE'] = 'DATE';
|
||||
else
|
||||
$vcalendar->VEVENT->DTEND['TZID'] = $tz;
|
||||
}
|
||||
else {
|
||||
else
|
||||
unset($vcalendar->VEVENT->DTEND);
|
||||
}
|
||||
|
||||
$calendarData = $vcalendar->serialize();
|
||||
|
||||
@@ -747,16 +796,27 @@ class Cdav extends Controller {
|
||||
//Import calendar or addressbook
|
||||
if(($_FILES) && array_key_exists('userfile',$_FILES) && intval($_FILES['userfile']['size']) && $_REQUEST['target']) {
|
||||
|
||||
$src = @file_get_contents($_FILES['userfile']['tmp_name']);
|
||||
$src = $_FILES['userfile']['tmp_name'];
|
||||
|
||||
if($src) {
|
||||
|
||||
if($_REQUEST['c_upload']) {
|
||||
if($_REQUEST['target'] == 'channel_calendar') {
|
||||
$result = parse_ical_file($src,local_channel());
|
||||
if($result)
|
||||
info( t('Calendar entries imported.') . EOL);
|
||||
else
|
||||
notice( t('No calendar entries found.') . EOL);
|
||||
|
||||
@unlink($src);
|
||||
return;
|
||||
}
|
||||
|
||||
$id = explode(':', $_REQUEST['target']);
|
||||
$ext = 'ics';
|
||||
$table = 'calendarobjects';
|
||||
$column = 'calendarid';
|
||||
$objects = new \Sabre\VObject\Splitter\ICalendar($src);
|
||||
$objects = new \Sabre\VObject\Splitter\ICalendar(@file_get_contents($src));
|
||||
$profile = \Sabre\VObject\Node::PROFILE_CALDAV;
|
||||
$backend = new \Sabre\CalDAV\Backend\PDO($pdo);
|
||||
}
|
||||
@@ -766,7 +826,7 @@ class Cdav extends Controller {
|
||||
$ext = 'vcf';
|
||||
$table = 'cards';
|
||||
$column = 'addressbookid';
|
||||
$objects = new \Sabre\VObject\Splitter\VCard($src);
|
||||
$objects = new \Sabre\VObject\Splitter\VCard(@file_get_contents($src));
|
||||
$profile = \Sabre\VObject\Node::PROFILE_CARDDAV;
|
||||
$backend = new \Sabre\CardDAV\Backend\PDO($pdo);
|
||||
}
|
||||
@@ -832,15 +892,6 @@ class Cdav extends Controller {
|
||||
if(!local_channel())
|
||||
return;
|
||||
|
||||
if((argv(1) === 'calendar') && (! Apps::system_app_installed(local_channel(), 'CalDAV'))) {
|
||||
//Do not display any associated widgets at this point
|
||||
App::$pdl = '';
|
||||
|
||||
$o = '<b>' . t('CalDAV App') . ' (' . t('Not Installed') . '):</b><br>';
|
||||
$o .= t('CalDAV capable calendar');
|
||||
return $o;
|
||||
}
|
||||
|
||||
if((argv(1) === 'addressbook') && (! Apps::system_app_installed(local_channel(), 'CardDAV'))) {
|
||||
//Do not display any associated widgets at this point
|
||||
App::$pdl = '';
|
||||
@@ -869,28 +920,98 @@ class Cdav extends Controller {
|
||||
}
|
||||
|
||||
if(argv(1) === 'calendar') {
|
||||
nav_set_selected('CalDAV');
|
||||
nav_set_selected('Calendar');
|
||||
$caldavBackend = new \Sabre\CalDAV\Backend\PDO($pdo);
|
||||
$calendars = $caldavBackend->getCalendarsForUser($principalUri);
|
||||
}
|
||||
|
||||
//Display calendar(s) here
|
||||
if(argc() == 2 && argv(1) === 'calendar') {
|
||||
if(argc() <= 3 && argv(1) === 'calendar') {
|
||||
|
||||
head_add_css('/library/fullcalendar/fullcalendar.css');
|
||||
head_add_css('/library/fullcalendar/packages/core/main.min.css');
|
||||
head_add_css('/library/fullcalendar/packages/daygrid/main.min.css');
|
||||
head_add_css('/library/fullcalendar/packages/timegrid/main.min.css');
|
||||
head_add_css('/library/fullcalendar/packages/list/main.min.css');
|
||||
head_add_css('cdav_calendar.css');
|
||||
|
||||
head_add_js('/library/moment/moment.min.js', 1);
|
||||
head_add_js('/library/fullcalendar/fullcalendar.min.js', 1);
|
||||
head_add_js('/library/fullcalendar/locale-all.js', 1);
|
||||
head_add_js('/library/fullcalendar/packages/core/main.min.js');
|
||||
head_add_js('/library/fullcalendar/packages/interaction/main.min.js');
|
||||
head_add_js('/library/fullcalendar/packages/daygrid/main.min.js');
|
||||
head_add_js('/library/fullcalendar/packages/timegrid/main.min.js');
|
||||
head_add_js('/library/fullcalendar/packages/list/main.min.js');
|
||||
|
||||
$sources = '';
|
||||
$resource_id = '';
|
||||
$resource = null;
|
||||
|
||||
if(argc() == 3)
|
||||
$resource_id = argv(2);
|
||||
|
||||
if($resource_id) {
|
||||
$r = q("SELECT event.*, item.author_xchan, item.owner_xchan, item.plink, item.id as item_id FROM event LEFT JOIN item ON event.event_hash = item.resource_id
|
||||
WHERE event.uid = %d AND event.event_hash = '%s' LIMIT 1",
|
||||
intval(local_channel()),
|
||||
dbesc($resource_id)
|
||||
);
|
||||
if($r) {
|
||||
xchan_query($r);
|
||||
$r = fetch_post_tags($r,true);
|
||||
|
||||
$tz = get_iconfig($r[0], 'event', 'timezone');
|
||||
if(! $tz)
|
||||
$tz = 'UTC';
|
||||
|
||||
$r[0]['timezone'] = $tz;
|
||||
$r[0]['dtstart'] = (($r[0]['adjust']) ? datetime_convert('UTC', date_default_timezone_get(), $r[0]['dtstart'], 'c') : datetime_convert('UTC', 'UTC', $r[0]['dtstart'], 'c'));
|
||||
$r[0]['dtend'] = (($r[0]['adjust']) ? datetime_convert('UTC', date_default_timezone_get(), $r[0]['dtend'], 'c') : datetime_convert('UTC', 'UTC' ,$r[0]['dtend'], 'c'));
|
||||
|
||||
$r[0]['plink'] = [$r[0]['plink'], t('Link to source')];
|
||||
|
||||
$resource = $r[0];
|
||||
|
||||
$catsenabled = feature_enabled(local_channel(),'categories');
|
||||
$categories = '';
|
||||
if($catsenabled){
|
||||
if($r[0]['term']) {
|
||||
$cats = get_terms_oftype($r[0]['term'], TERM_CATEGORY);
|
||||
foreach ($cats as $cat) {
|
||||
if(strlen($categories))
|
||||
$categories .= ', ';
|
||||
$categories .= $cat['term'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if($r[0]['dismissed'] == 0) {
|
||||
q("UPDATE event SET dismissed = 1 WHERE event.uid = %d AND event.event_hash = '%s'",
|
||||
intval(local_channel()),
|
||||
dbesc($resource_id)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(get_pconfig(local_channel(), 'cdav_calendar', 'channel_calendar')) {
|
||||
$sources .= '{
|
||||
id: \'channel_calendar\',
|
||||
url: \'/channel_calendar/json/\',
|
||||
color: \'#3a87ad\'
|
||||
}, ';
|
||||
}
|
||||
|
||||
$channel_calendars[] = [
|
||||
'displayname' => $channel['channel_name'],
|
||||
'id' => 'channel_calendar'
|
||||
];
|
||||
|
||||
foreach($calendars as $calendar) {
|
||||
$editable = (($calendar['share-access'] == 2) ? 'false' : 'true'); // false/true must be string since we're passing it to javascript
|
||||
$color = (($calendar['{http://apple.com/ns/ical/}calendar-color']) ? $calendar['{http://apple.com/ns/ical/}calendar-color'] : '#3a87ad');
|
||||
$color = (($calendar['{http://apple.com/ns/ical/}calendar-color']) ? $calendar['{http://apple.com/ns/ical/}calendar-color'] : '#6cad39');
|
||||
$sharer = (($calendar['share-access'] == 3) ? $calendar['{urn:ietf:params:xml:ns:caldav}calendar-description'] : '');
|
||||
$switch = get_pconfig(local_channel(), 'cdav_calendar', $calendar['id'][0]);
|
||||
if($switch) {
|
||||
$sources .= '{
|
||||
id: ' . $calendar['id'][0] . ',
|
||||
url: \'/cdav/calendar/json/' . $calendar['id'][0] . '/' . $calendar['id'][1] . '\',
|
||||
color: \'' . $color . '\'
|
||||
}, ';
|
||||
@@ -910,16 +1031,31 @@ class Cdav extends Controller {
|
||||
$first_day = feature_enabled(local_channel(), 'cal_first_day');
|
||||
$first_day = (($first_day) ? $first_day : 0);
|
||||
|
||||
$title = ['title', t('Event title')];
|
||||
$dtstart = ['dtstart', t('Start date and time'), '', t('Example: YYYY-MM-DD HH:mm')];
|
||||
$dtend = ['dtend', t('End date and time'), '', t('Example: YYYY-MM-DD HH:mm')];
|
||||
$title = ['title', t('Event title') ];
|
||||
$dtstart = ['dtstart', t('Start date and time')];
|
||||
$dtend = ['dtend', t('End date and time')];
|
||||
$timezone_select = ['timezone_select' , t('Timezone:'), date_default_timezone_get(), '', get_timezones()];
|
||||
|
||||
$description = ['description', t('Description')];
|
||||
$location = ['location', t('Location')];
|
||||
|
||||
$catsenabled = feature_enabled(local_channel(), 'categories');
|
||||
|
||||
require_once('include/acl_selectors.php');
|
||||
|
||||
$accesslist = new \Zotlabs\Access\AccessList($channel);
|
||||
$perm_defaults = $accesslist->get();
|
||||
|
||||
//$acl = (($orig_event['event_xchan']) ? '' : populate_acl(((x($orig_event)) ? $orig_event : $perm_defaults), false, \Zotlabs\Lib\PermissionDescription::fromGlobalPermission('view_stream')));
|
||||
$acl = populate_acl($perm_defaults, false, \Zotlabs\Lib\PermissionDescription::fromGlobalPermission('view_stream'));
|
||||
|
||||
$permissions = (($resource_id) ? $resource : $perm_defaults);
|
||||
|
||||
$o .= replace_macros(get_markup_template('cdav_calendar.tpl'), [
|
||||
'$sources' => $sources,
|
||||
'$color' => $color,
|
||||
'$lang' => App::$language,
|
||||
'$timezone' => date_default_timezone_get(),
|
||||
'$first_day' => $first_day,
|
||||
'$prev' => t('Previous'),
|
||||
'$next' => t('Next'),
|
||||
@@ -931,6 +1067,7 @@ class Cdav extends Controller {
|
||||
'$list_week' => t('List week'),
|
||||
'$list_day' => t('List day'),
|
||||
'$title' => $title,
|
||||
'$channel_calendars' => $channel_calendars,
|
||||
'$writable_calendars' => $writable_calendars,
|
||||
'$dtstart' => $dtstart,
|
||||
'$dtend' => $dtend,
|
||||
@@ -938,11 +1075,28 @@ class Cdav extends Controller {
|
||||
'$location' => $location,
|
||||
'$more' => t('More'),
|
||||
'$less' => t('Less'),
|
||||
'$update' => t('Update'),
|
||||
'$calendar_select_label' => t('Select calendar'),
|
||||
'$calendar_optiopns_label' => [t('Channel Calendars'), t('CalDAV Calendars')],
|
||||
'$delete' => t('Delete'),
|
||||
'$delete_all' => t('Delete all'),
|
||||
'$cancel' => t('Cancel'),
|
||||
'$recurrence_warning' => t('Sorry! Editing of recurrent events is not yet implemented.')
|
||||
'$create' => t('Create'),
|
||||
'$recurrence_warning' => t('Sorry! Editing of recurrent events is not yet implemented.'),
|
||||
|
||||
'$channel_hash' => $channel['channel_hash'],
|
||||
'$acl' => $acl,
|
||||
'$lockstate' => (($accesslist->is_private()) ? 'lock' : 'unlock'),
|
||||
'$allow_cid' => acl2json($permissions['allow_cid']),
|
||||
'$allow_gid' => acl2json($permissions['allow_gid']),
|
||||
'$deny_cid' => acl2json($permissions['deny_cid']),
|
||||
'$deny_gid' => acl2json($permissions['deny_gid']),
|
||||
'$catsenabled' => $catsenabled,
|
||||
'$categories_label' => t('Categories'),
|
||||
|
||||
'$resource' => json_encode($resource),
|
||||
'$categories' => $categories,
|
||||
'$timezone_select' => ((feature_enabled(local_channel(),'event_tz_select')) ? $timezone_select : '')
|
||||
]);
|
||||
|
||||
return $o;
|
||||
@@ -952,10 +1106,12 @@ class Cdav extends Controller {
|
||||
//Provide json data for calendar
|
||||
if(argc() == 5 && argv(1) === 'calendar' && argv(2) === 'json' && intval(argv(3)) && intval(argv(4))) {
|
||||
|
||||
$events = [];
|
||||
|
||||
$id = [argv(3), argv(4)];
|
||||
|
||||
if(! cdav_perms($id[0],$calendars))
|
||||
killme();
|
||||
json_return_and_die($events);
|
||||
|
||||
if (x($_GET,'start'))
|
||||
$start = new \DateTime($_GET['start']);
|
||||
@@ -972,13 +1128,16 @@ class Cdav extends Controller {
|
||||
if($uris) {
|
||||
|
||||
$objects = $caldavBackend->getMultipleCalendarObjects($id, $uris);
|
||||
|
||||
foreach($objects as $object) {
|
||||
|
||||
$vcalendar = \Sabre\VObject\Reader::read($object['calendardata']);
|
||||
|
||||
if(isset($vcalendar->VEVENT->RRULE))
|
||||
if(isset($vcalendar->VEVENT->RRULE)) {
|
||||
// expanding recurrent events seems to loose timezone info
|
||||
// save it here so we can add it later
|
||||
$recurrent_timezone = (string)$vcalendar->VEVENT->DTSTART['TZID'];
|
||||
$vcalendar = $vcalendar->expand($start, $end);
|
||||
}
|
||||
|
||||
foreach($vcalendar->VEVENT as $vevent) {
|
||||
$title = (string)$vevent->SUMMARY;
|
||||
@@ -986,29 +1145,33 @@ class Cdav extends Controller {
|
||||
$dtend = (string)$vevent->DTEND;
|
||||
$description = (string)$vevent->DESCRIPTION;
|
||||
$location = (string)$vevent->LOCATION;
|
||||
|
||||
$timezone_str = (string)$vevent->DTSTART['TZID'];
|
||||
$rw = ((cdav_perms($id[0],$calendars,true)) ? true : false);
|
||||
$editable = $rw ? true : false;
|
||||
$recurrent = ((isset($vevent->{'RECURRENCE-ID'})) ? true : false);
|
||||
|
||||
$editable = $rw ? true : false;
|
||||
|
||||
if($recurrent)
|
||||
if($recurrent) {
|
||||
$editable = false;
|
||||
$timezone_str = $recurrent_timezone;
|
||||
}
|
||||
|
||||
$allDay = false;
|
||||
// Try to get an usable olson format timezone
|
||||
$timezone_obj = \Sabre\VObject\TimeZoneUtil::getTimeZone($timezone_str, $vcalendar);
|
||||
$timezone = $timezone_obj->getName();
|
||||
|
||||
// allDay event rules
|
||||
if(!strpos($dtstart, 'T') && !strpos($dtend, 'T'))
|
||||
$allDay = true;
|
||||
if(strpos($dtstart, 'T000000') && strpos($dtend, 'T000000'))
|
||||
$allDay = true;
|
||||
// If we got nothing fallback to UTC
|
||||
if(! $timezone)
|
||||
$timezone = 'UTC';
|
||||
|
||||
$allDay = (((string)$vevent->DTSTART['VALUE'] == 'DATE') ? true : false);
|
||||
|
||||
$events[] = [
|
||||
'calendar_id' => $id,
|
||||
'uri' => $object['uri'],
|
||||
'title' => $title,
|
||||
'start' => $dtstart,
|
||||
'end' => $dtend,
|
||||
'timezone' => $timezone,
|
||||
'start' => datetime_convert($timezone, date_default_timezone_get(), $dtstart, 'c'),
|
||||
'end' => (($dtend) ? datetime_convert($timezone, date_default_timezone_get(), $dtend, 'c') : ''),
|
||||
'description' => $description,
|
||||
'location' => $location,
|
||||
'allDay' => $allDay,
|
||||
@@ -1018,15 +1181,12 @@ class Cdav extends Controller {
|
||||
];
|
||||
}
|
||||
}
|
||||
json_return_and_die($events);
|
||||
}
|
||||
else {
|
||||
killme();
|
||||
}
|
||||
json_return_and_die($events);
|
||||
}
|
||||
|
||||
//enable/disable calendars
|
||||
if(argc() == 5 && argv(1) === 'calendar' && argv(2) === 'switch' && intval(argv(3)) && (argv(4) == 1 || argv(4) == 0)) {
|
||||
if(argc() == 5 && argv(1) === 'calendar' && argv(2) === 'switch' && argv(3) && (argv(4) == 1 || argv(4) == 0)) {
|
||||
$id = argv(3);
|
||||
|
||||
if(! cdav_perms($id,$calendars))
|
||||
@@ -1285,12 +1445,13 @@ class Cdav extends Controller {
|
||||
$caldavBackend = new \Sabre\CalDAV\Backend\PDO($pdo);
|
||||
$properties = [
|
||||
'{DAV:}displayname' => t('Default Calendar'),
|
||||
'{http://apple.com/ns/ical/}calendar-color' => '#3a87ad',
|
||||
'{http://apple.com/ns/ical/}calendar-color' => '#6cad39',
|
||||
'{urn:ietf:params:xml:ns:caldav}calendar-description' => $channel['channel_name']
|
||||
];
|
||||
|
||||
$id = $caldavBackend->createCalendar($uri, 'default', $properties);
|
||||
set_pconfig(local_channel(), 'cdav_calendar' , $id[0], 1);
|
||||
set_pconfig(local_channel(), 'cdav_calendar' , 'channel_calendar', 1);
|
||||
|
||||
//create default addressbook
|
||||
$carddavBackend = new \Sabre\CardDAV\Backend\PDO($pdo);
|
||||
|
||||
@@ -31,7 +31,7 @@ class Changeaddr extends \Zotlabs\Web\Controller {
|
||||
|
||||
if($account['account_password_changed'] > NULL_DATE) {
|
||||
$d1 = datetime_convert('UTC','UTC','now - 48 hours');
|
||||
if($account['account_password_changed'] > d1) {
|
||||
if($account['account_password_changed'] > $d1) {
|
||||
notice( t('Channel name changes are not allowed within 48 hours of changing the account password.') . EOL);
|
||||
return;
|
||||
}
|
||||
@@ -49,7 +49,7 @@ class Changeaddr extends \Zotlabs\Web\Controller {
|
||||
|
||||
if(check_webbie(array($new_address)) !== $new_address) {
|
||||
notice( t('Nickname has unsupported characters or is already being used on this site.') . EOL);
|
||||
return $ret;
|
||||
return;
|
||||
}
|
||||
|
||||
channel_change_address($channel,$new_address);
|
||||
|
||||
@@ -6,6 +6,8 @@ namespace Zotlabs\Module;
|
||||
use App;
|
||||
use Zotlabs\Web\Controller;
|
||||
use Zotlabs\Lib\PermissionDescription;
|
||||
use Zotlabs\Web\HTTPSig;
|
||||
use Zotlabs\Lib\Libzot;
|
||||
|
||||
require_once('include/items.php');
|
||||
require_once('include/security.php');
|
||||
@@ -43,6 +45,48 @@ class Channel extends Controller {
|
||||
$profile = 0;
|
||||
$channel = App::get_channel();
|
||||
|
||||
if((local_channel()) && (argc() > 2) && (argv(2) === 'view')) {
|
||||
$which = $channel['channel_address'];
|
||||
$profile = argv(1);
|
||||
}
|
||||
|
||||
$channel = channelx_by_nick($which);
|
||||
if(! $channel) {
|
||||
http_status_exit(404, 'Not found');
|
||||
}
|
||||
|
||||
// handle zot6 channel discovery
|
||||
|
||||
if(Libzot::is_zot_request()) {
|
||||
|
||||
$sigdata = HTTPSig::verify(file_get_contents('php://input'));
|
||||
|
||||
if($sigdata && $sigdata['signer'] && $sigdata['header_valid']) {
|
||||
$data = json_encode(Libzot::zotinfo([ 'address' => $channel['channel_address'], 'target_url' => $sigdata['signer'] ]));
|
||||
$s = q("select site_crypto, hubloc_sitekey from site left join hubloc on hubloc_url = site_url where hubloc_id_url = '%s' and hubloc_network = 'zot6' limit 1",
|
||||
dbesc($sigdata['signer'])
|
||||
);
|
||||
|
||||
if($s) {
|
||||
$data = json_encode(crypto_encapsulate($data,$s[0]['hubloc_sitekey'],Libzot::best_algorithm($s[0]['site_crypto'])));
|
||||
}
|
||||
}
|
||||
else {
|
||||
$data = json_encode(Libzot::zotinfo([ 'address' => $channel['channel_address'] ]));
|
||||
}
|
||||
|
||||
$headers = [
|
||||
'Content-Type' => 'application/x-zot+json',
|
||||
'Digest' => HTTPSig::generate_digest_header($data),
|
||||
'(request-target)' => strtolower($_SERVER['REQUEST_METHOD']) . ' ' . $_SERVER['REQUEST_URI']
|
||||
];
|
||||
$h = HTTPSig::create_sig($headers,$channel['channel_prvkey'],channel_url($channel));
|
||||
HTTPSig::set_headers($h);
|
||||
echo $data;
|
||||
killme();
|
||||
}
|
||||
|
||||
|
||||
if((local_channel()) && (argc() > 2) && (argv(2) === 'view')) {
|
||||
$which = $channel['channel_address'];
|
||||
$profile = argv(1);
|
||||
@@ -67,6 +111,17 @@ class Channel extends Controller {
|
||||
// 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";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function get($update = 0, $load = false) {
|
||||
@@ -266,10 +321,6 @@ class Channel extends Controller {
|
||||
$sql_extra2 .= protect_sprintf(sprintf(" AND item.created >= '%s' ", dbesc(datetime_convert(date_default_timezone_get(),'',$datequery2))));
|
||||
}
|
||||
|
||||
if($datequery || $datequery2) {
|
||||
$sql_extra2 .= " and item.item_thread_top != 0 ";
|
||||
}
|
||||
|
||||
if($order === 'post')
|
||||
$ordering = "created";
|
||||
else
|
||||
@@ -298,7 +349,7 @@ class Channel extends Controller {
|
||||
AND (abook.abook_blocked = 0 or abook.abook_flags is null)
|
||||
AND item.item_wall = 1 AND item.item_thread_top = 1
|
||||
$sql_extra $sql_extra2
|
||||
ORDER BY $ordering DESC $pager_sql ",
|
||||
ORDER BY $ordering DESC, item_id $pager_sql ",
|
||||
intval(App::$profile['profile_uid'])
|
||||
);
|
||||
}
|
||||
@@ -370,12 +421,12 @@ class Channel extends Controller {
|
||||
'$page' => ((App::$pager['page'] != 1) ? App::$pager['page'] : 1),
|
||||
'$search' => $search,
|
||||
'$xchan' => '',
|
||||
'$order' => $order,
|
||||
'$order' => (($order) ? urlencode($order) : ''),
|
||||
'$list' => ((x($_REQUEST,'list')) ? intval($_REQUEST['list']) : 0),
|
||||
'$file' => '',
|
||||
'$cats' => (($category) ? urlencode($category) : ''),
|
||||
'$tags' => (($hashtags) ? urlencode($hashtags) : ''),
|
||||
'$mid' => $mid,
|
||||
'$mid' => (($mid) ? urlencode($mid) : ''),
|
||||
'$verb' => '',
|
||||
'$net' => '',
|
||||
'$dend' => $datequery,
|
||||
|
||||
495
Zotlabs/Module/Channel_calendar.php
Normal file
495
Zotlabs/Module/Channel_calendar.php
Normal file
@@ -0,0 +1,495 @@
|
||||
<?php
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
require_once('include/conversation.php');
|
||||
require_once('include/bbcode.php');
|
||||
require_once('include/datetime.php');
|
||||
require_once('include/event.php');
|
||||
require_once('include/items.php');
|
||||
require_once('include/html2plain.php');
|
||||
|
||||
class Channel_calendar extends \Zotlabs\Web\Controller {
|
||||
|
||||
function post() {
|
||||
|
||||
logger('post: ' . print_r($_REQUEST,true), LOGGER_DATA);
|
||||
|
||||
if(! local_channel())
|
||||
return;
|
||||
|
||||
$event_id = ((x($_POST,'event_id')) ? intval($_POST['event_id']) : 0);
|
||||
$event_hash = ((x($_POST,'event_hash')) ? $_POST['event_hash'] : '');
|
||||
|
||||
$xchan = ((x($_POST,'xchan')) ? dbesc($_POST['xchan']) : '');
|
||||
$uid = local_channel();
|
||||
|
||||
// only allow editing your own events.
|
||||
if(($xchan) && ($xchan !== get_observer_hash()))
|
||||
return;
|
||||
|
||||
$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']));
|
||||
|
||||
$summary = escape_tags(trim($_POST['summary']));
|
||||
$desc = escape_tags(trim($_POST['desc']));
|
||||
$location = escape_tags(trim($_POST['location']));
|
||||
$type = escape_tags(trim($_POST['type']));
|
||||
|
||||
// Don't allow the event to finish before it begins.
|
||||
// It won't hurt anything, but somebody will file a bug report
|
||||
// and we'll waste a bunch of time responding to it. Time that
|
||||
// could've been spent doing something else.
|
||||
|
||||
if(strcmp($finish,$start) < 0 && !$nofinish) {
|
||||
notice( t('Event can not end before it has started.') . EOL);
|
||||
if(intval($_REQUEST['preview'])) {
|
||||
echo( t('Unable to generate preview.'));
|
||||
}
|
||||
killme();
|
||||
}
|
||||
|
||||
if((! $summary) || (! $start)) {
|
||||
notice( t('Event title and start time are required.') . EOL);
|
||||
if(intval($_REQUEST['preview'])) {
|
||||
echo( t('Unable to generate preview.'));
|
||||
}
|
||||
killme();
|
||||
}
|
||||
|
||||
$channel = \App::get_channel();
|
||||
|
||||
$acl = new \Zotlabs\Access\AccessList(false);
|
||||
|
||||
if($event_id) {
|
||||
$x = q("select * from event where id = %d and uid = %d limit 1",
|
||||
intval($event_id),
|
||||
intval(local_channel())
|
||||
);
|
||||
if(! $x) {
|
||||
notice( t('Event not found.') . EOL);
|
||||
if(intval($_REQUEST['preview'])) {
|
||||
echo( t('Unable to generate preview.'));
|
||||
killme();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
$acl->set($x[0]);
|
||||
|
||||
$created = $x[0]['created'];
|
||||
$edited = datetime_convert();
|
||||
}
|
||||
else {
|
||||
$created = $edited = datetime_convert();
|
||||
$acl->set_from_array($_POST);
|
||||
}
|
||||
|
||||
$post_tags = array();
|
||||
$channel = \App::get_channel();
|
||||
$ac = $acl->get();
|
||||
|
||||
$str_contact_allow = $ac['allow_cid'];
|
||||
$str_group_allow = $ac['allow_gid'];
|
||||
$str_contact_deny = $ac['deny_cid'];
|
||||
$str_group_deny = $ac['deny_gid'];
|
||||
|
||||
$private = $acl->is_private();
|
||||
|
||||
require_once('include/text.php');
|
||||
$results = linkify_tags($desc, local_channel());
|
||||
|
||||
if($results) {
|
||||
// Set permissions based on tag replacements
|
||||
set_linkified_perms($results, $str_contact_allow, $str_group_allow, local_channel(), false, $private);
|
||||
|
||||
foreach($results as $result) {
|
||||
$success = $result['success'];
|
||||
if($success['replaced']) {
|
||||
$post_tags[] = array(
|
||||
'uid' => local_channel(),
|
||||
'ttype' => $success['termtype'],
|
||||
'otype' => TERM_OBJ_POST,
|
||||
'term' => $success['term'],
|
||||
'url' => $success['url']
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(strlen($categories)) {
|
||||
$cats = explode(',',$categories);
|
||||
foreach($cats as $cat) {
|
||||
$post_tags[] = array(
|
||||
'uid' => local_channel(),
|
||||
'ttype' => TERM_CATEGORY,
|
||||
'otype' => TERM_OBJ_POST,
|
||||
'term' => trim($cat),
|
||||
'url' => $channel['xchan_url'] . '?f=&cat=' . urlencode(trim($cat))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$datarray = array();
|
||||
$datarray['dtstart'] = $start;
|
||||
$datarray['dtend'] = $finish;
|
||||
$datarray['summary'] = $summary;
|
||||
$datarray['description'] = $desc;
|
||||
$datarray['location'] = $location;
|
||||
$datarray['etype'] = $type;
|
||||
$datarray['adjust'] = $adjust;
|
||||
$datarray['nofinish'] = 0;
|
||||
$datarray['uid'] = local_channel();
|
||||
$datarray['account'] = get_account_id();
|
||||
$datarray['event_xchan'] = $channel['channel_hash'];
|
||||
$datarray['allow_cid'] = $str_contact_allow;
|
||||
$datarray['allow_gid'] = $str_group_allow;
|
||||
$datarray['deny_cid'] = $str_contact_deny;
|
||||
$datarray['deny_gid'] = $str_group_deny;
|
||||
$datarray['private'] = intval($private);
|
||||
$datarray['id'] = $event_id;
|
||||
$datarray['created'] = $created;
|
||||
$datarray['edited'] = $edited;
|
||||
$datarray['timezone'] = $tz;
|
||||
|
||||
|
||||
if(intval($_REQUEST['preview'])) {
|
||||
$html = format_event_html($datarray);
|
||||
echo $html;
|
||||
killme();
|
||||
}
|
||||
|
||||
$event = event_store_event($datarray);
|
||||
|
||||
if($post_tags)
|
||||
$datarray['term'] = $post_tags;
|
||||
|
||||
$item_id = event_store_item($datarray,$event);
|
||||
|
||||
if($item_id) {
|
||||
$r = q("select * from item where id = %d",
|
||||
intval($item_id)
|
||||
);
|
||||
if($r) {
|
||||
xchan_query($r);
|
||||
$sync_item = fetch_post_tags($r);
|
||||
$z = q("select * from event where event_hash = '%s' and uid = %d limit 1",
|
||||
dbesc($r[0]['resource_id']),
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
if($z) {
|
||||
build_sync_packet($channel['channel_id'],array('event_item' => array(encode_item($sync_item[0],true)),'event' => $z));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
\Zotlabs\Daemon\Master::Summon(array('Notifier','event',$item_id));
|
||||
|
||||
killme();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
function get() {
|
||||
|
||||
if(argc() > 2 && argv(1) == 'ical') {
|
||||
$event_id = argv(2);
|
||||
|
||||
require_once('include/security.php');
|
||||
$sql_extra = permissions_sql(local_channel());
|
||||
|
||||
$r = q("select * from event where event_hash = '%s' $sql_extra limit 1",
|
||||
dbesc($event_id)
|
||||
);
|
||||
if($r) {
|
||||
header('Content-type: text/calendar');
|
||||
header('content-disposition: attachment; filename="' . t('event') . '-' . $event_id . '.ics"' );
|
||||
echo ical_wrapper($r);
|
||||
killme();
|
||||
}
|
||||
else {
|
||||
notice( t('Event not found.') . EOL );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(! local_channel()) {
|
||||
notice( t('Permission denied.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
if((argc() > 2) && (argv(1) === 'ignore') && intval(argv(2))) {
|
||||
$r = q("update event set dismissed = 1 where id = %d and uid = %d",
|
||||
intval(argv(2)),
|
||||
intval(local_channel())
|
||||
);
|
||||
}
|
||||
|
||||
if((argc() > 2) && (argv(1) === 'unignore') && intval(argv(2))) {
|
||||
$r = q("update event set dismissed = 0 where id = %d and uid = %d",
|
||||
intval(argv(2)),
|
||||
intval(local_channel())
|
||||
);
|
||||
}
|
||||
|
||||
$channel = \App::get_channel();
|
||||
|
||||
$mode = 'view';
|
||||
$export = false;
|
||||
$ignored = ((x($_REQUEST,'ignored')) ? " and dismissed = " . intval($_REQUEST['ignored']) . " " : '');
|
||||
|
||||
if(argc() > 1) {
|
||||
if(argc() > 2 && argv(1) === 'add') {
|
||||
$mode = 'add';
|
||||
$item_id = intval(argv(2));
|
||||
}
|
||||
if(argc() > 2 && argv(1) === 'drop') {
|
||||
$mode = 'drop';
|
||||
$event_id = argv(2);
|
||||
}
|
||||
if(argc() <= 2 && argv(1) === 'export') {
|
||||
$export = true;
|
||||
}
|
||||
if(argc() > 2 && intval(argv(1)) && intval(argv(2))) {
|
||||
$mode = 'view';
|
||||
}
|
||||
if(argc() <= 2) {
|
||||
$mode = 'view';
|
||||
$event_id = argv(1);
|
||||
}
|
||||
}
|
||||
|
||||
if($mode === 'add') {
|
||||
event_addtocal($item_id,local_channel());
|
||||
killme();
|
||||
}
|
||||
|
||||
if($mode == 'view') {
|
||||
|
||||
/* edit/create form */
|
||||
if($event_id) {
|
||||
$r = q("SELECT * FROM event WHERE event_hash = '%s' AND uid = %d LIMIT 1",
|
||||
dbesc($event_id),
|
||||
intval(local_channel())
|
||||
);
|
||||
if(count($r))
|
||||
$orig_event = $r[0];
|
||||
}
|
||||
|
||||
$channel = \App::get_channel();
|
||||
|
||||
if (argv(1) === 'json'){
|
||||
if (x($_GET,'start')) $start = $_GET['start'];
|
||||
if (x($_GET,'end')) $finish = $_GET['end'];
|
||||
}
|
||||
|
||||
$start = datetime_convert('UTC','UTC',$start);
|
||||
$finish = datetime_convert('UTC','UTC',$finish);
|
||||
$adjust_start = datetime_convert('UTC', date_default_timezone_get(), $start);
|
||||
$adjust_finish = datetime_convert('UTC', date_default_timezone_get(), $finish);
|
||||
|
||||
if (x($_GET,'id')){
|
||||
$r = q("SELECT event.*, item.plink, item.item_flags, item.author_xchan, item.owner_xchan, item.id as item_id
|
||||
from event left join item on item.resource_id = event.event_hash
|
||||
where item.resource_type = 'event' and event.uid = %d and event.id = %d limit 1",
|
||||
intval(local_channel()),
|
||||
intval($_GET['id'])
|
||||
);
|
||||
}
|
||||
elseif($export) {
|
||||
$r = q("SELECT event.*, item.id as item_id
|
||||
from event left join item on item.resource_id = event.event_hash
|
||||
where event.uid = %d and event.dtstart > '%s' and event.dtend > event.dtstart",
|
||||
intval(local_channel()),
|
||||
dbesc(NULL_DATE)
|
||||
);
|
||||
}
|
||||
else {
|
||||
// fixed an issue with "nofinish" events not showing up in the calendar.
|
||||
// There's still an issue if the finish date crosses the end of month.
|
||||
// Noting this for now - it will need to be fixed here and in Friendica.
|
||||
// Ultimately the finish date shouldn't be involved in the query.
|
||||
|
||||
$r = q("SELECT event.*, item.plink, item.item_flags, item.author_xchan, item.owner_xchan, item.id as item_id
|
||||
from event left join item on event.event_hash = item.resource_id
|
||||
where item.resource_type = 'event' and event.uid = %d and event.uid = item.uid $ignored
|
||||
AND (( event.adjust = 0 AND ( event.dtend >= '%s' or event.nofinish = 1 ) AND event.dtstart <= '%s' )
|
||||
OR ( event.adjust = 1 AND ( event.dtend >= '%s' or event.nofinish = 1 ) AND event.dtstart <= '%s' )) ",
|
||||
intval(local_channel()),
|
||||
dbesc($start),
|
||||
dbesc($finish),
|
||||
dbesc($adjust_start),
|
||||
dbesc($adjust_finish)
|
||||
);
|
||||
}
|
||||
|
||||
if($r && ! $export) {
|
||||
xchan_query($r);
|
||||
$r = fetch_post_tags($r,true);
|
||||
$r = sort_by_date($r);
|
||||
}
|
||||
|
||||
$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'));
|
||||
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'));
|
||||
}
|
||||
|
||||
$catsenabled = feature_enabled(local_channel(),'categories');
|
||||
$categories = '';
|
||||
if($catsenabled){
|
||||
if($rr['term']) {
|
||||
$cats = get_terms_oftype($rr['term'], TERM_CATEGORY);
|
||||
foreach ($cats as $cat) {
|
||||
if(strlen($categories))
|
||||
$categories .= ', ';
|
||||
$categories .= $cat['term'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$edit = ((local_channel() && $rr['author_xchan'] == get_observer_hash()) ? array(z_root().'/events/'.$rr['event_hash'].'?expandform=1',t('Edit event'),'','') : false);
|
||||
|
||||
$drop = array(z_root().'/events/drop/'.$rr['event_hash'],t('Delete event'),'','');
|
||||
|
||||
$events[] = array(
|
||||
'calendar_id' => 'channel_calendar',
|
||||
'rw' => true,
|
||||
'id'=>$rr['id'],
|
||||
'uri' => $rr['event_hash'],
|
||||
'timezone' => $tz,
|
||||
'start'=> $start,
|
||||
'end' => $end,
|
||||
'drop' => $drop,
|
||||
'allDay' => (($rr['adjust']) ? 0 : 1),
|
||||
'title' => html_entity_decode($rr['summary'], ENT_COMPAT, 'UTF-8'),
|
||||
'editable' => $edit ? true : false,
|
||||
'item' => $rr,
|
||||
'plink' => [$rr['plink'], t('Link to source')],
|
||||
'description' => html_entity_decode($rr['description'], ENT_COMPAT, 'UTF-8'),
|
||||
'location' => html_entity_decode($rr['location'], ENT_COMPAT, 'UTF-8'),
|
||||
'allow_cid' => expand_acl($rr['allow_cid']),
|
||||
'allow_gid' => expand_acl($rr['allow_gid']),
|
||||
'deny_cid' => expand_acl($rr['deny_cid']),
|
||||
'deny_gid' => expand_acl($rr['deny_gid']),
|
||||
'categories' => $categories
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if($export) {
|
||||
header('Content-type: text/calendar');
|
||||
header('content-disposition: attachment; filename="' . t('calendar') . '-' . $channel['channel_address'] . '.ics"' );
|
||||
echo ical_wrapper($r);
|
||||
killme();
|
||||
}
|
||||
|
||||
if (\App::$argv[1] === 'json'){
|
||||
json_return_and_die($events);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if($mode === 'drop' && $event_id) {
|
||||
$r = q("SELECT * FROM event WHERE event_hash = '%s' AND uid = %d LIMIT 1",
|
||||
dbesc($event_id),
|
||||
intval(local_channel())
|
||||
);
|
||||
|
||||
$sync_event = $r[0];
|
||||
|
||||
if($r) {
|
||||
$r = q("delete from event where event_hash = '%s' and uid = %d",
|
||||
dbesc($event_id),
|
||||
intval(local_channel())
|
||||
);
|
||||
|
||||
if($r) {
|
||||
|
||||
$sync_event['event_deleted'] = 1;
|
||||
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),
|
||||
intval(local_channel())
|
||||
);
|
||||
|
||||
if ($i) {
|
||||
|
||||
$can_delete = false;
|
||||
$local_delete = true;
|
||||
|
||||
$ob_hash = get_observer_hash();
|
||||
if($ob_hash && ($ob_hash === $i[0]['author_xchan'] || $ob_hash === $i[0]['owner_xchan'] || $ob_hash === $i[0]['source_xchan'])) {
|
||||
$can_delete = true;
|
||||
}
|
||||
|
||||
// The site admin can delete any post/item on the site.
|
||||
// If the item originated on this site+channel the deletion will propagate downstream.
|
||||
// Otherwise just the local copy is removed.
|
||||
|
||||
if(is_site_admin()) {
|
||||
$local_delete = true;
|
||||
if(intval($i[0]['item_origin']))
|
||||
$can_delete = true;
|
||||
}
|
||||
|
||||
if($can_delete || $local_delete) {
|
||||
|
||||
// if this is a different page type or it's just a local delete
|
||||
// but not by the item author or owner, do a simple deletion
|
||||
|
||||
$complex = false;
|
||||
|
||||
if(intval($i[0]['item_type']) || ($local_delete && (! $can_delete))) {
|
||||
drop_item($i[0]['id']);
|
||||
}
|
||||
else {
|
||||
// complex deletion that needs to propagate and be performed in phases
|
||||
drop_item($i[0]['id'],true,DROPITEM_PHASE1);
|
||||
$complex = true;
|
||||
}
|
||||
|
||||
$ii = q("select * from item where id = %d",
|
||||
intval($i[0]['id'])
|
||||
);
|
||||
if($ii) {
|
||||
xchan_query($ii);
|
||||
$sync_item = fetch_post_tags($ii);
|
||||
build_sync_packet($i[0]['uid'],array('item' => array(encode_item($sync_item[0],true))));
|
||||
}
|
||||
|
||||
if($complex) {
|
||||
tag_deliver($i[0]['uid'],$i[0]['id']);
|
||||
}
|
||||
}
|
||||
}
|
||||
killme();
|
||||
}
|
||||
notice( t('Failed to remove event' ) . EOL);
|
||||
killme();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -106,7 +106,7 @@ class Chanview extends \Zotlabs\Web\Controller {
|
||||
|
||||
if (\App::$poi) {
|
||||
$url = \App::$poi['xchan_url'];
|
||||
if(\App::$poi['xchan_network'] === 'zot') {
|
||||
if(in_array(\App::$poi['xchan_network'], ['zot', 'zot6'])) {
|
||||
$is_zot = true;
|
||||
}
|
||||
if(local_channel()) {
|
||||
|
||||
@@ -127,6 +127,20 @@ class Connections extends \Zotlabs\Web\Controller {
|
||||
$unblocked = true;
|
||||
}
|
||||
|
||||
switch($_REQUEST['order']) {
|
||||
case 'name_desc':
|
||||
$sql_order = 'xchan_name DESC';
|
||||
break;
|
||||
case 'connected':
|
||||
$sql_order = 'abook_created';
|
||||
break;
|
||||
case 'connected_desc':
|
||||
$sql_order = 'abook_created DESC';
|
||||
break;
|
||||
default:
|
||||
$sql_order = 'xchan_name';
|
||||
}
|
||||
|
||||
$search = ((x($_REQUEST,'search')) ? notags(trim($_REQUEST['search'])) : '');
|
||||
|
||||
$tabs = array(
|
||||
@@ -233,7 +247,7 @@ class Connections extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
|
||||
$r = q("SELECT abook.*, xchan.* FROM abook left join xchan on abook.abook_xchan = xchan.xchan_hash
|
||||
WHERE abook_channel = %d and abook_self = 0 and xchan_deleted = 0 and xchan_orphan = 0 $sql_extra $sql_extra2 ORDER BY xchan_name LIMIT %d OFFSET %d ",
|
||||
WHERE abook_channel = %d and abook_self = 0 and xchan_deleted = 0 and xchan_orphan = 0 $sql_extra $sql_extra2 ORDER BY $sql_order LIMIT %d OFFSET %d ",
|
||||
intval(local_channel()),
|
||||
intval(App::$pager['itemspage']),
|
||||
intval(App::$pager['start'])
|
||||
@@ -307,7 +321,7 @@ class Connections extends \Zotlabs\Web\Controller {
|
||||
'ignore_hover' => t('Ignore connection'),
|
||||
'ignore' => ((! $rr['abook_ignored']) ? t('Ignore') : false),
|
||||
'recent_label' => t('Recent activity'),
|
||||
'recentlink' => z_root() . '/network/?f=&cid=' . intval($rr['abook_id']),
|
||||
'recentlink' => z_root() . '/network/?f=&cid=' . intval($rr['abook_id']) . '&name=' . $rr['xchan_name'],
|
||||
'oneway' => $oneway
|
||||
);
|
||||
}
|
||||
@@ -329,7 +343,7 @@ class Connections extends \Zotlabs\Web\Controller {
|
||||
killme();
|
||||
}
|
||||
else {
|
||||
$o .= "<script> var page_query = '" . escape_tags($_GET['q']) . "'; var extra_args = '" . extra_query_args() . "' ; </script>";
|
||||
$o .= "<script> var page_query = '" . escape_tags(urlencode($_GET['q'])) . "'; var extra_args = '" . extra_query_args() . "' ; </script>";
|
||||
$o .= replace_macros(get_markup_template('connections.tpl'),array(
|
||||
'$header' => t('Connections') . (($head) ? ': ' . $head : ''),
|
||||
'$tabs' => $tabs,
|
||||
|
||||
@@ -8,6 +8,7 @@ namespace Zotlabs\Module;
|
||||
*/
|
||||
|
||||
use Zotlabs\Lib\Apps;
|
||||
use Zotlabs\Lib\Libzot;
|
||||
|
||||
require_once('include/socgraph.php');
|
||||
require_once('include/selectors.php');
|
||||
@@ -100,7 +101,8 @@ class Connedit extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
|
||||
|
||||
$profile_id = $_POST['profile_assign'];
|
||||
$profile_id = ((array_key_exists('profile_assign',$_POST)) ? $_POST['profile_assign'] : $orig_record[0]['abook_profile']);
|
||||
|
||||
if($profile_id) {
|
||||
$r = q("SELECT profile_guid FROM profile WHERE profile_guid = '%s' AND uid = %d LIMIT 1",
|
||||
dbesc($profile_id),
|
||||
@@ -112,18 +114,23 @@ class Connedit extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
}
|
||||
|
||||
$abook_incl = escape_tags($_POST['abook_incl']);
|
||||
$abook_excl = escape_tags($_POST['abook_excl']);
|
||||
|
||||
$abook_incl = ((array_key_exists('abook_incl',$_POST)) ? escape_tags($_POST['abook_incl']) : $orig_record[0]['abook_incl']);
|
||||
$abook_excl = ((array_key_exists('abook_excl',$_POST)) ? escape_tags($_POST['abook_excl']) : $orig_record[0]['abook_excl']);
|
||||
|
||||
|
||||
$hidden = intval($_POST['hidden']);
|
||||
|
||||
$priority = intval($_POST['poll']);
|
||||
if($priority > 5 || $priority < 0)
|
||||
$priority = 0;
|
||||
|
||||
if(! array_key_exists('closeness',$_POST)) {
|
||||
$_POST['closeness'] = 80;
|
||||
}
|
||||
$closeness = intval($_POST['closeness']);
|
||||
if($closeness < 0)
|
||||
$closeness = 99;
|
||||
if($closeness < 0 || $closeness > 99) {
|
||||
$closeness = 80;
|
||||
}
|
||||
|
||||
$rating = intval($_POST['rating']);
|
||||
if($rating < (-10))
|
||||
@@ -230,6 +237,8 @@ class Connedit extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
|
||||
$abook_pending = (($new_friend) ? 0 : $orig_record[0]['abook_pending']);
|
||||
|
||||
|
||||
|
||||
$r = q("UPDATE abook SET abook_profile = '%s', abook_closeness = %d, abook_pending = %d,
|
||||
abook_incl = '%s', abook_excl = '%s'
|
||||
@@ -475,6 +484,10 @@ class Connedit extends \Zotlabs\Web\Controller {
|
||||
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()))
|
||||
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
|
||||
@@ -697,7 +710,7 @@ class Connedit extends \Zotlabs\Web\Controller {
|
||||
|
||||
$tpl = get_markup_template("abook_edit.tpl");
|
||||
|
||||
if(feature_enabled(local_channel(),'affinity')) {
|
||||
if(Apps::system_app_installed(local_channel(),'Affinity Tool')) {
|
||||
|
||||
$sections['affinity'] = [
|
||||
'label' => t('Affinity'),
|
||||
@@ -728,9 +741,12 @@ class Connedit extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
|
||||
$slider_tpl = get_markup_template('contact_slider.tpl');
|
||||
|
||||
$slideval = intval($contact['abook_closeness']);
|
||||
|
||||
$slide = replace_macros($slider_tpl,array(
|
||||
'$min' => 1,
|
||||
'$val' => (($contact['abook_closeness']) ? $contact['abook_closeness'] : 99),
|
||||
'$val' => $slideval,
|
||||
'$labels' => $label_str,
|
||||
));
|
||||
}
|
||||
@@ -832,7 +848,7 @@ class Connedit extends \Zotlabs\Web\Controller {
|
||||
$locstr = unpunify($contact['xchan_url']);
|
||||
|
||||
$clone_warn = '';
|
||||
$clonable = (in_array($contact['xchan_network'],['zot','rss']) ? true : false);
|
||||
$clonable = (in_array($contact['xchan_network'],['zot', 'zot6', 'rss']) ? true : false);
|
||||
if(! $clonable) {
|
||||
$clone_warn = '<strong>';
|
||||
$clone_warn .= ((intval($contact['abook_not_here']))
|
||||
@@ -887,7 +903,7 @@ class Connedit extends \Zotlabs\Web\Controller {
|
||||
'$inherited' => t('inherited'),
|
||||
'$submit' => t('Submit'),
|
||||
'$lbl_vis2' => sprintf( t('Please choose the profile you would like to display to %s when viewing your profile securely.'), $contact['xchan_name']),
|
||||
'$close' => $contact['abook_closeness'],
|
||||
'$close' => (($contact['abook_closeness']) ? $contact['abook_closeness'] : 80),
|
||||
'$them' => t('Their Settings'),
|
||||
'$me' => t('My Settings'),
|
||||
'$perms' => $perms,
|
||||
|
||||
@@ -48,6 +48,32 @@ class Cover_photo extends \Zotlabs\Web\Controller {
|
||||
$channel = \App::get_channel();
|
||||
|
||||
check_form_security_token_redirectOnErr('/cover_photo', 'cover_photo');
|
||||
|
||||
// Remove cover photo
|
||||
if(isset($_POST['remove'])) {
|
||||
|
||||
$r = q("SELECT resource_id FROM photo WHERE photo_usage = %d AND uid = %d LIMIT 1",
|
||||
intval(PHOTO_COVER),
|
||||
intval(local_channel())
|
||||
);
|
||||
|
||||
if($r) {
|
||||
q("update photo set photo_usage = %d where photo_usage = %d and uid = %d",
|
||||
intval(PHOTO_NORMAL),
|
||||
intval(PHOTO_COVER),
|
||||
intval(local_channel())
|
||||
);
|
||||
|
||||
$sync = attach_export_data($channel,$r[0]['resource_id']);
|
||||
if($sync)
|
||||
build_sync_packet($channel['channel_id'],array('file' => array($sync)));
|
||||
}
|
||||
|
||||
// Update directory in background
|
||||
\Zotlabs\Daemon\Master::Summon(array('Directory',$channel['channel_id']));
|
||||
|
||||
goaway(z_root() . '/cover_photo');
|
||||
}
|
||||
|
||||
if((array_key_exists('cropfinal',$_POST)) && ($_POST['cropfinal'] == 1)) {
|
||||
|
||||
@@ -106,7 +132,7 @@ class Cover_photo extends \Zotlabs\Web\Controller {
|
||||
if(file_exists($tmp_name)) {
|
||||
$base_image = $r[0];
|
||||
$gis = getimagesize($tmp_name);
|
||||
logger('gis: ' . print_r($gis,true));
|
||||
logger('gis: ' . print_r($gis,true), LOGGER_DEBUG);
|
||||
$base_image['width'] = $gis[0];
|
||||
$base_image['height'] = $gis[1];
|
||||
$base_image['content'] = @file_get_contents($tmp_name);
|
||||
@@ -167,25 +193,18 @@ logger('gis: ' . print_r($gis,true));
|
||||
'filename' => $base_image['filename'],
|
||||
'album' => t('Cover Photos'),
|
||||
'os_path' => $base_image['os_path'],
|
||||
'display_path' => $base_image['display_path']
|
||||
'display_path' => $base_image['display_path'],
|
||||
'photo_usage' => PHOTO_COVER
|
||||
];
|
||||
|
||||
$p['imgscale'] = 7;
|
||||
$p['photo_usage'] = PHOTO_COVER;
|
||||
|
||||
$r1 = $im->save($p);
|
||||
|
||||
$r1 = $im->storeThumbnail($p, PHOTO_RES_COVER_1200);
|
||||
|
||||
$im->doScaleImage(850,310);
|
||||
$p['imgscale'] = 8;
|
||||
|
||||
$r2 = $im->save($p);
|
||||
|
||||
$r2 = $im->storeThumbnail($p, PHOTO_RES_COVER_850);
|
||||
|
||||
$im->doScaleImage(425,160);
|
||||
$p['imgscale'] = 9;
|
||||
|
||||
$r3 = $im->save($p);
|
||||
|
||||
$r3 = $im->storeThumbnail($p, PHOTO_RES_COVER_425);
|
||||
|
||||
if($r1 === false || $r2 === false || $r3 === false) {
|
||||
// if one failed, delete them all so we can start over.
|
||||
notice( t('Image resize failed.') . EOL );
|
||||
@@ -193,13 +212,28 @@ logger('gis: ' . print_r($gis,true));
|
||||
dbesc($base_image['resource_id']),
|
||||
local_channel()
|
||||
);
|
||||
|
||||
$x = q("SELECT content FROM photo WHERE resource_id = '%s' AND uid = %d AND os_storage = 1 AND imgscale >= 7",
|
||||
dbesc($base_image['resource_id']),
|
||||
local_channel()
|
||||
);
|
||||
if($x) {
|
||||
foreach($x as $xx) {
|
||||
@unlink(dbunescbin($xx['content']));
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$channel = \App::get_channel();
|
||||
|
||||
$this->send_cover_photo_activity($channel,$base_image,$profile);
|
||||
|
||||
|
||||
|
||||
$sync = attach_export_data($channel,$base_image['resource_id']);
|
||||
if($sync)
|
||||
build_sync_packet($channel['channel_id'],array('file' => array($sync)));
|
||||
|
||||
// Update directory in background
|
||||
\Zotlabs\Daemon\Master::Summon(array('Directory',$channel['channel_id']));
|
||||
}
|
||||
else
|
||||
notice( t('Unable to process image') . EOL);
|
||||
@@ -215,7 +249,7 @@ logger('gis: ' . print_r($gis,true));
|
||||
|
||||
require_once('include/attach.php');
|
||||
|
||||
$res = attach_store(\App::get_channel(), get_observer_hash(), '', array('album' => t('Cover Photos'), 'hash' => $hash));
|
||||
$res = attach_store(\App::get_channel(), get_observer_hash(), '', array('album' => t('Cover Photos'), 'hash' => $hash, 'nosync' => true));
|
||||
|
||||
logger('attach_store: ' . print_r($res,true));
|
||||
|
||||
@@ -393,6 +427,7 @@ logger('gis: ' . print_r($gis,true));
|
||||
'$lbl_profiles' => t('Select a profile:'),
|
||||
'$title' => t('Change Cover Photo'),
|
||||
'$submit' => t('Upload'),
|
||||
'$remove' => t('Remove'),
|
||||
'$profiles' => $profiles,
|
||||
'$embedPhotos' => t('Use a photo from your albums'),
|
||||
'$embedPhotosModalTitle' => t('Use a photo from your albums'),
|
||||
|
||||
@@ -8,8 +8,9 @@
|
||||
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
use \Sabre\DAV as SDAV;
|
||||
use \Zotlabs\Storage;
|
||||
use Sabre\DAV as SDAV;
|
||||
use Zotlabs\Storage;
|
||||
use Zotlabs\Web\HTTPSig;
|
||||
|
||||
require_once('include/attach.php');
|
||||
require_once('include/auth.php');
|
||||
@@ -46,7 +47,7 @@ class Dav extends \Zotlabs\Web\Controller {
|
||||
continue;
|
||||
}
|
||||
|
||||
$sigblock = \Zotlabs\Web\HTTPSig::parse_sigheader($_SERVER[$head]);
|
||||
$sigblock = HTTPSig::parse_sigheader($_SERVER[$head]);
|
||||
if($sigblock) {
|
||||
$keyId = str_replace('acct:','',$sigblock['keyId']);
|
||||
if($keyId) {
|
||||
@@ -69,7 +70,7 @@ class Dav extends \Zotlabs\Web\Controller {
|
||||
continue;
|
||||
|
||||
if($record) {
|
||||
$verified = \Zotlabs\Web\HTTPSig::verify('',$record['channel']['channel_pubkey']);
|
||||
$verified = HTTPSig::verify('',$record['channel']['channel_pubkey']);
|
||||
if(! ($verified && $verified['header_signed'] && $verified['header_valid'])) {
|
||||
$record = null;
|
||||
}
|
||||
|
||||
@@ -103,8 +103,14 @@ class Directory extends \Zotlabs\Web\Controller {
|
||||
$suggest = (local_channel() && x($_REQUEST,'suggest')) ? $_REQUEST['suggest'] : '';
|
||||
|
||||
if($suggest) {
|
||||
|
||||
$r = suggestion_query(local_channel(),get_observer_hash());
|
||||
|
||||
// the directory options have no effect in suggestion mode
|
||||
|
||||
$globaldir = 1;
|
||||
$safe_mode = 1;
|
||||
$type = 0;
|
||||
|
||||
$r = suggestion_query(local_channel(),get_observer_hash(),0,60);
|
||||
|
||||
if(! $r) {
|
||||
notice( t('No default suggestions were found.') . EOL);
|
||||
@@ -212,12 +218,17 @@ class Directory extends \Zotlabs\Web\Controller {
|
||||
if($j) {
|
||||
|
||||
if($j['results']) {
|
||||
|
||||
|
||||
$results = $j['results'];
|
||||
if($suggest) {
|
||||
$results = self::reorder_results($results,$addresses);
|
||||
}
|
||||
|
||||
$entries = array();
|
||||
|
||||
$photo = 'thumb';
|
||||
|
||||
foreach($j['results'] as $rr) {
|
||||
foreach($results as $rr) {
|
||||
|
||||
$profile_link = chanlink_url($rr['url']);
|
||||
|
||||
@@ -399,7 +410,7 @@ class Directory extends \Zotlabs\Web\Controller {
|
||||
|
||||
$dirtitle = (($globaldir) ? t('Global Directory') : t('Local Directory'));
|
||||
|
||||
$o .= "<script> var page_query = '" . escape_tags($_GET['q']) . "'; var extra_args = '" . extra_query_args() . "' ; divmore_height = " . intval($maxheight) . "; </script>";
|
||||
$o .= "<script> var page_query = '" . escape_tags(urlencode($_GET['q'])) . "'; var extra_args = '" . extra_query_args() . "' ; divmore_height = " . intval($maxheight) . "; </script>";
|
||||
$o .= replace_macros($tpl, array(
|
||||
'$search' => $search,
|
||||
'$desc' => t('Find'),
|
||||
@@ -438,5 +449,22 @@ class Directory extends \Zotlabs\Web\Controller {
|
||||
return $o;
|
||||
}
|
||||
|
||||
|
||||
static public function reorder_results($results,$suggests) {
|
||||
|
||||
if(! $suggests)
|
||||
return $results;
|
||||
|
||||
$out = [];
|
||||
foreach($suggests as $k => $v) {
|
||||
foreach($results as $rv) {
|
||||
if($k == $rv['address']) {
|
||||
$out[intval($v)] = $rv;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -116,12 +116,12 @@ class Dirsearch extends \Zotlabs\Web\Controller {
|
||||
$sql_extra .= $this->dir_query_build($joiner,'xchan_name',$name);
|
||||
if($address)
|
||||
$sql_extra .= $this->dir_query_build($joiner,'xchan_addr',$address);
|
||||
if($city)
|
||||
$sql_extra .= $this->dir_query_build($joiner,'xprof_locale',$city);
|
||||
if($locale)
|
||||
$sql_extra .= $this->dir_query_build($joiner,'xprof_locale',$locale);
|
||||
if($region)
|
||||
$sql_extra .= $this->dir_query_build($joiner,'xprof_region',$region);
|
||||
if($post)
|
||||
$sql_extra .= $this->dir_query_build($joiner,'xprof_postcode',$post);
|
||||
if($postcode)
|
||||
$sql_extra .= $this->dir_query_build($joiner,'xprof_postcode',$postcode);
|
||||
if($country)
|
||||
$sql_extra .= $this->dir_query_build($joiner,'xprof_country',$country);
|
||||
if($gender)
|
||||
@@ -394,7 +394,7 @@ class Dirsearch extends \Zotlabs\Web\Controller {
|
||||
$quoted_string = false;
|
||||
}
|
||||
else
|
||||
$curr['value'] .= ' ' . trim(q);
|
||||
$curr['value'] .= ' ' . trim($q);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -175,11 +175,15 @@ class Display extends \Zotlabs\Web\Controller {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
if ($target_item['item_type'] == ITEM_TYPE_CUSTOM) {
|
||||
call_hooks('item_custom_display',$target_item);
|
||||
notice( t('Page not found.') . EOL);
|
||||
return '';
|
||||
}
|
||||
|
||||
|
||||
$static = ((array_key_exists('static',$_REQUEST)) ? intval($_REQUEST['static']) : 0);
|
||||
|
||||
|
||||
|
||||
$simple_update = (($update) ? " AND item_unseen = 1 " : '');
|
||||
|
||||
if($update && $_SESSION['loadtime'])
|
||||
@@ -234,7 +238,7 @@ class Display extends \Zotlabs\Web\Controller {
|
||||
'$dbegin' => '',
|
||||
'$verb' => '',
|
||||
'$net' => '',
|
||||
'$mid' => $mid
|
||||
'$mid' => (($mid) ? urlencode($mid) : '')
|
||||
));
|
||||
|
||||
head_add_link([
|
||||
@@ -314,7 +318,7 @@ class Display extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
}
|
||||
|
||||
if(! $r) {
|
||||
if($r === null) {
|
||||
// in case somebody turned off public access to sys channel content using permissions
|
||||
// make that content unsearchable by ensuring the owner_xchan can't match
|
||||
if(! perm_is_allowed($sysid,$observer_hash,'view_stream'))
|
||||
|
||||
@@ -16,10 +16,21 @@ class Dreport extends \Zotlabs\Web\Controller {
|
||||
$channel = \App::get_channel();
|
||||
|
||||
$mid = ((argc() > 1) ? argv(1) : '');
|
||||
$encoded_mid = '';
|
||||
|
||||
if(strpos($mid,'b64.') === 0) {
|
||||
$encoded_mid = $mid;
|
||||
$mid = @base64url_decode(substr($mid,4));
|
||||
}
|
||||
if($mid === 'push') {
|
||||
$table = 'push';
|
||||
$mid = ((argc() > 2) ? argv(2) : '');
|
||||
|
||||
if(strpos($mid,'b64.') === 0) {
|
||||
$encoded_mid = $mid;
|
||||
$mid = @base64url_decode(substr($mid,4));
|
||||
}
|
||||
|
||||
if($mid) {
|
||||
$i = q("select id from item where mid = '%s' and uid = %d and ( author_xchan = '%s' or ( owner_xchan = '%s' and item_wall = 1 )) ",
|
||||
dbesc($mid),
|
||||
@@ -32,12 +43,15 @@ class Dreport extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
}
|
||||
sleep(3);
|
||||
goaway(z_root() . '/dreport/' . urlencode($mid));
|
||||
goaway(z_root() . '/dreport/' . (($encoded_mid) ? $encoded_mid : $mid));
|
||||
}
|
||||
|
||||
if($mid === 'mail') {
|
||||
$table = 'mail';
|
||||
$mid = ((argc() > 2) ? argv(2) : '');
|
||||
if(strpos($mid,'b64.') === 0)
|
||||
$mid = @base64url_decode(substr($mid,4));
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -69,8 +83,9 @@ class Dreport extends \Zotlabs\Web\Controller {
|
||||
return;
|
||||
}
|
||||
|
||||
$r = q("select * from dreport where dreport_xchan = '%s' and dreport_mid = '%s'",
|
||||
$r = q("select * from dreport where (dreport_xchan = '%s' or dreport_xchan = '%s') and dreport_mid = '%s'",
|
||||
dbesc($channel['channel_hash']),
|
||||
dbesc($channel['channel_portable_id']),
|
||||
dbesc($mid)
|
||||
);
|
||||
|
||||
@@ -80,7 +95,6 @@ class Dreport extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
|
||||
for($x = 0; $x < count($r); $x++ ) {
|
||||
$r[$x]['name'] = escape_tags(substr($r[$x]['dreport_recip'],strpos($r[$x]['dreport_recip'],' ')));
|
||||
|
||||
// This has two purposes: 1. make the delivery report strings translateable, and
|
||||
// 2. assign an ordering to item delivery results so we can group them and provide
|
||||
@@ -138,16 +152,17 @@ class Dreport extends \Zotlabs\Web\Controller {
|
||||
$entries = array();
|
||||
foreach($r as $rr) {
|
||||
$entries[] = [
|
||||
'name' => $rr['name'],
|
||||
'name' => escape_tags($rr['dreport_name'] ?: $rr['dreport_recip']),
|
||||
'result' => escape_tags($rr['dreport_result']),
|
||||
'time' => escape_tags(datetime_convert('UTC',date_default_timezone_get(),$rr['dreport_time']))
|
||||
];
|
||||
}
|
||||
|
||||
$o = replace_macros(get_markup_template('dreport.tpl'), array(
|
||||
'$title' => sprintf( t('Delivery report for %1$s'),substr($mid,0,32)) . '...',
|
||||
'$title' => sprintf( t('Delivery report for %1$s'),basename($mid)) . '...',
|
||||
'$table' => $table,
|
||||
'$mid' => urlencode($mid),
|
||||
'$safe_mid' => urlencode(gen_link_id($mid)),
|
||||
'$options' => t('Options'),
|
||||
'$push' => t('Redeliver'),
|
||||
'$entries' => $entries
|
||||
@@ -162,9 +177,9 @@ class Dreport extends \Zotlabs\Web\Controller {
|
||||
|
||||
private static function dreport_gravity_sort($a,$b) {
|
||||
if($a['gravity'] == $b['gravity']) {
|
||||
if($a['name'] === $b['name'])
|
||||
if($a['dreport_name'] === $b['dreport_name'])
|
||||
return strcmp($a['dreport_time'],$b['dreport_time']);
|
||||
return strcmp($a['name'],$b['name']);
|
||||
return strcmp($a['dreport_name'],$b['dreport_name']);
|
||||
}
|
||||
return (($a['gravity'] > $b['gravity']) ? 1 : (-1));
|
||||
}
|
||||
|
||||
@@ -45,7 +45,8 @@ class Editpost extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
|
||||
if($itm[0]['resource_type'] === 'event' && $itm[0]['resource_id']) {
|
||||
goaway(z_root() . '/events/' . $itm[0]['resource_id'] . '?expandform=1');
|
||||
goaway(z_root() . '/cdav/calendar/' . $itm[0]['resource_id']);
|
||||
//goaway(z_root() . '/events/' . $itm[0]['resource_id'] . '?expandform=1');
|
||||
}
|
||||
|
||||
$owner_uid = $itm[0]['uid'];
|
||||
|
||||
22
Zotlabs/Module/Embed.php
Normal file
22
Zotlabs/Module/Embed.php
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
require_once('include/security.php');
|
||||
require_once('include/bbcode.php');
|
||||
|
||||
|
||||
class Embed extends \Zotlabs\Web\Controller {
|
||||
|
||||
function init() {
|
||||
|
||||
$post_id = ((argc() > 1) ? intval(argv(1)) : 0);
|
||||
|
||||
if(! $post_id)
|
||||
killme();
|
||||
|
||||
echo '[share=' . $post_id . '][/share]';
|
||||
killme();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3,8 +3,10 @@
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* @brief Embedphoto endpoint.
|
||||
*
|
||||
* Provide an AJAX endpoint to fill the embedPhotoModal with folders and photos
|
||||
* selection.
|
||||
*/
|
||||
class Embedphotos extends \Zotlabs\Web\Controller {
|
||||
|
||||
@@ -13,93 +15,116 @@ class Embedphotos extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This is the POST destination for the embedphotos button.
|
||||
*
|
||||
* This is the POST destination for the embedphotos button
|
||||
*
|
||||
* @return string A JSON string.
|
||||
*/
|
||||
function post() {
|
||||
public function post() {
|
||||
if (argc() > 1 && argv(1) === 'album') {
|
||||
// API: /embedphotos/album
|
||||
$name = (x($_POST,'name') ? $_POST['name'] : null );
|
||||
if(!$name) {
|
||||
$name = (x($_POST, 'name') ? $_POST['name'] : null );
|
||||
if (!$name) {
|
||||
json_return_and_die(array('errormsg' => 'Error retrieving album', 'status' => false));
|
||||
}
|
||||
$album = $this->embedphotos_widget_album(array('channel' => \App::get_channel(), 'album' => $name));
|
||||
json_return_and_die(array('status' => true, 'content' => $album));
|
||||
}
|
||||
if(argc() > 1 && argv(1) === 'albumlist') {
|
||||
if (argc() > 1 && argv(1) === 'albumlist') {
|
||||
// API: /embedphotos/albumlist
|
||||
$album_list = $this->embedphotos_album_list($a);
|
||||
$album_list = $this->embedphotos_album_list();
|
||||
json_return_and_die(array('status' => true, 'albumlist' => $album_list));
|
||||
}
|
||||
if(argc() > 1 && argv(1) === 'photolink') {
|
||||
if (argc() > 1 && argv(1) === 'photolink') {
|
||||
// API: /embedphotos/photolink
|
||||
$href = (x($_POST,'href') ? $_POST['href'] : null );
|
||||
if(!$href) {
|
||||
$href = (x($_POST, 'href') ? $_POST['href'] : null );
|
||||
if (!$href) {
|
||||
json_return_and_die(array('errormsg' => 'Error retrieving link ' . $href, 'status' => false));
|
||||
}
|
||||
$resource_id = array_pop(explode("/", $href));
|
||||
$r = q("SELECT obj from item where resource_type = 'photo' and resource_id = '%s' limit 1",
|
||||
dbesc($resource_id)
|
||||
);
|
||||
if(!$r) {
|
||||
json_return_and_die(array('errormsg' => 'Error retrieving resource ' . $resource_id, 'status' => false));
|
||||
}
|
||||
$obj = json_decode($r[0]['obj'], true);
|
||||
if(x($obj,'body')) {
|
||||
$photolink = $obj['body'];
|
||||
} elseif (x($obj,'bbcode')) {
|
||||
$photolink = $obj['bbcode'];
|
||||
} else {
|
||||
json_return_and_die(array('errormsg' => 'Error retrieving resource ' . $resource_id, 'status' => false));
|
||||
}
|
||||
json_return_and_die(array('status' => true, 'photolink' => $photolink, 'resource_id' => $resource_id));
|
||||
$resource_id = array_pop(explode('/', $href));
|
||||
$x = self::photolink($resource_id);
|
||||
if($x)
|
||||
json_return_and_die(array('status' => true, 'photolink' => $x, 'resource_id' => $resource_id));
|
||||
json_return_and_die(array('errormsg' => 'Error retrieving resource ' . $resource_id, 'status' => false));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copied from include/widgets.php::widget_album() with a modification to get the profile_uid from
|
||||
* the input array as in widget_item()
|
||||
*
|
||||
* @param array $args
|
||||
* @return string with HTML
|
||||
*/
|
||||
function embedphotos_widget_album($args) {
|
||||
|
||||
protected static function photolink($resource) {
|
||||
$channel = \App::get_channel();
|
||||
$output = EMPTY_STR;
|
||||
if($channel) {
|
||||
$resolution = ((feature_enabled($channel['channel_id'],'large_photos')) ? 1 : 2);
|
||||
$r = q("select mimetype, height, width from photo where resource_id = '%s' and $resolution = %d and uid = %d limit 1",
|
||||
dbesc($resource),
|
||||
intval($resolution),
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
if(! $r)
|
||||
return $output;
|
||||
|
||||
if($r[0]['mimetype'] === 'image/jpeg')
|
||||
$ext = '.jpg';
|
||||
elseif($r[0]['mimetype'] === 'image/png')
|
||||
$ext = '.png';
|
||||
elseif($r[0]['mimetype'] === 'image/gif')
|
||||
$ext = '.gif';
|
||||
else
|
||||
$ext = EMPTY_STR;
|
||||
|
||||
$output = '[zrl=' . z_root() . '/photos/' . $channel['channel_address'] . '/image/' . $resource . ']' .
|
||||
'[zmg=' . $r[0]['width'] . 'x' . $r[0]['height'] . ']' . z_root() . '/photo/' . $resource . '-' . $resolution . $ext . '[/zmg][/zrl]';
|
||||
|
||||
return $output;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get photos from an album.
|
||||
*
|
||||
* @see \\Zotlabs\\Widget\\Album::widget()
|
||||
*
|
||||
* @param array $args associative array with
|
||||
* * \e array \b channel
|
||||
* * \e string \b album
|
||||
* @return string with HTML code from 'photo_album.tpl'
|
||||
*/
|
||||
protected function embedphotos_widget_album($args) {
|
||||
$channel_id = 0;
|
||||
if(array_key_exists('channel', $args))
|
||||
|
||||
if (array_key_exists('channel', $args)) {
|
||||
$channel = $args['channel'];
|
||||
$channel_id = intval($channel['channel_id']);
|
||||
if(! $channel_id)
|
||||
$channel_id = intval($channel['channel_id']);
|
||||
}
|
||||
if (! $channel_id)
|
||||
$channel_id = \App::$profile_uid;
|
||||
if(! $channel_id)
|
||||
if (! $channel_id)
|
||||
return '';
|
||||
|
||||
$owner_uid = $channel_id;
|
||||
require_once('include/security.php');
|
||||
$sql_extra = permissions_sql($channel_id);
|
||||
|
||||
if(! perm_is_allowed($channel_id,get_observer_hash(),'view_storage'))
|
||||
if (! perm_is_allowed($channel_id, get_observer_hash(), 'view_storage'))
|
||||
return '';
|
||||
|
||||
if($args['album'])
|
||||
if (isset($args['album']))
|
||||
$album = (($args['album'] === '/') ? '' : $args['album']);
|
||||
if($args['title'])
|
||||
if (isset($args['title']))
|
||||
$title = $args['title'];
|
||||
|
||||
/**
|
||||
* This may return incorrect permissions if you have multiple directories of the same name.
|
||||
* @note This may return incorrect permissions if you have multiple directories of the same name.
|
||||
* It is a limitation of the photo table using a name for a photo album instead of a folder hash
|
||||
*/
|
||||
if($album) {
|
||||
if ($album) {
|
||||
require_once('include/attach.php');
|
||||
$x = q("select hash from attach where filename = '%s' and uid = %d limit 1",
|
||||
dbesc($album),
|
||||
intval($owner_uid)
|
||||
intval($channel_id)
|
||||
);
|
||||
if($x) {
|
||||
$y = attach_can_view_folder($owner_uid,get_observer_hash(),$x[0]['hash']);
|
||||
if(! $y)
|
||||
if ($x) {
|
||||
$y = attach_can_view_folder($channel_id, get_observer_hash(), $x[0]['hash']);
|
||||
if (! $y)
|
||||
return '';
|
||||
}
|
||||
}
|
||||
@@ -110,30 +135,33 @@ class Embedphotos extends \Zotlabs\Web\Controller {
|
||||
(SELECT resource_id, max(imgscale) imgscale FROM photo WHERE uid = %d AND album = '%s' AND imgscale <= 4 AND photo_usage IN ( %d, %d ) $sql_extra GROUP BY resource_id) ph
|
||||
ON (p.resource_id = ph.resource_id AND p.imgscale = ph.imgscale)
|
||||
ORDER BY created $order",
|
||||
intval($owner_uid),
|
||||
intval($channel_id),
|
||||
dbesc($album),
|
||||
intval(PHOTO_NORMAL),
|
||||
intval(PHOTO_PROFILE)
|
||||
);
|
||||
|
||||
$photos = array();
|
||||
if(count($r)) {
|
||||
$photos = [];
|
||||
if (count($r)) {
|
||||
$twist = 'rotright';
|
||||
foreach($r as $rr) {
|
||||
if($twist == 'rotright')
|
||||
foreach ($r as $rr) {
|
||||
if ($twist == 'rotright')
|
||||
$twist = 'rotleft';
|
||||
else
|
||||
$twist = 'rotright';
|
||||
|
||||
$ph = photo_factory('');
|
||||
$phototypes = $ph->supportedTypes();
|
||||
|
||||
$ext = $phototypes[$rr['mimetype']];
|
||||
|
||||
$imgalt_e = $rr['filename'];
|
||||
$desc_e = $rr['description'];
|
||||
|
||||
$imagelink = (z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/image/' . $rr['resource_id']
|
||||
$imagelink = (z_root() . '/photos/' . $channel['channel_address'] . '/image/' . $rr['resource_id']
|
||||
. (($_GET['order'] === 'posted') ? '?f=&order=posted' : ''));
|
||||
|
||||
$photos[] = array(
|
||||
$photos[] = [
|
||||
'id' => $rr['id'],
|
||||
'twist' => ' ' . $twist . rand(2,4),
|
||||
'link' => $imagelink,
|
||||
@@ -143,35 +171,43 @@ class Embedphotos extends \Zotlabs\Web\Controller {
|
||||
'desc'=> $desc_e,
|
||||
'ext' => $ext,
|
||||
'hash'=> $rr['resource_id'],
|
||||
'unknown' => t('Unknown')
|
||||
);
|
||||
'unknown' => t('Unknown'),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
$tpl = get_markup_template('photo_album.tpl');
|
||||
$o .= replace_macros($tpl, array(
|
||||
$o = replace_macros($tpl, [
|
||||
'$photos' => $photos,
|
||||
'$album' => (($title) ? $title : $album),
|
||||
'$album_id' => rand(),
|
||||
'$album_edit' => array(t('Edit Album'), $album_edit),
|
||||
'$album_edit' => array(t('Edit Album'), false),
|
||||
'$can_post' => false,
|
||||
'$upload' => array(t('Upload'), z_root() . '/photos/' . \App::$profile['channel_address'] . '/upload/' . bin2hex($album)),
|
||||
'$order' => false,
|
||||
'$upload_form' => $upload_form,
|
||||
'$no_fullscreen_btn' => true
|
||||
));
|
||||
'$upload_form' => '',
|
||||
'$no_fullscreen_btn' => true,
|
||||
]);
|
||||
|
||||
return $o;
|
||||
}
|
||||
|
||||
function embedphotos_album_list($a) {
|
||||
/**
|
||||
* @brief Get albums observer is allowed to see.
|
||||
*
|
||||
* @see photos_albums_list()
|
||||
*
|
||||
* @return NULL|array
|
||||
*/
|
||||
protected function embedphotos_album_list() {
|
||||
require_once('include/photos.php');
|
||||
$p = photos_albums_list(\App::get_channel(), \App::get_observer());
|
||||
if($p['success']) {
|
||||
|
||||
if ($p['success']) {
|
||||
return $p['albums'];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -11,6 +11,9 @@ require_once('include/html2plain.php');
|
||||
class Events extends \Zotlabs\Web\Controller {
|
||||
|
||||
function post() {
|
||||
|
||||
// this module is deprecated
|
||||
return;
|
||||
|
||||
logger('post: ' . print_r($_REQUEST,true), LOGGER_DATA);
|
||||
|
||||
@@ -97,8 +100,8 @@ class Events extends \Zotlabs\Web\Controller {
|
||||
$type = escape_tags(trim($_POST['type']));
|
||||
|
||||
require_once('include/text.php');
|
||||
linkify_tags($a, $desc, local_channel());
|
||||
linkify_tags($a, $location, local_channel());
|
||||
linkify_tags($desc, local_channel());
|
||||
linkify_tags($location, local_channel());
|
||||
|
||||
//$action = ($event_hash == '') ? 'new' : "event/" . $event_hash;
|
||||
|
||||
@@ -245,6 +248,9 @@ class Events extends \Zotlabs\Web\Controller {
|
||||
|
||||
|
||||
function get() {
|
||||
|
||||
// this module is deprecated
|
||||
return;
|
||||
|
||||
if(argc() > 2 && argv(1) == 'ical') {
|
||||
$event_id = argv(2);
|
||||
@@ -662,9 +668,10 @@ class Events extends \Zotlabs\Web\Controller {
|
||||
'html'=>$html,
|
||||
'plink' => array($rr['plink'],t('Link to Source'),'',''),
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if($export) {
|
||||
header('Content-type: text/calendar');
|
||||
header('content-disposition: attachment; filename="' . t('calendar') . '-' . $channel['channel_address'] . '.ics"' );
|
||||
|
||||
@@ -5,6 +5,8 @@ namespace Zotlabs\Module;
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
class Filestorage extends \Zotlabs\Web\Controller {
|
||||
|
||||
function post() {
|
||||
@@ -71,14 +73,6 @@ class Filestorage extends \Zotlabs\Web\Controller {
|
||||
return;
|
||||
}
|
||||
|
||||
// Since we have ACL'd files in the wild, but don't have ACL here yet, we
|
||||
// need to return for anyone other than the owner, despite the perms check for now.
|
||||
|
||||
$is_owner = (((local_channel()) && ($owner == local_channel())) ? true : false);
|
||||
if(! ($is_owner || is_site_admin())){
|
||||
info( t('Permission Denied.') . EOL );
|
||||
return;
|
||||
}
|
||||
|
||||
if(argc() > 3 && argv(3) === 'delete') {
|
||||
|
||||
@@ -101,18 +95,31 @@ class Filestorage extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
|
||||
$file = intval(argv(2));
|
||||
$r = q("SELECT hash FROM attach WHERE id = %d AND uid = %d LIMIT 1",
|
||||
$r = q("SELECT hash, creator FROM attach WHERE id = %d AND uid = %d LIMIT 1",
|
||||
dbesc($file),
|
||||
intval($owner)
|
||||
);
|
||||
if(! $r) {
|
||||
notice( t('File not found.') . EOL);
|
||||
|
||||
if($json_return)
|
||||
json_return_and_die([ 'success' => false ]);
|
||||
|
||||
notice( t('File not found.') . EOL);
|
||||
goaway(z_root() . '/cloud/' . $which);
|
||||
}
|
||||
|
||||
if(local_channel() !== $owner) {
|
||||
if($r[0]['creator'] && $r[0]['creator'] !== $ob_hash) {
|
||||
notice( t('Permission denied.') . EOL);
|
||||
|
||||
if($json_return)
|
||||
json_return_and_die([ 'success' => false ]);
|
||||
|
||||
goaway(z_root() . '/cloud/' . $which);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$f = $r[0];
|
||||
|
||||
$channel = channelx_by_n($owner);
|
||||
@@ -134,6 +141,19 @@ class Filestorage extends \Zotlabs\Web\Controller {
|
||||
goaway(dirname($url));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Since we have ACL'd files in the wild, but don't have ACL here yet, we
|
||||
// need to return for anyone other than the owner, despite the perms check for now.
|
||||
|
||||
$is_owner = (((local_channel()) && ($owner == local_channel())) ? true : false);
|
||||
if(! ($is_owner || is_site_admin())){
|
||||
info( t('Permission Denied.') . EOL );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if(argc() > 3 && argv(3) === 'edit') {
|
||||
require_once('include/acl_selectors.php');
|
||||
if(! $perms['write_storage']) {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
<?php
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
use Zotlabs\Web\HTTPSig;
|
||||
|
||||
/**
|
||||
* module: getfile
|
||||
*
|
||||
@@ -35,7 +37,6 @@ class Getfile extends \Zotlabs\Web\Controller {
|
||||
$sig = $_POST['signature'];
|
||||
$resource = $_POST['resource'];
|
||||
$revision = intval($_POST['revision']);
|
||||
$resolution = (-1);
|
||||
|
||||
if(! $hash)
|
||||
killme();
|
||||
@@ -47,7 +48,7 @@ class Getfile extends \Zotlabs\Web\Controller {
|
||||
continue;
|
||||
}
|
||||
|
||||
$sigblock = \Zotlabs\Web\HTTPSig::parse_sigheader($_SERVER[$head]);
|
||||
$sigblock = HTTPSig::parse_sigheader($_SERVER[$head]);
|
||||
if($sigblock) {
|
||||
$keyId = $sigblock['keyId'];
|
||||
|
||||
@@ -58,7 +59,7 @@ class Getfile extends \Zotlabs\Web\Controller {
|
||||
);
|
||||
if($r) {
|
||||
$hubloc = $r[0];
|
||||
$verified = \Zotlabs\Web\HTTPSig::verify('',$hubloc['xchan_pubkey']);
|
||||
$verified = HTTPSig::verify('',$hubloc['xchan_pubkey']);
|
||||
if($verified && $verified['header_signed'] && $verified['header_valid'] && $hash == $hubloc['hubloc_hash']) {
|
||||
$header_verified = true;
|
||||
}
|
||||
@@ -81,9 +82,14 @@ class Getfile extends \Zotlabs\Web\Controller {
|
||||
killme();
|
||||
}
|
||||
|
||||
if(substr($resource,-2,1) == '-') {
|
||||
if(isset($_POST['resolution']))
|
||||
$resolution = intval($_POST['resolution']);
|
||||
elseif(substr($resource,-2,1) == '-') {
|
||||
$resolution = intval(substr($resource,-1,1));
|
||||
$resource = substr($resource,0,-2);
|
||||
}
|
||||
else {
|
||||
$resolution = (-1);
|
||||
}
|
||||
|
||||
$slop = intval(get_pconfig($channel['channel_id'],'system','getfile_time_slop'));
|
||||
@@ -106,9 +112,10 @@ class Getfile extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
|
||||
if($resolution > 0) {
|
||||
$r = q("select * from photo where resource_id = '%s' and uid = %d limit 1",
|
||||
$r = q("SELECT * FROM photo WHERE resource_id = '%s' AND uid = %d AND imgscale = %d LIMIT 1",
|
||||
dbesc($resource),
|
||||
intval($channel['channel_id'])
|
||||
intval($channel['channel_id']),
|
||||
$resolution
|
||||
);
|
||||
if($r) {
|
||||
header('Content-type: ' . $r[0]['mimetype']);
|
||||
|
||||
@@ -66,6 +66,9 @@ class Group extends Controller {
|
||||
$groupname = notags(trim($_POST['groupname']));
|
||||
$public = intval($_POST['public']);
|
||||
|
||||
$hookinfo = [ 'pgrp_extras' => '', 'group'=>$group['id'] ];
|
||||
call_hooks ('privacygroup_extras_post',$hookinfo);
|
||||
|
||||
if((strlen($groupname)) && (($groupname != $group['gname']) || ($public != $group['visible']))) {
|
||||
$r = q("UPDATE pgrp SET gname = '%s', visible = %d WHERE uid = %d AND id = %d",
|
||||
dbesc($groupname),
|
||||
@@ -75,6 +78,8 @@ class Group extends Controller {
|
||||
);
|
||||
if($r)
|
||||
info( t('Privacy group updated.') . EOL );
|
||||
|
||||
|
||||
build_sync_packet(local_channel(),null,true);
|
||||
}
|
||||
|
||||
@@ -127,6 +132,10 @@ class Group extends Controller {
|
||||
$i++;
|
||||
}
|
||||
|
||||
$hookinfo = [ 'pgrp_extras' => '', 'group'=>argv(1) ];
|
||||
call_hooks ('privacygroup_extras',$hookinfo);
|
||||
$pgrp_extras = $hookinfo['pgrp_extras'];
|
||||
|
||||
$tpl = get_markup_template('privacy_groups.tpl');
|
||||
$o = replace_macros($tpl, [
|
||||
'$title' => t('Privacy Groups'),
|
||||
@@ -136,6 +145,7 @@ class Group extends Controller {
|
||||
// new group form
|
||||
'$gname' => array('groupname',t('Privacy group name')),
|
||||
'$public' => array('public',t('Members are visible to other channels'), false),
|
||||
'$pgrp_extras' => $pgrp_extras,
|
||||
'$form_security_token' => get_form_security_token("group_edit"),
|
||||
'$submit' => t('Submit'),
|
||||
|
||||
@@ -166,8 +176,11 @@ class Group extends Controller {
|
||||
);
|
||||
if($r)
|
||||
$result = group_rmv(local_channel(),$r[0]['gname']);
|
||||
if($result)
|
||||
if($result) {
|
||||
$hookinfo = [ 'pgrp_extras' => '', 'group' => argv(2) ];
|
||||
call_hooks ('privacygroup_extras_drop',$hookinfo);
|
||||
info( t('Privacy group removed.') . EOL);
|
||||
}
|
||||
else
|
||||
notice( t('Unable to remove privacy group.') . EOL);
|
||||
}
|
||||
@@ -230,6 +243,10 @@ class Group extends Controller {
|
||||
}
|
||||
}
|
||||
|
||||
$hookinfo = [ 'pgrp_extras' => '', 'group'=>$group['id'] ];
|
||||
call_hooks ('privacygroup_extras',$hookinfo);
|
||||
$pgrp_extras = $hookinfo['pgrp_extras'];
|
||||
|
||||
$context = $context + array(
|
||||
'$title' => sprintf(t('Privacy Group: %s'), $group['gname']),
|
||||
'$details_label' => t('Edit'),
|
||||
@@ -240,6 +257,7 @@ class Group extends Controller {
|
||||
'$form_security_token_edit' => get_form_security_token('group_edit'),
|
||||
'$delete' => t('Delete Group'),
|
||||
'$form_security_token_drop' => get_form_security_token("group_drop"),
|
||||
'$pgrp_extras' => $pgrp_extras,
|
||||
);
|
||||
|
||||
}
|
||||
@@ -283,6 +301,7 @@ class Group extends Controller {
|
||||
|
||||
$context['$groupeditor'] = $groupeditor;
|
||||
$context['$desc'] = t('Click a channel to toggle membership');
|
||||
$context['$pgrp_extras'] = $pgrp_extras;
|
||||
|
||||
if($change) {
|
||||
$tpl = get_markup_template('groupeditor.tpl');
|
||||
|
||||
@@ -194,7 +194,7 @@ class Hq extends \Zotlabs\Web\Controller {
|
||||
'$dbegin' => '',
|
||||
'$verb' => '',
|
||||
'$net' => '',
|
||||
'$mid' => $mid
|
||||
'$mid' => (($mid) ? urlencode($mid) : '')
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
119
Zotlabs/Module/Id.php
Normal file
119
Zotlabs/Module/Id.php
Normal file
@@ -0,0 +1,119 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
/**
|
||||
*
|
||||
* Controller for responding to x-zot: protocol requests
|
||||
* x-zot:_jkfRG85nJ-714zn-LW_VbTFW8jSjGAhAydOcJzHxqHkvEHWG2E0RbA_pbch-h4R63RG1YJZifaNzgccoLa3MQ/453c1678-1a79-4af7-ab65-6b012f6cab77
|
||||
*
|
||||
*/
|
||||
|
||||
use Zotlabs\Lib\Activity;
|
||||
use Zotlabs\Lib\ActivityStreams;
|
||||
use Zotlabs\Lib\LDSignatures;
|
||||
use Zotlabs\Web\HTTPSig;
|
||||
use Zotlabs\Web\Controller;
|
||||
use Zotlabs\Lib\Libzot;
|
||||
use Zotlabs\Lib\ThreadListener;
|
||||
use Zotlabs\Lib\IConfig;
|
||||
use Zotlabs\Lib\Enotify;
|
||||
use App;
|
||||
|
||||
require_once('include/attach.php');
|
||||
require_once('include/bbcode.php');
|
||||
require_once('include/security.php');
|
||||
|
||||
|
||||
class Id extends Controller {
|
||||
|
||||
function init() {
|
||||
|
||||
if(Libzot::is_zot_request()) {
|
||||
|
||||
$conversation = false;
|
||||
|
||||
$request_portable_id = argv(1);
|
||||
if(argc() > 2) {
|
||||
$item_id = argv(2);
|
||||
}
|
||||
|
||||
$portable_id = EMPTY_STR;
|
||||
|
||||
$sigdata = HTTPSig::verify(EMPTY_STR);
|
||||
if($sigdata['portable_id'] && $sigdata['header_valid']) {
|
||||
$portable_id = $sigdata['portable_id'];
|
||||
}
|
||||
|
||||
|
||||
$chan = channelx_by_hash($request_portable_id);
|
||||
|
||||
if($chan) {
|
||||
$channel_id = $chan['channel_id'];
|
||||
if(! $item_id) {
|
||||
$handler = new Channel();
|
||||
App::$argc = 2;
|
||||
App::$argv[0] = 'channel';
|
||||
App::$argv[1] = $chan['channel_address'];
|
||||
$handler->init();
|
||||
}
|
||||
}
|
||||
else {
|
||||
http_status_exit(404, 'Not found');
|
||||
}
|
||||
|
||||
|
||||
$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 uuid = '%s' $item_normal $sql_extra and uid = %d limit 1",
|
||||
dbesc($item_id),
|
||||
intval($channel_id)
|
||||
);
|
||||
if(! $r) {
|
||||
|
||||
$r = q("select * from item where uuid = '%s' $item_normal and uid = %d limit 1",
|
||||
dbesc($item_id),
|
||||
intval($channel_id)
|
||||
);
|
||||
if($r) {
|
||||
http_status_exit(403, 'Forbidden');
|
||||
}
|
||||
http_status_exit(404, 'Not found');
|
||||
}
|
||||
|
||||
if(! perm_is_allowed($chan['channel_id'],get_observer_hash(),'view_stream'))
|
||||
http_status_exit(403, 'Forbidden');
|
||||
|
||||
xchan_query($r,true);
|
||||
$items = fetch_post_tags($r,true);
|
||||
|
||||
$i = Activity::encode_item($items[0]);
|
||||
|
||||
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' ;
|
||||
$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();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -133,9 +133,11 @@ class Impel extends \Zotlabs\Web\Controller {
|
||||
$arr['author_xchan'] = (($j['author_xchan']) ? $j['author_xchan'] : get_observer_hash());
|
||||
$arr['mimetype'] = (($j['mimetype']) ? $j['mimetype'] : 'text/bbcode');
|
||||
|
||||
if(! $j['mid'])
|
||||
$j['mid'] = item_message_id();
|
||||
|
||||
if(! $j['mid']) {
|
||||
$j['uuid'] = item_message_id();
|
||||
$j['mid'] = z_root() . '/item/' . $j['uuid'];
|
||||
}
|
||||
$arr['uuid'] = $j['uuid'];
|
||||
$arr['mid'] = $arr['parent_mid'] = $j['mid'];
|
||||
|
||||
|
||||
|
||||
@@ -8,6 +8,8 @@ require_once('include/import.php');
|
||||
require_once('include/perm_upgrade.php');
|
||||
require_once('library/urlify/URLify.php');
|
||||
|
||||
use Zotlabs\Lib\Libzot;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Module for channel import.
|
||||
@@ -228,13 +230,45 @@ class Import extends \Zotlabs\Web\Controller {
|
||||
);
|
||||
|
||||
// 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_hash' => $channel['channel_portable_id'],
|
||||
'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_portable_id']),
|
||||
dbesc(z_root())
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
logger('import step 5');
|
||||
@@ -246,8 +280,9 @@ class Import extends \Zotlabs\Web\Controller {
|
||||
|
||||
// replace any existing xchan we may have on this site if we're seizing control
|
||||
|
||||
$r = q("delete from xchan where xchan_hash = '%s'",
|
||||
dbesc($channel['channel_hash'])
|
||||
$r = q("delete from xchan where ( xchan_hash = '%s' or xchan_hash = '%s' ) ",
|
||||
dbesc($channel['channel_hash']),
|
||||
dbesc($channel['channel_portable_id'])
|
||||
);
|
||||
|
||||
$r = xchan_store_lowlevel(
|
||||
@@ -269,6 +304,30 @@ class Import extends \Zotlabs\Web\Controller {
|
||||
'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');
|
||||
@@ -278,10 +337,20 @@ class Import extends \Zotlabs\Web\Controller {
|
||||
if($xchans) {
|
||||
foreach($xchans as $xchan) {
|
||||
|
||||
$hash = make_xchan_hash($xchan['xchan_guid'],$xchan['xchan_guid_sig']);
|
||||
if($xchan['xchan_network'] === 'zot' && $hash !== $xchan['xchan_hash']) {
|
||||
logger('forged xchan: ' . print_r($xchan,true));
|
||||
continue;
|
||||
if($xchan['xchan_network'] === 'zot') {
|
||||
$hash = make_xchan_hash($xchan['xchan_guid'],$xchan['xchan_guid_sig']);
|
||||
if($hash !== $xchan['xchan_hash']) {
|
||||
logger('forged xchan: ' . print_r($xchan,true));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if($xchan['xchan_network'] === 'zot6') {
|
||||
$zhash = \Zotlabs\Lib\Libzot::make_xchan_hash($xchan['xchan_guid'],$xchan['xchan_pubkey']);
|
||||
if($zhash !== $xchan['xchan_hash']) {
|
||||
logger('forged xchan: ' . print_r($xchan,true));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if(! array_key_exists('xchan_hidden',$xchan)) {
|
||||
@@ -472,6 +541,9 @@ class Import extends \Zotlabs\Web\Controller {
|
||||
if(is_array($data['app']))
|
||||
import_apps($channel,$data['app']);
|
||||
|
||||
if(is_array($data['sysapp']))
|
||||
import_sysapps($channel,$data['sysapp']);
|
||||
|
||||
if(is_array($data['chatroom']))
|
||||
import_chatrooms($channel,$data['chatroom']);
|
||||
|
||||
|
||||
@@ -2,6 +2,23 @@
|
||||
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
use Zotlabs\Lib\IConfig;
|
||||
use Zotlabs\Lib\Enotify;
|
||||
use Zotlabs\Web\Controller;
|
||||
use Zotlabs\Daemon\Master;
|
||||
use Zotlabs\Lib\Activity;
|
||||
use Zotlabs\Lib\ActivityStreams;
|
||||
use Zotlabs\Lib\LDSignatures;
|
||||
use Zotlabs\Web\HTTPSig;
|
||||
use Zotlabs\Lib\Libzot;
|
||||
use Zotlabs\Lib\ThreadListener;
|
||||
use App;
|
||||
|
||||
require_once('include/crypto.php');
|
||||
require_once('include/items.php');
|
||||
require_once('include/security.php');
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* This is the POST destination for most all locally posted
|
||||
@@ -17,16 +34,187 @@ namespace Zotlabs\Module;
|
||||
*
|
||||
*/
|
||||
|
||||
require_once('include/crypto.php');
|
||||
require_once('include/items.php');
|
||||
require_once('include/attach.php');
|
||||
require_once('include/bbcode.php');
|
||||
require_once('include/security.php');
|
||||
|
||||
class Item extends Controller {
|
||||
|
||||
|
||||
use \Zotlabs\Lib as Zlib;
|
||||
function init() {
|
||||
|
||||
if (Libzot::is_zot_request()) {
|
||||
|
||||
$conversation = false;
|
||||
|
||||
$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() . '/item/' . $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 = Activity::encode_item_collection($nitems,'conversation/' . $item_id,'OrderedCollection');
|
||||
if($portable_id) {
|
||||
ThreadListener::store(z_root() . '/item/' . $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(argc() > 1 && argv(1) !== 'drop') {
|
||||
$x = q("select uid, item_wall, llink, mid from item where mid = '%s' ",
|
||||
dbesc(z_root() . '/item/' . argv(1))
|
||||
);
|
||||
if($x) {
|
||||
foreach($x as $xv) {
|
||||
if (intval($xv['item_wall'])) {
|
||||
$c = channelx_by_n($xv['uid']);
|
||||
if ($c) {
|
||||
goaway($c['xchan_url'] . '?mid=' . gen_link_id($xv['mid']));
|
||||
}
|
||||
}
|
||||
}
|
||||
goaway($x[0]['llink']);
|
||||
}
|
||||
http_status_exit(404, 'Not found');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
class Item extends \Zotlabs\Web\Controller {
|
||||
|
||||
function post() {
|
||||
|
||||
@@ -382,16 +570,17 @@ class Item extends \Zotlabs\Web\Controller {
|
||||
$public_policy = $orig_post['public_policy'];
|
||||
$private = $orig_post['item_private'];
|
||||
}
|
||||
|
||||
if($private || $public_policy || $acl->is_private())
|
||||
$private = 1;
|
||||
|
||||
|
||||
if($public_policy || $acl->is_private()) {
|
||||
$private = (($private) ? $private : 1);
|
||||
}
|
||||
|
||||
$location = $orig_post['location'];
|
||||
$coord = $orig_post['coord'];
|
||||
$verb = $orig_post['verb'];
|
||||
$app = $orig_post['app'];
|
||||
$title = escape_tags(trim($_REQUEST['title']));
|
||||
$summary = trim($_REQUEST['summary']);
|
||||
$body = trim($_REQUEST['body']);
|
||||
$item_flags = $orig_post['item_flags'];
|
||||
|
||||
@@ -454,18 +643,18 @@ class Item extends \Zotlabs\Web\Controller {
|
||||
$coord = notags(trim($_REQUEST['coord']));
|
||||
$verb = notags(trim($_REQUEST['verb']));
|
||||
$title = escape_tags(trim($_REQUEST['title']));
|
||||
$summary = trim($_REQUEST['summary']);
|
||||
$body = trim($_REQUEST['body']);
|
||||
$body .= trim($_REQUEST['attachment']);
|
||||
$postopts = '';
|
||||
|
||||
$allow_empty = ((array_key_exists('allow_empty',$_REQUEST)) ? intval($_REQUEST['allow_empty']) : 0);
|
||||
|
||||
$private = intval($acl->is_private() || ($public_policy));
|
||||
$private = (($private) ? $private : intval($acl->is_private() || ($public_policy)));
|
||||
|
||||
// If this is a comment, set the permissions from the parent.
|
||||
|
||||
if($parent_item) {
|
||||
$private = 0;
|
||||
$acl->set($parent_item);
|
||||
$private = intval($acl->is_private() || $parent_item['item_private']);
|
||||
$public_policy = $parent_item['public_policy'];
|
||||
@@ -505,12 +694,14 @@ class Item extends \Zotlabs\Web\Controller {
|
||||
&& ($channel['channel_pageflags'] & PAGE_ALLOWCODE)) ? true : false);
|
||||
|
||||
if($preview) {
|
||||
$summary = z_input_filter($summary,$mimetype,$execflag);
|
||||
$body = z_input_filter($body,$mimetype,$execflag);
|
||||
}
|
||||
|
||||
|
||||
$arr = [ 'profile_uid' => $profile_uid, 'content' => $body, 'mimetype' => $mimetype ];
|
||||
$arr = [ 'profile_uid' => $profile_uid, 'summary' => $summary, 'content' => $body, 'mimetype' => $mimetype ];
|
||||
call_hooks('post_content',$arr);
|
||||
$summary = $arr['summary'];
|
||||
$body = $arr['content'];
|
||||
$mimetype = $arr['mimetype'];
|
||||
|
||||
@@ -531,10 +722,24 @@ class Item extends \Zotlabs\Web\Controller {
|
||||
// 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);
|
||||
|
||||
$body = cleanup_bbcode($body);
|
||||
|
||||
// Look for tags and linkify them
|
||||
$results = linkify_tags($a, $body, ($uid) ? $uid : $profile_uid);
|
||||
|
||||
$results = linkify_tags($summary, ($uid) ? $uid : $profile_uid);
|
||||
$results = linkify_tags($body, ($uid) ? $uid : $profile_uid);
|
||||
|
||||
if($results) {
|
||||
|
||||
@@ -555,7 +760,12 @@ class Item extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(($str_contact_allow) && (! $str_group_allow)) {
|
||||
// direct message - private between individual channels but not groups
|
||||
$private = 2;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -579,6 +789,9 @@ class Item extends \Zotlabs\Web\Controller {
|
||||
if(! $preview) {
|
||||
fix_attached_photo_permissions($profile_uid,$owner_xchan['xchan_hash'],((strpos($body,'[/crypt]')) ? $_POST['media_str'] : $body),$str_contact_allow,$str_group_allow,$str_contact_deny,$str_group_deny);
|
||||
|
||||
fix_attached_photo_permissions($profile_uid,$owner_xchan['xchan_hash'],((strpos($summary,'[/crypt]')) ? $_POST['media_str'] : $summary),$str_contact_allow,$str_group_allow,$str_contact_deny,$str_group_deny);
|
||||
|
||||
|
||||
fix_attached_file_permissions($channel,$observer['xchan_hash'],((strpos($body,'[/crypt]')) ? $_POST['media_str'] : $body),$str_contact_allow,$str_group_allow,$str_contact_deny,$str_group_deny);
|
||||
|
||||
}
|
||||
@@ -616,9 +829,9 @@ class Item extends \Zotlabs\Web\Controller {
|
||||
|
||||
|
||||
if(preg_match_all('/(\[share=(.*?)\](.*?)\[\/share\])/',$body,$match)) {
|
||||
|
||||
// process share by id
|
||||
|
||||
$verb = ACTIVITY_SHARE;
|
||||
$i = 0;
|
||||
foreach($match[2] as $mtch) {
|
||||
$reshare = new \Zotlabs\Lib\Share($mtch);
|
||||
@@ -711,7 +924,8 @@ class Item extends \Zotlabs\Web\Controller {
|
||||
$notify_type = (($parent) ? 'comment-new' : 'wall-new' );
|
||||
|
||||
if(! $mid) {
|
||||
$mid = (($message_id) ? $message_id : item_message_id());
|
||||
$uuid = (($message_id) ? $message_id : item_message_id());
|
||||
$mid = z_root() . '/item/' . $uuid;
|
||||
}
|
||||
|
||||
|
||||
@@ -736,7 +950,7 @@ class Item extends \Zotlabs\Web\Controller {
|
||||
// fix permalinks for cards
|
||||
|
||||
if($webpage == ITEM_TYPE_CARD) {
|
||||
$plink = z_root() . '/cards/' . $channel['channel_address'] . '/' . (($pagetitle) ? $pagetitle : substr($mid,0,16));
|
||||
$plink = z_root() . '/cards/' . $channel['channel_address'] . '/' . (($pagetitle) ? $pagetitle : $uuid);
|
||||
}
|
||||
if(($parent_item) && ($parent_item['item_type'] == ITEM_TYPE_CARD)) {
|
||||
$r = q("select v from iconfig where iconfig.cat = 'system' and iconfig.k = 'CARD' and iconfig.iid = %d limit 1",
|
||||
@@ -748,7 +962,7 @@ class Item extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
|
||||
if($webpage == ITEM_TYPE_ARTICLE) {
|
||||
$plink = z_root() . '/articles/' . $channel['channel_address'] . '/' . (($pagetitle) ? $pagetitle : substr($mid,0,16));
|
||||
$plink = z_root() . '/articles/' . $channel['channel_address'] . '/' . (($pagetitle) ? $pagetitle : $uuid);
|
||||
}
|
||||
if(($parent_item) && ($parent_item['item_type'] == ITEM_TYPE_ARTICLE)) {
|
||||
$r = q("select v from iconfig where iconfig.cat = 'system' and iconfig.k = 'ARTICLE' and iconfig.iid = %d limit 1",
|
||||
@@ -760,12 +974,13 @@ class Item extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
|
||||
if ((! $plink) && ($item_thread_top)) {
|
||||
$plink = z_root() . '/channel/' . $channel['channel_address'] . '/?f=&mid=' . $mid;
|
||||
$plink = z_root() . '/channel/' . $channel['channel_address'] . '/?f=&mid=' . gen_link_id($mid);
|
||||
$plink = substr($plink,0,190);
|
||||
}
|
||||
|
||||
$datarray['aid'] = $channel['channel_account_id'];
|
||||
$datarray['uid'] = $profile_uid;
|
||||
$datarray['uuid'] = $uuid;
|
||||
$datarray['owner_xchan'] = (($owner_hash) ? $owner_hash : $owner_xchan['xchan_hash']);
|
||||
$datarray['author_xchan'] = $observer['xchan_hash'];
|
||||
$datarray['created'] = $created;
|
||||
@@ -778,6 +993,7 @@ class Item extends \Zotlabs\Web\Controller {
|
||||
$datarray['parent_mid'] = $parent_mid;
|
||||
$datarray['mimetype'] = $mimetype;
|
||||
$datarray['title'] = $title;
|
||||
$datarray['summary'] = $summary;
|
||||
$datarray['body'] = $body;
|
||||
$datarray['app'] = $app;
|
||||
$datarray['location'] = $location;
|
||||
@@ -887,12 +1103,12 @@ class Item extends \Zotlabs\Web\Controller {
|
||||
$datarray['title'] = mb_substr($datarray['title'],0,191);
|
||||
|
||||
if($webpage) {
|
||||
Zlib\IConfig::Set($datarray,'system', webpage_to_namespace($webpage),
|
||||
(($pagetitle) ? $pagetitle : substr($datarray['mid'],0,16)),true);
|
||||
IConfig::Set($datarray,'system', webpage_to_namespace($webpage),
|
||||
(($pagetitle) ? $pagetitle : basename($datarray['mid'])), true);
|
||||
}
|
||||
elseif($namespace) {
|
||||
Zlib\IConfig::Set($datarray,'system', $namespace,
|
||||
(($remote_id) ? $remote_id : substr($datarray['mid'],0,16)),true);
|
||||
IConfig::Set($datarray,'system', $namespace,
|
||||
(($remote_id) ? $remote_id : basename($datarray['mid'])), true);
|
||||
}
|
||||
|
||||
|
||||
@@ -924,7 +1140,7 @@ class Item extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
}
|
||||
if(! $nopush)
|
||||
\Zotlabs\Daemon\Master::Summon(array('Notifier', 'edit_post', $post_id));
|
||||
Master::Summon([ 'Notifier', 'edit_post', $post_id ]);
|
||||
|
||||
|
||||
if($api_source)
|
||||
@@ -959,7 +1175,7 @@ class Item extends \Zotlabs\Web\Controller {
|
||||
// otherwise it will happen during delivery
|
||||
|
||||
if(($datarray['owner_xchan'] != $datarray['author_xchan']) && (intval($parent_item['item_wall']))) {
|
||||
Zlib\Enotify::submit(array(
|
||||
Enotify::submit(array(
|
||||
'type' => NOTIFY_COMMENT,
|
||||
'from_xchan' => $datarray['author_xchan'],
|
||||
'to_xchan' => $datarray['owner_xchan'],
|
||||
@@ -977,7 +1193,7 @@ class Item extends \Zotlabs\Web\Controller {
|
||||
$parent = $post_id;
|
||||
|
||||
if(($datarray['owner_xchan'] != $datarray['author_xchan']) && ($datarray['item_type'] == ITEM_TYPE_POST)) {
|
||||
Zlib\Enotify::submit(array(
|
||||
Enotify::submit(array(
|
||||
'type' => NOTIFY_WALL,
|
||||
'from_xchan' => $datarray['author_xchan'],
|
||||
'to_xchan' => $datarray['owner_xchan'],
|
||||
@@ -1039,7 +1255,7 @@ class Item extends \Zotlabs\Web\Controller {
|
||||
call_hooks('post_local_end', $datarray);
|
||||
|
||||
if(! $nopush)
|
||||
\Zotlabs\Daemon\Master::Summon(array('Notifier', $notify_type, $post_id));
|
||||
Master::Summon([ 'Notifier', $notify_type, $post_id ]);
|
||||
|
||||
logger('post_complete');
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
<?php
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
use Zotlabs\Lib\Activity;
|
||||
|
||||
require_once('include/security.php');
|
||||
require_once('include/bbcode.php');
|
||||
require_once('include/items.php');
|
||||
@@ -374,10 +376,13 @@ class Like extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
}
|
||||
|
||||
$mid = item_message_id();
|
||||
$uuid = item_message_id();
|
||||
|
||||
$arr = array();
|
||||
|
||||
$arr['uuid'] = $uuid;
|
||||
$arr['mid'] = z_root() . '/item/' . $uuid;
|
||||
|
||||
if($extended_like) {
|
||||
$arr['item_thread_top'] = 1;
|
||||
$arr['item_origin'] = 1;
|
||||
@@ -400,6 +405,7 @@ class Like extends \Zotlabs\Web\Controller {
|
||||
$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'],
|
||||
@@ -479,14 +485,13 @@ class Like extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
|
||||
|
||||
$arr['mid'] = $mid;
|
||||
$arr['aid'] = (($extended_like) ? $ch[0]['channel_account_id'] : $owner_aid);
|
||||
$arr['uid'] = $owner_uid;
|
||||
|
||||
|
||||
$arr['item_flags'] = $item_flags;
|
||||
$arr['item_wall'] = $item_wall;
|
||||
$arr['parent_mid'] = (($extended_like) ? $mid : $item['mid']);
|
||||
$arr['parent_mid'] = (($extended_like) ? $arr['mid'] : $item['mid']);
|
||||
$arr['owner_xchan'] = (($extended_like) ? $ch[0]['xchan_hash'] : $thread_owner['xchan_hash']);
|
||||
$arr['author_xchan'] = $observer['xchan_hash'];
|
||||
|
||||
@@ -541,7 +546,7 @@ class Like extends \Zotlabs\Web\Controller {
|
||||
dbesc($observer['xchan_hash']),
|
||||
dbesc($ch[0]['channel_hash']),
|
||||
intval($post_id),
|
||||
dbesc($mid),
|
||||
dbesc($arr['mid']),
|
||||
dbesc($activity),
|
||||
dbesc(($tgttype)? $tgttype : $objtype),
|
||||
dbesc($obj_id),
|
||||
@@ -550,7 +555,7 @@ class Like extends \Zotlabs\Web\Controller {
|
||||
$r = q("select * from likes where liker = '%s' and likee = '%s' and i_mid = '%s' and verb = '%s' and target_type = '%s' and target_id = '%s' ",
|
||||
dbesc($observer['xchan_hash']),
|
||||
dbesc($ch[0]['channel_hash']),
|
||||
dbesc($mid),
|
||||
dbesc($arr['mid']),
|
||||
dbesc($activity),
|
||||
dbesc(($tgttype)? $tgttype : $objtype),
|
||||
dbesc($obj_id)
|
||||
|
||||
@@ -2,9 +2,6 @@
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class Linkinfo extends \Zotlabs\Web\Controller {
|
||||
|
||||
function get() {
|
||||
@@ -48,7 +45,22 @@ class Linkinfo extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
|
||||
logger('linkinfo: ' . $url);
|
||||
|
||||
|
||||
// Replace plink URL with 'share' tag if possible
|
||||
preg_match("/(mid=b64\.|display\/|posts\/)([\w\-]+)(&.+)?$/", $url, $mid);
|
||||
|
||||
if (!empty($mid) && $mid[1] == 'mid=b64.')
|
||||
$mid[2] = base64_decode($mid[2]);
|
||||
|
||||
$r = q("SELECT id FROM item WHERE mid = '%s' AND uid = %d AND item_private = 0 LIMIT 1",
|
||||
dbesc((empty($mid) ? $url : $mid[2])),
|
||||
intval(local_channel())
|
||||
);
|
||||
if ($r) {
|
||||
echo "[share=" . $r[0]['id'] . "][/share]";
|
||||
killme();
|
||||
}
|
||||
|
||||
$result = z_fetch_url($url,false,0,array('novalidate' => true, 'nobody' => true));
|
||||
if($result['success']) {
|
||||
$hdrs=array();
|
||||
@@ -69,6 +81,14 @@ class Linkinfo extends \Zotlabs\Web\Controller {
|
||||
killme();
|
||||
}
|
||||
if(stripos($type,'video/') !== false) {
|
||||
$thumb = self::get_video_poster($url);
|
||||
if($thumb) {
|
||||
if ($zrl)
|
||||
echo $br . '[zvideo poster=\'' . $thumb . '\']' . $url . '[/zvideo]' . $br;
|
||||
else
|
||||
echo $br . '[video poster=\'' . $thumb . '\']' . $url . '[/video]' . $br;
|
||||
killme();
|
||||
}
|
||||
if($zrl)
|
||||
echo $br . '[zvideo]' . $url . '[/zvideo]' . $br;
|
||||
else
|
||||
@@ -216,7 +236,42 @@ class Linkinfo extends \Zotlabs\Web\Controller {
|
||||
|
||||
return($complete);
|
||||
}
|
||||
|
||||
|
||||
public static function get_video_poster($url) {
|
||||
|
||||
if(strpos($url,z_root() . '/cloud/') === false) {
|
||||
return EMPTY_STR;
|
||||
}
|
||||
$m = parse_url($url,PHP_URL_PATH);
|
||||
if($m) {
|
||||
// strip leading '/cloud/'
|
||||
$m = substr($m,7);
|
||||
}
|
||||
$nick = substr($m,0,strpos($m,'/'));
|
||||
$p = substr($m,strpos($m,'/')+1);
|
||||
|
||||
// get the channel to check permissions
|
||||
|
||||
$u = channelx_by_nick($nick);
|
||||
|
||||
if($u && $p) {
|
||||
|
||||
$sql_extra = permissions_sql(intval($u['channel_id']));
|
||||
|
||||
$r = q("select hash, content from attach where display_path = '%s' and uid = %d and os_storage = 1 $sql_extra limit 1",
|
||||
dbesc($p),
|
||||
intval($u['channel_id'])
|
||||
);
|
||||
if($r) {
|
||||
$path = dbunescbin($r[0]['content']);
|
||||
if($path && @file_exists($path . '.thumb')) {
|
||||
return z_root() . '/poster/' . $nick . '/' . $r[0]['hash'];
|
||||
}
|
||||
}
|
||||
}
|
||||
return EMPTY_STR;
|
||||
}
|
||||
|
||||
|
||||
public static function parseurl_getsiteinfo($url) {
|
||||
$siteinfo = array();
|
||||
@@ -232,7 +287,7 @@ class Linkinfo extends \Zotlabs\Web\Controller {
|
||||
// Check codepage in HTTP headers or HTML if not exist
|
||||
$cp = (preg_match('/Content-Type: text\/html; charset=(.+)\r\n/i', $header, $o) ? $o[1] : '');
|
||||
if(empty($cp))
|
||||
$cp = (preg_match('/meta.+content=["|\']text\/html; charset=([^"|\']+)/i', $body, $o) ? $o[1] : 'AUTO');
|
||||
$cp = (preg_match('/meta.+content=["\']text\/html; charset=([^"\']+)/i', $body, $o) ? $o[1] : 'AUTO');
|
||||
|
||||
$body = mb_convert_encoding($body, 'UTF-8', $cp);
|
||||
$body = mb_convert_encoding($body, 'HTML-ENTITIES', "UTF-8");
|
||||
@@ -401,8 +456,9 @@ class Linkinfo extends \Zotlabs\Web\Controller {
|
||||
|
||||
while (strpos($text, " "))
|
||||
$text = trim(str_replace(" ", " ", $text));
|
||||
|
||||
$siteinfo["text"] = html_entity_decode(substr($text,0,350), ENT_QUOTES, "UTF-8").'...';
|
||||
|
||||
$text = substr(html_entity_decode($text, ENT_QUOTES, "UTF-8"), 0, 350);
|
||||
$siteinfo["text"] = rtrim(substr($text, 0, strrpos($text, " ")), "?.,:;!-") . '...';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -76,7 +76,7 @@ class Lockview extends \Zotlabs\Web\Controller {
|
||||
killme();
|
||||
}
|
||||
|
||||
if(($item['item_private'] == 1) && (! strlen($item['allow_cid'])) && (! strlen($item['allow_gid']))
|
||||
if(intval($item['item_private']) && (! strlen($item['allow_cid'])) && (! strlen($item['allow_gid']))
|
||||
&& (! strlen($item['deny_cid'])) && (! strlen($item['deny_gid']))) {
|
||||
|
||||
// if the post is private, but public_policy is blank ("visible to the internet"), and there aren't any
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
<?php
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
use Zotlabs\Web\HTTPSig;
|
||||
|
||||
@require_once('include/zot.php');
|
||||
|
||||
|
||||
@@ -152,10 +154,9 @@ class Magic extends \Zotlabs\Web\Controller {
|
||||
$headers['Accept'] = 'application/x-zot+json' ;
|
||||
$headers['X-Open-Web-Auth'] = random_string();
|
||||
$headers['Host'] = $parsed['host'];
|
||||
$headers['Digest'] = 'SHA-256=' . \Zotlabs\Web\HTTPSig::generate_digest($data,false);
|
||||
$headers['Digest'] = HTTPSig::generate_digest_header($data);
|
||||
|
||||
$headers = \Zotlabs\Web\HTTPSig::create_sig('',$headers,$channel['channel_prvkey'],
|
||||
'acct:' . $channel['channel_address'] . '@' . \App::get_hostname(),false,true,'sha512');
|
||||
$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']) {
|
||||
@@ -169,8 +170,8 @@ class Magic extends \Zotlabs\Web\Controller {
|
||||
$token = $j['token'];
|
||||
}
|
||||
|
||||
$x = strpbrk($dest,'?&');
|
||||
$args = (($x) ? '&owt=' . $token : '?f=&owt=' . $token) . (($delegate) ? '&delegate=1' : '');
|
||||
$strp = strpbrk($dest,'?&');
|
||||
$args = (($strp) ? '&owt=' . $token : '?f=&owt=' . $token) . (($delegate) ? '&delegate=1' : '');
|
||||
goaway($dest . $args);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,10 @@ class Mail extends \Zotlabs\Web\Controller {
|
||||
$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) {
|
||||
|
||||
@@ -34,7 +38,7 @@ class Mail extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
else {
|
||||
$body = cleanup_bbcode($body);
|
||||
$results = linkify_tags($a, $body, local_channel());
|
||||
$results = linkify_tags($body, local_channel());
|
||||
|
||||
if(preg_match_all('/(\[attachment\](.*?)\[\/attachment\])/',$body,$match)) {
|
||||
$attachments = array();
|
||||
@@ -111,7 +115,7 @@ class Mail extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
|
||||
require_once('include/text.php');
|
||||
linkify_tags($a, $body, local_channel());
|
||||
linkify_tags($body, local_channel());
|
||||
|
||||
|
||||
if(! $recipient) {
|
||||
@@ -123,7 +127,7 @@ class Mail extends \Zotlabs\Web\Controller {
|
||||
|
||||
// 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);
|
||||
$ret = send_message(0, $recipient, $body, $subject, $replyto, $expires, $mimetype, $raw, $sig);
|
||||
|
||||
if($ret['success']) {
|
||||
xchan_mail_query($ret['mail']);
|
||||
@@ -396,8 +400,9 @@ class Mail extends \Zotlabs\Web\Controller {
|
||||
'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'];
|
||||
|
||||
}
|
||||
|
||||
@@ -70,7 +70,8 @@ class Mood extends Controller {
|
||||
|
||||
$poster = App::get_observer();
|
||||
|
||||
$mid = item_message_id();
|
||||
$uuid = item_message_id();
|
||||
$mid = z_root() . '/item/' . $uuid;
|
||||
|
||||
$action = sprintf( t('%1$s is %2$s','mood'), '[zrl=' . $poster['xchan_url'] . ']' . $poster['xchan_name'] . '[/zrl]' , $verbs[$verb]);
|
||||
|
||||
@@ -78,6 +79,7 @@ class Mood extends Controller {
|
||||
|
||||
$arr['aid'] = get_account_id();
|
||||
$arr['uid'] = $uid;
|
||||
$arr['uuid'] = $uuid;
|
||||
$arr['mid'] = $mid;
|
||||
$arr['parent_mid'] = (($parent_mid) ? $parent_mid : $mid);
|
||||
$arr['author_xchan'] = $poster['xchan_hash'];
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
<?php
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
use Zotlabs\Lib\Group;
|
||||
use Zotlabs\Lib\Apps;
|
||||
use App;
|
||||
|
||||
require_once('include/items.php');
|
||||
@@ -114,8 +116,8 @@ class Network extends \Zotlabs\Web\Controller {
|
||||
$def_acl = array('allow_gid' => '<' . $r[0]['hash'] . '>');
|
||||
}
|
||||
|
||||
$default_cmin = ((feature_enabled(local_channel(),'affinity')) ? get_pconfig(local_channel(),'affinity','cmin',0) : (-1));
|
||||
$default_cmax = ((feature_enabled(local_channel(),'affinity')) ? get_pconfig(local_channel(),'affinity','cmax',99) : (-1));
|
||||
$default_cmin = ((Apps::system_app_installed(local_channel(),'Affinity Tool')) ? get_pconfig(local_channel(),'affinity','cmin',0) : (-1));
|
||||
$default_cmax = ((Apps::system_app_installed(local_channel(),'Affinity Tool')) ? get_pconfig(local_channel(),'affinity','cmax',99) : (-1));
|
||||
|
||||
$cid = ((x($_GET,'cid')) ? intval($_GET['cid']) : 0);
|
||||
$star = ((x($_GET,'star')) ? intval($_GET['star']) : 0);
|
||||
@@ -132,6 +134,13 @@ class Network extends \Zotlabs\Web\Controller {
|
||||
|
||||
$deftag = '';
|
||||
|
||||
if (Apps::system_app_installed(local_channel(),'Affinity Tool')) {
|
||||
$affinity_locked = intval(get_pconfig(local_channel(),'affinity','lock',1));
|
||||
if ($affinity_locked) {
|
||||
set_pconfig(local_channel(),'affinity','cmin',$cmin);
|
||||
set_pconfig(local_channel(),'affinity','cmax',$cmax);
|
||||
}
|
||||
}
|
||||
|
||||
if(x($_GET,'search') || $file || (!$pf && $cid) || $hashtags || $verb || $category || $conv || $unseen)
|
||||
$nouveau = true;
|
||||
@@ -359,19 +368,19 @@ class Network extends \Zotlabs\Web\Controller {
|
||||
'$static' => $static,
|
||||
'$list' => ((x($_REQUEST,'list')) ? intval($_REQUEST['list']) : 0),
|
||||
'$page' => ((App::$pager['page'] != 1) ? App::$pager['page'] : 1),
|
||||
'$search' => (($search) ? $search : ''),
|
||||
'$xchan' => $xchan,
|
||||
'$search' => (($search) ? urlencode($search) : ''),
|
||||
'$xchan' => (($xchan) ? urlencode($xchan) : ''),
|
||||
'$order' => $order,
|
||||
'$file' => $file,
|
||||
'$cats' => urlencode($category),
|
||||
'$tags' => urlencode($hashtags),
|
||||
'$file' => (($file) ? urlencode($file) : ''),
|
||||
'$cats' => (($category) ? urlencode($category) : ''),
|
||||
'$tags' => (($hashtags) ? urlencode($hashtags) : ''),
|
||||
'$dend' => $datequery,
|
||||
'$mid' => '',
|
||||
'$verb' => $verb,
|
||||
'$net' => $net,
|
||||
'$verb' => (($verb) ? urlencode($verb) : ''),
|
||||
'$net' => (($net) ? urlencode($net) : ''),
|
||||
'$dbegin' => $datequery2,
|
||||
'$pf' => (($pf) ? $pf : '0'),
|
||||
'$unseen' => $unseen
|
||||
'$pf' => (($pf) ? intval($pf) : 0),
|
||||
'$unseen' => (($unseen) ? urlencode($unseen) : '')
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
@@ -134,7 +134,7 @@ class New_channel extends \Zotlabs\Web\Controller {
|
||||
$default_role = '';
|
||||
$aid = get_account_id();
|
||||
if($aid) {
|
||||
$r = q("select count(channel_id) as total from channel where channel_account_id = %d",
|
||||
$r = q("select count(channel_id) as total from channel where channel_account_id = %d and channel_removed = 0",
|
||||
intval($aid)
|
||||
);
|
||||
if($r && (! intval($r[0]['total']))) {
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
<?php
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
|
||||
class Nojs extends \Zotlabs\Web\Controller {
|
||||
|
||||
function init() {
|
||||
$n = ((argc() > 1) ? intval(argv(1)) : 1);
|
||||
setcookie('jsdisabled', $n, 0, '/');
|
||||
$p = hex2bin($_GET['redir']);
|
||||
$hasq = strpbrk($p,'?&');
|
||||
goaway(z_root() . (($p) ? '/' . $p : '') . (($hasq) ? '' : '?f=' ) . '&jsdisabled=' . $n);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,28 +1,31 @@
|
||||
<?php
|
||||
namespace Zotlabs\Module; /** @file */
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
use App;
|
||||
use Zotlabs\Web\Controller;
|
||||
use Zotlabs\Lib\Apps;
|
||||
|
||||
/**
|
||||
* @brief Notes Module controller.
|
||||
*/
|
||||
class Notes extends Controller {
|
||||
|
||||
function post() {
|
||||
|
||||
|
||||
if(! local_channel())
|
||||
return EMPTY_STR;
|
||||
|
||||
if(! Apps::system_app_installed(local_channel(), 'Notes'))
|
||||
return EMPTY_STR;
|
||||
|
||||
|
||||
$ret = array('success' => true);
|
||||
if(array_key_exists('note_text',$_REQUEST)) {
|
||||
$body = escape_tags($_REQUEST['note_text']);
|
||||
|
||||
|
||||
// I've had my notes vanish into thin air twice in four years.
|
||||
// Provide a backup copy if there were contents previously
|
||||
// Provide a backup copy if there were contents previously
|
||||
// and there are none being saved now.
|
||||
|
||||
|
||||
if(! $body) {
|
||||
$old_text = get_pconfig(local_channel(),'notes','text');
|
||||
if($old_text)
|
||||
@@ -40,11 +43,9 @@ class Notes extends Controller {
|
||||
|
||||
logger('notes saved.', LOGGER_DEBUG);
|
||||
json_return_and_die($ret);
|
||||
|
||||
}
|
||||
|
||||
function get() {
|
||||
|
||||
if(! local_channel())
|
||||
return EMPTY_STR;
|
||||
|
||||
@@ -61,7 +62,6 @@ class Notes extends Controller {
|
||||
$arr = ['app' => true];
|
||||
|
||||
return $w->widget($arr);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -181,7 +181,7 @@ class Oep extends \Zotlabs\Web\Controller {
|
||||
dbesc($res)
|
||||
);
|
||||
if($r) {
|
||||
$sql_extra = "and item.id = " . intval($r[0]['iid']) . " ";
|
||||
$sql_extra .= " and item.id = " . intval($r[0]['iid']) . " ";
|
||||
}
|
||||
else {
|
||||
return $ret;
|
||||
@@ -194,6 +194,9 @@ class Oep extends \Zotlabs\Web\Controller {
|
||||
intval(ITEM_TYPE_CARD)
|
||||
);
|
||||
|
||||
if(! $r)
|
||||
return;
|
||||
|
||||
$item_normal = " and item.item_hidden = 0 and item.item_type in (0,6) and item.item_deleted = 0
|
||||
and item.item_unpublished = 0 and item.item_delayed = 0 and item.item_pending_remove = 0
|
||||
and item.item_blocked = 0 ";
|
||||
@@ -255,7 +258,6 @@ class Oep extends \Zotlabs\Web\Controller {
|
||||
if(! $channel)
|
||||
return $ret;
|
||||
|
||||
|
||||
if(! perm_is_allowed($channel['channel_id'],get_observer_hash(),'view_pages'))
|
||||
return $ret;
|
||||
|
||||
@@ -265,7 +267,7 @@ class Oep extends \Zotlabs\Web\Controller {
|
||||
dbesc($res)
|
||||
);
|
||||
if($r) {
|
||||
$sql_extra = "and item.id = " . intval($r[0]['iid']) . " ";
|
||||
$sql_extra .= " and item.id = " . intval($r[0]['iid']) . " ";
|
||||
}
|
||||
else {
|
||||
return $ret;
|
||||
@@ -278,6 +280,9 @@ class Oep extends \Zotlabs\Web\Controller {
|
||||
intval(ITEM_TYPE_ARTICLE)
|
||||
);
|
||||
|
||||
if(! $r)
|
||||
return;
|
||||
|
||||
$item_normal = " and item.item_hidden = 0 and item.item_type in (0,7) and item.item_deleted = 0
|
||||
and item.item_unpublished = 0 and item.item_delayed = 0 and item.item_pending_remove = 0
|
||||
and item.item_blocked = 0 ";
|
||||
@@ -451,7 +456,7 @@ class Oep extends \Zotlabs\Web\Controller {
|
||||
|
||||
if(preg_match('|//(.*?)/(.*?)/(.*?)/album/|',$url,$matches)) {
|
||||
$chn = $matches[3];
|
||||
$res = hex2bin(basename($url));
|
||||
$res = basename($url);
|
||||
}
|
||||
|
||||
if(! ($chn && $res))
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
use Zotlabs\Web\HTTPSig;
|
||||
|
||||
/**
|
||||
* OpenWebAuth verifier and token generator
|
||||
* See https://macgirvin.com/wiki/mike/OpenWebAuth/Home
|
||||
@@ -25,17 +27,34 @@ class Owa extends \Zotlabs\Web\Controller {
|
||||
continue;
|
||||
}
|
||||
|
||||
$sigblock = \Zotlabs\Web\HTTPSig::parse_sigheader($_SERVER[$head]);
|
||||
$sigblock = HTTPSig::parse_sigheader($_SERVER[$head]);
|
||||
if($sigblock) {
|
||||
$keyId = $sigblock['keyId'];
|
||||
|
||||
if($keyId) {
|
||||
|
||||
// Hubzilla connections can have both zot and zot6 hublocs
|
||||
// The connections will usually be zot so match those first
|
||||
|
||||
$r = q("select * from hubloc left join xchan on hubloc_hash = xchan_hash
|
||||
where ( hubloc_addr = '%s' or hubloc_id_url = '%s' ) ",
|
||||
where ( hubloc_addr = '%s' or hubloc_id_url = '%s' ) and hubloc_network = 'zot' ",
|
||||
dbesc(str_replace('acct:','',$keyId)),
|
||||
dbesc($keyId)
|
||||
);
|
||||
if(! $r) {
|
||||
|
||||
// If nothing was found, try searching on any network
|
||||
|
||||
if (! $r) {
|
||||
$r = q("select * from hubloc left join xchan on hubloc_hash = xchan_hash
|
||||
where ( hubloc_addr = '%s' or hubloc_id_url = '%s' )",
|
||||
dbesc(str_replace('acct:','',$keyId)),
|
||||
dbesc($keyId)
|
||||
);
|
||||
}
|
||||
|
||||
// If nothing was found on any network, use network discovery and create a new record
|
||||
|
||||
if (! $r) {
|
||||
$found = discover_by_webbie(str_replace('acct:','',$keyId));
|
||||
if($found) {
|
||||
$r = q("select * from hubloc left join xchan on hubloc_hash = xchan_hash
|
||||
@@ -45,15 +64,16 @@ class Owa extends \Zotlabs\Web\Controller {
|
||||
);
|
||||
}
|
||||
}
|
||||
if($r) {
|
||||
|
||||
if ($r) {
|
||||
foreach($r as $hubloc) {
|
||||
$verified = \Zotlabs\Web\HTTPSig::verify(file_get_contents('php://input'),$hubloc['xchan_pubkey']);
|
||||
$verified = HTTPSig::verify(file_get_contents('php://input'),$hubloc['xchan_pubkey']);
|
||||
if($verified && $verified['header_signed'] && $verified['header_valid']) {
|
||||
logger('OWA header: ' . print_r($verified,true),LOGGER_DATA);
|
||||
logger('OWA success: ' . $hubloc['hubloc_addr'],LOGGER_DATA);
|
||||
$ret['success'] = true;
|
||||
$token = random_string(32);
|
||||
\Zotlabs\Lib\Verify::create('owt',0,$token,$hubloc['hubloc_addr']);
|
||||
\Zotlabs\Lib\Verify::create('owt',0,$token,$hubloc['hubloc_network'] . ',' . $hubloc['hubloc_addr']);
|
||||
$result = '';
|
||||
openssl_public_encrypt($token,$result,$hubloc['xchan_pubkey']);
|
||||
$ret['encrypted_token'] = base64url_encode($result);
|
||||
|
||||
@@ -24,7 +24,7 @@ class Pconfig extends \Zotlabs\Web\Controller {
|
||||
$aj = intval($_POST['aj']);
|
||||
|
||||
// Do not store "serialized" data received in the $_POST
|
||||
if (preg_match('|^a:[0-9]+:{.*}$|s',$v) || preg_match('O:8:"stdClass":[0-9]+:{.*}$|s',$v)) {
|
||||
if (preg_match('|^a:[0-9]+:{.*}$|s',$v) || preg_match('|O:8:"stdClass":[0-9]+:{.*}$|s',$v)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ class Pconfig extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
|
||||
|
||||
function get() {
|
||||
function get() {
|
||||
|
||||
if(! local_channel()) {
|
||||
return login();
|
||||
|
||||
@@ -1,19 +1,20 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
require_once('include/security.php');
|
||||
require_once('include/attach.php');
|
||||
require_once('include/photo/photo_driver.php');
|
||||
|
||||
|
||||
class Photo extends \Zotlabs\Web\Controller {
|
||||
|
||||
function init() {
|
||||
|
||||
$prvcachecontrol = false;
|
||||
$streaming = null;
|
||||
$channel = null;
|
||||
$person = 0;
|
||||
$renew = false;
|
||||
|
||||
switch(argc()) {
|
||||
case 4:
|
||||
@@ -29,9 +30,17 @@ class Photo extends \Zotlabs\Web\Controller {
|
||||
killme();
|
||||
// NOTREACHED
|
||||
}
|
||||
|
||||
|
||||
$cache_mode = array(
|
||||
'on' => false,
|
||||
'age' => 86400,
|
||||
'exp' => true,
|
||||
'leak' => false
|
||||
);
|
||||
call_hooks('cache_mode_hook', $cache_mode);
|
||||
|
||||
$observer_xchan = get_observer_hash();
|
||||
$ismodified = $_SERVER['HTTP_IF_MODIFIED_SINCE'];
|
||||
$cachecontrol = '';
|
||||
|
||||
if(isset($type)) {
|
||||
|
||||
@@ -59,39 +68,44 @@ class Photo extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
}
|
||||
|
||||
$modified = filemtime($default);
|
||||
$default = z_root() . '/' . $default;
|
||||
$uid = $person;
|
||||
|
||||
$data = '';
|
||||
|
||||
$d = [ 'imgscale' => $resolution, 'channel_id' => $uid, 'default' => $default, 'data' => '', 'mimetype' => '' ];
|
||||
call_hooks('get_profile_photo',$d);
|
||||
|
||||
$resolution = $d['imgscale'];
|
||||
$uid = $d['channel_id'];
|
||||
$default = $d['default'];
|
||||
$data = $d['data'];
|
||||
$mimetype = $d['mimetype'];
|
||||
|
||||
$r = q("SELECT * FROM photo WHERE imgscale = %d AND uid = %d AND photo_usage = %d LIMIT 1",
|
||||
intval($resolution),
|
||||
intval($uid),
|
||||
intval(PHOTO_PROFILE)
|
||||
);
|
||||
if($r) {
|
||||
$modified = strtotime($r[0]['edited'] . "Z");
|
||||
$mimetype = $r[0]['mimetype'];
|
||||
if(intval($r[0]['os_storage']))
|
||||
$data = file_get_contents(dbunescbin($r[0]['content']));
|
||||
else
|
||||
$data = dbunescbin($r[0]['content']);
|
||||
}
|
||||
|
||||
if(! $data) {
|
||||
$r = q("SELECT * FROM photo WHERE imgscale = %d AND uid = %d AND photo_usage = %d LIMIT 1",
|
||||
intval($resolution),
|
||||
intval($uid),
|
||||
intval(PHOTO_PROFILE)
|
||||
);
|
||||
if($r) {
|
||||
$modified = strtotime($r[0]['edited'] . "Z");
|
||||
$data = dbunescbin($r[0]['content']);
|
||||
$mimetype = $r[0]['mimetype'];
|
||||
}
|
||||
if(intval($r[0]['os_storage']))
|
||||
$data = file_get_contents($data);
|
||||
$d = [ 'imgscale' => $resolution, 'channel_id' => $uid, 'default' => $default, 'data' => '', 'mimetype' => '' ];
|
||||
call_hooks('get_profile_photo',$d);
|
||||
|
||||
$resolution = $d['imgscale'];
|
||||
$uid = $d['channel_id'];
|
||||
$default = $d['default'];
|
||||
$data = $d['data'];
|
||||
$mimetype = $d['mimetype'];
|
||||
$modified = 0;
|
||||
}
|
||||
|
||||
if(! $data) {
|
||||
$x = z_fetch_url($default,true,0,[ 'novalidate' => true ]);
|
||||
$x = z_fetch_url(z_root() . '/' . $default, true, 0, [ 'novalidate' => true ]);
|
||||
$data = ($x['success'] ? $x['body'] : EMPTY_STR);
|
||||
$mimetype = 'image/png';
|
||||
$modified = filemtime($default);
|
||||
}
|
||||
|
||||
$cachecontrol = ', must-revalidate';
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -106,13 +120,14 @@ class Photo extends \Zotlabs\Web\Controller {
|
||||
License link: http://creativecommons.org/licenses/by/3.0/
|
||||
*/
|
||||
|
||||
// @FIXME It seems this part doesn't work because we are not setting such cookie
|
||||
$cookie_value = false;
|
||||
if (isset($_COOKIE['devicePixelRatio'])) {
|
||||
$cookie_value = intval($_COOKIE['devicePixelRatio']);
|
||||
}
|
||||
else {
|
||||
// Force revalidation of cache on next request
|
||||
$cache_directive = 'no-cache';
|
||||
// $prvcachecontrol = 'no-cache';
|
||||
$status = 'no cookie';
|
||||
}
|
||||
|
||||
@@ -129,27 +144,43 @@ class Photo extends \Zotlabs\Web\Controller {
|
||||
$resolution = 1;
|
||||
}
|
||||
|
||||
$r = q("SELECT uid, photo_usage FROM photo WHERE resource_id = '%s' AND imgscale = %d LIMIT 1",
|
||||
$r = q("SELECT uid, photo_usage, display_path FROM photo WHERE resource_id = '%s' AND imgscale = %d LIMIT 1",
|
||||
dbesc($photo),
|
||||
intval($resolution)
|
||||
);
|
||||
if($r) {
|
||||
|
||||
$allowed = (-1);
|
||||
|
||||
if(intval($r[0]['photo_usage'])) {
|
||||
$u = intval($r[0]['photo_usage']);
|
||||
if($u) {
|
||||
$allowed = 1;
|
||||
if(intval($r[0]['photo_usage']) === PHOTO_COVER)
|
||||
if($u === PHOTO_COVER)
|
||||
if($resolution < PHOTO_RES_COVER_1200)
|
||||
$allowed = (-1);
|
||||
if(intval($r[0]['photo_usage']) === PHOTO_PROFILE)
|
||||
if($u === PHOTO_PROFILE)
|
||||
if(! in_array($resolution,[4,5,6]))
|
||||
$allowed = (-1);
|
||||
if($u === PHOTO_CACHE) {
|
||||
// Validate cache
|
||||
if($cache_mode['on']) {
|
||||
$cache = array(
|
||||
'resid' => $photo,
|
||||
'status' => false
|
||||
);
|
||||
call_hooks('cache_url_hook', $cache);
|
||||
if(! $cache['status']) {
|
||||
$url = html_entity_decode($r[0]['display_path'], ENT_QUOTES);
|
||||
// SSLify if needed
|
||||
if(strpos(z_root(),'https:') !== false && strpos($url,'https:') === false)
|
||||
$url = z_root() . '/sslify/' . $filename . '?f=&url=' . urlencode($url);
|
||||
goaway($url);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if($allowed === (-1)) {
|
||||
if($allowed === (-1))
|
||||
$allowed = attach_can_view($r[0]['uid'],$observer_xchan,$photo);
|
||||
}
|
||||
|
||||
$channel = channelx_by_n($r[0]['uid']);
|
||||
|
||||
@@ -158,18 +189,21 @@ class Photo extends \Zotlabs\Web\Controller {
|
||||
dbesc($photo),
|
||||
intval($resolution)
|
||||
);
|
||||
|
||||
|
||||
$exists = (($e) ? true : false);
|
||||
|
||||
|
||||
if($exists && $allowed) {
|
||||
$expires = strtotime($e[0]['expires'] . 'Z');
|
||||
$data = dbunescbin($e[0]['content']);
|
||||
$filesize = $e[0]['filesize'];
|
||||
$mimetype = $e[0]['mimetype'];
|
||||
$modified = strtotime($e[0]['edited'] . 'Z');
|
||||
if(intval($e[0]['os_storage']))
|
||||
|
||||
if(intval($e[0]['os_storage'])) {
|
||||
$streaming = $data;
|
||||
}
|
||||
if($e[0]['allow_cid'] != '' || $e[0]['allow_gid'] != '' || $e[0]['deny_gid'] != '' || $e[0]['deny_gid'] != '')
|
||||
$prvcachecontrol = true;
|
||||
$prvcachecontrol = 'no-store, no-cache, must-revalidate';
|
||||
}
|
||||
else {
|
||||
if(! $allowed) {
|
||||
@@ -180,43 +214,28 @@ class Photo extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
http_status_exit(404,'not found');
|
||||
}
|
||||
}
|
||||
|
||||
if(! $data)
|
||||
killme();
|
||||
|
||||
$etag = '"' . md5($data . $modified) . '"';
|
||||
|
||||
if($modified == 0)
|
||||
$modified = time();
|
||||
|
||||
header_remove('Pragma');
|
||||
|
||||
if($ismodified === gmdate("D, d M Y H:i:s", $modified) . " GMT") {
|
||||
if($_SERVER['HTTP_IF_NONE_MATCH'] === $etag || $_SERVER['HTTP_IF_MODIFIED_SINCE'] === gmdate("D, d M Y H:i:s", $modified) . " GMT") {
|
||||
header_remove('Expires');
|
||||
header_remove('Cache-Control');
|
||||
header_remove('Set-Cookie');
|
||||
http_status_exit(304,'not modified');
|
||||
}
|
||||
|
||||
if(! isset($data)) {
|
||||
if(isset($resolution)) {
|
||||
switch($resolution) {
|
||||
case 4:
|
||||
$default = get_default_profile_photo();
|
||||
break;
|
||||
case 5:
|
||||
$default = get_default_profile_photo(80);
|
||||
break;
|
||||
case 6:
|
||||
$default = get_default_profile_photo(48);
|
||||
break;
|
||||
default:
|
||||
killme();
|
||||
// NOTREACHED
|
||||
break;
|
||||
}
|
||||
$x = z_fetch_url(z_root() . '/' . $default,true,0,[ 'novalidate' => true ]);
|
||||
$data = ($x['success'] ? $x['body'] : EMPTY_STR);
|
||||
$mimetype = 'image/png';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(isset($res) && intval($res) && $res < 500) {
|
||||
$ph = photo_factory($data, $mimetype);
|
||||
if($ph->is_valid()) {
|
||||
@@ -225,24 +244,14 @@ class Photo extends \Zotlabs\Web\Controller {
|
||||
$mimetype = $ph->getType();
|
||||
}
|
||||
}
|
||||
|
||||
// @FIXME Seems never invoked
|
||||
// Writing in cachefile
|
||||
if (isset($cachefile) && $cachefile != '') {
|
||||
file_put_contents($cachefile, $data);
|
||||
$modified = filemtime($cachefile);
|
||||
}
|
||||
|
||||
|
||||
header("Content-type: " . $mimetype);
|
||||
|
||||
if($prvcachecontrol) {
|
||||
if(isset($prvcachecontrol)) {
|
||||
|
||||
// it is a private photo that they have no permission to view.
|
||||
// tell the browser not to cache it, in case they authenticate
|
||||
// and subsequently have permission to see it
|
||||
|
||||
header("Cache-Control: no-store, no-cache, must-revalidate");
|
||||
header("Cache-Control: " . $prvcachecontrol);
|
||||
|
||||
}
|
||||
else {
|
||||
@@ -255,18 +264,24 @@ class Photo extends \Zotlabs\Web\Controller {
|
||||
// This has performance considerations but we highly recommend you
|
||||
// leave it alone.
|
||||
|
||||
$cache = get_config('system','photo_cache_time', 86400); // 1 day by default
|
||||
$maxage = $cache_mode['age'];
|
||||
|
||||
header("Expires: " . gmdate("D, d M Y H:i:s", time() + $cache) . " GMT");
|
||||
header("Cache-Control: max-age=" . $cache);
|
||||
if($cache_mode['exp'] || (! isset($expires)) || (isset($expires) && $expires - 60 < time()))
|
||||
$expires = time() + $maxage;
|
||||
else
|
||||
$maxage = $expires - time();
|
||||
|
||||
header("Expires: " . gmdate("D, d M Y H:i:s", $expires) . " GMT");
|
||||
header("Cache-Control: max-age=" . $maxage . $cachecontrol);
|
||||
|
||||
}
|
||||
|
||||
header("Content-type: " . $mimetype);
|
||||
header("Last-Modified: " . gmdate("D, d M Y H:i:s", $modified) . " GMT");
|
||||
header("ETag: " . $etag);
|
||||
header("Content-Length: " . (isset($filesize) ? $filesize : strlen($data)));
|
||||
|
||||
// If it's a file resource, stream it.
|
||||
|
||||
if($streaming && $channel) {
|
||||
if(strpos($streaming,'store') !== false)
|
||||
$istream = fopen($streaming,'rb');
|
||||
|
||||
@@ -239,95 +239,53 @@ class Photos extends \Zotlabs\Web\Controller {
|
||||
intval($page_owner_uid)
|
||||
);
|
||||
if(count($r)) {
|
||||
$d = (($r[0]['os_storage']) ? @file_get_contents(dbunescbin($r[0]['content'])) : dbunescbin($r[0]['content']));
|
||||
$ph = photo_factory($d, $r[0]['mimetype']);
|
||||
|
||||
$ph = photo_factory(@file_get_contents(dbunescbin($r[0]['content'])), $r[0]['mimetype']);
|
||||
if($ph->is_valid()) {
|
||||
$rotate_deg = ( (intval($_POST['rotate']) == 1) ? 270 : 90 );
|
||||
$ph->rotate($rotate_deg);
|
||||
|
||||
$width = $ph->getWidth();
|
||||
$height = $ph->getHeight();
|
||||
|
||||
if(intval($r[0]['os_storage'])) {
|
||||
@file_put_contents($r[0]['content'],$ph->imageString());
|
||||
$data = $r[0]['content'];
|
||||
$fsize = @filesize($r[0]['content']);
|
||||
q("update attach set filesize = %d where hash = '%s' and uid = %d",
|
||||
intval($fsize),
|
||||
dbesc($resource_id),
|
||||
intval($page_owner_uid)
|
||||
);
|
||||
}
|
||||
else {
|
||||
$data = $ph->imageString();
|
||||
$fsize = strlen($data);
|
||||
}
|
||||
|
||||
$x = q("update photo set edited = '%s', content = '%s', filesize = %d, height = %d, width = %d where resource_id = '%s' and uid = %d and imgscale = 0",
|
||||
dbesc(datetime_convert()),
|
||||
dbescbin($data),
|
||||
intval($fsize),
|
||||
intval($height),
|
||||
intval($width),
|
||||
|
||||
$edited = datetime_convert();
|
||||
|
||||
q("update attach set filesize = %d, edited = '%s' where hash = '%s' and uid = %d",
|
||||
strlen($ph->imageString()),
|
||||
dbescdate($edited),
|
||||
dbesc($resource_id),
|
||||
intval($page_owner_uid)
|
||||
);
|
||||
|
||||
|
||||
$ph->saveImage(dbunescbin($r[0]['content']));
|
||||
|
||||
$arr = [
|
||||
'aid' => get_account_id(),
|
||||
'uid' => intval($page_owner_uid),
|
||||
'resource_id' => dbesc($resource_id),
|
||||
'filename' => $r[0]['filename'],
|
||||
'imgscale' => 0,
|
||||
'album' => $r[0]['album'],
|
||||
'os_path' => $r[0]['os_path'],
|
||||
'os_storage' => 1,
|
||||
'os_syspath' => dbunescbin($r[0]['content']),
|
||||
'display_path' => $r[0]['display_path'],
|
||||
'photo_usage' => PHOTO_NORMAL,
|
||||
'edited' => dbescdate($edited)
|
||||
];
|
||||
|
||||
$ph->save($arr);
|
||||
|
||||
unset($arr['os_syspath']);
|
||||
|
||||
if($width > 1024 || $height > 1024)
|
||||
$ph->scaleImage(1024);
|
||||
|
||||
$width = $ph->getWidth();
|
||||
$height = $ph->getHeight();
|
||||
$data = $ph->imageString();
|
||||
$fsize = strlen($data);
|
||||
|
||||
$x = q("update photo set edited = '%s', content = '%s', filesize = %d, height = %d, width = %d where resource_id = '%s' and uid = %d and imgscale = 1",
|
||||
dbesc(datetime_convert()),
|
||||
dbescbin($data),
|
||||
intval($fsize),
|
||||
intval($height),
|
||||
intval($width),
|
||||
dbesc($resource_id),
|
||||
intval($page_owner_uid)
|
||||
);
|
||||
|
||||
|
||||
$ph->storeThumbnail($arr, PHOTO_RES_1024);
|
||||
|
||||
if($width > 640 || $height > 640)
|
||||
$ph->scaleImage(640);
|
||||
|
||||
$width = $ph->getWidth();
|
||||
$height = $ph->getHeight();
|
||||
$data = $ph->imageString();
|
||||
$fsize = strlen($data);
|
||||
|
||||
$x = q("update photo set edited = '%s', content = '%s', filesize = %d, height = %d, width = %d where resource_id = '%s' and uid = %d and imgscale = 2",
|
||||
dbesc(datetime_convert()),
|
||||
dbescbin($data),
|
||||
intval($fsize),
|
||||
intval($height),
|
||||
intval($width),
|
||||
dbesc($resource_id),
|
||||
intval($page_owner_uid)
|
||||
);
|
||||
|
||||
|
||||
$ph->storeThumbnail($arr, PHOTO_RES_640);
|
||||
|
||||
if($width > 320 || $height > 320)
|
||||
$ph->scaleImage(320);
|
||||
|
||||
$width = $ph->getWidth();
|
||||
$height = $ph->getHeight();
|
||||
$data = $ph->imageString();
|
||||
$fsize = strlen($data);
|
||||
|
||||
$x = q("update photo set edited = '%s', content = '%s', filesize = %d, height = %d, width = %d where resource_id = '%s' and uid = %d and imgscale = 3",
|
||||
dbesc(datetime_convert()),
|
||||
dbescbin($data),
|
||||
intval($fsize),
|
||||
intval($height),
|
||||
intval($width),
|
||||
dbesc($resource_id),
|
||||
intval($page_owner_uid)
|
||||
);
|
||||
$ph->storeThumbnail($arr, PHOTO_RES_320);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -422,7 +380,7 @@ class Photos extends \Zotlabs\Web\Controller {
|
||||
require_once('include/text.php');
|
||||
$profile_uid = \App::$profile['profile_uid'];
|
||||
|
||||
$results = linkify_tags($a, $rawtags, (local_channel()) ? local_channel() : $profile_uid);
|
||||
$results = linkify_tags($rawtags, (local_channel()) ? local_channel() : $profile_uid);
|
||||
|
||||
$success = $results['success'];
|
||||
$post_tags = array();
|
||||
@@ -848,7 +806,7 @@ class Photos extends \Zotlabs\Web\Controller {
|
||||
killme();
|
||||
}
|
||||
else {
|
||||
$o .= "<script> var page_query = '" . escape_tags($_GET['q']) . "'; var extra_args = '" . extra_query_args() . "' ; </script>";
|
||||
$o .= "<script> var page_query = '" . escape_tags(urlencode($_GET['q'])) . "'; var extra_args = '" . extra_query_args() . "' ; </script>";
|
||||
$tpl = get_markup_template('photo_album.tpl');
|
||||
$o .= replace_macros($tpl, array(
|
||||
'$photos' => $photos,
|
||||
@@ -1396,7 +1354,7 @@ class Photos extends \Zotlabs\Web\Controller {
|
||||
killme();
|
||||
}
|
||||
else {
|
||||
$o .= "<script> var page_query = '" . escape_tags($_GET['q']) . "'; var extra_args = '" . extra_query_args() . "' ; </script>";
|
||||
$o .= "<script> var page_query = '" . escape_tags(urlencode($_GET['q'])) . "'; var extra_args = '" . extra_query_args() . "' ; </script>";
|
||||
$tpl = get_markup_template('photos_recent.tpl');
|
||||
$o .= replace_macros($tpl, array(
|
||||
'$title' => t('Recent Photos'),
|
||||
|
||||
@@ -282,8 +282,8 @@ class Ping extends \Zotlabs\Web\Controller {
|
||||
if(strpos($message, $tt['xname']) === 0)
|
||||
$message = substr($message, strlen($tt['xname']) + 1);
|
||||
|
||||
|
||||
$mid = basename($tt['link']);
|
||||
$mid = ((strpos($mid, 'b64.') === 0) ? @base64url_decode(substr($mid, 4)) : $mid);
|
||||
|
||||
if(in_array($tt['verb'], [ACTIVITY_LIKE, ACTIVITY_DISLIKE])) {
|
||||
// we need the thread parent
|
||||
@@ -291,7 +291,6 @@ class Ping extends \Zotlabs\Web\Controller {
|
||||
dbesc($mid),
|
||||
intval(local_channel())
|
||||
);
|
||||
|
||||
$b64mid = ((strpos($r[0]['thr_parent'], 'b64.') === 0) ? $r[0]['thr_parent'] : 'b64.' . base64url_encode($r[0]['thr_parent']));
|
||||
}
|
||||
else {
|
||||
@@ -447,7 +446,7 @@ class Ping extends \Zotlabs\Web\Controller {
|
||||
$when = day_translate(datetime_convert('UTC', (($rr['adjust']) ? date_default_timezone_get() : 'UTC'), $rr['dtstart'], $bd_format)) . (($today) ? ' ' . t('[today]') : '');
|
||||
|
||||
$result[] = array(
|
||||
'notify_link' => z_root() . '/events', /// @FIXME this takes you to an edit page and it may not be yours, we really want to just view the single event --> '/events/event/' . $rr['event_hash'],
|
||||
'notify_link' => z_root() . '/cdav/calendar/' . $rr['event_hash'],
|
||||
'name' => $rr['xchan_name'],
|
||||
'addr' => $rr['xchan_addr'],
|
||||
'url' => $rr['xchan_url'],
|
||||
|
||||
37
Zotlabs/Module/Poster.php
Normal file
37
Zotlabs/Module/Poster.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
use Zotlabs\Web\Controller;
|
||||
|
||||
require_once('include/security.php');
|
||||
|
||||
class Poster extends Controller {
|
||||
|
||||
function init() {
|
||||
|
||||
$nick = argv(1);
|
||||
$hash = argv(2);
|
||||
|
||||
if(! ($nick && $hash)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$u = channelx_by_nick($nick);
|
||||
|
||||
$sql_extra = permissions_sql(intval($u['channel_id']));
|
||||
|
||||
$r = q("select content from attach where hash = '%s' and uid = %d and os_storage = 1 $sql_extra limit 1",
|
||||
dbesc($hash),
|
||||
intval($u['channel_id'])
|
||||
);
|
||||
if($r) {
|
||||
$path = dbunescbin($r[0]['content']);
|
||||
if($path && @file_exists($path . '.thumb')) {
|
||||
header('Content-Type: image/jpeg');
|
||||
echo file_get_contents($path . '.thumb');
|
||||
killme();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -52,14 +52,39 @@ class Profile_photo extends \Zotlabs\Web\Controller {
|
||||
return;
|
||||
}
|
||||
|
||||
$channel = \App::get_channel();
|
||||
|
||||
check_form_security_token_redirectOnErr('/profile_photo', 'profile_photo');
|
||||
|
||||
// Remove cover photo
|
||||
if(isset($_POST['remove'])) {
|
||||
|
||||
$r = q("SELECT resource_id FROM photo WHERE photo_usage = %d AND uid = %d LIMIT 1",
|
||||
intval(PHOTO_PROFILE),
|
||||
intval(local_channel())
|
||||
);
|
||||
|
||||
if($r) {
|
||||
q("update photo set photo_usage = %d where photo_usage = %d and uid = %d",
|
||||
intval(PHOTO_NORMAL),
|
||||
intval(PHOTO_PROFILE),
|
||||
intval(local_channel())
|
||||
);
|
||||
|
||||
$sync = attach_export_data($channel,$r[0]['resource_id']);
|
||||
if($sync)
|
||||
build_sync_packet($channel['channel_id'],array('file' => array($sync)));
|
||||
}
|
||||
|
||||
$_SESSION['reload_avatar'] = true;
|
||||
|
||||
goaway(z_root() . '/profiles');
|
||||
}
|
||||
|
||||
if((array_key_exists('cropfinal',$_POST)) && (intval($_POST['cropfinal']) == 1)) {
|
||||
|
||||
// logger('crop: ' . print_r($_POST,true));
|
||||
|
||||
|
||||
|
||||
// phase 2 - we have finished cropping
|
||||
|
||||
if(argc() != 2) {
|
||||
@@ -119,39 +144,48 @@ class Profile_photo extends \Zotlabs\Web\Controller {
|
||||
'filename' => $base_image['filename'],
|
||||
'album' => t('Profile Photos'),
|
||||
'os_path' => $base_image['os_path'],
|
||||
'display_path' => $base_image['display_path']
|
||||
'display_path' => $base_image['display_path'],
|
||||
'photo_usage' => PHOTO_PROFILE,
|
||||
'edited' => dbescdate($base_image['edited'])
|
||||
];
|
||||
|
||||
$p['imgscale'] = PHOTO_RES_PROFILE_300;
|
||||
$p['photo_usage'] = (($is_default_profile) ? PHOTO_PROFILE : PHOTO_NORMAL);
|
||||
|
||||
$r1 = $im->save($p);
|
||||
$r1 = $im->storeThumbnail($p, PHOTO_RES_PROFILE_300);
|
||||
|
||||
$im->scaleImage(80);
|
||||
$p['imgscale'] = PHOTO_RES_PROFILE_80;
|
||||
|
||||
$r2 = $im->save($p);
|
||||
$r2 = $im->storeThumbnail($p, PHOTO_RES_PROFILE_80);
|
||||
|
||||
$im->scaleImage(48);
|
||||
$p['imgscale'] = PHOTO_RES_PROFILE_48;
|
||||
|
||||
$r3 = $im->save($p);
|
||||
|
||||
$r3 = $im->storeThumbnail($p, PHOTO_RES_PROFILE_48);
|
||||
|
||||
if($r1 === false || $r2 === false || $r3 === false) {
|
||||
// if one failed, delete them all so we can start over.
|
||||
notice( t('Image resize failed.') . EOL );
|
||||
$x = q("delete from photo where resource_id = '%s' and uid = %d and imgscale in ( %d, %d, %d ) ",
|
||||
$x = q("delete from photo where resource_id = '%s' and uid = %d and imgscale in ( %d, %d, %d )",
|
||||
dbesc($base_image['resource_id']),
|
||||
local_channel(),
|
||||
intval(PHOTO_RES_PROFILE_300),
|
||||
intval(PHOTO_RES_PROFILE_80),
|
||||
intval(PHOTO_RES_PROFILE_48)
|
||||
);
|
||||
|
||||
$x = q("SELECT content FROM photo WHERE resource_id = '%s' AND uid = %d AND os_storage = 1 AND imgscale IN ( %d, %d, %d )",
|
||||
dbesc($base_image['resource_id']),
|
||||
local_channel(),
|
||||
intval(PHOTO_RES_PROFILE_300),
|
||||
intval(PHOTO_RES_PROFILE_80),
|
||||
intval(PHOTO_RES_PROFILE_48)
|
||||
);
|
||||
if($x) {
|
||||
foreach($x as $xx) {
|
||||
@unlink(dbunescbin($xx['content']));
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$channel = \App::get_channel();
|
||||
|
||||
// If setting for the default profile, unset the profile photo flag from any other photos I own
|
||||
|
||||
if($is_default_profile) {
|
||||
@@ -198,7 +232,7 @@ class Profile_photo extends \Zotlabs\Web\Controller {
|
||||
$r = q("UPDATE xchan set xchan_photo_mimetype = '%s', xchan_photo_date = '%s', xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s'
|
||||
where xchan_hash = '%s'",
|
||||
dbesc($im->getType()),
|
||||
dbesc(datetime_convert()),
|
||||
dbescdate($base_image['edited']),
|
||||
dbesc(z_root() . '/photo/profile/l/' . $channel['channel_id']),
|
||||
dbesc(z_root() . '/photo/profile/m/' . $channel['channel_id']),
|
||||
dbesc(z_root() . '/photo/profile/s/' . $channel['channel_id']),
|
||||
@@ -245,7 +279,7 @@ class Profile_photo extends \Zotlabs\Web\Controller {
|
||||
else {
|
||||
require_once('include/attach.php');
|
||||
|
||||
$res = attach_store(\App::get_channel(), get_observer_hash(), '', array('album' => t('Profile Photos'), 'hash' => $hash));
|
||||
$res = attach_store(\App::get_channel(), get_observer_hash(), '', array('album' => t('Profile Photos'), 'hash' => $hash, 'nosync' => true));
|
||||
|
||||
logger('attach_store: ' . print_r($res,true));
|
||||
}
|
||||
@@ -353,20 +387,23 @@ class Profile_photo extends \Zotlabs\Web\Controller {
|
||||
|
||||
if($havescale) {
|
||||
// unset any existing profile photos
|
||||
$r = q("UPDATE photo SET photo_usage = %d WHERE photo_usage = %d AND uid = %d",
|
||||
$x = q("UPDATE photo SET photo_usage = %d WHERE photo_usage = %d AND uid = %d",
|
||||
intval(PHOTO_NORMAL),
|
||||
intval(PHOTO_PROFILE),
|
||||
intval(local_channel()));
|
||||
|
||||
$r = q("UPDATE photo SET photo_usage = %d WHERE uid = %d AND resource_id = '%s'",
|
||||
intval(local_channel())
|
||||
);
|
||||
|
||||
$edited = datetime_convert();
|
||||
|
||||
$x = q("UPDATE photo SET photo_usage = %d, edited = '%s' WHERE uid = %d AND resource_id = '%s' AND imgscale > 0",
|
||||
intval(PHOTO_PROFILE),
|
||||
dbescdate($edited),
|
||||
intval(local_channel()),
|
||||
dbesc($resource_id)
|
||||
);
|
||||
);
|
||||
|
||||
$r = q("UPDATE xchan set xchan_photo_date = '%s'
|
||||
where xchan_hash = '%s'",
|
||||
dbesc(datetime_convert()),
|
||||
$x = q("UPDATE xchan SET xchan_photo_date = '%s' WHERE xchan_hash = '%s'",
|
||||
dbescdate($edited),
|
||||
dbesc($channel['xchan_hash'])
|
||||
);
|
||||
|
||||
@@ -376,8 +413,10 @@ class Profile_photo extends \Zotlabs\Web\Controller {
|
||||
if($sync)
|
||||
build_sync_packet($channel['channel_id'],array('file' => array($sync)));
|
||||
|
||||
$_SESSION['reload_avatar'] = true;
|
||||
|
||||
\Zotlabs\Daemon\Master::Summon(array('Directory',local_channel()));
|
||||
|
||||
goaway(z_root() . '/profiles');
|
||||
}
|
||||
|
||||
@@ -457,6 +496,7 @@ class Profile_photo extends \Zotlabs\Web\Controller {
|
||||
'$lbl_profiles' => t('Select a profile:'),
|
||||
'$title' => (($importing) ? t('Use Photo for Profile') : t('Change Profile Photo')),
|
||||
'$submit' => (($importing) ? t('Use') : t('Upload')),
|
||||
'$remove' => t('Remove'),
|
||||
'$profiles' => $profiles,
|
||||
'$single' => ((count($profiles) == 1) ? true : false),
|
||||
'$profile0' => $profiles[0],
|
||||
|
||||
@@ -354,20 +354,20 @@ class Profiles extends \Zotlabs\Web\Controller {
|
||||
|
||||
|
||||
require_once('include/text.php');
|
||||
linkify_tags($a, $likes, local_channel());
|
||||
linkify_tags($a, $dislikes, local_channel());
|
||||
linkify_tags($a, $about, local_channel());
|
||||
linkify_tags($a, $interest, local_channel());
|
||||
linkify_tags($a, $interest, local_channel());
|
||||
linkify_tags($a, $contact, local_channel());
|
||||
linkify_tags($a, $channels, local_channel());
|
||||
linkify_tags($a, $music, local_channel());
|
||||
linkify_tags($a, $book, local_channel());
|
||||
linkify_tags($a, $tv, local_channel());
|
||||
linkify_tags($a, $film, local_channel());
|
||||
linkify_tags($a, $romance, local_channel());
|
||||
linkify_tags($a, $work, local_channel());
|
||||
linkify_tags($a, $education, local_channel());
|
||||
linkify_tags($likes, local_channel());
|
||||
linkify_tags($dislikes, local_channel());
|
||||
linkify_tags($about, local_channel());
|
||||
linkify_tags($interest, local_channel());
|
||||
linkify_tags($interest, local_channel());
|
||||
linkify_tags($contact, local_channel());
|
||||
linkify_tags($channels, local_channel());
|
||||
linkify_tags($music, local_channel());
|
||||
linkify_tags($book, local_channel());
|
||||
linkify_tags($tv, local_channel());
|
||||
linkify_tags($film, local_channel());
|
||||
linkify_tags($romance, local_channel());
|
||||
linkify_tags($work, local_channel());
|
||||
linkify_tags($education, local_channel());
|
||||
|
||||
|
||||
$with = ((x($_POST,'with')) ? escape_tags(trim($_POST['with'])) : '');
|
||||
|
||||
@@ -149,11 +149,11 @@ class Pubstream extends \Zotlabs\Web\Controller {
|
||||
'$order' => 'comment',
|
||||
'$file' => '',
|
||||
'$cats' => '',
|
||||
'$tags' => $hashtags,
|
||||
'$tags' => (($hashtags) ? urlencode($hashtags) : ''),
|
||||
'$dend' => '',
|
||||
'$mid' => $mid,
|
||||
'$mid' => (($mid) ? urlencode($mid) : ''),
|
||||
'$verb' => '',
|
||||
'$net' => $net,
|
||||
'$net' => (($net) ? urlencode($net) : ''),
|
||||
'$dbegin' => ''
|
||||
));
|
||||
}
|
||||
|
||||
@@ -44,6 +44,7 @@ class React extends \Zotlabs\Web\Controller {
|
||||
return;
|
||||
}
|
||||
|
||||
$uuid = item_message_id();
|
||||
|
||||
$n = array();
|
||||
$n['aid'] = $channel['channel_account_id'];
|
||||
@@ -52,11 +53,20 @@ class React extends \Zotlabs\Web\Controller {
|
||||
$n['item_type'] = $i[0]['item_type'];
|
||||
$n['parent'] = $postid;
|
||||
$n['parent_mid'] = $i[0]['mid'];
|
||||
$n['mid'] = item_message_id();
|
||||
$n['uuid'] = $uuid;
|
||||
$n['mid'] = z_root() . '/item/' . $uuid;
|
||||
$n['verb'] = ACTIVITY_REACT . '#' . $emoji;
|
||||
$n['body'] = "\n\n[zmg=32x32]" . z_root() . '/images/emoji/' . $emoji . '.png[/zmg]' . "\n\n";
|
||||
$n['author_xchan'] = $channel['channel_hash'];
|
||||
|
||||
$n['tgt_type'] = 'Image';
|
||||
$n['target'] = [
|
||||
'type' => 'Image',
|
||||
'name' => $emoji,
|
||||
'url' => z_root() . '/images/emoji/' . $emoji . '.png'
|
||||
];
|
||||
|
||||
|
||||
$x = item_store($n);
|
||||
|
||||
retain_item($postid);
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
<?php
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
require_once('include/channel.php');
|
||||
use Zotlabs\Web\Controller;
|
||||
|
||||
require_once('include/security.php');
|
||||
|
||||
class Register extends \Zotlabs\Web\Controller {
|
||||
class Register extends Controller {
|
||||
|
||||
function init() {
|
||||
|
||||
@@ -39,7 +40,9 @@ class Register extends \Zotlabs\Web\Controller {
|
||||
|
||||
|
||||
function post() {
|
||||
|
||||
|
||||
check_form_security_token_redirectOnErr('/register', 'register');
|
||||
|
||||
$max_dailies = intval(get_config('system','max_daily_registrations'));
|
||||
if($max_dailies) {
|
||||
$r = q("select count(account_id) as total from account where account_created > %s - INTERVAL %s",
|
||||
@@ -269,7 +272,8 @@ class Register extends \Zotlabs\Web\Controller {
|
||||
require_once('include/bbcode.php');
|
||||
|
||||
$o = replace_macros(get_markup_template('register.tpl'), array(
|
||||
|
||||
|
||||
'$form_security_token' => get_form_security_token("register"),
|
||||
'$title' => t('Registration'),
|
||||
'$reg_is' => $registration_is,
|
||||
'$registertext' => bbcode(get_config('system','register_text')),
|
||||
|
||||
@@ -14,6 +14,15 @@ class Rmagic extends \Zotlabs\Web\Controller {
|
||||
$r = q("select hubloc_url from hubloc where hubloc_addr = '%s' limit 1",
|
||||
dbesc($me)
|
||||
);
|
||||
if(! $r) {
|
||||
$w = discover_by_webbie($me);
|
||||
if($w) {
|
||||
$r = q("select hubloc_url from hubloc where hubloc_addr = '%s' limit 1",
|
||||
dbesc($me)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if($r) {
|
||||
if($r[0]['hubloc_url'] === z_root())
|
||||
goaway(z_root() . '/login');
|
||||
@@ -49,7 +58,16 @@ class Rmagic extends \Zotlabs\Web\Controller {
|
||||
$r = q("select hubloc_url from hubloc where hubloc_addr = '%s' limit 1",
|
||||
dbesc($address)
|
||||
);
|
||||
if(! $r) {
|
||||
$w = discover_by_webbie($address);
|
||||
if($w) {
|
||||
$r = q("select hubloc_url from hubloc where hubloc_addr = '%s' limit 1",
|
||||
dbesc($address)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if($r) {
|
||||
$url = $r[0]['hubloc_url'];
|
||||
}
|
||||
|
||||
@@ -38,8 +38,8 @@ class Search extends \Zotlabs\Web\Controller {
|
||||
$observer_hash = (($observer) ? $observer['xchan_hash'] : '');
|
||||
|
||||
$o = '<div id="live-search"></div>' . "\r\n";
|
||||
|
||||
$o = '<div class="generic-content-wrapper-styled">' . "\r\n";
|
||||
|
||||
$o .= '<div class="generic-content-wrapper-styled">' . "\r\n";
|
||||
|
||||
$o .= '<h3>' . t('Search') . '</h3>';
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ class Calendar {
|
||||
'$rpath' => $rpath,
|
||||
'$action_url' => 'settings/' . $module,
|
||||
'$form_security_token' => get_form_security_token('settings_' . $module),
|
||||
'$title' => t('CalDAV Settings'),
|
||||
'$title' => t('Calendar Settings'),
|
||||
'$features' => process_module_features_get(local_channel(), $features),
|
||||
'$submit' => t('Submit')
|
||||
));
|
||||
|
||||
@@ -10,20 +10,6 @@ class Featured {
|
||||
|
||||
call_hooks('feature_settings_post', $_POST);
|
||||
|
||||
if($_POST['affinity_slider-submit']) {
|
||||
$cmax = intval($_POST['affinity_cmax']);
|
||||
if($cmax < 0 || $cmax > 99)
|
||||
$cmax = 99;
|
||||
$cmin = intval($_POST['affinity_cmin']);
|
||||
if($cmin < 0 || $cmin > 99)
|
||||
$cmin = 0;
|
||||
set_pconfig(local_channel(),'affinity','cmin',$cmin);
|
||||
set_pconfig(local_channel(),'affinity','cmax',$cmax);
|
||||
|
||||
info( t('Affinity Slider settings updated.') . EOL);
|
||||
|
||||
}
|
||||
|
||||
build_sync_packet();
|
||||
return;
|
||||
}
|
||||
@@ -37,30 +23,10 @@ class Featured {
|
||||
if(! $r)
|
||||
$settings_addons = t('No feature settings configured');
|
||||
|
||||
if(feature_enabled(local_channel(),'affinity')) {
|
||||
|
||||
$cmax = intval(get_pconfig(local_channel(),'affinity','cmax'));
|
||||
$cmax = (($cmax) ? $cmax : 99);
|
||||
$setting_fields .= replace_macros(get_markup_template('field_input.tpl'), array(
|
||||
'$field' => array('affinity_cmax', t('Default maximum affinity level'), $cmax, t('0-99 default 99'))
|
||||
));
|
||||
$cmin = intval(get_pconfig(local_channel(),'affinity','cmin'));
|
||||
$cmin = (($cmin) ? $cmin : 0);
|
||||
$setting_fields .= replace_macros(get_markup_template('field_input.tpl'), array(
|
||||
'$field' => array('affinity_cmin', t('Default minimum affinity level'), $cmin, t('0-99 - default 0'))
|
||||
));
|
||||
|
||||
$settings_addons .= replace_macros(get_markup_template('generic_addon_settings.tpl'), array(
|
||||
'$addon' => array('affinity_slider', '' . t('Affinity Slider Settings'), '', t('Submit')),
|
||||
'$content' => $setting_fields
|
||||
));
|
||||
}
|
||||
|
||||
call_hooks('feature_settings', $settings_addons);
|
||||
|
||||
$this->sortpanels($settings_addons);
|
||||
|
||||
|
||||
$tpl = get_markup_template("settings_addons.tpl");
|
||||
$o .= replace_macros($tpl, array(
|
||||
'$form_security_token' => get_form_security_token("settings_featured"),
|
||||
|
||||
@@ -39,12 +39,12 @@ class Setup extends \Zotlabs\Web\Controller {
|
||||
ini_set('display_errors', '1');
|
||||
|
||||
// $baseurl/setup/testrewrite to test if rewrite in .htaccess is working
|
||||
if (argc() == 2 && argv(1) == "testrewrite") {
|
||||
if(argc() == 2 && argv(1) == 'testrewrite') {
|
||||
echo 'ok';
|
||||
killme();
|
||||
}
|
||||
|
||||
if (x($_POST, 'pass')) {
|
||||
if(x($_POST, 'pass')) {
|
||||
$this->install_wizard_pass = intval($_POST['pass']);
|
||||
} else {
|
||||
$this->install_wizard_pass = 1;
|
||||
@@ -63,7 +63,6 @@ class Setup extends \Zotlabs\Web\Controller {
|
||||
return;
|
||||
// implied break;
|
||||
case 3:
|
||||
$urlpath = \App::get_path();
|
||||
$dbhost = trim($_POST['dbhost']);
|
||||
$dbport = intval(trim($_POST['dbport']));
|
||||
$dbuser = trim($_POST['dbuser']);
|
||||
@@ -89,7 +88,6 @@ class Setup extends \Zotlabs\Web\Controller {
|
||||
return;
|
||||
// implied break;
|
||||
case 4:
|
||||
$urlpath = \App::get_path();
|
||||
$dbhost = trim($_POST['dbhost']);
|
||||
$dbport = intval(trim($_POST['dbport']));
|
||||
$dbuser = trim($_POST['dbuser']);
|
||||
@@ -162,7 +160,6 @@ class Setup extends \Zotlabs\Web\Controller {
|
||||
*
|
||||
* @return string parsed HTML output
|
||||
*/
|
||||
|
||||
function get() {
|
||||
|
||||
$o = '';
|
||||
@@ -213,10 +210,10 @@ class Setup extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
|
||||
if(x(\App::$data, 'txt') && strlen(\App::$data['txt'])) {
|
||||
$db_return_text .= $this->manual_config($a);
|
||||
$db_return_text .= $this->manual_config();
|
||||
}
|
||||
|
||||
if ($db_return_text != "") {
|
||||
if($db_return_text != '') {
|
||||
$tpl = get_markup_template('install.tpl');
|
||||
return replace_macros($tpl, array(
|
||||
'$title' => $install_title,
|
||||
@@ -242,7 +239,7 @@ class Setup extends \Zotlabs\Web\Controller {
|
||||
|
||||
$this->check_keys($checks);
|
||||
|
||||
if (x($_POST, 'phpath'))
|
||||
if(x($_POST, 'phpath'))
|
||||
$phpath = notags(trim($_POST['phpath']));
|
||||
|
||||
$this->check_php($phpath, $checks);
|
||||
@@ -278,7 +275,6 @@ class Setup extends \Zotlabs\Web\Controller {
|
||||
$dbtype = intval(trim($_POST['dbtype']));
|
||||
$phpath = trim($_POST['phpath']);
|
||||
$adminmail = trim($_POST['adminmail']);
|
||||
$siteurl = trim($_POST['siteurl']);
|
||||
|
||||
$tpl = get_markup_template('install_db.tpl');
|
||||
$o .= replace_macros($tpl, array(
|
||||
@@ -320,7 +316,6 @@ class Setup extends \Zotlabs\Web\Controller {
|
||||
$phpath = trim($_POST['phpath']);
|
||||
|
||||
$adminmail = trim($_POST['adminmail']);
|
||||
$siteurl = trim($_POST['siteurl']);
|
||||
$timezone = ((x($_POST,'timezone')) ? ($_POST['timezone']) : 'America/Los_Angeles');
|
||||
|
||||
|
||||
@@ -363,12 +358,12 @@ class Setup extends \Zotlabs\Web\Controller {
|
||||
* @param string $help optional help string
|
||||
*/
|
||||
function check_add(&$checks, $title, $status, $required, $help = '') {
|
||||
$checks[] = array(
|
||||
$checks[] = [
|
||||
'title' => $title,
|
||||
'status' => $status,
|
||||
'required' => $required,
|
||||
'help' => $help
|
||||
);
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -380,12 +375,12 @@ class Setup extends \Zotlabs\Web\Controller {
|
||||
function check_php(&$phpath, &$checks) {
|
||||
$help = '';
|
||||
|
||||
if(version_compare(PHP_VERSION, '5.5') < 0) {
|
||||
$help .= t('PHP version 5.5 or greater is required.');
|
||||
$this->check_add($checks, t('PHP version'), false, false, $help);
|
||||
if(version_compare(PHP_VERSION, '7.1') < 0) {
|
||||
$help .= t('PHP version 7.1 or greater is required.');
|
||||
$this->check_add($checks, t('PHP version'), false, true, $help);
|
||||
}
|
||||
|
||||
if (strlen($phpath)) {
|
||||
if(strlen($phpath)) {
|
||||
$passed = file_exists($phpath);
|
||||
}
|
||||
elseif(function_exists('shell_exec')) {
|
||||
@@ -419,6 +414,7 @@ class Setup extends \Zotlabs\Web\Controller {
|
||||
$result = trim(shell_exec($cmd));
|
||||
else
|
||||
$help .= t('Unable to check command line PHP, as shell_exec() is disabled. This is required.') . EOL;
|
||||
|
||||
$passed2 = (($result == $str) ? true : false);
|
||||
if(!$passed2) {
|
||||
$help .= t('The command line version of PHP on your system does not have "register_argc_argv" enabled.'). EOL;
|
||||
@@ -441,13 +437,18 @@ class Setup extends \Zotlabs\Web\Controller {
|
||||
require_once 'include/environment.php';
|
||||
|
||||
$help = '';
|
||||
$mem_warning = '';
|
||||
|
||||
$result = getPhpiniUploadLimits();
|
||||
if($result['post_max_size'] < 4194304 || $result['max_upload_filesize'] < 4194304) {
|
||||
$mem_warning = '<strong>' .t('This is not sufficient to upload larger images or files. You should be able to upload at least 4 MB at once.') . '</strong>';
|
||||
}
|
||||
$help = sprintf(t('Your max allowed total upload size is set to %s. Maximum size of one file to upload is set to %s. You are allowed to upload up to %d files at once.'),
|
||||
userReadableSize($result['post_max_size']),
|
||||
userReadableSize($result['max_upload_filesize']),
|
||||
$result['max_file_uploads']
|
||||
);
|
||||
$help .= $mem_warning;
|
||||
$help .= '<br><br>' . t('You can adjust these settings in the server php.ini file.');
|
||||
|
||||
$this->check_add($checks, t('PHP upload limits'), true, false, $help);
|
||||
@@ -462,7 +463,7 @@ class Setup extends \Zotlabs\Web\Controller {
|
||||
$help = '';
|
||||
$res = false;
|
||||
|
||||
if (function_exists('openssl_pkey_new')) {
|
||||
if(function_exists('openssl_pkey_new')) {
|
||||
$res = openssl_pkey_new(array(
|
||||
'digest_alg' => 'sha1',
|
||||
'private_key_bits' => 4096,
|
||||
@@ -472,7 +473,7 @@ class Setup extends \Zotlabs\Web\Controller {
|
||||
|
||||
// Get private key
|
||||
|
||||
if (! $res) {
|
||||
if(! $res) {
|
||||
$help .= t('Error: the "openssl_pkey_new" function on this system is not able to generate encryption keys'). EOL;
|
||||
$help .= t('If running under Windows, please see "http://www.php.net/manual/en/openssl.installation.php".');
|
||||
}
|
||||
@@ -503,7 +504,7 @@ class Setup extends \Zotlabs\Web\Controller {
|
||||
$this->check_add($ck_funcs, t('zip PHP module'), true, true);
|
||||
|
||||
if(function_exists('apache_get_modules')){
|
||||
if (! in_array('mod_rewrite', apache_get_modules())) {
|
||||
if(! in_array('mod_rewrite', apache_get_modules())) {
|
||||
$this->check_add($ck_funcs, t('Apache mod_rewrite module'), false, true, t('Error: Apache webserver mod-rewrite module is required but not installed.'));
|
||||
} else {
|
||||
$this->check_add($ck_funcs, t('Apache mod_rewrite module'), true, true);
|
||||
@@ -572,7 +573,7 @@ class Setup extends \Zotlabs\Web\Controller {
|
||||
|
||||
$fname = '.htconfig.php';
|
||||
|
||||
if((file_exists($fname) && is_writable($fname)) ||
|
||||
if((file_exists($fname) && is_writable($fname)) ||
|
||||
(! (file_exists($fname) && is_writable('.')))) {
|
||||
$this->check_add($checks, t('.htconfig.php is writable'), $status, true, $help);
|
||||
return;
|
||||
@@ -638,7 +639,7 @@ class Setup extends \Zotlabs\Web\Controller {
|
||||
|
||||
$url = z_root() . '/setup/testrewrite';
|
||||
|
||||
if (function_exists('curl_init')){
|
||||
if(function_exists('curl_init')){
|
||||
$test = z_fetch_url($url);
|
||||
if(! $test['success']) {
|
||||
if(strstr($url,'https://')) {
|
||||
@@ -661,14 +662,13 @@ class Setup extends \Zotlabs\Web\Controller {
|
||||
$help .= t('If your certificate is not recognized, members of other sites (who may themselves have valid certificates) will get a warning message on their own site complaining about security issues.') . EOL;
|
||||
$help .= t('This can cause usability issues elsewhere (not just on your own site) so we must insist on this requirement.') .EOL;
|
||||
$help .= t('Providers are available that issue free certificates which are browser-valid.'). EOL;
|
||||
|
||||
$help .= t('If you are confident that the certificate is valid and signed by a trusted authority, check to see if you have failed to install an intermediate cert. These are not normally required by browsers, but are required for server-to-server communications.') . EOL;
|
||||
|
||||
$this->check_add($checks, t('SSL certificate validation'), false, true, $help);
|
||||
}
|
||||
}
|
||||
|
||||
if ((! $test['success']) || ($test['body'] != "ok")) {
|
||||
if((! $test['success']) || ($test['body'] != "ok")) {
|
||||
$status = false;
|
||||
$help = t('Url rewrite in .htaccess is not working. Check your server configuration.'.'Test: '.var_export($test,true));
|
||||
}
|
||||
@@ -682,10 +682,9 @@ class Setup extends \Zotlabs\Web\Controller {
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @param App &$a
|
||||
* @return string with paresed HTML
|
||||
*/
|
||||
function manual_config(&$a) {
|
||||
function manual_config() {
|
||||
$data = htmlspecialchars(\App::$data['txt'], ENT_COMPAT, 'UTF-8');
|
||||
$o = t('The database configuration file ".htconfig.php" could not be written. Please use the enclosed text to create a configuration file in your web server root.');
|
||||
$o .= "<textarea rows=\"24\" cols=\"80\" >$data</textarea>";
|
||||
@@ -695,14 +694,19 @@ class Setup extends \Zotlabs\Web\Controller {
|
||||
|
||||
function load_database_rem($v, $i){
|
||||
$l = trim($i);
|
||||
if (strlen($l)>1 && ($l[0]=="-" || ($l[0]=="/" && $l[1]=="*"))){
|
||||
if(strlen($l)>1 && ($l[0]=="-" || ($l[0]=="/" && $l[1]=="*"))){
|
||||
return $v;
|
||||
} else {
|
||||
return $v."\n".$i;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Executes the SQL install script and create database tables.
|
||||
*
|
||||
* @param dba_driver $db (unused)
|
||||
* @return boolean|string false on success or error message as string
|
||||
*/
|
||||
function load_database($db) {
|
||||
$str = file_get_contents(\DBA::$dba->get_install_script());
|
||||
$arr = explode(';', $str);
|
||||
@@ -728,6 +732,12 @@ class Setup extends \Zotlabs\Web\Controller {
|
||||
// install the standard theme
|
||||
set_config('system', 'allowed_themes', 'redbasic');
|
||||
|
||||
// if imagick converter is installed, use it
|
||||
if(@is_executable('/usr/bin/convert')) {
|
||||
set_config('system','imagick_convert_path','/usr/bin/convert');
|
||||
}
|
||||
|
||||
|
||||
// Set a lenient list of ciphers if using openssl. Other ssl engines
|
||||
// (e.g. NSS used in RedHat) require different syntax, so hopefully
|
||||
// the default curl cipher list will work for most sites. If not,
|
||||
@@ -762,12 +772,12 @@ class Setup extends \Zotlabs\Web\Controller {
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @param unknown $v
|
||||
* @param array $v
|
||||
* @param array $c
|
||||
* @return array
|
||||
*/
|
||||
static private function check_passed($v, $c) {
|
||||
if ($c['required'])
|
||||
if($c['required'])
|
||||
$v = $v && $c['status'];
|
||||
|
||||
return $v;
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
<?php
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
use App;
|
||||
use Zotlabs\Daemon\Master;
|
||||
use Zotlabs\Lib\Activity;
|
||||
|
||||
|
||||
require_once('include/security.php');
|
||||
require_once('include/bbcode.php');
|
||||
|
||||
@@ -14,23 +19,23 @@ class Share extends \Zotlabs\Web\Controller {
|
||||
if(! $post_id)
|
||||
killme();
|
||||
|
||||
echo '[share=' . $post_id . '][/share]';
|
||||
killme();
|
||||
|
||||
|
||||
/**
|
||||
* The remaining code is deprecated and handled in Zotlabs/Lib/Share.php at post
|
||||
* submission time.
|
||||
*/
|
||||
|
||||
if(! (local_channel() || remote_channel()))
|
||||
if(! local_channel()) {
|
||||
killme();
|
||||
|
||||
}
|
||||
|
||||
$observer = App::get_observer();
|
||||
|
||||
$channel = App::get_channel();
|
||||
|
||||
$r = q("SELECT * from item left join xchan on author_xchan = xchan_hash WHERE id = %d LIMIT 1",
|
||||
intval($post_id)
|
||||
);
|
||||
if(! $r)
|
||||
killme();
|
||||
|
||||
|
||||
|
||||
|
||||
if(($r[0]['item_private']) && ($r[0]['xchan_network'] !== 'rss'))
|
||||
killme();
|
||||
|
||||
@@ -46,59 +51,86 @@ class Share extends \Zotlabs\Web\Controller {
|
||||
|
||||
if($r[0]['mimetype'] !== 'text/bbcode')
|
||||
killme();
|
||||
|
||||
/** @FIXME eventually we want to post remotely via rpost on your home site */
|
||||
// When that works remove this next bit:
|
||||
|
||||
if(! local_channel())
|
||||
killme();
|
||||
|
||||
|
||||
xchan_query($r);
|
||||
|
||||
$is_photo = (($r[0]['obj_type'] === ACTIVITY_OBJ_PHOTO) ? true : false);
|
||||
if($is_photo) {
|
||||
$object = json_decode($r[0]['obj'],true);
|
||||
$photo_bb = $object['body'];
|
||||
}
|
||||
|
||||
if (strpos($r[0]['body'], "[/share]") !== false) {
|
||||
$pos = strpos($r[0]['body'], "[share");
|
||||
$o = substr($r[0]['body'], $pos);
|
||||
} else {
|
||||
$o = "[share author='" . urlencode($r[0]['author']['xchan_name']) .
|
||||
"' profile='" . $r[0]['author']['xchan_url'] .
|
||||
"' avatar='" . $r[0]['author']['xchan_photo_s'] .
|
||||
"' link='" . $r[0]['plink'] .
|
||||
"' auth='" . (($r[0]['author']['network'] === 'zot') ? 'true' : 'false') .
|
||||
"' posted='" . $r[0]['created'] .
|
||||
"' message_id='" . $r[0]['mid'] .
|
||||
"']";
|
||||
if($r[0]['title'])
|
||||
$o .= '[b]'.$r[0]['title'].'[/b]'."\r\n";
|
||||
$o .= (($is_photo) ? $photo_bb . "\r\n" . $r[0]['body'] : $r[0]['body']);
|
||||
$o .= "[/share]";
|
||||
}
|
||||
|
||||
if(local_channel()) {
|
||||
echo $o;
|
||||
$arr = [];
|
||||
|
||||
$item = $r[0];
|
||||
|
||||
$owner_uid = $r[0]['uid'];
|
||||
$owner_aid = $r[0]['aid'];
|
||||
|
||||
$can_comment = false;
|
||||
if((array_key_exists('owner',$item)) && intval($item['owner']['abook_self']))
|
||||
$can_comment = perm_is_allowed($item['uid'],$observer['xchan_hash'],'post_comments');
|
||||
else
|
||||
$can_comment = can_comment_on_post($observer['xchan_hash'],$item);
|
||||
|
||||
if(! $can_comment) {
|
||||
notice( t('Permission denied') . EOL);
|
||||
killme();
|
||||
}
|
||||
|
||||
$observer = \App::get_observer();
|
||||
$parsed = $observer['xchan_url'];
|
||||
if($parsed) {
|
||||
$post_url = $parsed['scheme'] . '://' . $parsed['host'] . (($parsed['port']) ? ':' . $parsed['port'] : '')
|
||||
. '/rpost';
|
||||
|
||||
/**
|
||||
* @FIXME we were probably called from JS so we don't know the return page.
|
||||
* In fact we won't be able to load the remote page.
|
||||
* we might need an iframe
|
||||
*/
|
||||
|
||||
$x = z_post_url($post_url, array('f' => '', 'body' => $o ));
|
||||
|
||||
$r = q("select * from xchan where xchan_hash = '%s' limit 1",
|
||||
dbesc($item['owner_xchan'])
|
||||
);
|
||||
|
||||
if($r)
|
||||
$thread_owner = $r[0];
|
||||
else
|
||||
killme();
|
||||
|
||||
$r = q("select * from xchan where xchan_hash = '%s' limit 1",
|
||||
dbesc($item['author_xchan'])
|
||||
);
|
||||
if($r)
|
||||
$item_author = $r[0];
|
||||
else
|
||||
killme();
|
||||
|
||||
|
||||
$arr['aid'] = $owner_aid;
|
||||
$arr['uid'] = $owner_uid;
|
||||
|
||||
$arr['item_origin'] = 1;
|
||||
$arr['item_wall'] = $item['item_wall'];
|
||||
$arr['uuid'] = item_message_id();
|
||||
$arr['mid'] = z_root() . '/activity/' . $arr['uuid'];
|
||||
$arr['parent_mid'] = $item['mid'];
|
||||
|
||||
$mention = '@[zrl=' . $item['author']['xchan_url'] . ']' . $item['author']['xchan_name'] . '[/zrl]';
|
||||
$arr['body'] = sprintf( t('🔁 Repeated %1$s\'s %2$s'), $mention, Activity::activity_obj_mapper($item['obj_type']));
|
||||
|
||||
$arr['author_xchan'] = $channel['channel_hash'];
|
||||
$arr['owner_xchan'] = $item['author_xchan'];
|
||||
$arr['obj'] = Activity::encode_item($item);
|
||||
$arr['obj_type'] = $item['obj_type'];
|
||||
$arr['verb'] = ACTIVITY_SHARE;
|
||||
|
||||
$post = item_store($arr);
|
||||
|
||||
$post_id = $post['item_id'];
|
||||
|
||||
$arr['id'] = $post_id;
|
||||
|
||||
call_hooks('post_local_end', $arr);
|
||||
|
||||
info( t('Post repeated') . EOL);
|
||||
|
||||
$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($channel['channel_id'], [ 'item' => [ encode_item($sync_item[0],true) ] ]);
|
||||
}
|
||||
|
||||
Master::Summon([ 'Notifier','like',$post_id ]);
|
||||
|
||||
killme();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -12,10 +12,16 @@ class Sslify extends \Zotlabs\Web\Controller {
|
||||
list($k,$v) = array_map("trim", explode(":", trim($l), 2));
|
||||
$hdrs[strtolower($k)] = $v;
|
||||
}
|
||||
if (array_key_exists('content-type', $hdrs)) {
|
||||
$type = $hdrs['content-type'];
|
||||
header('Content-Type: ' . $type);
|
||||
}
|
||||
|
||||
if (array_key_exists('content-type', $hdrs))
|
||||
header('Content-Type: ' . $hdrs['content-type']);
|
||||
if (array_key_exists('last-modified', $hdrs))
|
||||
header('Last-Modified: ' . $hdrs['last-modified']);
|
||||
if (array_key_exists('cache-control', $hdrs))
|
||||
header('Cache-Control: ' . $hdrs['cache-control']);
|
||||
if (array_key_exists('expires', $hdrs))
|
||||
header('Expires: ' . $hdrs['expires']);
|
||||
|
||||
|
||||
echo $x['body'];
|
||||
killme();
|
||||
|
||||
@@ -33,7 +33,7 @@ class Subthread extends \Zotlabs\Web\Controller {
|
||||
|
||||
if(! $i) {
|
||||
$i = q("select * from item where id = %d and uid = %d",
|
||||
intval($postid),
|
||||
intval($item_id),
|
||||
intval($sys['channel_id'])
|
||||
);
|
||||
|
||||
@@ -106,8 +106,9 @@ class Subthread extends \Zotlabs\Web\Controller {
|
||||
|
||||
|
||||
|
||||
$mid = item_message_id();
|
||||
|
||||
$uuid = item_message_id();
|
||||
$mid = z_root() . '/item/' . $uuid;
|
||||
|
||||
$post_type = (($item['resource_type'] === 'photo') ? t('photo') : t('status'));
|
||||
|
||||
$links = array(array('rel' => 'alternate','type' => 'text/html', 'href' => $item['plink']));
|
||||
@@ -145,6 +146,7 @@ class Subthread extends \Zotlabs\Web\Controller {
|
||||
|
||||
$arr = array();
|
||||
|
||||
$arr['uuid'] = $uuid;
|
||||
$arr['mid'] = $mid;
|
||||
$arr['aid'] = $owner_aid;
|
||||
$arr['uid'] = $owner_uid;
|
||||
|
||||
@@ -69,7 +69,7 @@ class Tagger extends \Zotlabs\Web\Controller {
|
||||
$post_type = t('photo');
|
||||
break;
|
||||
case 'event':
|
||||
$targgettype = ACTIVITY_OBJ_EVENT;
|
||||
$targettype = ACTIVITY_OBJ_EVENT;
|
||||
$post_type = t('event');
|
||||
break;
|
||||
default:
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user