mirror of
https://framagit.org/hubzilla/core.git
synced 2026-06-21 00:52:33 -04:00
Compare commits
2719 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bbcf7e9aa1 | ||
|
|
45a2ebc662 | ||
|
|
aece22aee6 | ||
|
|
9904eba277 | ||
|
|
7c0f98a513 | ||
|
|
8d25b6eae4 | ||
|
|
9369085835 | ||
|
|
9c20b4809a | ||
|
|
00b3039b6e | ||
|
|
2695094d16 | ||
|
|
bcfdb73001 | ||
|
|
1650809cd8 | ||
|
|
991815469f | ||
|
|
c5fb8eafac | ||
|
|
a0c98e070e | ||
|
|
7d6202be13 | ||
|
|
4ba470318c | ||
|
|
e948aaf751 | ||
|
|
3789017ca0 | ||
|
|
48f5acced3 | ||
|
|
13e2d2f654 | ||
|
|
8d45fd36a1 | ||
|
|
6ed2301a94 | ||
|
|
a0eb701503 | ||
|
|
39f9a38b23 | ||
|
|
590c0ea778 | ||
|
|
f36d8e4bd2 | ||
|
|
4e3bec8a35 | ||
|
|
eec918bf4a | ||
|
|
13002af4c3 | ||
|
|
40c63a7f12 | ||
|
|
3d0621eb8c | ||
|
|
030c02dfdc | ||
|
|
00c1509549 | ||
|
|
8122c40252 | ||
|
|
787c63b7ae | ||
|
|
ee988edc83 | ||
|
|
a71f5e123a | ||
|
|
7579749adc | ||
|
|
cf408c3fac | ||
|
|
0c97792ca7 | ||
|
|
84d63b3b67 | ||
|
|
63aa50eb8d | ||
|
|
7fb13f23fe | ||
|
|
65156a0e4d | ||
|
|
e3eebcd95d | ||
|
|
9eff1a08d4 | ||
|
|
cfcac590c3 | ||
|
|
872415bffe | ||
|
|
a46b781664 | ||
|
|
b77fac43c8 | ||
|
|
2b4b409c01 | ||
|
|
67aa547c48 | ||
|
|
e288f33776 | ||
|
|
a5aab4c30e | ||
|
|
cf7613b3e0 | ||
|
|
fa01a2b348 | ||
|
|
65c8de3410 | ||
|
|
d9b262348f | ||
|
|
ea9d2a0acf | ||
|
|
5d55006be8 | ||
|
|
d9ced0c6bf | ||
|
|
8d4d1b17c7 | ||
|
|
453f6a08a3 | ||
|
|
b6560e5456 | ||
|
|
b805f48c32 | ||
|
|
33b78a4943 | ||
|
|
48b187ccd8 | ||
|
|
f680bba3e6 | ||
|
|
09aabc6b41 | ||
|
|
0dd456c653 | ||
|
|
97ba14cbe0 | ||
|
|
ee6367a549 | ||
|
|
fc52d1b44f | ||
|
|
bfce562a46 | ||
|
|
8d8a7f44e1 | ||
|
|
6c8da6ce36 | ||
|
|
e19a050b92 | ||
|
|
a13bf6a3fe | ||
|
|
0edf761499 | ||
|
|
bf76d5981f | ||
|
|
33fcb43173 | ||
|
|
ffae47f523 | ||
|
|
c07cdb30fa | ||
|
|
546c4fcad2 | ||
|
|
0a17b83578 | ||
|
|
2782b6d724 | ||
|
|
dc076a4c00 | ||
|
|
a550c7c853 | ||
|
|
7a3d59bff3 | ||
|
|
82a3b71a51 | ||
|
|
e39b2eb7b9 | ||
|
|
9f8248cc9c | ||
|
|
71e4326606 | ||
|
|
7eb6f9b11d | ||
|
|
4625ffa6b4 | ||
|
|
3e6a646603 | ||
|
|
324b281813 | ||
|
|
03d1f3383e | ||
|
|
69a23c604d | ||
|
|
174469970a | ||
|
|
89b254dc1c | ||
|
|
8e51988e96 | ||
|
|
52e279f443 | ||
|
|
4efa853690 | ||
|
|
9b13055dfe | ||
|
|
06afd8a375 | ||
|
|
6f027544d6 | ||
|
|
2d2c9fa519 | ||
|
|
27efb887d2 | ||
|
|
ccd52584a4 | ||
|
|
ab0fdb13d4 | ||
|
|
2bca44ed25 | ||
|
|
eab08d0bcb | ||
|
|
d3f00704bd | ||
|
|
1e1a7109a9 | ||
|
|
ebab5ff281 | ||
|
|
0165f44063 | ||
|
|
5fb6e5d6f7 | ||
|
|
8fc0e41beb | ||
|
|
3ad63a6e82 | ||
|
|
5a84ffdcda | ||
|
|
ad993645be | ||
|
|
392cb020aa | ||
|
|
0701cde239 | ||
|
|
a136c288d5 | ||
|
|
884b612ffc | ||
|
|
ae0d138d2a | ||
|
|
1624a2620a | ||
|
|
48ef4744ac | ||
|
|
a17cb75baf | ||
|
|
f4769d0f04 | ||
|
|
c8e30a00e2 | ||
|
|
169c971cb1 | ||
|
|
51745d3652 | ||
|
|
3ebbb91ae9 | ||
|
|
762d402dea | ||
|
|
051cef79fc | ||
|
|
b05a440f03 | ||
|
|
9bb4988eda | ||
|
|
f66f0e398b | ||
|
|
49cb73c8c7 | ||
|
|
2a00bd9a28 | ||
|
|
553b3f6faa | ||
|
|
2980827925 | ||
|
|
45a78dcbc0 | ||
|
|
5813b65aed | ||
|
|
f8acd1d3a5 | ||
|
|
c9ebb23b69 | ||
|
|
bc998eacd0 | ||
|
|
648979467a | ||
|
|
5c0ff6f584 | ||
|
|
632721da4e | ||
|
|
f3a702e927 | ||
|
|
58985f2200 | ||
|
|
c55662510d | ||
|
|
f01e917fff | ||
|
|
3940187d19 | ||
|
|
1215e8a030 | ||
|
|
5b6e27233a | ||
|
|
b80cba4e68 | ||
|
|
f2b28f5bbb | ||
|
|
4aeb4963a4 | ||
|
|
de9b10e850 | ||
|
|
36a1d98c52 | ||
|
|
cf66f245b4 | ||
|
|
b1f2f67a04 | ||
|
|
bd10c1e40a | ||
|
|
e146eaa8f8 | ||
|
|
92e21c4f3d | ||
|
|
55265c8a3e | ||
|
|
c3cc624621 | ||
|
|
b466932e37 | ||
|
|
a3248e8b3b | ||
|
|
9ec2db7c97 | ||
|
|
9bd94287dd | ||
|
|
faca95b21c | ||
|
|
79f8b06ede | ||
|
|
a2dde34b1b | ||
|
|
fb5824417e | ||
|
|
804b4effa2 | ||
|
|
4c8e1de4c6 | ||
|
|
d9c69b747d | ||
|
|
0e4be679e4 | ||
|
|
14360c4735 | ||
|
|
2da55d3bd8 | ||
|
|
e9222d0d9a | ||
|
|
93f72a53f5 | ||
|
|
93c4bd4692 | ||
|
|
486c21b519 | ||
|
|
7785487d77 | ||
|
|
9756023e39 | ||
|
|
bb0a22ee58 | ||
|
|
e88ae54bef | ||
|
|
d37d181d94 | ||
|
|
d59d808883 | ||
|
|
b59fe77906 | ||
|
|
1941b4f026 | ||
|
|
5c82229e34 | ||
|
|
66d502d8e1 | ||
|
|
66acfc66ce | ||
|
|
2e13640ab4 | ||
|
|
277b4f7d10 | ||
|
|
edf2a6db1b | ||
|
|
8ad000ec70 | ||
|
|
563628fef8 | ||
|
|
15b6353c1c | ||
|
|
1a86348a6c | ||
|
|
a80ab5887c | ||
|
|
475ae7ba13 | ||
|
|
e107298125 | ||
|
|
428ffa5e35 | ||
|
|
0bffe6e019 | ||
|
|
9e2f3dc05f | ||
|
|
9fa18a5557 | ||
|
|
9608ab27c4 | ||
|
|
464b331deb | ||
|
|
0189d04614 | ||
|
|
cbb3ad1620 | ||
|
|
c0f9d55cfb | ||
|
|
0da51e0f71 | ||
|
|
9014a288b0 | ||
|
|
dcef9f61b5 | ||
|
|
3d80db0cdc | ||
|
|
3a2f787f96 | ||
|
|
f7a9b84943 | ||
|
|
46e6600169 | ||
|
|
243a2a9bdf | ||
|
|
91baa52b8b | ||
|
|
5338793883 | ||
|
|
9acc73b273 | ||
|
|
c626985448 | ||
|
|
5cfb3842f1 | ||
|
|
25b089c1a9 | ||
|
|
67a9292aaa | ||
|
|
81dda15669 | ||
|
|
5b7f8d986c | ||
|
|
5dee600735 | ||
|
|
01da60b385 | ||
|
|
951800eca6 | ||
|
|
72c47cd8db | ||
|
|
e3a8668c32 | ||
|
|
fd9977eada | ||
|
|
bd3304ff94 | ||
|
|
586cda5155 | ||
|
|
c9a8914b07 | ||
|
|
b21b9260d9 | ||
|
|
b5c07e4c01 | ||
|
|
28b5b0cab5 | ||
|
|
39d0a3f1f6 | ||
|
|
513cd3b99a | ||
|
|
ce9d67f7b1 | ||
|
|
8268ed1ba7 | ||
|
|
6c1d0851d7 | ||
|
|
3bc0fd5db4 | ||
|
|
4c3f3d1477 | ||
|
|
17411a501c | ||
|
|
d446f171c5 | ||
|
|
b24b409a01 | ||
|
|
3791dfab3a | ||
|
|
31a146b23a | ||
|
|
e52714ed16 | ||
|
|
2c17d0b031 | ||
|
|
57e69372d3 | ||
|
|
43acb86aab | ||
|
|
e339fbcc46 | ||
|
|
f05b8bd87d | ||
|
|
4e6696b049 | ||
|
|
fbc79e36e0 | ||
|
|
c9d4b068c2 | ||
|
|
b6dbbbc82f | ||
|
|
954d92c354 | ||
|
|
8dbebc2b42 | ||
|
|
14207c68ca | ||
|
|
0ed08274f1 | ||
|
|
2a152e0803 | ||
|
|
a0c54c5f04 | ||
|
|
ac8c80ddbe | ||
|
|
ebad9d56c9 | ||
|
|
0481901b59 | ||
|
|
0534fe6886 | ||
|
|
6e51571309 | ||
|
|
fe30b54975 | ||
|
|
b00ae997a5 | ||
|
|
b5b7d0cda9 | ||
|
|
300d461a1a | ||
|
|
e516c1352f | ||
|
|
4b4cac63fd | ||
|
|
47f109451d | ||
|
|
e466c73407 | ||
|
|
17183cc5dc | ||
|
|
e5aae2af0f | ||
|
|
939e5d9ca5 | ||
|
|
600209e21e | ||
|
|
173c4d242d | ||
|
|
76b8c36f7c | ||
|
|
12c88c06d8 | ||
|
|
f35352090e | ||
|
|
e5db47e0d5 | ||
|
|
6a52e502aa | ||
|
|
6a866fe904 | ||
|
|
229efddbf1 | ||
|
|
abb67a4565 | ||
|
|
2e324d4cef | ||
|
|
d4d1a7523d | ||
|
|
d9d239bf3a | ||
|
|
429d15f009 | ||
|
|
7a3f2c1ba9 | ||
|
|
9f473fc204 | ||
|
|
35a05073f2 | ||
|
|
472484dde0 | ||
|
|
5c3bdbd1e0 | ||
|
|
ec02453d37 | ||
|
|
2b44be58c3 | ||
|
|
c44db397ff | ||
|
|
a385fdff37 | ||
|
|
20aacb82c6 | ||
|
|
0d17d8dad9 | ||
|
|
2ab0118c13 | ||
|
|
30419bdbf6 | ||
|
|
21b60bf119 | ||
|
|
5db3f93be9 | ||
|
|
d25314c75b | ||
|
|
e20327d267 | ||
|
|
8ab3ad6531 | ||
|
|
bf008465ad | ||
|
|
a29a1c768d | ||
|
|
90bc987ea7 | ||
|
|
46fdce4402 | ||
|
|
38c947590e | ||
|
|
c5faa012b5 | ||
|
|
2f0a47e583 | ||
|
|
c958cc6f90 | ||
|
|
541a0f6476 | ||
|
|
065f85bab1 | ||
|
|
38ac60e618 | ||
|
|
160c40b580 | ||
|
|
005d4ad351 | ||
|
|
90a1dad02c | ||
|
|
4daba84223 | ||
|
|
fc182f1b07 | ||
|
|
23a19ecf1f | ||
|
|
0207c02420 | ||
|
|
68135c28da | ||
|
|
274bfa9024 | ||
|
|
4bb28a21c4 | ||
|
|
8b75f50f23 | ||
|
|
0e50b1d10c | ||
|
|
8f4c3a2f88 | ||
|
|
73006ccdf5 | ||
|
|
1006ebbf61 | ||
|
|
436b1673cf | ||
|
|
e530476e6c | ||
|
|
e0a91bed7a | ||
|
|
168ec53686 | ||
|
|
4d1be3aea5 | ||
|
|
e8f816a981 | ||
|
|
e649ba5b13 | ||
|
|
92ce66e766 | ||
|
|
96210f5ecc | ||
|
|
1411eafa9b | ||
|
|
20db45c815 | ||
|
|
4acdb8fb10 | ||
|
|
9e9e8efb2d | ||
|
|
f4495fd441 | ||
|
|
e2ae8f0c4d | ||
|
|
074dc440cc | ||
|
|
e9dc4b553b | ||
|
|
d7fa6f6709 | ||
|
|
40a9989be2 | ||
|
|
d1648927b5 | ||
|
|
ecde4a3ded | ||
|
|
687cda3673 | ||
|
|
47cdef390a | ||
|
|
05a5b644bf | ||
|
|
84556854e8 | ||
|
|
314443d41e | ||
|
|
c23a71c936 | ||
|
|
12b33a23de | ||
|
|
a305c20e08 | ||
|
|
c70bd08c10 | ||
|
|
e2cfe245b7 | ||
|
|
12b24e0e5e | ||
|
|
d5291e9b07 | ||
|
|
a1818b1a29 | ||
|
|
e8eb283fd8 | ||
|
|
96d5370122 | ||
|
|
2bcb6a4fed | ||
|
|
aee396421a | ||
|
|
897568a087 | ||
|
|
69109a558b | ||
|
|
4aff6d19d6 | ||
|
|
a5c1b669b4 | ||
|
|
3cb5d14037 | ||
|
|
5f685bcf63 | ||
|
|
cb44f7e360 | ||
|
|
2aee659cbd | ||
|
|
b117cf9dc7 | ||
|
|
c2ce1d9881 | ||
|
|
2ed8908127 | ||
|
|
6588e272db | ||
|
|
c13645f136 | ||
|
|
8cee16be1b | ||
|
|
45c0091d3d | ||
|
|
44232677c8 | ||
|
|
16603ca854 | ||
|
|
75184355d0 | ||
|
|
1988d21e6c | ||
|
|
bccac55cf9 | ||
|
|
19eeadfe5b | ||
|
|
8f74ee67e3 | ||
|
|
b0a11537de | ||
|
|
2693e9e990 | ||
|
|
04741c761a | ||
|
|
4de9cb1142 | ||
|
|
8f890fb6fa | ||
|
|
158ddfb009 | ||
|
|
2b4f344181 | ||
|
|
1afb2a4ce8 | ||
|
|
2e5f922561 | ||
|
|
a6498a0cfc | ||
|
|
8ffab25f5d | ||
|
|
1073392398 | ||
|
|
7d41deebce | ||
|
|
76064dbb33 | ||
|
|
7e48caae6b | ||
|
|
afbeb58c16 | ||
|
|
1ab4f36a1b | ||
|
|
cea9c88b9e | ||
|
|
babe118383 | ||
|
|
2b140e53cc | ||
|
|
9008760aa6 | ||
|
|
fb1514a782 | ||
|
|
7679894684 | ||
|
|
520cf1015c | ||
|
|
64bd8eef4b | ||
|
|
aa42f6a6b2 | ||
|
|
13345d3cbe | ||
|
|
888ee16d52 | ||
|
|
0f3e01f343 | ||
|
|
79220ede66 | ||
|
|
6b98b799c8 | ||
|
|
9f49d313f5 | ||
|
|
a5f0253aef | ||
|
|
4e6f871bc4 | ||
|
|
803cd74b48 | ||
|
|
0bfdb958f5 | ||
|
|
becd4c6ffd | ||
|
|
3f411787c1 | ||
|
|
5782a674b0 | ||
|
|
fc79e47d88 | ||
|
|
1c45030c58 | ||
|
|
18f3887050 | ||
|
|
2cc962e53a | ||
|
|
5b93aa1148 | ||
|
|
4daa03f025 | ||
|
|
8ae9df3bb7 | ||
|
|
25d9d3ba1b | ||
|
|
26ce231951 | ||
|
|
fb9464437e | ||
|
|
4dff1a1e5b | ||
|
|
b498e50f74 | ||
|
|
2c05638776 | ||
|
|
5cbd42bbc4 | ||
|
|
ac6720e118 | ||
|
|
8c87b06caa | ||
|
|
339e702beb | ||
|
|
8750c5f7bc | ||
|
|
5281f4dd9b | ||
|
|
c3b4397ea3 | ||
|
|
c12ef4fbf4 | ||
|
|
424b31b7f0 | ||
|
|
20ee1a5b5b | ||
|
|
2cd779cbe9 | ||
|
|
a3f1189df7 | ||
|
|
2bc088e555 | ||
|
|
67d8b977b6 | ||
|
|
5b1e532791 | ||
|
|
0e1bf2cef0 | ||
|
|
4f129e05e5 | ||
|
|
3733a80c1d | ||
|
|
220571d2a9 | ||
|
|
f6b9a1dd3c | ||
|
|
393d5020f8 | ||
|
|
06ac41c005 | ||
|
|
39ee872f49 | ||
|
|
a7c51f5d65 | ||
|
|
5309c032db | ||
|
|
176298ffeb | ||
|
|
fdf19e659e | ||
|
|
e799589781 | ||
|
|
10acf90d06 | ||
|
|
b184533115 | ||
|
|
b50e06a9d9 | ||
|
|
66901dbe3e | ||
|
|
4a7879aad2 | ||
|
|
30aa0e3822 | ||
|
|
cadc7ee29e | ||
|
|
5a44b8c40c | ||
|
|
487e68ebd1 | ||
|
|
6cdbc28d79 | ||
|
|
4113bea104 | ||
|
|
294359d7f5 | ||
|
|
8ff870482f | ||
|
|
56cb6f1034 | ||
|
|
7eb23aa8b8 | ||
|
|
c793cea2f0 | ||
|
|
4e19f1c8be | ||
|
|
3d3fcd7334 | ||
|
|
61c03e4b4e | ||
|
|
dd0be272d0 | ||
|
|
b781739949 | ||
|
|
2221d8dd12 | ||
|
|
d67a0b14e3 | ||
|
|
b838632318 | ||
|
|
8c38466b75 | ||
|
|
2919b36e91 | ||
|
|
52f7b508af | ||
|
|
15f6bc93cf | ||
|
|
8c4269d037 | ||
|
|
7394c97f23 | ||
|
|
33e45d98a3 | ||
|
|
241cc1ad63 | ||
|
|
b26db5bde6 | ||
|
|
9be799de15 | ||
|
|
014737fe21 | ||
|
|
d3093dce1b | ||
|
|
61f9ad8274 | ||
|
|
7067a0adc2 | ||
|
|
eb8cab37f3 | ||
|
|
467e0b32b4 | ||
|
|
204d91c3c3 | ||
|
|
1bd52867fb | ||
|
|
898fb4f800 | ||
|
|
63a01c0214 | ||
|
|
39933052a9 | ||
|
|
719dbf091a | ||
|
|
2dad3a8fe5 | ||
|
|
d99ba64206 | ||
|
|
202b797fe6 | ||
|
|
9df96fa03b | ||
|
|
7afb01e488 | ||
|
|
ae140465d7 | ||
|
|
475cbf6510 | ||
|
|
39e5e29ce5 | ||
|
|
f4ffef967a | ||
|
|
77a6a21ea2 | ||
|
|
4e35d34226 | ||
|
|
3708896a65 | ||
|
|
7c3f28f9d2 | ||
|
|
afc8b88933 | ||
|
|
4668178dee | ||
|
|
bfec7b6901 | ||
|
|
f026afe11c | ||
|
|
f388fcaf08 | ||
|
|
9bd2b3ab17 | ||
|
|
2d0b216a2c | ||
|
|
c5bca0279c | ||
|
|
3fca63a15f | ||
|
|
c47900f366 | ||
|
|
84f64214c3 | ||
|
|
9cd01e2e13 | ||
|
|
841b4f7d81 | ||
|
|
70212cdb59 | ||
|
|
5f77e9f4ce | ||
|
|
6276f36b90 | ||
|
|
2461e709d2 | ||
|
|
1055718935 | ||
|
|
82f69018a6 | ||
|
|
c22f633ae0 | ||
|
|
c71eb401c0 | ||
|
|
5a1079750e | ||
|
|
3d03c24f06 | ||
|
|
983fc84f28 | ||
|
|
1861eeeb0a | ||
|
|
663aeca2a7 | ||
|
|
526730672a | ||
|
|
7f292d4765 | ||
|
|
99bff67168 | ||
|
|
bb3caeb629 | ||
|
|
65185a70d5 | ||
|
|
6d1f34284b | ||
|
|
2cfdbbd956 | ||
|
|
5f66ad5bc5 | ||
|
|
aff11443b4 | ||
|
|
6ced7ecf89 | ||
|
|
2d467a15ba | ||
|
|
28c8229218 | ||
|
|
0bcecc4baa | ||
|
|
78e68519e8 | ||
|
|
d2b06995c7 | ||
|
|
5cbae0fb81 | ||
|
|
2ddc087512 | ||
|
|
b0fe94b4b3 | ||
|
|
45275910e6 | ||
|
|
c04e781926 | ||
|
|
09a609ef6b | ||
|
|
213ee83a92 | ||
|
|
db5e524e3c | ||
|
|
f882c44fb3 | ||
|
|
8f9e9116df | ||
|
|
04a35dac9a | ||
|
|
ed03befa02 | ||
|
|
f944f46744 | ||
|
|
3f5c45a567 | ||
|
|
464149e22d | ||
|
|
b51ed67efb | ||
|
|
30ba0661aa | ||
|
|
afdc3d6d18 | ||
|
|
26cb32612d | ||
|
|
6a710c3cc3 | ||
|
|
7028e07535 | ||
|
|
6666bdfda9 | ||
|
|
3e57f150bc | ||
|
|
a50b3181ad | ||
|
|
de992452ee | ||
|
|
4cddc3d0df | ||
|
|
241d96e9fa | ||
|
|
8ae6e785f3 | ||
|
|
1c34c354cf | ||
|
|
0f02553d12 | ||
|
|
3f5cfc8fa2 | ||
|
|
0097840e32 | ||
|
|
082b615e50 | ||
|
|
62cbd87e71 | ||
|
|
72453c49f8 | ||
|
|
66ea277045 | ||
|
|
40a93d92c8 | ||
|
|
7df701b434 | ||
|
|
d760790643 | ||
|
|
1ed8383c33 | ||
|
|
d139f2fe87 | ||
|
|
20a8da0683 | ||
|
|
ff018b975b | ||
|
|
fcd657040e | ||
|
|
605f982520 | ||
|
|
fb1c66fbc9 | ||
|
|
d02fa7c268 | ||
|
|
5abe14982a | ||
|
|
8be9b109fd | ||
|
|
91147d5c5b | ||
|
|
08d4bd94fa | ||
|
|
76a92ac2e1 | ||
|
|
7c688de9cd | ||
|
|
93a45be181 | ||
|
|
d187c0025a | ||
|
|
4e9432263a | ||
|
|
0d4c3fd215 | ||
|
|
62aefadc27 | ||
|
|
6e0d0e3832 | ||
|
|
798e870e71 | ||
|
|
6a63a38e8d | ||
|
|
9199a1ba81 | ||
|
|
ac1e20b188 | ||
|
|
ad9fb4d530 | ||
|
|
ffc2455bea | ||
|
|
0a818191c1 | ||
|
|
c7ec3159ea | ||
|
|
4d5a7ec39f | ||
|
|
13c074f8b8 | ||
|
|
088a87914f | ||
|
|
5110dcb912 | ||
|
|
64748cf1f1 | ||
|
|
4ba4b2976e | ||
|
|
06183ba01a | ||
|
|
539ae37553 | ||
|
|
8f41d170a5 | ||
|
|
d9e97a7c1f | ||
|
|
51fe071c5e | ||
|
|
c5cab3004f | ||
|
|
9c62514c1b | ||
|
|
0428a97e00 | ||
|
|
43a2c21d87 | ||
|
|
69862bc6df | ||
|
|
388e7c88df | ||
|
|
9348bd6ea5 | ||
|
|
0c1d0f7498 | ||
|
|
81ba070e1a | ||
|
|
a7812657f1 | ||
|
|
bd5f77dbeb | ||
|
|
d862a6f075 | ||
|
|
18725c47a0 | ||
|
|
59b8c8ad48 | ||
|
|
494ff44a69 | ||
|
|
5efc6bdd2f | ||
|
|
4835758293 | ||
|
|
d0bb3a7354 | ||
|
|
14df925aa6 | ||
|
|
350f84913a | ||
|
|
78ab2e33ef | ||
|
|
75e1b70584 | ||
|
|
1dc73935d9 | ||
|
|
7d7b43c5b9 | ||
|
|
a4d63ab9a3 | ||
|
|
c009c5f43a | ||
|
|
9d56bb952e | ||
|
|
84abf28cec | ||
|
|
cad82d12d2 | ||
|
|
1846ed75bf | ||
|
|
0a6bb06f86 | ||
|
|
a10402a788 | ||
|
|
5da0cc138f | ||
|
|
2145207ad2 | ||
|
|
f086dfd8ca | ||
|
|
26cfc29303 | ||
|
|
10d1cbd3ce | ||
|
|
1299fdb7be | ||
|
|
430347a295 | ||
|
|
960354b16c | ||
|
|
481e08b904 | ||
|
|
76ce4705e2 | ||
|
|
7a5bb99d87 | ||
|
|
11d7a4c9f7 | ||
|
|
9dd63db736 | ||
|
|
f74922db39 | ||
|
|
605aa37ad3 | ||
|
|
262cebb568 | ||
|
|
bfa81490c1 | ||
|
|
219f0dfeca | ||
|
|
3a50a0b715 | ||
|
|
b25662e183 | ||
|
|
47a86f8771 | ||
|
|
07696d4bd1 | ||
|
|
52e97fe115 | ||
|
|
58033f3255 | ||
|
|
ba4773a61e | ||
|
|
977e6a02f4 | ||
|
|
6a53ddef21 | ||
|
|
2fb9c0ec0d | ||
|
|
98c3e2f93f | ||
|
|
fb4568001d | ||
|
|
5eab32a65b | ||
|
|
483221e2a8 | ||
|
|
2e575dee52 | ||
|
|
058c7d6c13 | ||
|
|
630cecd740 | ||
|
|
4d29cffde5 | ||
|
|
c6116e367a | ||
|
|
b6e6cecf70 | ||
|
|
ce15852b9a | ||
|
|
7c34a3676d | ||
|
|
1c92c7476b | ||
|
|
80e124f53e | ||
|
|
48cec94505 | ||
|
|
26c1fa07c9 | ||
|
|
78a6774206 | ||
|
|
3b812f2570 | ||
|
|
2e15207d0b | ||
|
|
716013633e | ||
|
|
1ca91c49aa | ||
|
|
7de629a8c3 | ||
|
|
592359ef49 | ||
|
|
a56d727c26 | ||
|
|
0b2781f42e | ||
|
|
b5223a4efb | ||
|
|
fe43e0994f | ||
|
|
d71c2c245f | ||
|
|
f85d2d3423 | ||
|
|
3859c010f0 | ||
|
|
526729c0f1 | ||
|
|
1cd3369f6a | ||
|
|
418b1eaf78 | ||
|
|
c26ae553e6 | ||
|
|
e0ac7b7f9f | ||
|
|
8d78698d00 | ||
|
|
d5c189753a | ||
|
|
9861e7a0c4 | ||
|
|
6d5fa9205c | ||
|
|
0fee7804fb | ||
|
|
80d1e07908 | ||
|
|
f72f5c7321 | ||
|
|
a5d483fb5d | ||
|
|
26a7cef0d8 | ||
|
|
53354a1930 | ||
|
|
c052b7fa99 | ||
|
|
9ecd38911e | ||
|
|
4002dbaa8b | ||
|
|
57e32a7912 | ||
|
|
b6a72d6e4e | ||
|
|
6e592ed200 | ||
|
|
637f39f282 | ||
|
|
842df8a799 | ||
|
|
6c033fc776 | ||
|
|
2ff84ab25a | ||
|
|
01c6fd03b7 | ||
|
|
b139e5bb00 | ||
|
|
7c4362db53 | ||
|
|
3c0d6339bb | ||
|
|
a0cfe22501 | ||
|
|
0dc959d9fe | ||
|
|
f7bf9ede72 | ||
|
|
ecdd9a4d6e | ||
|
|
1aeb05628b | ||
|
|
b464fae3bf | ||
|
|
a34ce0732d | ||
|
|
f457b6623d | ||
|
|
01ebd51fb2 | ||
|
|
cb25fc031b | ||
|
|
6c6fc82f43 | ||
|
|
990017b588 | ||
|
|
192ab22cda | ||
|
|
5e5a0d7c91 | ||
|
|
2dc1adf091 | ||
|
|
371b8440c3 | ||
|
|
49509e7347 | ||
|
|
66f5b34c07 | ||
|
|
6a3d372050 | ||
|
|
c95359024c | ||
|
|
edf898d7b7 | ||
|
|
ee0060619d | ||
|
|
4f8ede35bd | ||
|
|
9d9c102da8 | ||
|
|
3de8f5e7de | ||
|
|
a18e873d08 | ||
|
|
b3c260a145 | ||
|
|
1097bcdaf9 | ||
|
|
cfde1be097 | ||
|
|
6df4da5313 | ||
|
|
f910de849f | ||
|
|
d6eaeba239 | ||
|
|
5c2e10c01e | ||
|
|
8754f72e63 | ||
|
|
569f243ebd | ||
|
|
651a3f8380 | ||
|
|
40714ecdd0 | ||
|
|
d4b1bcd641 | ||
|
|
acc1834b0d | ||
|
|
e237cf226a | ||
|
|
7c5a0887cc | ||
|
|
0745d0616a | ||
|
|
9cbb9a4874 | ||
|
|
14f3b72c82 | ||
|
|
b05845f495 | ||
|
|
2114779037 | ||
|
|
937b6d360e | ||
|
|
0d30eed4a7 | ||
|
|
39d4f67417 | ||
|
|
68d989c79e | ||
|
|
9600789d6b | ||
|
|
ea7559c158 | ||
|
|
baa12b7497 | ||
|
|
ac4aa6a9ea | ||
|
|
732dbfd6f5 | ||
|
|
5860abf46f | ||
|
|
2874d3e1e1 | ||
|
|
42b0205ad0 | ||
|
|
36778850ee | ||
|
|
19c0e97658 | ||
|
|
fe018d646a | ||
|
|
24132e56d9 | ||
|
|
8fc0210428 | ||
|
|
64560cbca9 | ||
|
|
6e97c97920 | ||
|
|
916edcb45e | ||
|
|
8873c10364 | ||
|
|
77e1220cf9 | ||
|
|
f402baffd3 | ||
|
|
216f3755fc | ||
|
|
d846cefade | ||
|
|
f3efdbf230 | ||
|
|
826ef11247 | ||
|
|
b68ddc4cd3 | ||
|
|
41f909c415 | ||
|
|
0b4e086376 | ||
|
|
5af3c35778 | ||
|
|
dddcddc453 | ||
|
|
754d90a676 | ||
|
|
8b0dce56ad | ||
|
|
42696606e3 | ||
|
|
b645ede168 | ||
|
|
6e12b5ec08 | ||
|
|
fbf36992be | ||
|
|
e0de813700 | ||
|
|
39448a0871 | ||
|
|
4fb37ef6f3 | ||
|
|
a9d4adaf23 | ||
|
|
70dfce356b | ||
|
|
10fbfa06e9 | ||
|
|
6315757967 | ||
|
|
9ddd840897 | ||
|
|
6c5627ac0e | ||
|
|
c2d6d376a4 | ||
|
|
55532c7cb1 | ||
|
|
a93fed5ae2 | ||
|
|
ba1b48f177 | ||
|
|
898762dd95 | ||
|
|
81ce67df94 | ||
|
|
55097c47c5 | ||
|
|
97b82fc77b | ||
|
|
b7bda0b87d | ||
|
|
6bf61dfa6b | ||
|
|
0e59cfb839 | ||
|
|
328ce0a837 | ||
|
|
34e24ea5e9 | ||
|
|
907426af5e | ||
|
|
360713c689 | ||
|
|
ee8aba3221 | ||
|
|
ae657754b0 | ||
|
|
0a730935f5 | ||
|
|
d285da09fe | ||
|
|
b291f1bad3 | ||
|
|
e1b660bfa3 | ||
|
|
0036c0cde9 | ||
|
|
49c1833a46 | ||
|
|
46fa26502b | ||
|
|
ba1e705c61 | ||
|
|
043e2ff58b | ||
|
|
deba1863f5 | ||
|
|
0e27f010f9 | ||
|
|
45b1be8962 | ||
|
|
fe9ca30c5e | ||
|
|
9e8ba5f6e2 | ||
|
|
5207e1e774 | ||
|
|
c1228d6b6d | ||
|
|
6262d351b7 | ||
|
|
27e57ff7aa | ||
|
|
74fc7508f3 | ||
|
|
3eea4f475c | ||
|
|
37b22fe542 | ||
|
|
b5b8106e7a | ||
|
|
b77100ff6d | ||
|
|
5eb6572277 | ||
|
|
69bed9c889 | ||
|
|
3c88c5e66a | ||
|
|
d40d62ac4f | ||
|
|
d23ed6b11f | ||
|
|
1e2a4a57b6 | ||
|
|
7892eeb2d2 | ||
|
|
d7ceb977da | ||
|
|
36d0594b8e | ||
|
|
3f32a5239d | ||
|
|
15a7d2d4de | ||
|
|
80ed2ff89a | ||
|
|
37a0343163 | ||
|
|
8529e2f14e | ||
|
|
b73401bd7f | ||
|
|
af839a0589 | ||
|
|
4bbeb224f6 | ||
|
|
8435d9eb13 | ||
|
|
d97df1859f | ||
|
|
46f67eaa1e | ||
|
|
54451851bb | ||
|
|
5b7387459c | ||
|
|
5d64a9c90f | ||
|
|
ffaa985339 | ||
|
|
291e12574a | ||
|
|
fc5b5ba021 | ||
|
|
056c55a963 | ||
|
|
02a0af3eef | ||
|
|
96e8316633 | ||
|
|
37878bf0a3 | ||
|
|
b4f079c4b5 | ||
|
|
18abfb11ef | ||
|
|
25dbc8a9f6 | ||
|
|
c639704f3c | ||
|
|
3dd7394247 | ||
|
|
b860b730a9 | ||
|
|
17e2877c91 | ||
|
|
b7bc28c333 | ||
|
|
fb5a52cbde | ||
|
|
6d125d02d8 | ||
|
|
0b18b35f5f | ||
|
|
9859008271 | ||
|
|
423c36f67b | ||
|
|
1e0195e439 | ||
|
|
30271bb32f | ||
|
|
e2b1670d6c | ||
|
|
2bfdfbe3cc | ||
|
|
9a85421a0e | ||
|
|
1fa59df6f3 | ||
|
|
2c93294eea | ||
|
|
316829269a | ||
|
|
55236f86e0 | ||
|
|
060210e930 | ||
|
|
9291622885 | ||
|
|
07978a061e | ||
|
|
08b2356ed1 | ||
|
|
d17934ed80 | ||
|
|
94f17f0dae | ||
|
|
7ccb2a2615 | ||
|
|
067a66b927 | ||
|
|
096fad5e8c | ||
|
|
e21e4c7127 | ||
|
|
5754ea828d | ||
|
|
5fbc203367 | ||
|
|
08884c44fb | ||
|
|
bd04ca21a4 | ||
|
|
19ae8cfdfc | ||
|
|
86e953f495 | ||
|
|
4bc4f5b2a6 | ||
|
|
5f2e808497 | ||
|
|
4f69e02768 | ||
|
|
e6ce2885c0 | ||
|
|
ec19ee9d82 | ||
|
|
983f063d33 | ||
|
|
eb6a143fff | ||
|
|
1881029040 | ||
|
|
209651705d | ||
|
|
fab3c92a7c | ||
|
|
8ad7376865 | ||
|
|
c41831aff9 | ||
|
|
8515aa6966 | ||
|
|
691de5bf2e | ||
|
|
2e155892fe | ||
|
|
6680c2faf3 | ||
|
|
decc8f2162 | ||
|
|
7d7a0c160f | ||
|
|
e89563eb4c | ||
|
|
dd204ec34f | ||
|
|
b3a5dd8aa8 | ||
|
|
26ee56f39c | ||
|
|
300b0e27bd | ||
|
|
29489f62cf | ||
|
|
09465619e5 | ||
|
|
390af7722d | ||
|
|
e18157f818 | ||
|
|
5435d2881c | ||
|
|
2e8f3d1869 | ||
|
|
3ad1cab006 | ||
|
|
b806a3ccc2 | ||
|
|
5e780ba089 | ||
|
|
c0a7dfe2f6 | ||
|
|
fe50d78a0f | ||
|
|
e513950cb5 | ||
|
|
adc6390a22 | ||
|
|
9449e8bd61 | ||
|
|
f13af0f60b | ||
|
|
acdb773f89 | ||
|
|
651a288148 | ||
|
|
b0664f7349 | ||
|
|
51586037e1 | ||
|
|
f573c1772a | ||
|
|
f08e91e19d | ||
|
|
8cd9fff26a | ||
|
|
d489a2854e | ||
|
|
9cfd1c2318 | ||
|
|
2dd0677d23 | ||
|
|
00d403e729 | ||
|
|
d83e2daf36 | ||
|
|
8fe6aede03 | ||
|
|
fa4ab45692 | ||
|
|
f57fbaa5dd | ||
|
|
aba8002170 | ||
|
|
9cc85adf47 | ||
|
|
01ed001041 | ||
|
|
403539919a | ||
|
|
52ea2fa33e | ||
|
|
ecd4754f6d | ||
|
|
f71033b30d | ||
|
|
885068834f | ||
|
|
c4c4ab2f3d | ||
|
|
aec3247952 | ||
|
|
b05b756148 | ||
|
|
03819abb22 | ||
|
|
d074e2aba0 | ||
|
|
2bbecfe8dd | ||
|
|
e078e13325 | ||
|
|
9d3b852d38 | ||
|
|
fadb0a5bf2 | ||
|
|
fa7aa6cedb | ||
|
|
6df98f2fad | ||
|
|
c597017402 | ||
|
|
9cb95f6065 | ||
|
|
477b1535a2 | ||
|
|
1d652cfcbd | ||
|
|
28b604c7c7 | ||
|
|
8c11be07cd | ||
|
|
e8dd2c28ff | ||
|
|
0bdffc4a2d | ||
|
|
94b1fe4a8b | ||
|
|
11ed445319 | ||
|
|
400dfb4e6b | ||
|
|
6b951734ce | ||
|
|
000fcfd1ac | ||
|
|
051e2ed6cd | ||
|
|
aac406a245 | ||
|
|
ef2952b5fd | ||
|
|
ffdf54b097 | ||
|
|
58593d7da6 | ||
|
|
3d13f36ce2 | ||
|
|
8c843ec6d0 | ||
|
|
232c7f5301 | ||
|
|
16cd8caef3 | ||
|
|
43dabee53d | ||
|
|
f016760851 | ||
|
|
99b5166f21 | ||
|
|
4aa29db7aa | ||
|
|
f5b8b18c8e | ||
|
|
6e5566f9c8 | ||
|
|
ca216ae819 | ||
|
|
4713241444 | ||
|
|
4917170a0d | ||
|
|
87775ae37a | ||
|
|
eaa244a2a3 | ||
|
|
db91d66d1a | ||
|
|
4d64481564 | ||
|
|
0a31fc176c | ||
|
|
659a8c967c | ||
|
|
626887a792 | ||
|
|
256b66de41 | ||
|
|
5ee4f37b8d | ||
|
|
3dc122db84 | ||
|
|
99c5a4e2f8 | ||
|
|
f922a92ffa | ||
|
|
a36de8ba1a | ||
|
|
e3d30763da | ||
|
|
c73518d8ec | ||
|
|
ed0d2fed66 | ||
|
|
960bcb6b53 | ||
|
|
6252340804 | ||
|
|
517d67b2e0 | ||
|
|
e95b7ca3a0 | ||
|
|
c771d7c31a | ||
|
|
ce0e8d7497 | ||
|
|
852678e238 | ||
|
|
16e6eec3fb | ||
|
|
afe8552be6 | ||
|
|
cd0e50da24 | ||
|
|
85001c034b | ||
|
|
a56f6576e2 | ||
|
|
d3e5d05026 | ||
|
|
322b619a71 | ||
|
|
dff906ca69 | ||
|
|
515d1d5e63 | ||
|
|
bb6ed22594 | ||
|
|
d655e1d765 | ||
|
|
db70ed006d | ||
|
|
ce1dd5c632 | ||
|
|
9e2a253dda | ||
|
|
95c645865d | ||
|
|
ceb510bbf5 | ||
|
|
2590e3c99b | ||
|
|
f2f9cfaf28 | ||
|
|
62db8c3969 | ||
|
|
ae3db366e5 | ||
|
|
57570c144a | ||
|
|
c3a235242e | ||
|
|
b629eb5657 | ||
|
|
2e674cd0b3 | ||
|
|
3330e9a19a | ||
|
|
c5f6208396 | ||
|
|
c0d93bbcf4 | ||
|
|
db941e7007 | ||
|
|
4761857157 | ||
|
|
3aefe23184 | ||
|
|
6f852814fd | ||
|
|
b15e521b0e | ||
|
|
63c401e6d6 | ||
|
|
e59750e8de | ||
|
|
9c184ddfd0 | ||
|
|
9df6e821d8 | ||
|
|
9551dc5ecd | ||
|
|
d372daff60 | ||
|
|
f742e6e394 | ||
|
|
414b2b0e4c | ||
|
|
603c5692ae | ||
|
|
b35e994d1b | ||
|
|
abe2ab229a | ||
|
|
5ad9939bcf | ||
|
|
ce451128ba | ||
|
|
70470016cc | ||
|
|
2122ea77e1 | ||
|
|
69266cd6c6 | ||
|
|
062d61567e | ||
|
|
d6120fc908 | ||
|
|
91f8e7a07b | ||
|
|
f57d89245c | ||
|
|
c307a71f53 | ||
|
|
1e4e59bb57 | ||
|
|
f62d16d274 | ||
|
|
f175712d4b | ||
|
|
5f942d78e6 | ||
|
|
538c8885ad | ||
|
|
c8158c3d62 | ||
|
|
1f4762060f | ||
|
|
81c3682781 | ||
|
|
2e6e1fdd55 | ||
|
|
1a09cd560b | ||
|
|
8c9d2bc6f6 | ||
|
|
78ad5ca713 | ||
|
|
43c2e71b25 | ||
|
|
5b9f32fade | ||
|
|
76a1a6da34 | ||
|
|
a2b0abc90d | ||
|
|
0fd8e02a88 | ||
|
|
55c4bfb670 | ||
|
|
ea1030f8bf | ||
|
|
6dd285811a | ||
|
|
ee149ed1eb | ||
|
|
c3aa96d423 | ||
|
|
6e59d95da5 | ||
|
|
a396e74a79 | ||
|
|
80bdb39ae3 | ||
|
|
5cb1a9dcc6 | ||
|
|
1cfa81450c | ||
|
|
1f18fed3a2 | ||
|
|
33cb429e15 | ||
|
|
cfdbf02e6b | ||
|
|
f8c631a3f0 | ||
|
|
74911e9f6d | ||
|
|
0f453ae4cf | ||
|
|
febebc8d3d | ||
|
|
166c45f97f | ||
|
|
af58364fef | ||
|
|
eadf83d61b | ||
|
|
3c20231aad | ||
|
|
402bf395d1 | ||
|
|
9a45938fe6 | ||
|
|
d963e4a2c4 | ||
|
|
1063a67ae2 | ||
|
|
602ef883bb | ||
|
|
aad6042d42 | ||
|
|
85d8c1a97e | ||
|
|
547e6542ba | ||
|
|
f74044f9b0 | ||
|
|
42651707f8 | ||
|
|
95c13eaf5a | ||
|
|
c74068ae4d | ||
|
|
ca92dd0299 | ||
|
|
798f791b6b | ||
|
|
331622309f | ||
|
|
4f334525c2 | ||
|
|
82e704ec5b | ||
|
|
67aaa97904 | ||
|
|
4f55248a6c | ||
|
|
61b46f1a3e | ||
|
|
286104a988 | ||
|
|
8ea6ead08a | ||
|
|
bd9cc23681 | ||
|
|
f2d7298cf4 | ||
|
|
da636ca881 | ||
|
|
39bfa30185 | ||
|
|
d7c005a2f1 | ||
|
|
763b69bf5b | ||
|
|
2f2e353ece | ||
|
|
0092b7c0a4 | ||
|
|
9f48109640 | ||
|
|
b976adb8aa | ||
|
|
fe38c81e07 | ||
|
|
fed9bc7072 | ||
|
|
044e252d19 | ||
|
|
6920fb2793 | ||
|
|
3d1171de8d | ||
|
|
6e09754d06 | ||
|
|
32f2de17d4 | ||
|
|
600e8081a8 | ||
|
|
59fd7c3c9a | ||
|
|
7e70fe1126 | ||
|
|
5265c774ae | ||
|
|
d1421d720c | ||
|
|
2bd09d3b30 | ||
|
|
56e54ac820 | ||
|
|
08d85798ed | ||
|
|
38c2b36606 | ||
|
|
01b747287a | ||
|
|
c925e13e5a | ||
|
|
1ced89a869 | ||
|
|
a5e32dc3de | ||
|
|
150174c3bb | ||
|
|
601ee0b40b | ||
|
|
9627c3e7c8 | ||
|
|
d88c67eba3 | ||
|
|
bb38a90dda | ||
|
|
c36743f7ee | ||
|
|
860275f888 | ||
|
|
670228ff63 | ||
|
|
4338e4ef86 | ||
|
|
dbc712c53c | ||
|
|
bb6011ea73 | ||
|
|
1915f34de8 | ||
|
|
675f26fe90 | ||
|
|
491e309911 | ||
|
|
283d27c5b1 | ||
|
|
24d862c1bc | ||
|
|
3708c1ac8c | ||
|
|
df60be423a | ||
|
|
a1e583129f | ||
|
|
a06b28b693 | ||
|
|
198070700c | ||
|
|
3a01aa40d8 | ||
|
|
b628af2258 | ||
|
|
0cb5d0d63e | ||
|
|
526c85e2ca | ||
|
|
8a21c8e618 | ||
|
|
8d3d5747d2 | ||
|
|
f1f1406596 | ||
|
|
9e42be9884 | ||
|
|
75e75b93cf | ||
|
|
0e8ecbc9fc | ||
|
|
a88236b36f | ||
|
|
df06c54bd2 | ||
|
|
f2d88387c9 | ||
|
|
db4c6bbd3b | ||
|
|
c8e7f79f50 | ||
|
|
1157dc7dc8 | ||
|
|
c12833521f | ||
|
|
5d9346999e | ||
|
|
52c0631833 | ||
|
|
e16aefec2c | ||
|
|
053a247cc8 | ||
|
|
1426b7a6dc | ||
|
|
ec66949b35 | ||
|
|
bc9d8d1136 | ||
|
|
542a527d0d | ||
|
|
5e0c392287 | ||
|
|
05ff94941c | ||
|
|
a27d75d610 | ||
|
|
446e842904 | ||
|
|
ba153e2c18 | ||
|
|
3342ea6891 | ||
|
|
8c3d5fd295 | ||
|
|
5fc58fb10a | ||
|
|
4e2ae9cd4e | ||
|
|
4167ca2e5c | ||
|
|
9b3e9dcf02 | ||
|
|
f203fcc92e | ||
|
|
0b20069c20 | ||
|
|
bad7b778b3 | ||
|
|
f89ce93940 | ||
|
|
1ddbc8a26d | ||
|
|
0a3094fc9a | ||
|
|
816bbad28a | ||
|
|
ce4150cd06 | ||
|
|
be19b75031 | ||
|
|
3ddab5966b | ||
|
|
2d5c99f459 | ||
|
|
a5a1bbf5d7 | ||
|
|
c4af4e3297 | ||
|
|
1acfc05e2d | ||
|
|
b40c38f58c | ||
|
|
87c41cb9ac | ||
|
|
0ec715d7c9 | ||
|
|
e6a261a789 | ||
|
|
3bd2a91992 | ||
|
|
c721bc672c | ||
|
|
931b876b44 | ||
|
|
87b91e5023 | ||
|
|
4b1384be83 | ||
|
|
8da6e6a096 | ||
|
|
5181e575b4 | ||
|
|
ca994735be | ||
|
|
718c303086 | ||
|
|
7200c71673 | ||
|
|
14c97799c6 | ||
|
|
a06e8bfaee | ||
|
|
7dad60bbd5 | ||
|
|
a66b4626fb | ||
|
|
330add963d | ||
|
|
da1ccc620b | ||
|
|
c412c01a65 | ||
|
|
74d7fa61d9 | ||
|
|
ef6ea4484e | ||
|
|
ba2d775215 | ||
|
|
f866771854 | ||
|
|
70b8c57d22 | ||
|
|
b04e0d0fd4 | ||
|
|
3f9d5e11d1 | ||
|
|
09fe271b25 | ||
|
|
d5c1a49984 | ||
|
|
e80d3653c9 | ||
|
|
30b0d0a5cc | ||
|
|
9beceb9b02 | ||
|
|
6f13cabfba | ||
|
|
7bd2de9967 | ||
|
|
b0b0973e2d | ||
|
|
3d866e8975 | ||
|
|
63fb8d0392 | ||
|
|
384de0925e | ||
|
|
5b5c569c82 | ||
|
|
6f2371ee74 | ||
|
|
d6e7d90197 | ||
|
|
aa73db0fe6 | ||
|
|
d85088fc3d | ||
|
|
7e21aeedcd | ||
|
|
342460fa17 | ||
|
|
e57211fbd1 | ||
|
|
d31eb4c89c | ||
|
|
6753d260e4 | ||
|
|
a3092204a1 | ||
|
|
10b49af776 | ||
|
|
3497ced9f9 | ||
|
|
7a0f22b0a7 | ||
|
|
4f03272a5f | ||
|
|
7755936a2e | ||
|
|
9f6844ec30 | ||
|
|
c2952aa803 | ||
|
|
8f7383f5c2 | ||
|
|
750641ef19 | ||
|
|
fb48dfc082 | ||
|
|
1de5bce1c1 | ||
|
|
676603239d | ||
|
|
4c87f36a8c | ||
|
|
12b2137a04 | ||
|
|
762e1c9c2b | ||
|
|
cd26ead043 | ||
|
|
6a560cfec4 | ||
|
|
489ba72d5c | ||
|
|
5df9779669 | ||
|
|
e49d2f6b8f | ||
|
|
9550a7a954 | ||
|
|
d9f855b97e | ||
|
|
e275dae6e3 | ||
|
|
88ccc2a3b9 | ||
|
|
84487edc05 | ||
|
|
7177649969 | ||
|
|
18b7b3f125 | ||
|
|
89c7e1a8ee | ||
|
|
774a9b118e | ||
|
|
327841280b | ||
|
|
1e0a686561 | ||
|
|
96883100b4 | ||
|
|
1fcb05ed8c | ||
|
|
8c85516c57 | ||
|
|
6989a3eaad | ||
|
|
57796a2f96 | ||
|
|
59b217f7ea | ||
|
|
fb9a193c44 | ||
|
|
2739f1f3f0 | ||
|
|
0c2cb18578 | ||
|
|
db2c5aae84 | ||
|
|
aa2cec103b | ||
|
|
a532a70ac0 | ||
|
|
ec6cec8854 | ||
|
|
3fb22d27ab | ||
|
|
1cbaab5889 | ||
|
|
fef19b47c2 | ||
|
|
5126613825 | ||
|
|
07097d2fa3 | ||
|
|
8c9fb32ca0 | ||
|
|
68d921e918 | ||
|
|
330b36159d | ||
|
|
046152e798 | ||
|
|
11ca5bb7d5 | ||
|
|
e0838ff8ab | ||
|
|
11a2419c22 | ||
|
|
f3420c0adb | ||
|
|
bd84ff4838 | ||
|
|
87689df062 | ||
|
|
1bfbd57ee4 | ||
|
|
64d7585282 | ||
|
|
0ee03a565f | ||
|
|
1b0e268416 | ||
|
|
0e8d1afcaf | ||
|
|
48a33f08e2 | ||
|
|
f9ca956510 | ||
|
|
65a472c113 | ||
|
|
4b17ea04a7 | ||
|
|
423fdc0a96 | ||
|
|
396b124e84 | ||
|
|
6a27afa6ac | ||
|
|
b9812ba06a | ||
|
|
bc6aded074 | ||
|
|
904401617a | ||
|
|
02089f15c4 | ||
|
|
43a18a2569 | ||
|
|
4c2dc2bf16 | ||
|
|
e6eb2a8476 | ||
|
|
af5ae163f3 | ||
|
|
d00860430f | ||
|
|
af0b4a0fca | ||
|
|
404189f88c | ||
|
|
1a27fad9b9 | ||
|
|
c2cfe481df | ||
|
|
3a56fb6ec6 | ||
|
|
61950decb3 | ||
|
|
1a614ea023 | ||
|
|
a83b6a5e63 | ||
|
|
65d98af24c | ||
|
|
62d35627f3 | ||
|
|
84f1ed1587 | ||
|
|
31b4fb343d | ||
|
|
3c3f5c60da | ||
|
|
18914f2081 | ||
|
|
b50da2d8b7 | ||
|
|
5bdd699c9d | ||
|
|
29e8e6d95c | ||
|
|
049fc91615 | ||
|
|
b7c96f2cbd | ||
|
|
1e6408df13 | ||
|
|
7b90548c1d | ||
|
|
5d330e18ff | ||
|
|
07662ff076 | ||
|
|
9252ae1596 | ||
|
|
0155e9131d | ||
|
|
247cf40ace | ||
|
|
4a6b450c55 | ||
|
|
5b80d57a54 | ||
|
|
8ac4547e73 | ||
|
|
3658975b69 | ||
|
|
abc3545ef9 | ||
|
|
01f8cb698d | ||
|
|
5e4d0f45fc | ||
|
|
efd2f78274 | ||
|
|
690ff955fa | ||
|
|
3fb27bdc55 | ||
|
|
d8306fca6f | ||
|
|
380775540d | ||
|
|
65e3b0dafd | ||
|
|
4ae81d753c | ||
|
|
0f01aac823 | ||
|
|
ce0a96351e | ||
|
|
93dda6f1fd | ||
|
|
5e83db959e | ||
|
|
74436eb03e | ||
|
|
993178fc49 | ||
|
|
1c217cf446 | ||
|
|
0bf2be1f9d | ||
|
|
548589be4d | ||
|
|
697a1b1ed1 | ||
|
|
d893c7eb33 | ||
|
|
8957d24752 | ||
|
|
677e730235 | ||
|
|
4227d973b9 | ||
|
|
06c0af50c3 | ||
|
|
4d3a48d1c1 | ||
|
|
f6b66f4cad | ||
|
|
a56f9ab4e6 | ||
|
|
ca913e5077 | ||
|
|
b25ebe12c5 | ||
|
|
984980b170 | ||
|
|
be45005dbb | ||
|
|
b8c9f04989 | ||
|
|
bf2d41eb14 | ||
|
|
158f9afb37 | ||
|
|
f884e31d21 | ||
|
|
d3a5ff9d68 | ||
|
|
7185780d4e | ||
|
|
f995b2822f | ||
|
|
d7490ac738 | ||
|
|
383d0e17f2 | ||
|
|
7c1a3ab36e | ||
|
|
edc8d17031 | ||
|
|
f3f861234d | ||
|
|
93278c00b7 | ||
|
|
5bbe93d49f | ||
|
|
21cd8d31d7 | ||
|
|
d649b4df28 | ||
|
|
2bb9550343 | ||
|
|
ef0feff4a5 | ||
|
|
dfa43b4856 | ||
|
|
a24a1ca6d7 | ||
|
|
2d4b35fbc9 | ||
|
|
57e2910477 | ||
|
|
ffbaa7e4dc | ||
|
|
df42036100 | ||
|
|
ca9491d343 | ||
|
|
96ae569eaf | ||
|
|
fb295d53f1 | ||
|
|
95d07974f4 | ||
|
|
39d78064da | ||
|
|
a2bcbb90ed | ||
|
|
c31b37f570 | ||
|
|
2a1341b910 | ||
|
|
354e341d69 | ||
|
|
13946b2b76 | ||
|
|
29aa52df6a | ||
|
|
c3267a27d3 | ||
|
|
3543e6dd32 | ||
|
|
5412ba617d | ||
|
|
1f81a2cb1b | ||
|
|
5da58d42f6 | ||
|
|
299b6037c9 | ||
|
|
1ed8b9dd14 | ||
|
|
cf4912cb3d | ||
|
|
e6ec87f910 | ||
|
|
f72fb974a9 | ||
|
|
bdb25315b6 | ||
|
|
60f0739c3e | ||
|
|
0faab9277f | ||
|
|
51fce12cd7 | ||
|
|
d79290df75 | ||
|
|
0bf65bcad5 | ||
|
|
44dbf19e89 | ||
|
|
469a76f1f6 | ||
|
|
f851c272fa | ||
|
|
027a9fec61 | ||
|
|
09fde2f839 | ||
|
|
8a14e4261d | ||
|
|
6c9f1de265 | ||
|
|
3ad0179b62 | ||
|
|
81f33da499 | ||
|
|
80d70e64f5 | ||
|
|
eec4845cd0 | ||
|
|
b99a4ade1a | ||
|
|
84e25e8fd2 | ||
|
|
39e14eb95c | ||
|
|
f277d08244 | ||
|
|
d7c479fa6d | ||
|
|
44e5dc7d97 | ||
|
|
fdd54057a8 | ||
|
|
d43485141f | ||
|
|
2350561903 | ||
|
|
5674badccd | ||
|
|
a793f4414d | ||
|
|
e99957f99f | ||
|
|
ad5bbc463b | ||
|
|
81993cf2a3 | ||
|
|
5d40742ee6 | ||
|
|
1ce050d911 | ||
|
|
8e7393fc26 | ||
|
|
ad45205ddf | ||
|
|
409e9208ee | ||
|
|
d8811b499d | ||
|
|
dd1f9494f1 | ||
|
|
20f4538db4 | ||
|
|
d08c8e6edc | ||
|
|
f1667dbbe6 | ||
|
|
2bab7e2693 | ||
|
|
824497b97a | ||
|
|
0b7bece8e3 | ||
|
|
6ddf1a5786 | ||
|
|
b9827dfe02 | ||
|
|
64f30831ac | ||
|
|
bf5722cd25 | ||
|
|
ae074153c8 | ||
|
|
63d46dbdfb | ||
|
|
bdf1b23198 | ||
|
|
6f1c261f6b | ||
|
|
3233d5485f | ||
|
|
aa06400a50 | ||
|
|
30724bd7c4 | ||
|
|
0d3b389538 | ||
|
|
9f7dbe16fd | ||
|
|
432024123a | ||
|
|
261762448e | ||
|
|
7ce4175876 | ||
|
|
a57739c462 | ||
|
|
03bdbfa705 | ||
|
|
92246ce3a8 | ||
|
|
cdf74c2e41 | ||
|
|
4a72ea6666 | ||
|
|
f76d9b7908 | ||
|
|
dcfdf3a5d7 | ||
|
|
4873f61d6c | ||
|
|
1538107ae4 | ||
|
|
9b93dc5137 | ||
|
|
5ec721b978 | ||
|
|
24568c0e2f | ||
|
|
92a89ca258 | ||
|
|
ba71c53bc6 | ||
|
|
b3cfeb573a | ||
|
|
9083e99d2a | ||
|
|
70ca247c88 | ||
|
|
14fc0c735b | ||
|
|
70b3c8080e | ||
|
|
2c483c460a | ||
|
|
79405cf1d3 | ||
|
|
5c755fdd1c | ||
|
|
89285f1408 | ||
|
|
17c0bb2069 | ||
|
|
192736f6d7 | ||
|
|
ae928b9aff | ||
|
|
4eee8ce770 | ||
|
|
723eb6597a | ||
|
|
3dcfdba74b | ||
|
|
5428053663 | ||
|
|
d0b41d0b07 | ||
|
|
a82d861d2c | ||
|
|
1e184b781b | ||
|
|
54b684fdb8 | ||
|
|
c1ddb89990 | ||
|
|
2f5fa4df75 | ||
|
|
20735083b3 | ||
|
|
7ac7cb129f | ||
|
|
f8b2f738bb | ||
|
|
11b9e546a9 | ||
|
|
7e4721e4c7 | ||
|
|
3a3fd38e3a | ||
|
|
63a8611579 | ||
|
|
38a1b79174 | ||
|
|
0a679e503e | ||
|
|
e7c529f2c3 | ||
|
|
95cbcf30d7 | ||
|
|
dfc70021e3 | ||
|
|
9daecca0ad | ||
|
|
c9d8a4dc1d | ||
|
|
5fada6a497 | ||
|
|
ac9c33fb3b | ||
|
|
641b1c2e1b | ||
|
|
f031707563 | ||
|
|
7f0518f693 | ||
|
|
634d2f02b5 | ||
|
|
d7aee292d3 | ||
|
|
1987517836 | ||
|
|
203d9d651f | ||
|
|
8af5788fc1 | ||
|
|
3de81877c6 | ||
|
|
2665b34962 | ||
|
|
2ffef2be8f | ||
|
|
c2e5610455 | ||
|
|
234bb64250 | ||
|
|
d43a56614c | ||
|
|
9f10e7e356 | ||
|
|
dc6075aa3f | ||
|
|
972d6917ac | ||
|
|
ec3ba87f3a | ||
|
|
da034045cc | ||
|
|
65f001b4b7 | ||
|
|
d81473487f | ||
|
|
06a8d5a4fa | ||
|
|
3653a86ad3 | ||
|
|
c8d913fba7 | ||
|
|
b70acd0079 | ||
|
|
f167648115 | ||
|
|
b457c66bf9 | ||
|
|
ca0bd3ed32 | ||
|
|
7dacc7c268 | ||
|
|
0db2e6b62c | ||
|
|
e412bdbdbe | ||
|
|
f032bcc5f2 | ||
|
|
9ab9ac0e2e | ||
|
|
fd3adf4d11 | ||
|
|
c42911bd8d | ||
|
|
828087ee8c | ||
|
|
efcda1d37d | ||
|
|
656400b418 | ||
|
|
ca7bd49964 | ||
|
|
3527137264 | ||
|
|
e045a36559 | ||
|
|
ee8fc701a6 | ||
|
|
777fdeb462 | ||
|
|
1078b774ae | ||
|
|
62a363debc | ||
|
|
7839b931f1 | ||
|
|
cbf8c4bdb2 | ||
|
|
321cd9f2e0 | ||
|
|
09a60774d7 | ||
|
|
1ca988b177 | ||
|
|
07fd8cf6cd | ||
|
|
e7fb56447a | ||
|
|
de3e83f0a2 | ||
|
|
6c78f7b769 | ||
|
|
2c459fefce | ||
|
|
a1eb39872b | ||
|
|
724b8cc6a5 | ||
|
|
2bfd18e6cd | ||
|
|
20658f3b4a | ||
|
|
c945698eb4 | ||
|
|
5f89bd75a4 | ||
|
|
09c9b47265 | ||
|
|
ea2b653b9b | ||
|
|
9c3660e2f6 | ||
|
|
4bcacf858b | ||
|
|
7faa3359f0 | ||
|
|
71f1814477 | ||
|
|
a3913c5ca4 | ||
|
|
ae1cc65b23 | ||
|
|
9a16bf65bd | ||
|
|
c3d3dc9d92 | ||
|
|
e54eb21b71 | ||
|
|
0140f9fe56 | ||
|
|
03243df16a | ||
|
|
28dc8443a8 | ||
|
|
ec6832687b | ||
|
|
9065a90ac0 | ||
|
|
94b26e1e66 | ||
|
|
a2fc2e776a | ||
|
|
79b40179b4 | ||
|
|
60c968222f | ||
|
|
e99dc2193f | ||
|
|
cf1838f76e | ||
|
|
0db5016666 | ||
|
|
c4b37ba462 | ||
|
|
c3b908dcfc | ||
|
|
23f93044c1 | ||
|
|
32dcc28414 | ||
|
|
ddae3eaf84 | ||
|
|
a9ae17036d | ||
|
|
08e925758e | ||
|
|
213c8a6eec | ||
|
|
ca4ad836a3 | ||
|
|
56361fa2fc | ||
|
|
fedce4cd74 | ||
|
|
cac48fc4bf | ||
|
|
1cad844d2d | ||
|
|
2d5e09f930 | ||
|
|
fbda34935d | ||
|
|
c5ca7f236f | ||
|
|
9dc949b62c | ||
|
|
40394b94d7 | ||
|
|
bae446973f | ||
|
|
2805520d1b | ||
|
|
fb7ca18820 | ||
|
|
1b00d5657f | ||
|
|
cd9f35e78a | ||
|
|
f9cedab964 | ||
|
|
9ec516e5a4 | ||
|
|
550b6d90a4 | ||
|
|
5cb92b6e21 | ||
|
|
8a7b221412 | ||
|
|
d092e79ebc | ||
|
|
2ddb88a34d | ||
|
|
71761c9039 | ||
|
|
16555b93bb | ||
|
|
bd5e834b42 | ||
|
|
2eb4f093be | ||
|
|
d4bf587103 | ||
|
|
ae7bd8b644 | ||
|
|
f89cede020 | ||
|
|
59facf6f00 | ||
|
|
01d93733ae | ||
|
|
4c434129a6 | ||
|
|
b40499b4c1 | ||
|
|
66333aedb7 | ||
|
|
47071c58aa | ||
|
|
79d99688b4 | ||
|
|
edcb0631aa | ||
|
|
bc361e6469 | ||
|
|
c95ef1a5c0 | ||
|
|
0c0891f64f | ||
|
|
23828f53bc | ||
|
|
f909e129ab | ||
|
|
7d4bcc2e8b | ||
|
|
2eb4d87621 | ||
|
|
435888c1a3 | ||
|
|
e69fabcd71 | ||
|
|
1a283301cf | ||
|
|
031df70cf8 | ||
|
|
3ad36db7dd | ||
|
|
e16ea1ae05 | ||
|
|
941135a0a6 | ||
|
|
29776ecea2 | ||
|
|
d2edef5c5a | ||
|
|
da9349ea62 | ||
|
|
de0d2afc15 | ||
|
|
d8c94c2003 | ||
|
|
0e71bfe222 | ||
|
|
0ae402e624 | ||
|
|
b96dc11ddd | ||
|
|
37b539eaa5 | ||
|
|
0741708086 | ||
|
|
a30cfd8fec | ||
|
|
633cd11c5b | ||
|
|
3101c6540a | ||
|
|
d2d6be73b8 | ||
|
|
a46e2c1e6d | ||
|
|
2b0404fefc | ||
|
|
7ef9462286 | ||
|
|
c6e7a7eaee | ||
|
|
999e142370 | ||
|
|
a7ad117a83 | ||
|
|
1ba44fc117 | ||
|
|
ca5610ebf1 | ||
|
|
e5c70a1304 | ||
|
|
7dd2308534 | ||
|
|
62eee07b6e | ||
|
|
f6d9406063 | ||
|
|
34125177e8 | ||
|
|
d977b5d662 | ||
|
|
e36677b757 | ||
|
|
4d54755057 | ||
|
|
91917c98e4 | ||
|
|
2f687de477 | ||
|
|
5446062b95 | ||
|
|
c9e170dfcc | ||
|
|
e3a19469eb | ||
|
|
45f8e43be4 | ||
|
|
7ef0b05ce6 | ||
|
|
c5a0ec4e93 | ||
|
|
1c17768dc5 | ||
|
|
86e1dd4673 | ||
|
|
0ee41c3341 | ||
|
|
e1c2835173 | ||
|
|
5c6d3753ef | ||
|
|
6e881bcef2 | ||
|
|
4f9a933108 | ||
|
|
9f8585914c | ||
|
|
3ba27b9752 | ||
|
|
abae5de4d8 | ||
|
|
6952c5a3f5 | ||
|
|
0184d2c292 | ||
|
|
7a40561aaa | ||
|
|
79e6c9590a | ||
|
|
12a963cc40 | ||
|
|
f89975fd0e | ||
|
|
b4dffe5946 | ||
|
|
539b69d507 | ||
|
|
9927363f39 | ||
|
|
1a4f59cd70 | ||
|
|
25727a24a5 | ||
|
|
2fd2dc964b | ||
|
|
935b032f15 | ||
|
|
2bb58843ab | ||
|
|
00512579f3 | ||
|
|
6f09796142 | ||
|
|
697a74f37e | ||
|
|
d16b6c3838 | ||
|
|
e4461f2e61 | ||
|
|
baf1b8b02d | ||
|
|
3ce1373ae0 | ||
|
|
4002531b92 | ||
|
|
004d0f074d | ||
|
|
e87887c328 | ||
|
|
2de2c8e207 | ||
|
|
c76f19f19a | ||
|
|
a050e8c8f5 | ||
|
|
ae1fad5de7 | ||
|
|
68ca8951a8 | ||
|
|
1e4718eae1 | ||
|
|
680cf25f37 | ||
|
|
7ec6df495f | ||
|
|
aeda31fda7 | ||
|
|
5248aa3065 | ||
|
|
67767c5853 | ||
|
|
6de1aec683 | ||
|
|
221d3cdf6a | ||
|
|
1ff12c5520 | ||
|
|
41376ec2cd | ||
|
|
bf335ecaf3 | ||
|
|
424bc73f58 | ||
|
|
59e6989cbc | ||
|
|
0e6b27c9f4 | ||
|
|
0e157e4e8b | ||
|
|
805074a0f9 | ||
|
|
5216c5b232 | ||
|
|
8633162f0c | ||
|
|
c392a77b46 | ||
|
|
08c2c9bc22 | ||
|
|
f64bd590a8 | ||
|
|
131ffcf582 | ||
|
|
b17a0aef17 | ||
|
|
8a21783fa5 | ||
|
|
53152e2ef5 | ||
|
|
ca6ba92d82 | ||
|
|
04516b787a | ||
|
|
6e124a4d72 | ||
|
|
6da65c7ddc | ||
|
|
9eb332f032 | ||
|
|
30ddee65a4 | ||
|
|
63dc8d7fc4 | ||
|
|
a1a287bac7 | ||
|
|
e9b786d5e8 | ||
|
|
ad9fb411f6 | ||
|
|
1ff982983e | ||
|
|
8c6c43d762 | ||
|
|
6baf197842 | ||
|
|
42e5a50e4f | ||
|
|
b713c9a491 | ||
|
|
64ade742d9 | ||
|
|
1870c3c876 | ||
|
|
23b272aafd | ||
|
|
057db41758 | ||
|
|
839c5a8e41 | ||
|
|
36b8b6bf6c | ||
|
|
40d74fa779 | ||
|
|
249bdeb642 | ||
|
|
b4ee80d1ea | ||
|
|
96bf9d0769 | ||
|
|
7fc9c83986 | ||
|
|
5502f1cc63 | ||
|
|
b55801323c | ||
|
|
818374c8cc | ||
|
|
e80191d4cd | ||
|
|
c2a796b6ea | ||
|
|
00694f0dfd | ||
|
|
134f4c5b52 | ||
|
|
0840fc42f9 | ||
|
|
2650a647e9 | ||
|
|
3311269162 | ||
|
|
b2172d39f6 | ||
|
|
f4d39bd3c8 | ||
|
|
1cf659033b | ||
|
|
3dc5527690 | ||
|
|
81b02d04b5 | ||
|
|
95f6f9e10a | ||
|
|
9554f53519 | ||
|
|
5d7081a224 | ||
|
|
9cbdf3f31f | ||
|
|
c8bc1b560b | ||
|
|
40ae6b396f | ||
|
|
9c117ffa05 | ||
|
|
9e95f189ed | ||
|
|
221b31bcc6 | ||
|
|
8879776d64 | ||
|
|
5edd13c6bb | ||
|
|
7ca289edd0 | ||
|
|
bf434818d7 | ||
|
|
03aeb88832 | ||
|
|
bb5b33a0d3 | ||
|
|
53931017b9 | ||
|
|
e9ca17cec1 | ||
|
|
f70956964b | ||
|
|
4547a9d9d3 | ||
|
|
71accb6b0a | ||
|
|
2a95500b65 | ||
|
|
2ddad66ce7 | ||
|
|
108be24aed | ||
|
|
71efb05658 | ||
|
|
a9a36894cb | ||
|
|
bc9778e02f | ||
|
|
a83d2efe84 | ||
|
|
d3856caf81 | ||
|
|
e1f9b1c47d | ||
|
|
497c953d0e | ||
|
|
bec76bd057 | ||
|
|
54f4762e1a | ||
|
|
8bf5c18425 | ||
|
|
c36bb17475 | ||
|
|
2291fcdf11 | ||
|
|
4070c46d15 | ||
|
|
a749db8d0f | ||
|
|
10ba98c4f5 | ||
|
|
108a3efe0b | ||
|
|
ccd826f63a | ||
|
|
5e5f0aa955 | ||
|
|
f9a4c53e3f | ||
|
|
60b576568e | ||
|
|
d0e1b73205 | ||
|
|
ef2448e17e | ||
|
|
99a5cf1ad4 | ||
|
|
bc3113ae16 | ||
|
|
fb475da008 | ||
|
|
d5fc3ad646 | ||
|
|
8b7da6e318 | ||
|
|
ed208c4bcc | ||
|
|
6ab65519a0 | ||
|
|
4549bc89ec | ||
|
|
a0430f91bd | ||
|
|
624bb1db8d | ||
|
|
9f522bbe6c | ||
|
|
931da3b4f7 | ||
|
|
5a25fd54a4 | ||
|
|
9f0f4c50a4 | ||
|
|
0bf3d31578 | ||
|
|
8ca293c3e4 | ||
|
|
ba0c877ffc | ||
|
|
b8e00c2dc9 | ||
|
|
2dd48898a8 | ||
|
|
66fc807655 | ||
|
|
653eb2909b | ||
|
|
72520a2dd9 | ||
|
|
a7d4666a70 | ||
|
|
13476d5003 | ||
|
|
879cdedec3 | ||
|
|
05bd2a1f9e | ||
|
|
c49d1547c4 | ||
|
|
ad35363c2e | ||
|
|
b3f70140e5 | ||
|
|
2f21dc50b4 | ||
|
|
cbd8c2483b | ||
|
|
03475bfb15 | ||
|
|
bb9411e7dc | ||
|
|
bce4e2d022 | ||
|
|
7cfc14fef7 | ||
|
|
f220cf3173 | ||
|
|
725359b1aa | ||
|
|
937d6cb1ef | ||
|
|
118a5edebc | ||
|
|
1b4333e8d9 | ||
|
|
d66a0b50e9 | ||
|
|
1d56b9a1bb | ||
|
|
96535ee4df | ||
|
|
b55f314d7e | ||
|
|
480862d714 | ||
|
|
990a3af2a7 | ||
|
|
1f5a23143a | ||
|
|
fcfb9e9758 | ||
|
|
9beee689ce | ||
|
|
2c388c3833 | ||
|
|
1a75066616 | ||
|
|
3dfb0bcae9 | ||
|
|
9ac0b77e92 | ||
|
|
6421a32520 | ||
|
|
fdcae52740 | ||
|
|
a8752844ef | ||
|
|
e04ce5028e | ||
|
|
f2c4d80ac0 | ||
|
|
d8a6226805 | ||
|
|
fedf60a32c | ||
|
|
b3548fefc1 | ||
|
|
febd64c527 | ||
|
|
d67a5c5070 | ||
|
|
aefe7ddd8f | ||
|
|
254dea7558 | ||
|
|
b1550f7922 | ||
|
|
2d07c3e45d | ||
|
|
e5f3406cb5 | ||
|
|
185ddf1eaf | ||
|
|
2734335869 | ||
|
|
0132c4e36e | ||
|
|
7dee47183d | ||
|
|
9c4988c297 | ||
|
|
3bfbc70587 | ||
|
|
34858fce1c | ||
|
|
b47dab0ee9 | ||
|
|
6eeb033b96 | ||
|
|
0679cb8e00 | ||
|
|
3abc9ee387 | ||
|
|
2e9211cf41 | ||
|
|
40377796ed | ||
|
|
fedad7f31a | ||
|
|
d2a34e0107 | ||
|
|
769c822568 | ||
|
|
c452a621fe | ||
|
|
231ab95ef6 | ||
|
|
7c01b59ffb | ||
|
|
e79668ddf4 | ||
|
|
dc6b6fc353 | ||
|
|
34ea58cf38 | ||
|
|
199168c318 | ||
|
|
063d4bbd7d | ||
|
|
29fd9b9d64 | ||
|
|
c301baafb5 | ||
|
|
4282672201 | ||
|
|
ae705dd865 | ||
|
|
f0fa2ce171 | ||
|
|
d6a9a9927c | ||
|
|
40b4636858 | ||
|
|
97fe499b63 | ||
|
|
e0915cffda | ||
|
|
7602de85c3 | ||
|
|
0787817eb8 | ||
|
|
e030648957 | ||
|
|
b815935fd7 | ||
|
|
a5000ba311 | ||
|
|
5e2bb874c8 | ||
|
|
fcb5a7f645 | ||
|
|
b8c6520abb | ||
|
|
1d99c3d3f7 | ||
|
|
5e112b395d | ||
|
|
d1a8e7813a | ||
|
|
a0582fec12 | ||
|
|
2cd3a7b3f0 | ||
|
|
47448b11cd | ||
|
|
e63f043841 | ||
|
|
33dd0c83e3 | ||
|
|
32dad136f8 | ||
|
|
073ed52538 | ||
|
|
eef828cf3e | ||
|
|
d0b5930a3a | ||
|
|
c66ad9ccc8 | ||
|
|
9959a15c8e | ||
|
|
f0e4b4dc84 | ||
|
|
f62f808368 | ||
|
|
530a521679 | ||
|
|
50782dfb83 | ||
|
|
27a142d5c5 | ||
|
|
6d00b2e63d | ||
|
|
7be1415a3a | ||
|
|
0a30b12f7d | ||
|
|
3058cbfbb2 | ||
|
|
ae780c977b | ||
|
|
e146a67f4b | ||
|
|
162d86983a | ||
|
|
8534366a31 | ||
|
|
d1c6617dc9 | ||
|
|
6f994709b9 | ||
|
|
55d833a9c8 | ||
|
|
8ba4745097 | ||
|
|
940a0c8b10 | ||
|
|
8928b24e23 | ||
|
|
ae9a9191f3 | ||
|
|
cb553bd016 | ||
|
|
a75c61d71e | ||
|
|
c1dc16a89d | ||
|
|
66436ce4a2 | ||
|
|
62b1ff4ba1 | ||
|
|
304d136437 | ||
|
|
1b4268b9b0 | ||
|
|
a7968e6525 | ||
|
|
e59cc3d404 | ||
|
|
3a2d126877 | ||
|
|
ee3d6fcfee | ||
|
|
09d929bd56 | ||
|
|
bd55ae15f2 | ||
|
|
2ca80118bf | ||
|
|
04eb20ac35 | ||
|
|
f299391aa1 | ||
|
|
c334fc9d22 | ||
|
|
8520088376 | ||
|
|
9ada8518dc | ||
|
|
f0c09b374c | ||
|
|
c5f33baf27 | ||
|
|
2efcdd92e0 | ||
|
|
38fda98b6d | ||
|
|
f9fd195c24 | ||
|
|
01e82090b2 | ||
|
|
39602ede37 | ||
|
|
98a311ae40 | ||
|
|
5c398b3e8f | ||
|
|
83e585ee9b | ||
|
|
e386499bfa | ||
|
|
4552630bf8 | ||
|
|
2d8065a780 | ||
|
|
b94da93c74 | ||
|
|
695045f197 | ||
|
|
376733bd08 | ||
|
|
4c7c5137c5 | ||
|
|
930b9820f2 | ||
|
|
b2fa63f2c8 | ||
|
|
1390e1db39 | ||
|
|
e7768ae954 | ||
|
|
38d977e546 | ||
|
|
3e38a24f0a | ||
|
|
0784cd593a | ||
|
|
9c5d2ee563 | ||
|
|
be5f7c2e67 | ||
|
|
0d0f73fb67 | ||
|
|
680be6cfec | ||
|
|
2ab3d072b0 | ||
|
|
943ecff623 | ||
|
|
03973f5d1d | ||
|
|
c42a0fa9b6 | ||
|
|
61522ed31d | ||
|
|
29a527426a | ||
|
|
62ac0ff21e | ||
|
|
a41c7caa18 | ||
|
|
b3ca31bce7 | ||
|
|
b02f6a1dae | ||
|
|
d35609f33a | ||
|
|
8c19ab8f9f | ||
|
|
30ae198b89 | ||
|
|
bddeab3ac1 | ||
|
|
591349ee74 | ||
|
|
9081a25e64 | ||
|
|
1beadfc6e7 | ||
|
|
f4af532c5a | ||
|
|
76eb1a9d78 | ||
|
|
14a2790dcb | ||
|
|
46f54db197 | ||
|
|
4ffd7587a9 | ||
|
|
c48c62c7a8 | ||
|
|
9e7fd20ade | ||
|
|
efa1d381ba | ||
|
|
740fa058aa | ||
|
|
37f56e1efd | ||
|
|
6294be371a | ||
|
|
bee7549a1e | ||
|
|
db14dbacc9 | ||
|
|
27058e6297 | ||
|
|
b41175e0e2 | ||
|
|
eeea3251ad | ||
|
|
34ffff3947 | ||
|
|
65ed3818ec | ||
|
|
c8417df6f1 | ||
|
|
dc3be7ecf7 | ||
|
|
cf3c0b593b | ||
|
|
34f64148e8 | ||
|
|
fc5dad1983 | ||
|
|
c3c40548b9 | ||
|
|
0e2e932102 | ||
|
|
6930c4e23b | ||
|
|
01b9f2dfcf | ||
|
|
0cc6f66a26 | ||
|
|
d384f55dd1 | ||
|
|
1893368aa5 | ||
|
|
a520063265 | ||
|
|
1e171a72a0 | ||
|
|
5b1a0d93b9 | ||
|
|
7e04662a9c | ||
|
|
a804549781 | ||
|
|
2a60f1cc6e | ||
|
|
2ddff785e5 | ||
|
|
38882efb5c | ||
|
|
6f7786b068 | ||
|
|
0819141f03 | ||
|
|
329ef5049f | ||
|
|
34bb8c65d6 | ||
|
|
575ccae6f9 | ||
|
|
486be87e33 | ||
|
|
c0350861ef | ||
|
|
a7ec1805e3 | ||
|
|
4b06bc552f | ||
|
|
76ee7b7eea | ||
|
|
04b1e7e34f | ||
|
|
17dbb156e1 | ||
|
|
135117c637 | ||
|
|
d3348f7855 | ||
|
|
39bbcb66c8 | ||
|
|
d45e8e4d20 | ||
|
|
d65052c1ac | ||
|
|
2fbc42753f | ||
|
|
4195865965 | ||
|
|
de3f6fbeba | ||
|
|
6a377120bd | ||
|
|
502226b0a6 | ||
|
|
78206b48f4 | ||
|
|
dc3cec06ca | ||
|
|
5a7688e099 | ||
|
|
c721f01c76 | ||
|
|
463806822c | ||
|
|
b74c2f001d | ||
|
|
9fc7a8b626 | ||
|
|
3ffd92a6c3 | ||
|
|
29b02e5329 | ||
|
|
97584e046f | ||
|
|
09d2fce85d | ||
|
|
fc3060cb29 | ||
|
|
9804a67165 | ||
|
|
21eddefa41 | ||
|
|
9b62e7eedb | ||
|
|
bf30cfd8a4 | ||
|
|
139ffae367 | ||
|
|
51a48cc264 | ||
|
|
abbca12565 | ||
|
|
9e9d96a2ec | ||
|
|
615c9f1cbe | ||
|
|
7d75d0cfbd | ||
|
|
5468de2c6a | ||
|
|
6d8aabab23 | ||
|
|
e74359fcfe | ||
|
|
53c842c614 | ||
|
|
23ececeb34 | ||
|
|
521c9eb566 | ||
|
|
35877b1382 | ||
|
|
c531287170 | ||
|
|
8e79a81b88 | ||
|
|
b95ceb301f | ||
|
|
76a94495c4 | ||
|
|
b6b2299b4e | ||
|
|
34ddea87d3 | ||
|
|
3d318542cb | ||
|
|
4a8c3cdc61 | ||
|
|
c0b6f2d95f | ||
|
|
9ca7fccab8 | ||
|
|
d91fcfc866 | ||
|
|
29b53f3b9d | ||
|
|
30987095c7 | ||
|
|
43b93de570 | ||
|
|
5b310cf315 | ||
|
|
a1c2a57ea6 | ||
|
|
34bf8f1133 | ||
|
|
c708ec577e | ||
|
|
c185685f2d | ||
|
|
daee5b3477 | ||
|
|
5d0346ee30 | ||
|
|
85ad5355cf | ||
|
|
4c8b84633a | ||
|
|
c0dd4d748d | ||
|
|
c94f25570b | ||
|
|
ffa5e08832 | ||
|
|
63243c8e04 | ||
|
|
21c4ec2de0 | ||
|
|
a8d87af418 | ||
|
|
7b084a065e | ||
|
|
47f6b202e5 | ||
|
|
f588d8379b | ||
|
|
58827e130b | ||
|
|
d702334604 | ||
|
|
b04aa799e3 | ||
|
|
e113f6cb9d | ||
|
|
bc13b7eb72 | ||
|
|
f50b395da6 | ||
|
|
a0e8e40f1c | ||
|
|
cb6055c1b8 | ||
|
|
25424c16e4 | ||
|
|
99dcdee67a | ||
|
|
99928f1aea | ||
|
|
1740ae2104 | ||
|
|
d8372f8433 | ||
|
|
2a15d2c421 | ||
|
|
bacf19688f | ||
|
|
31fbdcf6c5 | ||
|
|
c8818cb7b3 | ||
|
|
eb20789821 | ||
|
|
c90862217e | ||
|
|
df87d6feeb | ||
|
|
6c808abcfc | ||
|
|
f1822bdfab | ||
|
|
c3428acd80 | ||
|
|
d619192b22 | ||
|
|
5bdc713afe | ||
|
|
46eff1c937 | ||
|
|
76e1ea1c02 | ||
|
|
755076a8e5 | ||
|
|
b49f7b8b34 | ||
|
|
c4dd8885e4 | ||
|
|
4c82952b58 | ||
|
|
0da69cb9c7 | ||
|
|
36e244060c | ||
|
|
b13a9f57af | ||
|
|
0aa67ad7f9 | ||
|
|
195a3a6827 | ||
|
|
38ecff1220 | ||
|
|
67e64287af | ||
|
|
b022703b0b | ||
|
|
e8069c0d93 | ||
|
|
7a1c6b64c2 | ||
|
|
8250cb1e8d | ||
|
|
ffe2c4d42b | ||
|
|
f06c970628 | ||
|
|
99bce46b32 | ||
|
|
f711913778 | ||
|
|
a8ac231667 | ||
|
|
f7c8791a6d | ||
|
|
7acc775c91 | ||
|
|
c2e21e837f | ||
|
|
755d0f54f7 | ||
|
|
f62d66ff25 | ||
|
|
406d19f930 | ||
|
|
42b13614eb | ||
|
|
c942bd67fe | ||
|
|
b8dc3d74b6 | ||
|
|
38fb263737 | ||
|
|
b55beed2f9 | ||
|
|
e9278c03c1 | ||
|
|
ae1fe83784 | ||
|
|
717a547c40 | ||
|
|
ec491e87ab | ||
|
|
42e30d0835 | ||
|
|
5b19418e48 | ||
|
|
1bc9a7373f | ||
|
|
23e59b5dcc | ||
|
|
c6b459cf96 | ||
|
|
33254b4cac | ||
|
|
44da40d18d | ||
|
|
c742f25801 | ||
|
|
b153687bf1 | ||
|
|
3318f093da | ||
|
|
d98d56c3b5 | ||
|
|
c3f5f6c7ad | ||
|
|
5f21edcc53 | ||
|
|
cd0731cbb0 | ||
|
|
f392ddec2f | ||
|
|
df71168ab7 | ||
|
|
e93b26bf54 | ||
|
|
a73d4a8cbd | ||
|
|
20ee57801c | ||
|
|
6a270d7f02 | ||
|
|
68639637c9 | ||
|
|
0d1eabbc33 | ||
|
|
dce249f7a9 | ||
|
|
1723d4fbd8 | ||
|
|
c4b09f1a4f | ||
|
|
788c973c13 | ||
|
|
465c5c8cfb | ||
|
|
ee28ba5be1 | ||
|
|
9a22e9cf39 | ||
|
|
2513f605b6 | ||
|
|
3b1ffb2028 | ||
|
|
47c6624e12 | ||
|
|
b6f1b064d3 | ||
|
|
17d89467df | ||
|
|
1282214d48 | ||
|
|
f4bc6ee615 | ||
|
|
f8b8d8c540 | ||
|
|
57ff667438 | ||
|
|
abe3039926 | ||
|
|
82a1117e91 | ||
|
|
b6ff3a4d99 | ||
|
|
f4046efcb2 | ||
|
|
fc1d3831cf | ||
|
|
867deda247 | ||
|
|
f8149face5 | ||
|
|
7e2aecd8bb | ||
|
|
105d121199 | ||
|
|
37d662f2f5 | ||
|
|
5b50454b4d | ||
|
|
b5e4c08fc5 | ||
|
|
db39cd8b7c | ||
|
|
a35f741a35 | ||
|
|
fc02e018cb | ||
|
|
b14a530efb | ||
|
|
f70bc571bd | ||
|
|
8cc64176b4 | ||
|
|
7450ac1a31 | ||
|
|
c72e5e3b66 | ||
|
|
5e811819e2 | ||
|
|
f1c0034a18 | ||
|
|
7342cb81a3 | ||
|
|
b40e858556 | ||
|
|
95a4ed7d6a | ||
|
|
2c2d4b6b95 | ||
|
|
4490eae4fe | ||
|
|
9d59cb0135 | ||
|
|
7d348fe69f | ||
|
|
fa8fb9e73f | ||
|
|
f6093872ec | ||
|
|
e8030e29d9 | ||
|
|
df8bb0596a | ||
|
|
0003e0b8a5 | ||
|
|
e42703d557 | ||
|
|
4636e56395 | ||
|
|
27ebeffad4 | ||
|
|
07110cee17 | ||
|
|
afa1f1416b | ||
|
|
f8dfcab0ca | ||
|
|
e14fd920d6 | ||
|
|
8c10fdae5b | ||
|
|
eee027d9ff | ||
|
|
1b1fb5d26a | ||
|
|
c36e0805d8 | ||
|
|
5c56041185 | ||
|
|
5aefe0b74f | ||
|
|
20e0359efd | ||
|
|
9c790e5a90 | ||
|
|
9c79b5be77 | ||
|
|
2d9a4f4e42 | ||
|
|
565602538c | ||
|
|
78972725ae | ||
|
|
5ab90f7791 | ||
|
|
b90d98fc2b | ||
|
|
eca3ae393b | ||
|
|
2bd69495d2 | ||
|
|
bfd3da43ac | ||
|
|
32a9eaf3b6 | ||
|
|
91cea1f28a | ||
|
|
220ed35f58 | ||
|
|
b1cf5d4e44 | ||
|
|
fe330ec1bb | ||
|
|
2968bf8241 | ||
|
|
a40babbf0d | ||
|
|
7822257e1c | ||
|
|
b37165c62b | ||
|
|
5e9d267959 | ||
|
|
1a1e6b6810 | ||
|
|
88140002e7 | ||
|
|
efc203d958 | ||
|
|
42d4cdcc39 | ||
|
|
fd433b3eb6 | ||
|
|
7483adb8ad | ||
|
|
45fd462f80 | ||
|
|
807003adf7 | ||
|
|
1b0a17c7db | ||
|
|
60b145833c | ||
|
|
39458b2ba8 | ||
|
|
5de38b3632 | ||
|
|
6ced3426cf | ||
|
|
43460c9d19 | ||
|
|
ca17fb01bc | ||
|
|
a6f65aa9c5 | ||
|
|
ae9a7727d6 | ||
|
|
3ac5d5257b | ||
|
|
668d7c73ed | ||
|
|
c95f708c91 | ||
|
|
06e214e567 | ||
|
|
18f8cafee0 | ||
|
|
6bd6afac05 | ||
|
|
fe7ecede70 | ||
|
|
089708ab9f | ||
|
|
daa844c038 | ||
|
|
4049992228 | ||
|
|
7c576c91b7 | ||
|
|
17bd364614 | ||
|
|
25ffd39519 | ||
|
|
acfa527e3e | ||
|
|
b512416cb3 | ||
|
|
bd116c53a1 | ||
|
|
1251fca256 | ||
|
|
b2fe21709c | ||
|
|
c082d12b59 | ||
|
|
9a4ca44255 | ||
|
|
6fce9a41b0 | ||
|
|
65acdd7b15 | ||
|
|
a209374cbd | ||
|
|
c1bb87db98 | ||
|
|
8bae40449f | ||
|
|
bc3bb4694a | ||
|
|
22588e58f3 | ||
|
|
69ba4eb055 | ||
|
|
687b9fb6a2 | ||
|
|
9b9ca9695c | ||
|
|
6357c69868 | ||
|
|
15cb7ab7a1 | ||
|
|
2c741bd24d | ||
|
|
3f72a3beb6 | ||
|
|
42de18d96d | ||
|
|
4bdbdab399 | ||
|
|
c7515b8687 | ||
|
|
c79e39a488 | ||
|
|
d639104b71 | ||
|
|
c66a5ba732 | ||
|
|
79f9b49dd7 | ||
|
|
8b542c250a | ||
|
|
55237683d2 | ||
|
|
27401794e1 | ||
|
|
862a7c2dba | ||
|
|
bb31a4620e | ||
|
|
7aaade8b23 | ||
|
|
a622f533ad | ||
|
|
0dd27dabd6 | ||
|
|
8ab464acf2 | ||
|
|
db18438db2 | ||
|
|
f885f98611 | ||
|
|
9b8b85545f | ||
|
|
532b479f96 | ||
|
|
422dfca6d7 | ||
|
|
c3d1474f59 | ||
|
|
99873504e4 | ||
|
|
138a67298d | ||
|
|
aca1551e86 | ||
|
|
ca32850a32 | ||
|
|
ba6f069997 | ||
|
|
c6c6b52ccd | ||
|
|
96c334e730 | ||
|
|
3e503ec3a3 | ||
|
|
e455fae334 | ||
|
|
29f3dc2fa3 | ||
|
|
aa41b16757 | ||
|
|
f4d59abe41 | ||
|
|
18de58fd8b | ||
|
|
4c2b188f8b | ||
|
|
08f65420f4 | ||
|
|
b90228b319 | ||
|
|
ad2c165f26 | ||
|
|
af5218593a | ||
|
|
f19acd9f50 | ||
|
|
59940e7f05 | ||
|
|
094536e633 | ||
|
|
4f2a439873 | ||
|
|
63bdab2b5f | ||
|
|
14733f8482 | ||
|
|
b830bbd084 | ||
|
|
c1894c5a39 | ||
|
|
e91e488e1f | ||
|
|
e6dac085cb | ||
|
|
5023a5b56b | ||
|
|
32d37d1178 | ||
|
|
848221649e | ||
|
|
f5f357060b | ||
|
|
98eea41865 | ||
|
|
8ac529f5ae | ||
|
|
b5fed08dd4 | ||
|
|
9bfcaf2669 | ||
|
|
af05ee7e1c | ||
|
|
3918439020 | ||
|
|
3b71e115a4 | ||
|
|
c33660a015 | ||
|
|
7963d4cb8f | ||
|
|
16281e0e7f | ||
|
|
72c58e60d7 | ||
|
|
4b48ff2868 | ||
|
|
8e212d30d0 | ||
|
|
b9ae396e74 | ||
|
|
3a38946f8a | ||
|
|
d0d3a5454e | ||
|
|
04c6d77d2c | ||
|
|
c2c5730d00 | ||
|
|
21a6dffd5f | ||
|
|
7430989212 | ||
|
|
2e26a13f81 | ||
|
|
404ebd4d5e | ||
|
|
11ea7bf0fc | ||
|
|
6da7fe7d27 | ||
|
|
538e540531 | ||
|
|
53138f4b09 | ||
|
|
3d71367f30 | ||
|
|
bb52ff9b4b | ||
|
|
ab5b82221c | ||
|
|
5c3b89a68b | ||
|
|
da923d7749 | ||
|
|
55d905fdd9 | ||
|
|
4ba70a3fae | ||
|
|
0722188ea6 | ||
|
|
d6f81e139a | ||
|
|
58ee147653 | ||
|
|
28ad6a6883 | ||
|
|
9de8aefa98 | ||
|
|
66c273ae8d | ||
|
|
b27fbf209e | ||
|
|
4afd1ac705 | ||
|
|
d556ef59e6 | ||
|
|
81e972b85c | ||
|
|
3bb04cc323 | ||
|
|
9ff43f081f | ||
|
|
8c014e3b6b | ||
|
|
d8378a17c9 | ||
|
|
574a01727e | ||
|
|
b5cea3301d | ||
|
|
9346a06f35 | ||
|
|
250e917c6e | ||
|
|
7b1cd37cd6 | ||
|
|
47e83a15c1 | ||
|
|
597e847a3b | ||
|
|
47f3b41d5e | ||
|
|
e7f4c1ffd1 | ||
|
|
9a87b8bf1b | ||
|
|
dac27aab68 | ||
|
|
069a5429c9 | ||
|
|
b1eaa810ce | ||
|
|
e5e3c268a2 | ||
|
|
22dff49673 | ||
|
|
591905c282 | ||
|
|
6ed160e4fa | ||
|
|
d462230b82 | ||
|
|
e48ed9d06d | ||
|
|
6236869ebe | ||
|
|
2c7c9ae2d7 | ||
|
|
b9b4e71f7d | ||
|
|
b0bf646d71 | ||
|
|
5cb5ecdb54 | ||
|
|
44fa5ac9a1 | ||
|
|
9a19f7eac9 | ||
|
|
af0896bb8b | ||
|
|
817237ef77 | ||
|
|
fbefff6eed | ||
|
|
4ba47698d7 | ||
|
|
2688abf25a | ||
|
|
5eb79bd51e | ||
|
|
d3f5f778a4 | ||
|
|
3eeb2b0ee4 | ||
|
|
230a1919dd | ||
|
|
14004fbf7f | ||
|
|
73e8af98f2 | ||
|
|
0117a0019b | ||
|
|
35ff8781f0 | ||
|
|
2d17442f28 | ||
|
|
5c179522bb | ||
|
|
b35d95da52 | ||
|
|
feca5afaa5 | ||
|
|
9cb5274d30 | ||
|
|
2870fd46da | ||
|
|
dff8ef91a6 | ||
|
|
0588975e37 | ||
|
|
e0600b241a | ||
|
|
d19aa8fb3b | ||
|
|
989a4f3d49 | ||
|
|
2a2c4d3e9c | ||
|
|
a451449766 | ||
|
|
3347fab105 | ||
|
|
33a6c92629 | ||
|
|
0707d33493 | ||
|
|
89e4006b2d | ||
|
|
4eb8921635 | ||
|
|
26ac452c96 | ||
|
|
7122e1522a | ||
|
|
5497adfde6 | ||
|
|
d4c2e50285 | ||
|
|
481ecee9e8 |
153
.debianinstall/README.md
Normal file
153
.debianinstall/README.md
Normal file
@@ -0,0 +1,153 @@
|
||||
|
||||
# How to use
|
||||
|
||||
## Disclaimers
|
||||
|
||||
- **This script does work with a fresh install of Debian 12 only**.
|
||||
- Do not use if you have already installed and configured a webserver or sql server that was not installed by this script.
|
||||
|
||||
### Keep it Simple and Stupid
|
||||
|
||||
The script keeps everything as simple as possible (KISS):
|
||||
|
||||
- Apache as webserver (there is no choice to use another webserver like nginx)
|
||||
- default PHP version of Debian
|
||||
- one single Hubzilla intance only
|
||||
- re-running the script does no harm
|
||||
|
||||
### When to use other Scripts
|
||||
|
||||
Use the scripts under [homeinstall](https://framagit.org/hubzilla/core/-/tree/master/.homeinstall)
|
||||
if you look for more choices. The main differences are:
|
||||
|
||||
- Apache or nginx as webserver
|
||||
- install multiple instances (domains) that run side by side on the server
|
||||
- adds apache vhosts (instead of using the standard doc root /var/www/html)
|
||||
- install PHP from https://packages.sury.org/php/ (instead of using the Debian repository)
|
||||
- graphical installer whiptail
|
||||
- The script stops (fails) if it finds results of a previous installation. (The [debian-setup.sh](https://framagit.org/ojrandom/core/-/tree/dev/.debianinstall) will just jump over it.)
|
||||
- If something fails the script tries to clean up everything that was installed up to the point of failure. (That might cause trouble if certbot registered a certificate already.)
|
||||
- The script under [homeinstall](https://framagit.org/hubzilla/core/-/tree/master/.homeinstall) seems to be an older version of the scripts used for Streams, i.e. [autoinstall](https://codeberg.org/streams/streams/src/branch/dev/contrib/autoinstall) and [easyinstall](https://codeberg.org/streams/streams/src/branch/dev/contrib/easyinstall)
|
||||
|
||||
## Preconditions
|
||||
|
||||
Hardware
|
||||
|
||||
+ internet connection and router at home
|
||||
+ computer connected to your router (a Raspberry 3 will do for very small Hubs)
|
||||
|
||||
Software
|
||||
|
||||
+ fresh installation of Debian 12 (bookworm)
|
||||
+ router with open ports 80 and 443 for your web server
|
||||
|
||||
You can of course run the script on a VPS or any distant server as long as the above sotfware requirements are satisfied.
|
||||
|
||||
## How to run the script
|
||||
|
||||
+ Register your own domain (for example at selfHOST) or a free subdomain (for example at freeDNS)
|
||||
+ Log on to your fresh Debian
|
||||
- apt-get install git
|
||||
- mkdir -p /var/www
|
||||
- cd /var/www
|
||||
- git clone https://framagit.org/hubzilla/core.git html
|
||||
- cd html/.debianinstall
|
||||
- cp config.txt.template config.txt
|
||||
- nano config.txt
|
||||
- read the comments carefully
|
||||
- enter your values: db pass, domain
|
||||
- (optionally) Enter your values for dyn DNS
|
||||
- ./debian-setup.sh as root
|
||||
- ... wait, wait, wait until the script is finished
|
||||
+ Open your domain with a browser and step throught the initial configuration of your hubzilla instance.
|
||||
- default database name = hubzilla
|
||||
- default dababase user = hubzilla
|
||||
|
||||
## Optional - Switch verification of email on/off
|
||||
|
||||
Do this just before you register the first user without email verification.
|
||||
|
||||
In a terminal
|
||||
|
||||
su -
|
||||
cd /var/www/html
|
||||
|
||||
Check the current setting
|
||||
|
||||
util/config system verify_email
|
||||
|
||||
Switch the verification off
|
||||
|
||||
util/config system verify_email 0
|
||||
|
||||
## What the script will do for you...
|
||||
|
||||
+ install everything required by your hubzilla instance, basically a web server (Apache), PHP, a database (MySQL), certbot,...
|
||||
+ create a database
|
||||
+ run certbot to have everything for a secure connection (httpS)
|
||||
+ create a script for daily maintenance
|
||||
- renew certfificate (letsencrypt)
|
||||
- update of your hubzilla instance for core and addons (git)
|
||||
- update of Debian
|
||||
- restart
|
||||
+ create cron jobs for
|
||||
- DynDNS (selfHOST.de or freedns.afraid.org) every 5 minutes
|
||||
- Master.php for your hubzilla instance every 10 minutes
|
||||
- daily maintenance script every day at 05:30
|
||||
|
||||
The script is known to work without adjustments with
|
||||
|
||||
+ Hardware
|
||||
- standard PC with Debian 12 (bookworm)
|
||||
- Raspberry 4 with Raspbian, Debian 12 (TODO: needs confirmation after swich to Debian12)
|
||||
- for tesing purposes: under localhost inside a virtual machine, [KVM](https://wiki.debian.org/KVM)
|
||||
+ DynDNS
|
||||
- selfHOST.de
|
||||
- freedns.afraid.org
|
||||
|
||||
# Step-by-Step - some Details
|
||||
|
||||
## Preparations
|
||||
|
||||
## Configure your Router
|
||||
|
||||
Your webserver has to be visible in the internet.
|
||||
|
||||
Open the ports 80 and 443 on your router for your Debian. Make sure your web server is marked as "exposed host".
|
||||
|
||||
## Preparations Dynamic IP Address
|
||||
|
||||
Follow the instructions in .debianinstall/config.txt.
|
||||
|
||||
In short...
|
||||
|
||||
Your Hubzilla server must be reachable by a domain that you can type in your browser
|
||||
|
||||
cooldomain.org
|
||||
|
||||
You can use subdomains as well
|
||||
|
||||
my.cooldomain.org
|
||||
|
||||
There are two ways to get a domain...
|
||||
|
||||
### Method 1: Buy a Domain
|
||||
|
||||
...for example buy at selfHOST.de
|
||||
|
||||
The cost is 1,50 € per month (2019).
|
||||
|
||||
### Method 2: Register a free subdomain
|
||||
|
||||
...for example register at freedns.afraid.org
|
||||
|
||||
## Note on Rasperry
|
||||
|
||||
It is recommended to run the Raspi without graphical frontend (X-Server). Use...
|
||||
|
||||
sudo raspi-config
|
||||
|
||||
to boot the Rapsi to the client console.
|
||||
|
||||
DO NOT FORGET TO CHANGE THE DEFAULT PASSWORD FOR USER PI!
|
||||
|
||||
110
.debianinstall/config.txt.template
Normal file
110
.debianinstall/config.txt.template
Normal file
@@ -0,0 +1,110 @@
|
||||
|
||||
###############################################
|
||||
### MANDATORY - database password #############
|
||||
#
|
||||
# Please give your database password
|
||||
# It is better to not use blanks inside the password.
|
||||
# Example: db_pass=pass_word_with_no_blanks_in_it
|
||||
db_pass=
|
||||
|
||||
###############################################
|
||||
### MANDATORY - let's encrypt #################
|
||||
#
|
||||
# Zot requires encrypted communication via secure HTTP (HTTPS).
|
||||
# This script automates installation of an SSL certificate from
|
||||
# Let's Encrypt (https://letsencrypt.org)
|
||||
#
|
||||
# Please give the domain name of your hub/instance
|
||||
#
|
||||
# Example: my.cooldomain.org
|
||||
# Example: cooldomain.org
|
||||
#
|
||||
# You might use "localhost" for a LOCAL TEST installation.
|
||||
# This is usefull if you want to debug the server inside a VM.
|
||||
#
|
||||
# Example: localhost
|
||||
#
|
||||
# Email is optional if you use "localhost".
|
||||
#
|
||||
#
|
||||
le_domain=
|
||||
le_email=
|
||||
|
||||
|
||||
###############################################
|
||||
### OPTIONAL - selfHOST - dynamic IP address ##
|
||||
#
|
||||
# 1. Register a domain at selfhost.de
|
||||
# - choose offer "DOMAIN dynamisch" 1,50€/mon at 04/2019
|
||||
# 2. Get your configuration for dynamic IP update
|
||||
# - Log in at selfhost.de
|
||||
# - go to "DynDNS Accounte"
|
||||
# - klick "Details" of your (freshly) registered domain
|
||||
# - You will find the configuration there
|
||||
# - Benutzername (user name) > use this for "selfhost_user="
|
||||
# - Passwort (pass word) > use this for "selfhost_pass="
|
||||
#
|
||||
#
|
||||
selfhost_user=
|
||||
selfhost_pass=
|
||||
|
||||
###############################################
|
||||
### OPTIONAL - FreeDNS - dynamic IP address ###
|
||||
#
|
||||
# Please give the alpha-numeric-key of freedns
|
||||
#
|
||||
# Get a free subdomain from freedns and use it for your dynamic ip address
|
||||
# Documentation under http://www.techjawab.com/2013/06/setup-dynamic-dns-dyndns-for-free-on.html
|
||||
#
|
||||
# - Register for a Free domain at http://freedns.afraid.org/signup/
|
||||
# - WATCH THIS: Make sure you choose a domain with as less subdomains as
|
||||
# possible. Why? Let's encrpyt issues a limited count of certificates each
|
||||
# day. Possible other users of this domain will try to issue a certificate
|
||||
# at the same day.
|
||||
# - Logon to FreeDNS (where you just registered)
|
||||
# - Goto http://freedns.afraid.org/dynamic/
|
||||
# - Right click on "Direct Link" and copy the URL and paste it somewhere.
|
||||
# - You should notice a large and unique alpha-numeric key in the URL
|
||||
#
|
||||
# http://freedns.afraid.org/dynamic/update.php?alpha-numeric-key
|
||||
#
|
||||
# Provided your url from freedns is
|
||||
#
|
||||
# http://freedns.afraid.org/dynamic/update.php?U1Z6aGt2R0NzMFNPNWRjbWxxZGpsd093OjE1Mzg5NDE5
|
||||
#
|
||||
# Then you have to provide
|
||||
#
|
||||
# freedns_key=U1Z6aGt2R0NzMFNPNWRjbWxxZGpsd093OjE1Mzg5NDE5
|
||||
#
|
||||
#
|
||||
freedns_key=
|
||||
|
||||
|
||||
###############################################
|
||||
### OPTIONAL - do not mess with things below ##
|
||||
# (...if you are not certain)
|
||||
#
|
||||
# Usually you are done here
|
||||
# Everything below is OPTIONAL
|
||||
#
|
||||
###############################################
|
||||
#
|
||||
# Database for your hub/instance
|
||||
# If left empty, both your database and user will be named after your zot instance (hubzilla, zap or misty)
|
||||
# Use custom name, at least fo the database, if you plan to run more than one hub/instance on the same server
|
||||
#
|
||||
db_name=hubzilla
|
||||
db_user=hubzilla
|
||||
#
|
||||
#
|
||||
# Password for package mysql-server
|
||||
# Example: mysqlpass=aberhallo
|
||||
# Example: mysqlpass="aber hallo has blanks in it"
|
||||
#
|
||||
mysqlpass=$db_pass
|
||||
|
||||
# Password for package phpmyadmin
|
||||
# Example: phpmyadminpass=aberhallo
|
||||
# Example: phpmyadminpass="aber hallo has blanks in it"
|
||||
phpmyadminpass=$db_pass
|
||||
|
||||
533
.debianinstall/debian-setup.sh
Normal file
533
.debianinstall/debian-setup.sh
Normal file
@@ -0,0 +1,533 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# How to use
|
||||
# ----------
|
||||
#
|
||||
# This file automates the installation of hubzilla: https://framagit.org/hubzilla/core
|
||||
# under Debian Linux "bookworm"
|
||||
#
|
||||
# 1) Copy the file "config.txt.template" to "config.txt"
|
||||
# Follow the instuctions there
|
||||
#
|
||||
# 2) Switch to user "root" by typing "su -"
|
||||
#
|
||||
# 3) Run with "./debian-setup.sh"
|
||||
# If this fails check if you can execute the script.
|
||||
# - To make it executable type "chmod +x debian-setup.sh"
|
||||
# - or run "bash debian-setup.sh"
|
||||
#
|
||||
#
|
||||
# What does this script do basically?
|
||||
# -----------------------------------
|
||||
#
|
||||
# This file automates the installation of a Hubzilla instance under Debian Linux
|
||||
# - install
|
||||
# * apache webserver,
|
||||
# * php,
|
||||
# * mariadb,
|
||||
# * adminer,
|
||||
# * addons
|
||||
# - configure cron
|
||||
# * "Master.php" for regular background processes of your hubzilla instance
|
||||
# * "apt-get update" and "apt-get dist-upgrade" and "apt-get autoremove" to keep linux up-to-date
|
||||
# * run command to keep the IP up-to-date > DynDNS provided by selfHOST.de or freedns.afraid.org
|
||||
# - run letsencrypt to create, register and use a certifacte for https
|
||||
#
|
||||
#
|
||||
# Credits
|
||||
# -------
|
||||
#
|
||||
# The script is derived from the easyinstall script of the Streams repository, which is based on
|
||||
# - Tom Wiedenhöfts (OJ Random) script homeinstall (for Hubzilla, ZAP,...) that was based on
|
||||
# - Thomas Willinghams script "debian-setup.sh" which he used to install the red#matrix.
|
||||
|
||||
function check_sanity {
|
||||
# Do some sanity checking.
|
||||
print_info "Sanity check..."
|
||||
if [ $(/usr/bin/id -u) != "0" ]
|
||||
then
|
||||
die 'Must be run by root user'
|
||||
fi
|
||||
|
||||
if [ -f /etc/lsb-release ]
|
||||
then
|
||||
die "Distribution is not supported"
|
||||
fi
|
||||
if [ ! -f /etc/debian_version ]
|
||||
then
|
||||
die "Debian is supported only"
|
||||
fi
|
||||
if ! grep -q 'Linux 12' /etc/issue
|
||||
then
|
||||
die "Linux 12 (bookworm) is supported only"x
|
||||
fi
|
||||
}
|
||||
|
||||
function check_config {
|
||||
print_info "config check..."
|
||||
# Check for required parameters
|
||||
if [ -z "$db_pass" ]
|
||||
then
|
||||
die "db_pass not set in $configfile"
|
||||
fi
|
||||
if [ -z "$le_domain" ]
|
||||
then
|
||||
die "le_domain not set in $configfile"
|
||||
fi
|
||||
}
|
||||
|
||||
function die {
|
||||
echo "ERROR: $1" > /dev/null 1>&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
|
||||
function update_upgrade {
|
||||
print_info "updated and upgrade..."
|
||||
# Run through the apt-get update/upgrade first. This should be done before
|
||||
# we try to install any package
|
||||
apt-get -q -y update && apt-get -q -y dist-upgrade && apt-get -q -y autoremove
|
||||
print_info "updated and upgraded linux"
|
||||
}
|
||||
|
||||
function nocheck_install {
|
||||
# export DEBIAN_FRONTEND=noninteractive ... answers from the package configuration database
|
||||
# - q ... without progress information
|
||||
# - y ... answer interactive questions with "yes"
|
||||
# DEBIAN_FRONTEND=noninteractive apt-get --no-install-recommends -q -y install $2
|
||||
# DEBIAN_FRONTEND=noninteractive apt-get --install-suggests -q -y install $1
|
||||
DEBIAN_FRONTEND=noninteractive apt-get -q -y install $1
|
||||
print_info "installed $1"
|
||||
}
|
||||
|
||||
|
||||
function print_info {
|
||||
echo -n -e '\e[1;34m'
|
||||
echo -n $1
|
||||
echo -e '\e[0m'
|
||||
}
|
||||
|
||||
function print_warn {
|
||||
echo -n -e '\e[1;31m'
|
||||
echo -n $1
|
||||
echo -e '\e[0m'
|
||||
}
|
||||
|
||||
function stop_zotserver {
|
||||
print_info "stopping apache..."
|
||||
systemctl stop apache2
|
||||
print_info "stopping mysql db..."
|
||||
systemctl stop mariadb
|
||||
}
|
||||
|
||||
function install_apache {
|
||||
print_info "installing apache..."
|
||||
nocheck_install "apache2 apache2-utils"
|
||||
a2enmod rewrite
|
||||
systemctl restart apache2
|
||||
}
|
||||
|
||||
function install_imagemagick {
|
||||
print_info "installing imagemagick..."
|
||||
nocheck_install "imagemagick"
|
||||
}
|
||||
|
||||
function install_curl {
|
||||
print_info "installing curl..."
|
||||
nocheck_install "curl"
|
||||
}
|
||||
|
||||
function install_wget {
|
||||
print_info "installing wget..."
|
||||
nocheck_install "wget"
|
||||
}
|
||||
|
||||
function install_sendmail {
|
||||
print_info "installing sendmail..."
|
||||
nocheck_install "sendmail sendmail-bin"
|
||||
}
|
||||
|
||||
function install_php {
|
||||
# openssl and mbstring are included in libapache2-mod-php
|
||||
print_info "installing php..."
|
||||
nocheck_install "libapache2-mod-php php php-pear php-curl php-gd php-mbstring php-xml php-zip php-intl php-bcmath"
|
||||
phpversion=$(php -v|grep --only-matching --perl-regexp "(PHP )\d+\.\\d+\.\\d+"|cut -c 5-7)
|
||||
sed -i "s/^upload_max_filesize =.*/upload_max_filesize = 100M/g" /etc/php/$phpversion/apache2/php.ini
|
||||
sed -i "s/^post_max_size =.*/post_max_size = 100M/g" /etc/php/$phpversion/apache2/php.ini
|
||||
}
|
||||
|
||||
function install_composer {
|
||||
print_info "We check if Composer is already downloaded"
|
||||
if [ ! -f /usr/local/bin/composer ]
|
||||
then
|
||||
EXPECTED_CHECKSUM="$(php -r 'copy("https://composer.github.io/installer.sig", "php://stdout");')"
|
||||
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
|
||||
ACTUAL_CHECKSUM="$(php -r "echo hash_file('sha384', 'composer-setup.php');")"
|
||||
if [ "$EXPECTED_CHECKSUM" != "$ACTUAL_CHECKSUM" ]
|
||||
then
|
||||
>&2 echo 'ERROR: Invalid installer checksum'
|
||||
rm composer-setup.php
|
||||
die 'ERROR: Invalid installer checksum'
|
||||
fi
|
||||
php composer-setup.php --quiet
|
||||
RESULT=$?
|
||||
rm composer-setup.php
|
||||
# exit $RESULT
|
||||
# We install Composer globally
|
||||
mv composer.phar /usr/local/bin/composer
|
||||
print_info "Composer was successfully downloaded."
|
||||
else
|
||||
print_info "Composer is already downloaded on this system."
|
||||
fi
|
||||
cd $install_path
|
||||
export COMPOSER_ALLOW_SUPERUSER=1;
|
||||
/usr/local/bin/composer install --no-dev
|
||||
/usr/local/bin/composer show
|
||||
export COMPOSER_ALLOW_SUPERUSER=0;
|
||||
}
|
||||
|
||||
|
||||
function install_mysql {
|
||||
print_info "installing mysql..."
|
||||
if [ -z "$mysqlpass" ]
|
||||
then
|
||||
die "mysqlpass not set in $configfile"
|
||||
fi
|
||||
if type mysql ; then
|
||||
echo "Yes, mysql is installed"
|
||||
else
|
||||
echo "mariadb-server"
|
||||
nocheck_install "mariadb-server"
|
||||
systemctl status mariadb
|
||||
systemctl start mariadb
|
||||
mysql --user=root <<_EOF_
|
||||
UPDATE mysql.user SET Password=PASSWORD('${mysqlpass}') WHERE User='root';
|
||||
DELETE FROM mysql.user WHERE User='';
|
||||
DROP DATABASE IF EXISTS test;
|
||||
DELETE FROM mysql.db WHERE Db='test' OR Db='test\\_%';
|
||||
FLUSH PRIVILEGES;
|
||||
_EOF_
|
||||
fi
|
||||
}
|
||||
|
||||
function install_adminer {
|
||||
print_info "installing adminer..."
|
||||
nocheck_install "adminer"
|
||||
if [ ! -f /etc/adminer/adminer.conf ]
|
||||
then
|
||||
echo "Alias /adminer /usr/share/adminer/adminer" > /etc/adminer/adminer.conf
|
||||
ln -s /etc/adminer/adminer.conf /etc/apache2/conf-available/adminer.conf
|
||||
else
|
||||
print_info "file /etc/adminer/adminer.conf exists already"
|
||||
fi
|
||||
|
||||
a2enmod rewrite
|
||||
|
||||
if [ ! -f /etc/apache2/apache2.conf ]
|
||||
then
|
||||
die "could not find file /etc/apache2/apache2.conf"
|
||||
fi
|
||||
sed -i \
|
||||
"s/AllowOverride None/AllowOverride all/" \
|
||||
/etc/apache2/apache2.conf
|
||||
|
||||
a2enconf adminer
|
||||
systemctl restart mariadb
|
||||
systemctl reload apache2
|
||||
}
|
||||
|
||||
function create_zotserver_db {
|
||||
print_info "creating zotserver database..."
|
||||
if [ -z "$db_name" ]
|
||||
then
|
||||
die "db_name not set in $configfile"
|
||||
fi
|
||||
if [ -z "$db_user" ]
|
||||
then
|
||||
die "db_user not set in $configfile"
|
||||
fi
|
||||
if [ -z "$db_pass" ]
|
||||
then
|
||||
die "db_pass not set in $configfile"
|
||||
fi
|
||||
systemctl restart mariadb
|
||||
# Make sure we don't write over an already existing database if we install more than one Zot hub/instance
|
||||
if [ -z $(mysql -h localhost -u root -p$mysqlpass -e "SHOW DATABASES;" | grep $db_name) ]
|
||||
then
|
||||
Q1="CREATE DATABASE IF NOT EXISTS $db_name;"
|
||||
Q2="GRANT USAGE ON *.* TO $db_user@localhost IDENTIFIED BY '$db_pass';"
|
||||
Q3="GRANT ALL PRIVILEGES ON $db_name.* to $db_user@localhost identified by '$db_pass';"
|
||||
Q4="FLUSH PRIVILEGES;"
|
||||
SQL="${Q1}${Q2}${Q3}${Q4}"
|
||||
mysql -uroot -p$mysqlpass -e "$SQL"
|
||||
else
|
||||
echo "database $db_name does exist already"
|
||||
Q1="CREATE DATABASE IF NOT EXISTS $db_name;"
|
||||
Q2="GRANT USAGE ON *.* TO $db_user@localhost IDENTIFIED BY '$db_pass';"
|
||||
Q3="GRANT ALL PRIVILEGES ON $db_name.* to $db_user@localhost identified by '$db_pass';"
|
||||
Q4="FLUSH PRIVILEGES;"
|
||||
SQL="${Q1}${Q2}${Q3}${Q4}"
|
||||
mysql -uroot -p$mysqlpass -e "$SQL"
|
||||
fi
|
||||
}
|
||||
|
||||
function run_freedns {
|
||||
print_info "run freedns (dynamic IP)..."
|
||||
if [ -z "$freedns_key" ]
|
||||
then
|
||||
print_info "freedns was not started because 'freedns_key' is empty in $configfile"
|
||||
else
|
||||
if [ -n "$selfhost_user" ]
|
||||
then
|
||||
die "You can not use freeDNS AND selfHOST for dynamic IP updates ('freedns_key' AND 'selfhost_user' set in $configfile)"
|
||||
fi
|
||||
wget --no-check-certificate -O - http://freedns.afraid.org/dynamic/update.php?$freedns_key
|
||||
fi
|
||||
}
|
||||
|
||||
function install_run_selfhost {
|
||||
print_info "install and start selfhost (dynamic IP)..."
|
||||
if [ -z "$selfhost_user" ]
|
||||
then
|
||||
print_info "selfHOST was not started because 'selfhost_user' is empty in $configfile"
|
||||
else
|
||||
if [ -n "$freedns_key" ]
|
||||
then
|
||||
die "You can not use freeDNS AND selfHOST for dynamic IP updates ('freedns_key' AND 'selfhost_user' set in $configfile)"
|
||||
fi
|
||||
if [ -z "$selfhost_pass" ]
|
||||
then
|
||||
die "selfHOST was not started because 'selfhost_pass' is empty in $configfile"
|
||||
fi
|
||||
if [ ! -d $selfhostdir ]
|
||||
then
|
||||
mkdir $selfhostdir
|
||||
fi
|
||||
# the old way
|
||||
# https://carol.selfhost.de/update?username=123456&password=supersafe
|
||||
#
|
||||
# the prefered way
|
||||
wget --output-document=$selfhostdir/$selfhostscript http://jonaspasche.de/selfhost-updater
|
||||
echo "router" > $selfhostdir/device
|
||||
echo "$selfhost_user" > $selfhostdir/user
|
||||
echo "$selfhost_pass" > $selfhostdir/pass
|
||||
bash $selfhostdir/$selfhostscript update
|
||||
fi
|
||||
}
|
||||
|
||||
function ping_domain {
|
||||
print_info "ping domain $domain..."
|
||||
# Is the domain resolved? Try to ping 6 times à 10 seconds
|
||||
COUNTER=0
|
||||
for i in {1..6}
|
||||
do
|
||||
print_info "loop $i for ping -c 1 $domain ..."
|
||||
if ping -c 4 -W 1 $le_domain
|
||||
then
|
||||
print_info "$le_domain resolved"
|
||||
break
|
||||
else
|
||||
if [ $i -gt 5 ]
|
||||
then
|
||||
die "Failed to: ping -c 1 $domain not resolved"
|
||||
fi
|
||||
fi
|
||||
sleep 10
|
||||
done
|
||||
sleep 5
|
||||
}
|
||||
|
||||
function configure_cron_freedns {
|
||||
print_info "configure cron for freedns..."
|
||||
if [ -z "$freedns_key" ]
|
||||
then
|
||||
print_info "freedns is not configured because freedns_key is empty in $configfile"
|
||||
else
|
||||
# Use cron for dynamich ip update
|
||||
# - at reboot
|
||||
# - every 30 minutes
|
||||
if [ -z "`grep 'freedns.afraid.org' /etc/crontab`" ]
|
||||
then
|
||||
echo "@reboot root http://freedns.afraid.org/dynamic/update.php?$freedns_key > /dev/null 2>&1" >> /etc/crontab
|
||||
echo "*/30 * * * * root wget --no-check-certificate -O - http://freedns.afraid.org/dynamic/update.php?$freedns_key > /dev/null 2>&1" >> /etc/crontab
|
||||
else
|
||||
print_info "cron for freedns was configured already"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
function configure_cron_selfhost {
|
||||
print_info "configure cron for selfhost..."
|
||||
if [ -z "$selfhost_user" ]
|
||||
then
|
||||
print_info "selfhost is not configured because selfhost_key is empty in $configfile"
|
||||
else
|
||||
# Use cron for dynamich ip update
|
||||
# - at reboot
|
||||
# - every 5 minutes
|
||||
if [ -z "`grep 'selfhost-updater.sh' /etc/crontab`" ]
|
||||
then
|
||||
echo "@reboot root bash /etc/selfhost/selfhost-updater.sh update > /dev/null 2>&1" >> /etc/crontab
|
||||
echo "*/5 * * * * root /bin/bash /etc/selfhost/selfhost-updater.sh update > /dev/null 2>&1" >> /etc/crontab
|
||||
else
|
||||
print_info "cron for selfhost was configured already"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
function install_letsencrypt {
|
||||
print_info "installing let's encrypt ..."
|
||||
# check if user gave domain
|
||||
if [ -z "$le_domain" ]
|
||||
then
|
||||
die "Failed to install let's encrypt: 'le_domain' is empty in $configfile"
|
||||
fi
|
||||
if [ -z "$le_email" ]
|
||||
then
|
||||
die "Failed to install let's encrypt: 'le_email' is empty in $configfile"
|
||||
fi
|
||||
nocheck_install "certbot python-certbot-apache"
|
||||
print_info "run certbot ..."
|
||||
certbot --apache -w $install_path -d $le_domain -m $le_email --agree-tos --non-interactive --redirect --hsts --uir
|
||||
service apache2 restart
|
||||
}
|
||||
|
||||
function check_https {
|
||||
print_info "checking httpS > testing ..."
|
||||
url_https=https://$le_domain
|
||||
wget_output=$(wget -nv --spider --max-redirect 0 $url_https)
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
print_warn "check not ok"
|
||||
else
|
||||
print_info "check ok"
|
||||
fi
|
||||
}
|
||||
|
||||
function install_zotserver {
|
||||
print_info "installing addons..."
|
||||
cd $install_path
|
||||
util/add_addon_repo https://framagit.org/hubzilla/addons hzaddons
|
||||
mkdir -p "store/[data]/smarty3"
|
||||
# chmod -R 777 store
|
||||
touch .htconfig.php
|
||||
# The next run of $cron_job (daily-update script) will correct the permissions of the next line
|
||||
chmod ou+w .htconfig.php
|
||||
cd /var/www/
|
||||
chown -R www-data:www-data $install_path
|
||||
chown root:www-data $install_path/
|
||||
chown root:www-data $install_path/.htaccess
|
||||
chmod 0644 $install_path/.htaccess
|
||||
print_info "installed addons"
|
||||
}
|
||||
|
||||
function configure_cron_daily {
|
||||
print_info "configuring cron..."
|
||||
# every 10 min for poller.php
|
||||
if [ -z "`grep 'php Zotlabs/Daemon/Master.php' /etc/crontab`" ]
|
||||
then
|
||||
echo "*/10 * * * * www-data cd $install_path; php Zotlabs/Daemon/Master.php Cron >> /dev/null 2>&1" >> /etc/crontab
|
||||
fi
|
||||
# Run external script daily at 05:30
|
||||
# - stop apache/nginx and mysql-server
|
||||
# - renew the certificate of letsencrypt
|
||||
# - update repository core and addon
|
||||
# - update and upgrade linux
|
||||
# - reboot is done by "shutdown -h now" because "reboot" hangs sometimes depending on the system
|
||||
echo "#!/bin/sh" > /var/www/$cron_job
|
||||
echo "#" >> /var/www/$cron_job
|
||||
echo "echo \" \"" >> /var/www/$cron_job
|
||||
echo "echo \"+++ \$(date) +++\"" >> /var/www/$cron_job
|
||||
echo "echo \" \"" >> /var/www/$cron_job
|
||||
echo "echo \"\$(date) - stopping apache and mysql...\"" >> /var/www/$cron_job
|
||||
echo "service apache2 stop" >> /var/www/$cron_job
|
||||
echo "/etc/init.d/mysql stop # to avoid inconsistencies" >> /var/www/$cron_job
|
||||
echo "#" >> /var/www/$cron_job
|
||||
echo "echo \"\$(date) - renew certificate...\"" >> /var/www/$cron_job
|
||||
echo "certbot renew --noninteractive" >> /var/www/$cron_job
|
||||
echo "#" >> /var/www/$cron_job
|
||||
echo "echo \"\$(date) - db size...\"" >> /var/www/$cron_job
|
||||
echo "du -h /var/lib/mysql/ | grep mysql/" >> /var/www/$cron_job
|
||||
echo "#" >> /var/www/$cron_job
|
||||
echo "# update of $le_domain Zot hub/instance" >> /var/www/$cron_job
|
||||
echo "echo \"\$(date) - updating core and addons...\"" >> /var/www/$cron_job
|
||||
echo "echo \"reaching git repository for $le_domain $zotserver hub/instance...\"" >> /var/www/$cron_job
|
||||
echo "(cd $install_path ; util/udall)" >> /var/www/$cron_job
|
||||
echo "chown -R www-data:www-data $install_path # make all accessible for the webserver" >> /var/www/$cron_job
|
||||
echo "chown root:www-data $install_path/.htaccess" >> /var/www/$cron_job
|
||||
echo "chmod 0644 $install_path/.htaccess # www-data can read but not write it" >> /var/www/$cron_job
|
||||
echo "echo \"\$(date) - updating linux...\"" >> /var/www/$cron_job
|
||||
echo "apt-get -q -y update && apt-get -q -y dist-upgrade && apt-get -q -y autoremove # update linux and upgrade" >> /var/www/$cron_job
|
||||
echo "echo \"\$(date) - Update finished. Rebooting...\"" >> /var/www/$cron_job
|
||||
echo "#" >> /var/www/$cron_job
|
||||
echo "shutdown -r now" >> /var/www/$cron_job
|
||||
|
||||
chmod a+x /var/www/$cron_job
|
||||
|
||||
# If global cron job does not exist we add it to /etc/crontab
|
||||
if grep -q $cron_job /etc/crontab
|
||||
then
|
||||
echo "cron job already in /etc/crontab"
|
||||
else
|
||||
echo "30 05 * * * root /bin/bash /var/www/$cron_job >> /var/www/daily-updates.log 2>&1" >> /etc/crontab
|
||||
echo "0 0 1 * * root rm /var/www/daily-updates.log" >> /etc/crontab
|
||||
fi
|
||||
|
||||
# This is active after either "reboot" or cron reload"
|
||||
systemctl restart cron
|
||||
print_info "configured cron for updates/upgrades"
|
||||
}
|
||||
|
||||
########################################################################
|
||||
# START OF PROGRAM
|
||||
########################################################################
|
||||
export PATH=/bin:/usr/bin:/sbin:/usr/sbin
|
||||
check_sanity
|
||||
|
||||
print_info "We're installing a $zotserver instance"
|
||||
install_path="$(dirname "$(pwd)")"
|
||||
|
||||
# Read config file edited by user
|
||||
configfile=config.txt
|
||||
source $configfile
|
||||
|
||||
selfhostdir=/etc/selfhost
|
||||
selfhostscript=selfhost-updater.sh
|
||||
cron_job="cron_job.sh"
|
||||
|
||||
#set -x # activate debugging from here
|
||||
|
||||
zotserver=hubzilla
|
||||
check_config
|
||||
stop_zotserver
|
||||
update_upgrade
|
||||
install_curl
|
||||
install_wget
|
||||
install_sendmail
|
||||
install_apache
|
||||
install_imagemagick
|
||||
install_php
|
||||
install_composer
|
||||
install_mysql
|
||||
install_adminer
|
||||
create_zotserver_db
|
||||
run_freedns
|
||||
install_run_selfhost
|
||||
ping_domain
|
||||
configure_cron_freedns
|
||||
configure_cron_selfhost
|
||||
|
||||
if [ "$le_domain" != "localhost" ]
|
||||
then
|
||||
install_letsencrypt
|
||||
check_https
|
||||
else
|
||||
print_info "is localhost - skipped installation of letsencrypt and configuration of apache for https"
|
||||
fi
|
||||
|
||||
install_zotserver
|
||||
|
||||
configure_cron_daily
|
||||
|
||||
|
||||
#set +x # stop debugging from here
|
||||
31
.gitignore
vendored
31
.gitignore
vendored
@@ -48,7 +48,10 @@ doc/html/
|
||||
.zotshrc
|
||||
# external repositories for themes/addons
|
||||
extend/
|
||||
# files generated by phpunit
|
||||
|
||||
# exclude test results and cache
|
||||
tests/.cache
|
||||
tests/.phpunit*
|
||||
tests/results/
|
||||
|
||||
## exclude IDE files
|
||||
@@ -65,7 +68,6 @@ nbproject/
|
||||
# PHPStorm
|
||||
.idea/
|
||||
|
||||
|
||||
## composer
|
||||
# locally installed composer binary
|
||||
composer.phar
|
||||
@@ -78,5 +80,30 @@ composer.phar
|
||||
vendor/**/tests/
|
||||
vendor/**/Test/
|
||||
vendor/sabre/*/examples/
|
||||
|
||||
# Exclude dev dependencies
|
||||
vendor/bin/pdepend
|
||||
vendor/bin/php-parse
|
||||
vendor/bin/phpcbf
|
||||
vendor/bin/phpcs
|
||||
vendor/bin/phpmd
|
||||
vendor/bin/phpstan*
|
||||
vendor/bin/phpunit
|
||||
vendor/composer/pcre/
|
||||
vendor/composer/xdebug-handler/
|
||||
vendor/dms/
|
||||
vendor/doctrine/
|
||||
vendor/myclabs/
|
||||
vendor/nikic/
|
||||
vendor/pdepend/
|
||||
vendor/phar-io/
|
||||
vendor/php-mock/
|
||||
vendor/phpmd/
|
||||
vendor/phpstan
|
||||
vendor/phpunit/
|
||||
vendor/psr/container/
|
||||
vendor/sebastian/
|
||||
vendor/squizlabs/
|
||||
vendor/theseer/
|
||||
# /info is a directory containing site-specific HTML documents
|
||||
/info/
|
||||
|
||||
294
.gitlab-ci.yml
294
.gitlab-ci.yml
@@ -1,147 +1,147 @@
|
||||
# Select image from https://hub.docker.com/_/php/
|
||||
#image: php:7.3
|
||||
# Use a prepared Hubzilla image to optimise pipeline duration
|
||||
image: registry.gitlab.com/dawnbreak/hubzilla/core:php7.3
|
||||
|
||||
stages:
|
||||
- test
|
||||
- deploy
|
||||
|
||||
|
||||
# Select what we should cache
|
||||
cache:
|
||||
paths:
|
||||
- vendor/
|
||||
- .cache/
|
||||
|
||||
|
||||
# global variables for all jobs, if no job specific variables
|
||||
variables:
|
||||
# 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
|
||||
|
||||
|
||||
before_script:
|
||||
# pecl and composer do not work with PHP production restrictions (from Hubzilla Docker image)
|
||||
- if [ -f /usr/local/etc/php/conf.d/z_prod.ini ]; then mv /usr/local/etc/php/conf.d/z_prod.ini /usr/local/etc/php/conf.d/z_prod.ini.off; fi
|
||||
# Install & enable Xdebug for code coverage reports
|
||||
- pecl install xdebug
|
||||
- docker-php-ext-enable xdebug
|
||||
# Install composer
|
||||
- curl -sS https://getcomposer.org/installer | php
|
||||
# Install dev libraries from composer
|
||||
- php ./composer.phar install --no-progress
|
||||
# php.ini settings
|
||||
- echo 'xdebug.mode=coverage' >> /usr/local/etc/php/php.ini
|
||||
|
||||
# hidden job definition with template for MySQL/MariaDB
|
||||
.job_template_mysql: &job_definition_mysql
|
||||
stage: test
|
||||
script:
|
||||
- echo "USE $MYSQL_DATABASE; $(cat ./install/schema_mysql.sql)" | mysql --user=root --password="$MYSQL_ROOT_PASSWORD" --host=mysql "$MYSQL_DATABASE"
|
||||
- echo "SHOW DATABASES;" | mysql --user=root --password="$MYSQL_ROOT_PASSWORD" --host=mysql "$MYSQL_DATABASE"
|
||||
- echo "USE $MYSQL_DATABASE; SHOW TABLES;" | mysql --user=root --password="$MYSQL_ROOT_PASSWORD" --host=mysql "$MYSQL_DATABASE"
|
||||
- vendor/bin/phpunit --configuration tests/phpunit.xml --coverage-text
|
||||
|
||||
# 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.3 with MySQL 5.7
|
||||
php7.3_mysql5.7:
|
||||
<<: *job_definition_mysql
|
||||
services:
|
||||
- mysql:5.7
|
||||
|
||||
|
||||
# PHP7.3 with MySQL 8 (latest)
|
||||
php7.3_mysql8:
|
||||
<<: *job_definition_mysql
|
||||
services:
|
||||
- name: mysql:8
|
||||
command: ["--default-authentication-plugin=mysql_native_password"]
|
||||
|
||||
|
||||
# PHP7.3 with MariaDB 10.2
|
||||
php7.3_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.3 with PostgreSQL latest (11)
|
||||
#php7.3_postgres11:
|
||||
# <<: *job_definition_postgres
|
||||
# artifacts: *artifacts_template
|
||||
|
||||
|
||||
# PHP7.3 with PostgreSQL latest (11)
|
||||
#php7.3_postgres11:
|
||||
# <<: *job_definition_postgres
|
||||
# image: registry.gitlab.com/dawnbreak/hubzilla/core:php7.3
|
||||
# artifacts: *artifacts_template
|
||||
|
||||
|
||||
# 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
|
||||
stages:
|
||||
- test
|
||||
- deploy
|
||||
|
||||
|
||||
# Select what we should cache
|
||||
cache:
|
||||
paths:
|
||||
- vendor/
|
||||
- .cache/
|
||||
|
||||
|
||||
# global variables for all jobs, if no job specific variables
|
||||
variables:
|
||||
# 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/)
|
||||
DB_HOST: mysql
|
||||
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
|
||||
|
||||
|
||||
before_script:
|
||||
# Install & enable Xdebug for code coverage reports
|
||||
- apt-get update
|
||||
- apt-get install -yqq libicu-dev libjpeg-dev libpng-dev libpq-dev libyaml-dev libzip-dev mariadb-client postgresql-client unzip zip
|
||||
- pecl install xdebug yaml
|
||||
- docker-php-ext-enable xdebug yaml
|
||||
- docker-php-ext-configure gd --with-jpeg=/usr/include/
|
||||
- docker-php-ext-install gd bcmath intl pdo_mysql pdo_pgsql zip
|
||||
|
||||
# Install composer
|
||||
- curl -sS https://getcomposer.org/installer | php
|
||||
# Install dev libraries from composer
|
||||
- php ./composer.phar install --no-progress
|
||||
# php.ini settings
|
||||
- echo 'xdebug.mode=coverage' >> /usr/local/etc/php/php.ini
|
||||
|
||||
# hidden job definition with template for MySQL/MariaDB
|
||||
.job_template_mysql: &job_definition_mysql
|
||||
stage: test
|
||||
variables:
|
||||
HZ_TEST_DB_HOST: $DB_HOST
|
||||
HZ_TEST_DB_TYPE: mysql
|
||||
HZ_TEST_DB_USER: root
|
||||
HZ_TEST_DB_PASS: $MYSQL_ROOT_PASSWORD
|
||||
HZ_TEST_DB_DATABASE: $MYSQL_DATABASE
|
||||
script:
|
||||
# Import hubzilla's DB schema
|
||||
- echo "USE $MYSQL_DATABASE; $(cat ./install/schema_mysql.sql)" | mysql --user=root --password="$MYSQL_ROOT_PASSWORD" --host="$DB_HOST" "$MYSQL_DATABASE"
|
||||
# Show databases and relations/tables of hubzilla's database
|
||||
- echo "SHOW DATABASES;" | mysql --user=root --password="$MYSQL_ROOT_PASSWORD" --host="$DB_HOST" "$MYSQL_DATABASE"
|
||||
- echo "USE $MYSQL_DATABASE; SHOW TABLES;" | mysql --user=root --password="$MYSQL_ROOT_PASSWORD" --host="$DB_HOST" "$MYSQL_DATABASE"
|
||||
# Run the actual tests
|
||||
- touch dbfail.out
|
||||
- vendor/bin/phpunit --configuration tests/phpunit.xml --no-progress --stop-on-error --coverage-text --colors=never --log-junit tests/results/junit.xml || exit_code=$?
|
||||
- if [ $exit_code -ne 0 ]; then echo "Test barfed!"; cat dbfail.out; exit $exit_code; fi
|
||||
coverage: '/^\s*Lines:\s*\d+.\d+\%/'
|
||||
|
||||
|
||||
# hidden job definition with template for PostgreSQL
|
||||
.job_template_postgres: &job_definition_postgres
|
||||
stage: test
|
||||
variables:
|
||||
HZ_TEST_DB_HOST: postgres
|
||||
HZ_TEST_DB_TYPE: postgres
|
||||
HZ_TEST_DB_USER: $POSTGRES_USER
|
||||
HZ_TEST_DB_PASS: $POSTGRES_PASSWORD
|
||||
HZ_TEST_DB_DATABASE: $POSTGRES_DB
|
||||
script:
|
||||
- export PGPASSWORD=$POSTGRES_PASSWORD
|
||||
- psql --version
|
||||
- psql -h "postgres" -U "$POSTGRES_USER" -d "$POSTGRES_DB" -c "SELECT VERSION();"
|
||||
# Import hubzilla's DB schema
|
||||
- psql -h "postgres" -U "$POSTGRES_USER" -v ON_ERROR_STOP=1 --quiet "$POSTGRES_DB" < ./install/schema_postgres.sql
|
||||
# Show databases and relations/tables of hubzilla's database
|
||||
- psql -h "postgres" -U "$POSTGRES_USER" -l
|
||||
- psql -h "postgres" -U "$POSTGRES_USER" -d "$POSTGRES_DB" -c "\dt;"
|
||||
# Run the actual tests
|
||||
- touch dbfail.out
|
||||
- vendor/bin/phpunit --configuration tests/phpunit.xml --no-progress --stop-on-error --coverage-text --colors=never --log-junit tests/results/junit.xml || exit_code=$?
|
||||
- if [ $exit_code -ne 0 ]; then echo "Test barfed!"; cat dbfail.out; exit $exit_code; fi
|
||||
coverage: '/^\s*Lines:\s*\d+.\d+\%/'
|
||||
|
||||
# hidden job definition with artifacts config template
|
||||
.artifacts_template: &artifacts_template
|
||||
artifacts:
|
||||
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/
|
||||
|
||||
|
||||
# PHP8.1 with MySQL 8.0
|
||||
php8.1_mysql8.0.22:
|
||||
image: php:8.1
|
||||
services:
|
||||
- mysql:8.0
|
||||
<<: *job_definition_mysql
|
||||
<<: *artifacts_template
|
||||
|
||||
# PHP8.1 with MariaDB 10.6
|
||||
php8.1_mariadb10.6:
|
||||
image: php:8.1
|
||||
services:
|
||||
- name: mariadb:10.6
|
||||
alias: mysql
|
||||
<<: *job_definition_mysql
|
||||
<<: *artifacts_template
|
||||
|
||||
# PHP8.1 with PostgreSQL 12
|
||||
php8.1_postgres12:
|
||||
image: php:8.1
|
||||
services:
|
||||
- postgres:12-alpine
|
||||
<<: *job_definition_postgres
|
||||
<<: *artifacts_template
|
||||
|
||||
|
||||
# Generate Doxygen API Documentation and deploy it as GitLab pages
|
||||
pages:
|
||||
stage: deploy
|
||||
cache: {}
|
||||
image: php:8-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
|
||||
|
||||
@@ -25,10 +25,10 @@ AddType audio/ogg .oga
|
||||
# in CGI mode.
|
||||
|
||||
RewriteCond %{REQUEST_URI} ^/\.well\-known/.*
|
||||
RewriteRule ^(.*)$ index.php?q=$1 [E=REMOTE_USER:%{HTTP:Authorization},L,QSA]
|
||||
RewriteRule ^(.*)$ index.php?q=$1 "[E=REMOTE_USER:%{HTTP:Authorization},L,QSA,B= ?]"
|
||||
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
RewriteRule ^(.*)$ index.php?q=$1 [E=REMOTE_USER:%{HTTP:Authorization},L,QSA]
|
||||
RewriteRule ^(.*)$ index.php?q=$1 "[E=REMOTE_USER:%{HTTP:Authorization},L,QSA,B= ?]"
|
||||
</IfModule>
|
||||
|
||||
|
||||
82
.phpcs.xml
Normal file
82
.phpcs.xml
Normal file
@@ -0,0 +1,82 @@
|
||||
<?xml version="1.0"?>
|
||||
<ruleset
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
name="PHP_CodeSniffer"
|
||||
xsi:noNamespaceSchemaLocation="phpcs.xsd"
|
||||
>
|
||||
|
||||
<description>PHP CodeSniffer config for Hubzilla</description>
|
||||
|
||||
<file>app</file>
|
||||
<file>boot.php</file>
|
||||
<file>include</file>
|
||||
<file>index.php</file>
|
||||
<file>install</file>
|
||||
<file>library</file>
|
||||
<file>tests</file>
|
||||
<file>util</file>
|
||||
<file>view</file>
|
||||
<file>Zotlabs</file>
|
||||
|
||||
<rule ref="Generic">
|
||||
<exclude name="Generic.Arrays.ArrayIndent"/>
|
||||
<exclude name="Generic.Arrays.DisallowLongArraySyntax"/>
|
||||
<exclude name="Generic.Arrays.DisallowShortArraySyntax"/>
|
||||
<exclude name="Generic.Files.EndFileNoNewline"/>
|
||||
<exclude name="Generic.Files.LowercasedFilename"/>
|
||||
<exclude name="Generic.Formatting.MultipleStatementAlignment"/>
|
||||
<exclude name="Generic.Formatting.SpaceAfterNot"/>
|
||||
<exclude name="Generic.Functions.FunctionCallArgumentSpacing"/>
|
||||
<exclude name="Generic.Functions.OpeningFunctionBraceBsdAllman"/>
|
||||
<exclude name="Generic.NamingConventions.CamelCapsFunctionName"/>
|
||||
<exclude name="Generic.PHP.ClosingPHPTag"/>
|
||||
<exclude name="Generic.PHP.RequireStrictTypes"/>
|
||||
<exclude name="Generic.PHP.UpperCaseConstant"/>
|
||||
<exclude name="Generic.WhiteSpace.DisallowTabIndent"/>
|
||||
<exclude name="Generic.WhiteSpace.ScopeIndent"/>
|
||||
<exclude name="Generic.Commenting.DocComment.ContentAfterOpen"/>
|
||||
<exclude name="Generic.Commenting.DocComment.ContentBeforeClose"/>
|
||||
<exclude name="Generic.Commenting.DocComment.LongNotCapital"/>
|
||||
<exclude name="Generic.Commenting.DocComment.MissingShort"/>
|
||||
<exclude name="Generic.Commenting.DocComment.NonParamGroup"/>
|
||||
<exclude name="Generic.Commenting.DocComment.ParamNotFirst"/>
|
||||
<exclude name="Generic.Commenting.DocComment.ShortNotCapital"/>
|
||||
<exclude name="Generic.Commenting.DocComment.SpacingAfter"/>
|
||||
<exclude name="Generic.Commenting.DocComment.SpacingBeforeShort"/>
|
||||
<exclude name="Generic.Commenting.DocComment.TagValueIndent"/>
|
||||
<exclude name="Generic.ControlStructures.InlineControlStructure.NotAllowed"/>
|
||||
<exclude name="Generic.Files.OneClassPerFile.MultipleFound"/>
|
||||
<exclude name="Generic.Files.OneObjectStructurePerFile.MultipleFound"/>
|
||||
<exclude name="Generic.Formatting.SpaceAfterCast.NoSpace"/>
|
||||
|
||||
<exclude name="Generic.Classes.OpeningBraceSameLine.BraceOnNewLine" />
|
||||
<exclude name="Generic.WhiteSpace.DisallowSpaceIndent.SpacesUsed" />
|
||||
<exclude name="Generic.Functions.OpeningFunctionBraceKernighanRitchie.BraceOnNewLine" />
|
||||
</rule>
|
||||
|
||||
<!--
|
||||
Warn about lines longer than 100 columns, lines longer than 150
|
||||
columns will flag an error.
|
||||
-->
|
||||
<rule ref="Generic.Files.LineLength">
|
||||
<properties>
|
||||
<property name="lineLimit" value="100" />
|
||||
<property name="absoluteLineLimit" value="150" />
|
||||
</properties>
|
||||
</rule>
|
||||
|
||||
<!--
|
||||
Mark deprecated functions.
|
||||
-->
|
||||
<rule ref="Generic.PHP.DeprecatedFunctions">
|
||||
<properties>
|
||||
<property name="forbiddenFunctions" type="array" extend="true">
|
||||
<element key="load_config" value="Zotlabs\Lib\Config::Load" />
|
||||
<element key="get_config" value="Zotlabs\Lib\Config::Get" />
|
||||
<element key="set_config" value="Zotlabs\Lib\Config::Set" />
|
||||
<element key="del_config" value="Zotlabs\Lib\Config::Delete" />
|
||||
</property>
|
||||
</properties>
|
||||
</rule>
|
||||
|
||||
</ruleset>
|
||||
@@ -1,48 +0,0 @@
|
||||
"air" is a branch name for revision of Account-Invite-Register at the Hubzilla project
|
||||
|
||||
Invite:
|
||||
* Rewritten and now language template driven
|
||||
* Selectable templates for the invite mails
|
||||
* Invitor may add personal notes in the mailtext
|
||||
+ Invite codes are bound to the recipients email address
|
||||
* Invite mod never more creates accounts
|
||||
* new db scheme for table register
|
||||
* existing register table will be migrated to the new schema even when detected at runtime
|
||||
* Bugfix: creating invite codes when admin only calls Invite w/o any further action
|
||||
* account library revision also together with invite mod
|
||||
* Depending on config: Users may send invitations also
|
||||
* Invitations expires, controlled by the invitor
|
||||
* Changed and new configs:
|
||||
* * invitation_only As usual before
|
||||
* * invitation_also Beside other registration policies, invitations may be used also
|
||||
* * invitation_max_per_day defaults 50, may be changed in adminUI admin>site
|
||||
* * invitation_max_per_user defaults 4
|
||||
* Requirements:
|
||||
* * Addon language has to be installed
|
||||
|
||||
Register:
|
||||
* Register panel (form) and js interaction changed
|
||||
* Unused registrations expire
|
||||
* Depending on config, anonymous registrations (w/o email) are supported
|
||||
* :... dont't panic, that may let grow security
|
||||
* Even anonymous users have to confirm their registration
|
||||
* Registrations may be enabled / disabled time driven for each day in the week (dudy)
|
||||
* Unsoliced registration floods may be blocked
|
||||
* Limited registrations from one single source ip
|
||||
* Using one additional log file, to easy interfare with f2b
|
||||
|
||||
Account:
|
||||
* An user account always becomes created only if all depending conditions are satisfied
|
||||
* AdminUI for site configuration, accounts and registrations enhancements
|
||||
* Still untouched, but accountUI needs enhanced async control in case for mass delete
|
||||
with deep level of recursion cascade of the dependencies (channels etc). An open TODO
|
||||
since years for instances with many much users and channels.
|
||||
|
||||
History:
|
||||
2020.03 Hubzilla Prod version 4.6 (master branch) of hubzilla/core was the base for AIR
|
||||
that was assigned Version 4.6.2 at sn/core
|
||||
2021.02 Hubzilla Prod version 5.2.1 (master branch) of hubzilla/core was new base for AIR
|
||||
that was assigned version 5.2.2 at sn/core (air.5)
|
||||
plus adjustment of hubzilla 5.2.2 (master) to sn/core (air.5) version 5.2.9
|
||||
|
||||
|
||||
19
SBOM.md
19
SBOM.md
@@ -2,20 +2,21 @@
|
||||
|
||||
|Name|Version|License|Source|
|
||||
|----|-------|-------|------|
|
||||
|blueimp/jquery-file-upload|10.31.0.0|MIT|https://github.com/vkhramtsov/jQuery-File-Upload.git|
|
||||
|brick/math|0.9.2.0|MIT|https://github.com/brick/math.git|
|
||||
|blueimp/jquery-file-upload|10.32.0.0|MIT|https://github.com/vkhramtsov/jQuery-File-Upload.git|
|
||||
|brick/math|0.9.3.0|MIT|https://github.com/brick/math.git|
|
||||
|bshaffer/oauth2-server-php|1.11.1.0|MIT|https://github.com/bshaffer/oauth2-server-php.git|
|
||||
|commerceguys/intl|1.1.0.0|MIT|https://github.com/commerceguys/intl.git|
|
||||
|desandro/imagesloaded|4.1.4.0|MIT|https://github.com/desandro/imagesloaded.git|
|
||||
|ezyang/htmlpurifier|4.13.0.0|LGPL-2.1-or-later|https://github.com/ezyang/htmlpurifier.git|
|
||||
|league/html-to-markdown|5.0.0.0|MIT|https://github.com/thephpleague/html-to-markdown.git|
|
||||
|jbroadway/urlify|1.2.2.0|BSD-3-Clause-Clear|https://github.com/jbroadway/urlify.git|
|
||||
|league/html-to-markdown|5.0.1.0|MIT|https://github.com/thephpleague/html-to-markdown.git|
|
||||
|lukasreschke/id3parser|0.0.3.0|GPL|https://github.com/LukasReschke/ID3Parser.git|
|
||||
|michelf/php-markdown|1.9.0.0|BSD-3-Clause|https://github.com/michelf/php-markdown.git|
|
||||
|pear/text_languagedetect|1.0.1.0|BSD-2-Clause|https://github.com/pear/Text_LanguageDetect.git|
|
||||
|phpseclib/phpseclib|2.0.30.0|MIT|https://github.com/phpseclib/phpseclib.git|
|
||||
|phpseclib/phpseclib|2.0.33.0|MIT|https://github.com/phpseclib/phpseclib.git|
|
||||
|psr/log|1.1.4.0|MIT|https://github.com/php-fig/log.git|
|
||||
|ramsey/collection|1.1.3.0|MIT|https://github.com/ramsey/collection.git|
|
||||
|ramsey/uuid|4.1.1.0|MIT|https://github.com/ramsey/uuid.git|
|
||||
|ramsey/collection|1.2.2.0|MIT|https://github.com/ramsey/collection.git|
|
||||
|ramsey/uuid|4.2.3.0|MIT|https://github.com/ramsey/uuid.git|
|
||||
|sabre/dav|4.1.5.0|BSD-3-Clause|https://github.com/sabre-io/dav.git|
|
||||
|sabre/event|5.1.2.0|BSD-3-Clause|https://github.com/sabre-io/event.git|
|
||||
|sabre/http|5.1.1.0|BSD-3-Clause|https://github.com/sabre-io/http.git|
|
||||
@@ -25,7 +26,11 @@
|
||||
|simplepie/simplepie|1.5.6.0|BSD-3-Clause|https://github.com/simplepie/simplepie.git|
|
||||
|smarty/smarty|3.1.39.0|LGPL-3.0|https://github.com/smarty-php/smarty.git|
|
||||
|symfony/polyfill-ctype|1.23.0.0|MIT|https://github.com/symfony/polyfill-ctype.git|
|
||||
|twbs/bootstrap|4.6.0.0|MIT|https://github.com/twbs/bootstrap.git|
|
||||
|symfony/polyfill-php80|1.23.1.0|MIT|https://github.com/symfony/polyfill-php80.git|
|
||||
|symfony/polyfill-php81|1.23.0.0|MIT|https://github.com/symfony/polyfill-php81.git|
|
||||
|twbs/bootstrap|5.1.3.0|MIT|https://github.com/twbs/bootstrap.git|
|
||||
|voku/portable-ascii|1.5.6.0|MIT|https://github.com/voku/portable-ascii.git|
|
||||
|voku/stop-words|2.0.1.0|MIT|https://github.com/voku/stop-words.git|
|
||||
|fullcalendar/fullcalendar|4.4.2.0|MIT|https://github.com/fullcalendar/fullcalendar.git|
|
||||
|miromannino/Justified-Gallery|3.8.1.0|MIT|https://github.com/miromannino/Justified-Gallery.git|
|
||||
|fengyuanchen/cropperjs|1.5.7.0|MIT|https://github.com/fengyuanchen/cropperjs.git|
|
||||
|
||||
31
SECURITY.md
Normal file
31
SECURITY.md
Normal file
@@ -0,0 +1,31 @@
|
||||
# Hubzilla Security Policy
|
||||
|
||||
The [Hubzilla] Project takes security, privacy and user control over personal data seriously. We ask that any security issues be disclosed to us in a responsible manner to allow us time to remediate the issues, and site administrators time to upgrade before information about the issue is made public.
|
||||
|
||||
This document outlines security procedures and policies for the Hubzilla project. It covers the following components:
|
||||
|
||||
* The Hubzilla core repository: https://framagit.org/hubzilla/core
|
||||
* The official addon repository: https://framagit.org/hubzilla/addons
|
||||
* The official themes repository: https://framagit.org/hubzilla/themes
|
||||
* The official widgets repository: https://framagit.org/hubzilla/widgets
|
||||
|
||||
## Coordinated Disclosure Guidelines
|
||||
|
||||
We are committed to working with security researchers to verify, reproduce, and respond to legitimate reported vulnerabilities. You can help us by following these simple guidelines:
|
||||
|
||||
* Submit suspected vulnerabilities by email to `security@hubzilla.org`, or as a confidential issue in the relevant repository listed above.
|
||||
* Provide clear instructions on how to reproduce the issue, and if possible, a minimal Proof of Concept (PoC) exploit.
|
||||
* We will acknowledge your submission as soon as we can, and will keep you updated as it is being processed. We may ask for more information, or clarifications about the issue or the steps to reproduce it during this time.
|
||||
* We will assign a CVE to the issue once it is confirmed.
|
||||
* We will do our best to fix the issue as soon as we can after it has been confirmed. We request that information about the vulnerability or details about how to exploit it is not disclosed to other parties until after the fix is released and some time has passed, to allow site administrators to upgrade. We will normally make the CVE public one month after a fix has been released. (This grace period can differ based on severity, and can be negotiated.)
|
||||
* Please perform all tests against a local instance of the software, and refrain from running any Denial of Service or automated testing tools against public hubs or the project managers (and their partners') infrastructure.
|
||||
* If the issue belongs to a third party module that we depend on, we may help with reporting it upstream if the submitter wants us to.
|
||||
|
||||
## Comments on this Policy
|
||||
|
||||
We welcome comments and suggestions for improving this policy. You can reach us at:
|
||||
|
||||
* Our ticketing system: https://framagit.org/hubzilla/core/-/issues
|
||||
* By sending us an email at `security@hubzilla.org`.
|
||||
|
||||
[Hubzilla]: https://hubzilla.org
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace Zotlabs\Access;
|
||||
|
||||
|
||||
/**
|
||||
* @brief AccessList class which represents individual content ACLs.
|
||||
*
|
||||
@@ -17,29 +18,48 @@ class AccessList {
|
||||
* @brief Allow contacts
|
||||
* @var string
|
||||
*/
|
||||
private $allow_cid;
|
||||
private ?string $allow_cid;
|
||||
/**
|
||||
* @brief Allow groups
|
||||
* @var string
|
||||
*/
|
||||
private $allow_gid;
|
||||
private ?string $allow_gid;
|
||||
/**
|
||||
* @brief Deny contacts
|
||||
* @var string
|
||||
*/
|
||||
private $deny_cid;
|
||||
private ?string $deny_cid;
|
||||
/**
|
||||
* @brief Deny groups
|
||||
* @var string
|
||||
*/
|
||||
private $deny_gid;
|
||||
private ?string $deny_gid;
|
||||
/**
|
||||
* @brief Indicates if we are using the default constructor values or
|
||||
* values that have been set explicitly.
|
||||
* @var boolean
|
||||
*/
|
||||
private $explicit;
|
||||
private bool $explicit;
|
||||
|
||||
/**
|
||||
* @brief Keys required by the constructor if the channel array is given.
|
||||
*/
|
||||
private const REQUIRED_KEYS_CONSTRUCTOR = [
|
||||
'channel_allow_cid',
|
||||
'channel_allow_gid',
|
||||
'channel_deny_cid',
|
||||
'channel_deny_gid'
|
||||
];
|
||||
|
||||
/**
|
||||
* @brief Keys required by the set method.
|
||||
*/
|
||||
private const REQUIRED_KEYS_SET = [
|
||||
'allow_cid',
|
||||
'allow_gid',
|
||||
'deny_cid',
|
||||
'deny_gid'
|
||||
];
|
||||
|
||||
/**
|
||||
* @brief Constructor for AccessList class.
|
||||
@@ -53,8 +73,9 @@ class AccessList {
|
||||
* * \e string \b channel_deny_cid => string of denied cids
|
||||
* * \e string \b channel_deny_gid => string of denied gids
|
||||
*/
|
||||
function __construct($channel) {
|
||||
function __construct(array $channel) {
|
||||
if ($channel) {
|
||||
$this->validate_input_array($channel, self::REQUIRED_KEYS_CONSTRUCTOR);
|
||||
$this->allow_cid = $channel['channel_allow_cid'];
|
||||
$this->allow_gid = $channel['channel_allow_gid'];
|
||||
$this->deny_cid = $channel['channel_deny_cid'];
|
||||
@@ -70,13 +91,24 @@ class AccessList {
|
||||
$this->explicit = false;
|
||||
}
|
||||
|
||||
private function validate_input_array(array $arr, array $required_keys) : void {
|
||||
$missing_keys = array_diff($required_keys, array_keys($arr));
|
||||
|
||||
if (!empty($missing_keys)) {
|
||||
throw new \Exception(
|
||||
'Invalid AccessList object: Expected array with keys: '
|
||||
. implode(', ', $missing_keys)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get if we are using the default constructor values
|
||||
* or values that have been set explicitly.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
function get_explicit() {
|
||||
function get_explicit() : bool {
|
||||
return $this->explicit;
|
||||
}
|
||||
|
||||
@@ -94,7 +126,9 @@ class AccessList {
|
||||
* * \e string \b deny_gid => string of denied gids
|
||||
* @param boolean $explicit (optional) default true
|
||||
*/
|
||||
function set($arr, $explicit = true) {
|
||||
function set(array $arr, bool $explicit = true) : void {
|
||||
$this->validate_input_array($arr, self::REQUIRED_KEYS_SET);
|
||||
|
||||
$this->allow_cid = $arr['allow_cid'];
|
||||
$this->allow_gid = $arr['allow_gid'];
|
||||
$this->deny_cid = $arr['deny_cid'];
|
||||
@@ -112,7 +146,7 @@ class AccessList {
|
||||
* * \e string \b deny_cid => string of denied cids
|
||||
* * \e string \b deny_gid => string of denied gids
|
||||
*/
|
||||
function get() {
|
||||
function get() : array {
|
||||
return [
|
||||
'allow_cid' => $this->allow_cid,
|
||||
'allow_gid' => $this->allow_gid,
|
||||
@@ -138,7 +172,12 @@ class AccessList {
|
||||
* * \e array|string \b group_deny => array with gids or comma-seperated string
|
||||
* @param boolean $explicit (optional) default true
|
||||
*/
|
||||
function set_from_array($arr, $explicit = true) {
|
||||
function set_from_array(array $arr, bool $explicit = true) : void {
|
||||
$arr['contact_allow'] = $arr['contact_allow'] ?? [];
|
||||
$arr['group_allow'] = $arr['group_allow'] ?? [];
|
||||
$arr['contact_deny'] = $arr['contact_deny'] ?? [];
|
||||
$arr['group_deny'] = $arr['group_deny'] ?? [];
|
||||
|
||||
$this->allow_cid = perms2str((is_array($arr['contact_allow']))
|
||||
? $arr['contact_allow'] : explode(',', $arr['contact_allow']));
|
||||
$this->allow_gid = perms2str((is_array($arr['group_allow']))
|
||||
@@ -156,7 +195,7 @@ class AccessList {
|
||||
*
|
||||
* @return boolean Return true if any of allow_* deny_* values is set.
|
||||
*/
|
||||
function is_private() {
|
||||
function is_private() : bool {
|
||||
return (($this->allow_cid || $this->allow_gid || $this->deny_cid || $this->deny_gid) ? true : false);
|
||||
}
|
||||
|
||||
|
||||
@@ -89,4 +89,4 @@ class PermissionLimits {
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
namespace Zotlabs\Access;
|
||||
|
||||
use Zotlabs\Lib\Config;
|
||||
|
||||
/**
|
||||
* @brief PermissionRoles class.
|
||||
*
|
||||
@@ -17,7 +19,7 @@ class PermissionRoles {
|
||||
* @return number
|
||||
*/
|
||||
static public function version() {
|
||||
return 2;
|
||||
return 3;
|
||||
}
|
||||
|
||||
static function role_perms($role) {
|
||||
@@ -27,6 +29,54 @@ class PermissionRoles {
|
||||
$ret['role'] = $role;
|
||||
|
||||
switch($role) {
|
||||
|
||||
case 'public':
|
||||
$ret['default_collection'] = false;
|
||||
$ret['perms_connect'] = [
|
||||
'view_stream', 'view_profile', 'view_contacts', 'view_storage', 'view_pages', 'view_wiki',
|
||||
'send_stream', 'post_comments', 'post_mail', 'post_wall', 'chat', 'post_like', 'republish'
|
||||
];
|
||||
$ret['limits'] = PermissionLimits::Std_Limits();
|
||||
$ret['limits']['post_comments'] = PERMS_AUTHED;
|
||||
$ret['limits']['post_mail'] = PERMS_AUTHED;
|
||||
$ret['limits']['post_like'] = PERMS_AUTHED;
|
||||
$ret['limits']['chat'] = PERMS_AUTHED;
|
||||
break;
|
||||
|
||||
// Hubzilla default role
|
||||
case 'personal':
|
||||
$ret['default_collection'] = true;
|
||||
$ret['perms_connect'] = [
|
||||
'view_stream', 'view_profile', 'view_contacts', 'view_storage', 'view_pages', 'view_wiki',
|
||||
'send_stream', 'post_comments', 'post_mail', 'chat', 'post_like'
|
||||
];
|
||||
$ret['limits'] = PermissionLimits::Std_Limits();
|
||||
$ret['limits']['view_contacts'] = PERMS_SPECIFIC;
|
||||
break;
|
||||
|
||||
case 'group':
|
||||
$ret['default_collection'] = false;
|
||||
$ret['perms_connect'] = [
|
||||
'view_stream', 'view_profile', 'view_contacts', 'view_storage',
|
||||
'view_pages', 'view_wiki', 'post_wall', 'post_comments',
|
||||
'post_mail', 'post_like', 'chat'
|
||||
];
|
||||
$ret['limits'] = PermissionLimits::Std_Limits();
|
||||
$ret['channel_type'] = 'group';
|
||||
break;
|
||||
|
||||
// Provide some defaults for the custom role so that we do not start
|
||||
// with no permissions at all if we create a new channel with this role
|
||||
case 'custom':
|
||||
$ret['default_collection'] = true;
|
||||
$ret['perms_connect'] = [
|
||||
'view_stream', 'view_profile', 'view_contacts', 'view_storage', 'view_pages', 'view_wiki',
|
||||
'send_stream', 'post_comments', 'post_mail', 'chat', 'post_like'
|
||||
];
|
||||
$ret['limits'] = PermissionLimits::Std_Limits();
|
||||
break;
|
||||
|
||||
/*
|
||||
case 'social':
|
||||
$ret['perms_auto'] = false;
|
||||
$ret['default_collection'] = false;
|
||||
@@ -193,13 +243,14 @@ class PermissionRoles {
|
||||
$ret['channel_type'] = 'group';
|
||||
|
||||
break;
|
||||
*/
|
||||
|
||||
case 'custom':
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
$x = get_config('system','role_perms');
|
||||
$x = Config::Get('system','role_perms');
|
||||
|
||||
// let system settings over-ride any or all
|
||||
if($x && is_array($x) && array_key_exists($role,$x))
|
||||
$ret = array_merge($ret,$x[$role]);
|
||||
@@ -284,6 +335,7 @@ class PermissionRoles {
|
||||
*/
|
||||
static public function roles() {
|
||||
$roles = [
|
||||
|
||||
t('Social Networking') => [
|
||||
'social_federation' => t('Social - Federation'),
|
||||
'social' => t('Social - Mostly Public'),
|
||||
@@ -317,4 +369,29 @@ class PermissionRoles {
|
||||
return $roles;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Array with translated role names and grouping.
|
||||
*
|
||||
* Return an associative array with role names that can be used
|
||||
* to create select groups like in \e field_select_grouped.tpl.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
static public function channel_roles() {
|
||||
$channel_roles = [
|
||||
//'public' => [t('Public'), t('A very permissive role suited for participation in the fediverse')],
|
||||
//'personal' => [t('Personal'), t('The $Projectname default role suited for a personal channel')],
|
||||
//'forum' => [t('Community forum'), t('This role configures your channel to act as an community forum')],
|
||||
//'custom' => [t('Custom'), t('This role comes with the presets of the personal role but allows you to configure it to your needs')]
|
||||
'public' => t('Public'),
|
||||
'personal' => t('Personal'),
|
||||
'group' => t('Community forum'),
|
||||
'custom' => t('Custom')
|
||||
];
|
||||
|
||||
call_hooks('list_channel_roles', $channel_roles);
|
||||
|
||||
return $channel_roles;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ class Permissions {
|
||||
* @return number
|
||||
*/
|
||||
static public function version() {
|
||||
return 2;
|
||||
return 3;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -67,9 +67,9 @@ class Permissions {
|
||||
'post_comments' => t('Can comment on or like my posts'),
|
||||
'post_mail' => t('Can send me direct messages'),
|
||||
'post_like' => t('Can like/dislike profiles and profile things'),
|
||||
'tag_deliver' => t('Can forward direct messages to all my channel connections (forum)'),
|
||||
'chat' => t('Can chat with me'),
|
||||
'republish' => t('Can source my public posts in derived channels'),
|
||||
'republish' => t('Can source/mirror my public posts in derived channels'),
|
||||
//'tag_deliver' => t('Can forward to my contacts via direct messages (forum)'),
|
||||
'delegate' => t('Can administer my channel')
|
||||
];
|
||||
|
||||
@@ -217,25 +217,23 @@ class Permissions {
|
||||
|
||||
$my_perms = [];
|
||||
$permcat = null;
|
||||
$automatic = 0;
|
||||
$automatic = get_pconfig($channel_id, 'system', 'autoperms');
|
||||
|
||||
// If a default permcat exists, use that
|
||||
|
||||
$pc = ((feature_enabled($channel_id, 'permcats')) ? get_pconfig($channel_id, 'system', 'default_permcat') : 'default');
|
||||
if (!in_array($pc, ['', 'default'])) {
|
||||
$pcp = new Zlib\Permcat($channel_id);
|
||||
$permcat = $pcp->fetch($pc);
|
||||
if ($permcat && $permcat['perms']) {
|
||||
foreach ($permcat['perms'] as $p) {
|
||||
$my_perms[$p['name']] = $p['value'];
|
||||
}
|
||||
$pc = get_pconfig($channel_id, 'system', 'default_permcat', 'default');
|
||||
$pcp = new Zlib\Permcat($channel_id);
|
||||
$permcat = $pcp->fetch($pc);
|
||||
if ($permcat && $permcat['perms']) {
|
||||
foreach ($permcat['perms'] as $p) {
|
||||
$my_perms[$p['name']] = $p['value'];
|
||||
}
|
||||
}
|
||||
|
||||
// look up the permission role to see if it specified auto-connect
|
||||
// and if there was no permcat or a default permcat, set the perms
|
||||
// from the role
|
||||
|
||||
/*
|
||||
$role = get_pconfig($channel_id, 'system', 'permissions_role');
|
||||
if ($role) {
|
||||
$xx = PermissionRoles::role_perms($role);
|
||||
@@ -247,11 +245,12 @@ class Permissions {
|
||||
$my_perms = Permissions::FilledPerms($default_perms);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// If we reached this point without having any permission information,
|
||||
// it is likely a custom permissions role. First see if there are any
|
||||
// automatic permissions.
|
||||
|
||||
/*
|
||||
if (!$my_perms) {
|
||||
$m = Permissions::FilledAutoperms($channel_id);
|
||||
if ($m) {
|
||||
@@ -259,11 +258,12 @@ class Permissions {
|
||||
$my_perms = $m;
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
// If we reached this point with no permissions, the channel is using
|
||||
// custom perms but they are not automatic. They will be stored in abconfig with
|
||||
// the channel's channel_hash (the 'self' connection).
|
||||
|
||||
/*
|
||||
if (!$my_perms) {
|
||||
$r = q("select channel_hash from channel where channel_id = %d",
|
||||
intval($channel_id)
|
||||
@@ -280,10 +280,10 @@ class Permissions {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (['perms' => $my_perms, 'automatic' => $automatic]);
|
||||
*/
|
||||
return (['perms' => $my_perms, 'automatic' => $automatic, 'role' => $pc]);
|
||||
}
|
||||
|
||||
/*
|
||||
static public function serialise($p) {
|
||||
$n = [];
|
||||
if ($p) {
|
||||
@@ -295,4 +295,5 @@ class Permissions {
|
||||
}
|
||||
return implode(',', $n);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
776
Zotlabs/ActivityStreams/ASObject.php
Normal file
776
Zotlabs/ActivityStreams/ASObject.php
Normal file
@@ -0,0 +1,776 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\ActivityStreams;
|
||||
|
||||
|
||||
use Zotlabs\Lib\BaseObject;
|
||||
|
||||
class ASObject extends BaseObject
|
||||
{
|
||||
public $id;
|
||||
public $type;
|
||||
public $attachment;
|
||||
public $attributedTo;
|
||||
public $audience;
|
||||
public $content;
|
||||
public $context;
|
||||
public $name;
|
||||
public $endTime;
|
||||
public $generator;
|
||||
public $icon;
|
||||
public $image;
|
||||
public $inReplyTo;
|
||||
public $location;
|
||||
public $preview;
|
||||
public $published;
|
||||
public $replies;
|
||||
public $startTime;
|
||||
public $summary;
|
||||
public $tag;
|
||||
public $updated;
|
||||
public $url;
|
||||
public $to;
|
||||
public $bto;
|
||||
public $cc;
|
||||
public $bcc;
|
||||
public $mediaType;
|
||||
public $duration;
|
||||
public $source;
|
||||
|
||||
|
||||
// Extension properties
|
||||
|
||||
public $signature;
|
||||
public $proof;
|
||||
public $sensitive;
|
||||
public $replyTo;
|
||||
public $wall;
|
||||
public $isContainedConversation;
|
||||
public $expires;
|
||||
public $canReply;
|
||||
public $canSearch;
|
||||
public $directMessage;
|
||||
public $commentPolicy;
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getDirectMessage()
|
||||
{
|
||||
return $this->directMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $directMessage
|
||||
* @return ASObject
|
||||
*/
|
||||
public function setDirectMessage($directMessage)
|
||||
{
|
||||
$this->directMessage = $directMessage;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getSignature()
|
||||
{
|
||||
return $this->signature;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $signature
|
||||
* @return ASObject
|
||||
*/
|
||||
public function setSignature($signature)
|
||||
{
|
||||
$this->signature = $signature;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getProof()
|
||||
{
|
||||
return $this->proof;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $proof
|
||||
* @return ASObject
|
||||
*/
|
||||
public function setProof($proof)
|
||||
{
|
||||
$this->proof = $proof;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getSensitive()
|
||||
{
|
||||
return $this->sensitive;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $sensitive
|
||||
* @return ASObject
|
||||
*/
|
||||
public function setSensitive($sensitive)
|
||||
{
|
||||
$this->sensitive = $sensitive;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getReplyTo()
|
||||
{
|
||||
return $this->replyTo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $replyTo
|
||||
* @return ASObject
|
||||
*/
|
||||
public function setReplyTo($replyTo)
|
||||
{
|
||||
$this->replyTo = $replyTo;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getWall()
|
||||
{
|
||||
return $this->wall;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $wall
|
||||
* @return ASObject
|
||||
*/
|
||||
public function setWall($wall)
|
||||
{
|
||||
$this->wall = $wall;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getIsContainedConversation()
|
||||
{
|
||||
return $this->isContainedConversation;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $isContainedConversation
|
||||
* @return ASObject
|
||||
*/
|
||||
public function setIsContainedConversation($isContainedConversation)
|
||||
{
|
||||
$this->isContainedConversation = $isContainedConversation;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getExpires()
|
||||
{
|
||||
return $this->expires;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $expires
|
||||
* @return ASObject
|
||||
*/
|
||||
public function setExpires($expires)
|
||||
{
|
||||
$this->expires = $expires;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getCanReply()
|
||||
{
|
||||
return $this->canReply;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $canReply
|
||||
* @return ASObject
|
||||
*/
|
||||
public function setCanReply($canReply)
|
||||
{
|
||||
$this->canReply = $canReply;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getCanSearch()
|
||||
{
|
||||
return $this->canSearch;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $canSearch
|
||||
* @return ASObject
|
||||
*/
|
||||
public function setCanSearch($canSearch)
|
||||
{
|
||||
$this->canSearch = $canSearch;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getCommentPolicy()
|
||||
{
|
||||
return $this->commentPolicy;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $commentPolicy
|
||||
* @return ASObject
|
||||
*/
|
||||
public function setCommentPolicy($commentPolicy)
|
||||
{
|
||||
$this->commentPolicy = $commentPolicy;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $id
|
||||
* @return ASObject
|
||||
*/
|
||||
public function setId($id)
|
||||
{
|
||||
$this->id = $id;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getType()
|
||||
{
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $type
|
||||
* @return ASObject
|
||||
*/
|
||||
public function setType($type)
|
||||
{
|
||||
$this->type = $type;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getAttachment()
|
||||
{
|
||||
return $this->attachment;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $attachment
|
||||
* @return ASObject
|
||||
*/
|
||||
public function setAttachment($attachment)
|
||||
{
|
||||
$this->attachment = $attachment;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getAttributedTo()
|
||||
{
|
||||
return $this->attributedTo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $attributedTo
|
||||
* @return ASObject
|
||||
*/
|
||||
public function setAttributedTo($attributedTo)
|
||||
{
|
||||
$this->attributedTo = $attributedTo;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getAudience()
|
||||
{
|
||||
return $this->audience;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $audience
|
||||
* @return ASObject
|
||||
*/
|
||||
public function setAudience($audience)
|
||||
{
|
||||
$this->audience = $audience;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getContent()
|
||||
{
|
||||
return $this->content;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $content
|
||||
* @return ASObject
|
||||
*/
|
||||
public function setContent($content)
|
||||
{
|
||||
$this->content = $content;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getContext()
|
||||
{
|
||||
return $this->context;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $context
|
||||
* @return ASObject
|
||||
*/
|
||||
public function setContext($context)
|
||||
{
|
||||
$this->context = $context;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $name
|
||||
* @return ASObject
|
||||
*/
|
||||
public function setName($name)
|
||||
{
|
||||
$this->name = $name;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getEndTime()
|
||||
{
|
||||
return $this->endTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $endTime
|
||||
* @return ASObject
|
||||
*/
|
||||
public function setEndTime($endTime)
|
||||
{
|
||||
$this->endTime = $endTime;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getGenerator()
|
||||
{
|
||||
return $this->generator;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $generator
|
||||
* @return ASObject
|
||||
*/
|
||||
public function setGenerator($generator)
|
||||
{
|
||||
$this->generator = $generator;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getIcon()
|
||||
{
|
||||
return $this->icon;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $icon
|
||||
* @return ASObject
|
||||
*/
|
||||
public function setIcon($icon)
|
||||
{
|
||||
$this->icon = $icon;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getImage()
|
||||
{
|
||||
return $this->image;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $image
|
||||
* @return ASObject
|
||||
*/
|
||||
public function setImage($image)
|
||||
{
|
||||
$this->image = $image;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getInReplyTo()
|
||||
{
|
||||
return $this->inReplyTo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $inReplyTo
|
||||
* @return ASObject
|
||||
*/
|
||||
public function setInReplyTo($inReplyTo)
|
||||
{
|
||||
$this->inReplyTo = $inReplyTo;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getLocation()
|
||||
{
|
||||
return $this->location;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $location
|
||||
* @return ASObject
|
||||
*/
|
||||
public function setLocation($location)
|
||||
{
|
||||
$this->location = $location;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getPreview()
|
||||
{
|
||||
return $this->preview;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $preview
|
||||
* @return ASObject
|
||||
*/
|
||||
public function setPreview($preview)
|
||||
{
|
||||
$this->preview = $preview;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getPublished()
|
||||
{
|
||||
return $this->published;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $published
|
||||
* @return ASObject
|
||||
*/
|
||||
public function setPublished($published)
|
||||
{
|
||||
$this->published = $published;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getReplies()
|
||||
{
|
||||
return $this->replies;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $replies
|
||||
* @return ASObject
|
||||
*/
|
||||
public function setReplies($replies)
|
||||
{
|
||||
$this->replies = $replies;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getStartTime()
|
||||
{
|
||||
return $this->startTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $startTime
|
||||
* @return ASObject
|
||||
*/
|
||||
public function setStartTime($startTime)
|
||||
{
|
||||
$this->startTime = $startTime;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getSummary()
|
||||
{
|
||||
return $this->summary;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $summary
|
||||
* @return ASObject
|
||||
*/
|
||||
public function setSummary($summary)
|
||||
{
|
||||
$this->summary = $summary;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getTag()
|
||||
{
|
||||
return $this->tag;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $tag
|
||||
* @return ASObject
|
||||
*/
|
||||
public function setTag($tag)
|
||||
{
|
||||
$this->tag = $tag;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getUpdated()
|
||||
{
|
||||
return $this->updated;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $updated
|
||||
* @return ASObject
|
||||
*/
|
||||
public function setUpdated($updated)
|
||||
{
|
||||
$this->updated = $updated;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getUrl()
|
||||
{
|
||||
return $this->url;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $url
|
||||
* @return ASObject
|
||||
*/
|
||||
public function setUrl($url)
|
||||
{
|
||||
$this->url = $url;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getTo()
|
||||
{
|
||||
return $this->to;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $to
|
||||
* @return ASObject
|
||||
*/
|
||||
public function setTo($to)
|
||||
{
|
||||
$this->to = $to;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getBto()
|
||||
{
|
||||
return $this->bto;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $bto
|
||||
* @return ASObject
|
||||
*/
|
||||
public function setBto($bto)
|
||||
{
|
||||
$this->bto = $bto;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getCc()
|
||||
{
|
||||
return $this->cc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $cc
|
||||
* @return ASObject
|
||||
*/
|
||||
public function setCc($cc)
|
||||
{
|
||||
$this->cc = $cc;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getBcc()
|
||||
{
|
||||
return $this->bcc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $bcc
|
||||
* @return ASObject
|
||||
*/
|
||||
public function setBcc($bcc)
|
||||
{
|
||||
$this->bcc = $bcc;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getMediaType()
|
||||
{
|
||||
return $this->mediaType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $mediaType
|
||||
* @return ASObject
|
||||
*/
|
||||
public function setMediaType($mediaType)
|
||||
{
|
||||
$this->mediaType = $mediaType;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getDuration()
|
||||
{
|
||||
return $this->duration;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $duration
|
||||
* @return ASObject
|
||||
*/
|
||||
public function setDuration($duration)
|
||||
{
|
||||
$this->duration = $duration;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getSource()
|
||||
{
|
||||
return $this->source;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $source
|
||||
* @return ASObject
|
||||
*/
|
||||
public function setSource($source)
|
||||
{
|
||||
$this->source = $source;
|
||||
return $this;
|
||||
}
|
||||
|
||||
}
|
||||
122
Zotlabs/ActivityStreams/Activity.php
Normal file
122
Zotlabs/ActivityStreams/Activity.php
Normal file
@@ -0,0 +1,122 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\ActivityStreams;
|
||||
|
||||
class Activity extends ASObject
|
||||
{
|
||||
public $actor;
|
||||
public $object;
|
||||
public $target;
|
||||
public $result;
|
||||
public $origin;
|
||||
public $instrument;
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getActor()
|
||||
{
|
||||
return $this->actor;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $actor
|
||||
* @return Activity
|
||||
*/
|
||||
public function setActor($actor)
|
||||
{
|
||||
$this->actor = $actor;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getObject()
|
||||
{
|
||||
return $this->object;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $object
|
||||
* @return Activity
|
||||
*/
|
||||
public function setObject($object)
|
||||
{
|
||||
$this->object = $object;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getTarget()
|
||||
{
|
||||
return $this->target;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $target
|
||||
* @return Activity
|
||||
*/
|
||||
public function setTarget($target)
|
||||
{
|
||||
$this->target = $target;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getResult()
|
||||
{
|
||||
return $this->result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $result
|
||||
* @return Activity
|
||||
*/
|
||||
public function setResult($result)
|
||||
{
|
||||
$this->result = $result;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getOrigin()
|
||||
{
|
||||
return $this->origin;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $origin
|
||||
* @return Activity
|
||||
*/
|
||||
public function setOrigin($origin)
|
||||
{
|
||||
$this->origin = $origin;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getInstrument()
|
||||
{
|
||||
return $this->instrument;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $instrument
|
||||
* @return Activity
|
||||
*/
|
||||
public function setInstrument($instrument)
|
||||
{
|
||||
$this->instrument = $instrument;
|
||||
return $this;
|
||||
}
|
||||
|
||||
}
|
||||
428
Zotlabs/ActivityStreams/Actor.php
Normal file
428
Zotlabs/ActivityStreams/Actor.php
Normal file
@@ -0,0 +1,428 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\ActivityStreams;
|
||||
|
||||
class Actor extends ASObject
|
||||
{
|
||||
public $inbox;
|
||||
public $outbox;
|
||||
public $followers;
|
||||
public $following;
|
||||
public $permissions; /* extension property */
|
||||
public $endpoints;
|
||||
public $publicKey;
|
||||
public $preferredUsername;
|
||||
public $alsoKnownAs;
|
||||
|
||||
// Extension properties
|
||||
|
||||
public $movedTo;
|
||||
public $copiedTo;
|
||||
public $discoverable;
|
||||
public $manuallyApprovesFollowers;
|
||||
public $webfinger;
|
||||
public $canSearch;
|
||||
public $indexable;
|
||||
public $assertionMethod;
|
||||
public $gateways;
|
||||
public $openwebauth;
|
||||
public $authredirect;
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getAlsoKnownAs()
|
||||
{
|
||||
return $this->alsoKnownAs;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $alsoKnownAs
|
||||
* @return Actor
|
||||
*/
|
||||
public function setAlsoKnownAs($alsoKnownAs)
|
||||
{
|
||||
$this->alsoKnownAs = $alsoKnownAs;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getMovedTo()
|
||||
{
|
||||
return $this->movedTo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getCopiedTo()
|
||||
{
|
||||
return $this->copiedTo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $copiedTo
|
||||
* @return Actor
|
||||
*/
|
||||
public function setCopiedTo($copiedTo)
|
||||
{
|
||||
$this->copiedTo = $copiedTo;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $movedTo
|
||||
* @return Actor
|
||||
*/
|
||||
public function setMovedTo($movedTo)
|
||||
{
|
||||
$this->movedTo = $movedTo;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getDiscoverable()
|
||||
{
|
||||
return $this->discoverable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $discoverable
|
||||
* @return Actor
|
||||
*/
|
||||
public function setDiscoverable($discoverable)
|
||||
{
|
||||
$this->discoverable = $discoverable;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getManuallyApprovesFollowers()
|
||||
{
|
||||
return $this->manuallyApprovesFollowers;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $manuallyApprovesFollowers
|
||||
* @return Actor
|
||||
*/
|
||||
public function setManuallyApprovesFollowers($manuallyApprovesFollowers)
|
||||
{
|
||||
$this->manuallyApprovesFollowers = $manuallyApprovesFollowers;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getPreferredUsername()
|
||||
{
|
||||
return $this->preferredUsername;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $preferredUsername
|
||||
* @return Actor
|
||||
*/
|
||||
public function setPreferredUsername($preferredUsername)
|
||||
{
|
||||
$this->preferredUsername = $preferredUsername;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $id
|
||||
* @return Actor
|
||||
*/
|
||||
public function setId($id)
|
||||
{
|
||||
$this->id = $id;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getType()
|
||||
{
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $type
|
||||
* @return Actor
|
||||
*/
|
||||
public function setType($type)
|
||||
{
|
||||
$this->type = $type;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getInbox()
|
||||
{
|
||||
return $this->inbox;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $inbox
|
||||
* @return Actor
|
||||
*/
|
||||
public function setInbox($inbox)
|
||||
{
|
||||
$this->inbox = $inbox;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getOutbox()
|
||||
{
|
||||
return $this->outbox;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $outbox
|
||||
* @return Actor
|
||||
*/
|
||||
public function setOutbox($outbox)
|
||||
{
|
||||
$this->outbox = $outbox;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getFollowers()
|
||||
{
|
||||
return $this->followers;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $followers
|
||||
* @return Actor
|
||||
*/
|
||||
public function setFollowers($followers)
|
||||
{
|
||||
$this->followers = $followers;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getFollowing()
|
||||
{
|
||||
return $this->following;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $following
|
||||
* @return Actor
|
||||
*/
|
||||
public function setFollowing($following)
|
||||
{
|
||||
$this->following = $following;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getEndpoints()
|
||||
{
|
||||
return $this->endpoints;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $endpoints
|
||||
* @return Actor
|
||||
*/
|
||||
public function setEndpoints($endpoints)
|
||||
{
|
||||
$this->endpoints = $endpoints;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getPublicKey()
|
||||
{
|
||||
return $this->publicKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $publicKey
|
||||
* @return Actor
|
||||
*/
|
||||
public function setPublicKey($publicKey)
|
||||
{
|
||||
$this->publicKey = $publicKey;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getWebfinger()
|
||||
{
|
||||
return $this->webfinger;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $webfinger
|
||||
* @return Actor
|
||||
*/
|
||||
public function setWebfinger($webfinger)
|
||||
{
|
||||
$this->webfinger = $webfinger;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getCanSearch()
|
||||
{
|
||||
return $this->canSearch;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $canSearch
|
||||
* @return Actor
|
||||
*/
|
||||
public function setCanSearch($canSearch)
|
||||
{
|
||||
$this->canSearch = $canSearch;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getIndexable()
|
||||
{
|
||||
return $this->indexable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $indexable
|
||||
* @return Actor
|
||||
*/
|
||||
public function setIndexable($indexable)
|
||||
{
|
||||
$this->indexable = $indexable;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getAssertionMethod()
|
||||
{
|
||||
return $this->assertionMethod;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $assertionMethod
|
||||
* @return Actor
|
||||
*/
|
||||
public function setAssertionMethod($assertionMethod)
|
||||
{
|
||||
$this->assertionMethod = $assertionMethod;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getGateways()
|
||||
{
|
||||
return $this->gateways;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $gateways
|
||||
* @return Actor
|
||||
*/
|
||||
public function setGateways($gateways)
|
||||
{
|
||||
$this->gateways = $gateways;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getPermissions()
|
||||
{
|
||||
return $this->permissions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $permissions
|
||||
* @return Actor
|
||||
*/
|
||||
public function setPermissions($permissions)
|
||||
{
|
||||
$this->permissions = $permissions;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getOpenwebauth()
|
||||
{
|
||||
return $this->openwebauth;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $openwebauth
|
||||
* @return Actor
|
||||
*/
|
||||
public function setOpenwebauth($openwebauth)
|
||||
{
|
||||
$this->openwebauth = $openwebauth;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getAuthredirect()
|
||||
{
|
||||
return $this->authredirect;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $authredirect
|
||||
* @return Actor
|
||||
*/
|
||||
public function setAuthredirect($authredirect)
|
||||
{
|
||||
$this->authredirect = $authredirect;
|
||||
return $this;
|
||||
}
|
||||
|
||||
}
|
||||
87
Zotlabs/ActivityStreams/AssertionMethod.php
Normal file
87
Zotlabs/ActivityStreams/AssertionMethod.php
Normal file
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\ActivityStreams;
|
||||
|
||||
class AssertionMethod extends ASObject
|
||||
{
|
||||
public $id;
|
||||
public $type;
|
||||
public $controller;
|
||||
public $publicKeyMultibase;
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $id
|
||||
* @return AssertionMethod
|
||||
*/
|
||||
public function setId($id)
|
||||
{
|
||||
$this->id = $id;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getType()
|
||||
{
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $type
|
||||
* @return AssertionMethod
|
||||
*/
|
||||
public function setType($type)
|
||||
{
|
||||
$this->type = $type;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getController()
|
||||
{
|
||||
return $this->controller;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $controller
|
||||
* @return AssertionMethod
|
||||
*/
|
||||
public function setController($controller)
|
||||
{
|
||||
$this->controller = $controller;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getPublicKeyMultibase()
|
||||
{
|
||||
return $this->publicKeyMultibase;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $publicKeyMultibase
|
||||
* @return AssertionMethod
|
||||
*/
|
||||
public function setPublicKeyMultibase($publicKeyMultibase)
|
||||
{
|
||||
$this->publicKeyMultibase = $publicKeyMultibase;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
124
Zotlabs/ActivityStreams/Collection.php
Normal file
124
Zotlabs/ActivityStreams/Collection.php
Normal file
@@ -0,0 +1,124 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\ActivityStreams;
|
||||
|
||||
class Collection extends ASObject
|
||||
{
|
||||
public int $totalItems;
|
||||
public string $current;
|
||||
public string $first;
|
||||
public string $last;
|
||||
public array $items;
|
||||
|
||||
public mixed $collectionOf;
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getTotalItems(): int
|
||||
{
|
||||
return $this->totalItems;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $totalItems
|
||||
* @return Collection
|
||||
*/
|
||||
public function setTotalItems(mixed $totalItems): static
|
||||
{
|
||||
$this->totalItems = $totalItems;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getCurrent(): string
|
||||
{
|
||||
return $this->current;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $current
|
||||
* @return Collection
|
||||
*/
|
||||
public function setCurrent(mixed $current): static
|
||||
{
|
||||
$this->current = $current;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getFirst(): string
|
||||
{
|
||||
return $this->first;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $first
|
||||
* @return Collection
|
||||
*/
|
||||
public function setFirst(mixed $first): static
|
||||
{
|
||||
$this->first = $first;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getLast(): string
|
||||
{
|
||||
return $this->last;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $last
|
||||
* @return Collection
|
||||
*/
|
||||
public function setLast(mixed $last): static
|
||||
{
|
||||
$this->last = $last;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getItems(): array
|
||||
{
|
||||
return $this->items;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $items
|
||||
* @return Collection
|
||||
*/
|
||||
public function setItems(mixed $items): static
|
||||
{
|
||||
$this->items = $items;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getCollectionOf(): mixed
|
||||
{
|
||||
return $this->collectionOf;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $collectionOf
|
||||
* @return Collection
|
||||
*/
|
||||
public function setCollectionOf(mixed $collectionOf): static
|
||||
{
|
||||
$this->collectionOf = $collectionOf;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
73
Zotlabs/ActivityStreams/CollectionPage.php
Normal file
73
Zotlabs/ActivityStreams/CollectionPage.php
Normal file
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\ActivityStreams;
|
||||
|
||||
class CollectionPage extends Collection
|
||||
{
|
||||
public $partOf;
|
||||
public $next;
|
||||
public $prev;
|
||||
|
||||
// startIndex only applies for OrderedCollectionPage. See
|
||||
// https://www.w3.org/ns/activitystreams#OrderedCollectionPage
|
||||
// It is provided here to avoid multiple inheritance
|
||||
|
||||
public $startIndex;
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getPartOf()
|
||||
{
|
||||
return $this->partOf;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $partOf
|
||||
* @return CollectionPage
|
||||
*/
|
||||
public function setPartOf($partOf)
|
||||
{
|
||||
$this->partOf = $partOf;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getNext()
|
||||
{
|
||||
return $this->next;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $next
|
||||
* @return CollectionPage
|
||||
*/
|
||||
public function setNext($next)
|
||||
{
|
||||
$this->next = $next;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getPrev()
|
||||
{
|
||||
return $this->prev;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $prev
|
||||
* @return CollectionPage
|
||||
*/
|
||||
public function setPrev($prev)
|
||||
{
|
||||
$this->prev = $prev;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
104
Zotlabs/ActivityStreams/IntransitiveActivity.php
Normal file
104
Zotlabs/ActivityStreams/IntransitiveActivity.php
Normal file
@@ -0,0 +1,104 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\ActivityStreams;
|
||||
|
||||
|
||||
class IntransitiveActivity extends ASObject
|
||||
{
|
||||
public $actor;
|
||||
public $target;
|
||||
public $result;
|
||||
public $origin;
|
||||
public $instrument;
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getActor()
|
||||
{
|
||||
return $this->actor;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $actor
|
||||
* @return IntransitiveActivity
|
||||
*/
|
||||
public function setActor($actor)
|
||||
{
|
||||
$this->actor = $actor;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getTarget()
|
||||
{
|
||||
return $this->target;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $target
|
||||
* @return IntransitiveActivity
|
||||
*/
|
||||
public function setTarget($target)
|
||||
{
|
||||
$this->target = $target;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getResult()
|
||||
{
|
||||
return $this->result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $result
|
||||
* @return IntransitiveActivity
|
||||
*/
|
||||
public function setResult($result)
|
||||
{
|
||||
$this->result = $result;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getOrigin()
|
||||
{
|
||||
return $this->origin;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $origin
|
||||
* @return IntransitiveActivity
|
||||
*/
|
||||
public function setOrigin($origin)
|
||||
{
|
||||
$this->origin = $origin;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getInstrument()
|
||||
{
|
||||
return $this->instrument;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $instrument
|
||||
* @return IntransitiveActivity
|
||||
*/
|
||||
public function setInstrument($instrument)
|
||||
{
|
||||
$this->instrument = $instrument;
|
||||
return $this;
|
||||
}
|
||||
|
||||
}
|
||||
183
Zotlabs/ActivityStreams/Link.php
Normal file
183
Zotlabs/ActivityStreams/Link.php
Normal file
@@ -0,0 +1,183 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\ActivityStreams;
|
||||
|
||||
use Zotlabs\Lib\BaseObject;
|
||||
|
||||
class Link extends BaseObject
|
||||
{
|
||||
public $type;
|
||||
public $href;
|
||||
public $rel;
|
||||
public $mediaType;
|
||||
public $name;
|
||||
public $hreflang;
|
||||
public $height;
|
||||
public $width;
|
||||
public $preview;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getType()
|
||||
{
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $type
|
||||
* @return Link
|
||||
*/
|
||||
public function setType($type)
|
||||
{
|
||||
$this->type = $type;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getHref()
|
||||
{
|
||||
return $this->href;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $href
|
||||
* @return Link
|
||||
*/
|
||||
public function setHref($href)
|
||||
{
|
||||
$this->href = $href;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getRel()
|
||||
{
|
||||
return $this->rel;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $rel
|
||||
* @return Link
|
||||
*/
|
||||
public function setRel($rel)
|
||||
{
|
||||
$this->rel = $rel;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getMediaType()
|
||||
{
|
||||
return $this->mediaType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $mediaType
|
||||
* @return Link
|
||||
*/
|
||||
public function setMediaType($mediaType)
|
||||
{
|
||||
$this->mediaType = $mediaType;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $name
|
||||
* @return Link
|
||||
*/
|
||||
public function setName($name)
|
||||
{
|
||||
$this->name = $name;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getHreflang()
|
||||
{
|
||||
return $this->hreflang;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $hreflang
|
||||
* @return Link
|
||||
*/
|
||||
public function setHreflang($hreflang)
|
||||
{
|
||||
$this->hreflang = $hreflang;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getHeight()
|
||||
{
|
||||
return $this->height;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $height
|
||||
* @return Link
|
||||
*/
|
||||
public function setHeight($height)
|
||||
{
|
||||
$this->height = $height;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getWidth()
|
||||
{
|
||||
return $this->width;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $width
|
||||
* @return Link
|
||||
*/
|
||||
public function setWidth($width)
|
||||
{
|
||||
$this->width = $width;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getPreview()
|
||||
{
|
||||
return $this->preview;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $preview
|
||||
* @return Link
|
||||
*/
|
||||
public function setPreview($preview)
|
||||
{
|
||||
$this->preview = $preview;
|
||||
return $this;
|
||||
}
|
||||
|
||||
}
|
||||
8
Zotlabs/ActivityStreams/OrderedCollection.php
Normal file
8
Zotlabs/ActivityStreams/OrderedCollection.php
Normal file
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\ActivityStreams;
|
||||
|
||||
class OrderedCollection extends Collection
|
||||
{
|
||||
|
||||
}
|
||||
92
Zotlabs/ActivityStreams/OrderedCollectionPage.php
Normal file
92
Zotlabs/ActivityStreams/OrderedCollectionPage.php
Normal file
@@ -0,0 +1,92 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\ActivityStreams;
|
||||
|
||||
/**
|
||||
* According to the specification, OrderedCollectionPage extends
|
||||
* both OrderedCollection and CollectionPage, but PHP is still a bit awkward
|
||||
* when it comes to multiple inheritance. Rather than try and do this with
|
||||
* traits, we'll just include the CollectionPage elements here - as this only
|
||||
* consists of three properties.
|
||||
*/
|
||||
|
||||
class OrderedCollectionPage extends OrderedCollection
|
||||
{
|
||||
public $partOf;
|
||||
public $next;
|
||||
public $prev;
|
||||
public $startIndex;
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getPartOf()
|
||||
{
|
||||
return $this->partOf;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $partOf
|
||||
* @return OrderedCollectionPage
|
||||
*/
|
||||
public function setPartOf($partOf)
|
||||
{
|
||||
$this->partOf = $partOf;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getNext()
|
||||
{
|
||||
return $this->next;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $next
|
||||
* @return OrderedCollectionPage
|
||||
*/
|
||||
public function setNext($next)
|
||||
{
|
||||
$this->next = $next;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getPrev()
|
||||
{
|
||||
return $this->prev;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $prev
|
||||
* @return OrderedCollectionPage
|
||||
*/
|
||||
public function setPrev($prev)
|
||||
{
|
||||
$this->prev = $prev;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getStartIndex()
|
||||
{
|
||||
return $this->startIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $startIndex
|
||||
* @return OrderedCollectionPage
|
||||
*/
|
||||
public function setStartIndex($startIndex)
|
||||
{
|
||||
$this->startIndex = $startIndex;
|
||||
return $this;
|
||||
}
|
||||
|
||||
}
|
||||
125
Zotlabs/ActivityStreams/Place.php
Normal file
125
Zotlabs/ActivityStreams/Place.php
Normal file
@@ -0,0 +1,125 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\ActivityStreams;
|
||||
|
||||
class Place extends ASObject
|
||||
{
|
||||
|
||||
public $accuracy;
|
||||
public $altitude;
|
||||
public $latitude;
|
||||
public $longitude;
|
||||
public $radius;
|
||||
public $units;
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getAccuracy()
|
||||
{
|
||||
return $this->accuracy;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $accuracy
|
||||
* @return Place
|
||||
*/
|
||||
public function setAccuracy($accuracy)
|
||||
{
|
||||
$this->accuracy = $accuracy;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getAltitude()
|
||||
{
|
||||
return $this->altitude;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $altitude
|
||||
* @return Place
|
||||
*/
|
||||
public function setAltitude($altitude)
|
||||
{
|
||||
$this->altitude = $altitude;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getLatitude()
|
||||
{
|
||||
return $this->latitude;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $latitude
|
||||
* @return Place
|
||||
*/
|
||||
public function setLatitude($latitude)
|
||||
{
|
||||
$this->latitude = $latitude;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getLongitude()
|
||||
{
|
||||
return $this->longitude;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $longitude
|
||||
* @return Place
|
||||
*/
|
||||
public function setLongitude($longitude)
|
||||
{
|
||||
$this->longitude = $longitude;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getRadius()
|
||||
{
|
||||
return $this->radius;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $radius
|
||||
* @return Place
|
||||
*/
|
||||
public function setRadius($radius)
|
||||
{
|
||||
$this->radius = $radius;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getUnits()
|
||||
{
|
||||
return $this->units;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $units
|
||||
* @return Place
|
||||
*/
|
||||
public function setUnits($units)
|
||||
{
|
||||
$this->units = $units;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
29
Zotlabs/ActivityStreams/Profile.php
Normal file
29
Zotlabs/ActivityStreams/Profile.php
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\ActivityStreams;
|
||||
|
||||
class Profile extends ASObject
|
||||
{
|
||||
|
||||
public $describes;
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getDescribes()
|
||||
{
|
||||
return $this->describes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $describes
|
||||
* @return Profile
|
||||
*/
|
||||
public function setDescribes($describes)
|
||||
{
|
||||
$this->describes = $describes;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
68
Zotlabs/ActivityStreams/PublicKey.php
Normal file
68
Zotlabs/ActivityStreams/PublicKey.php
Normal file
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\ActivityStreams;
|
||||
|
||||
class PublicKey extends ASObject
|
||||
{
|
||||
public $owner;
|
||||
public $signatureAlgorithm;
|
||||
public $publicKeyPem;
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getOwner()
|
||||
{
|
||||
return $this->owner;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $owner
|
||||
* @return PublicKey
|
||||
*/
|
||||
public function setOwner($owner)
|
||||
{
|
||||
$this->owner = $owner;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getSignatureAlgorithm()
|
||||
{
|
||||
return $this->signatureAlgorithm;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $signatureAlgorithm
|
||||
* @return PublicKey
|
||||
*/
|
||||
public function setSignatureAlgorithm($signatureAlgorithm)
|
||||
{
|
||||
$this->signatureAlgorithm = $signatureAlgorithm;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getPublicKeyPem()
|
||||
{
|
||||
return $this->publicKeyPem;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $publicKeyPem
|
||||
* @return PublicKey
|
||||
*/
|
||||
public function setPublicKeyPem($publicKeyPem)
|
||||
{
|
||||
$this->publicKeyPem = $publicKeyPem;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
67
Zotlabs/ActivityStreams/Question.php
Normal file
67
Zotlabs/ActivityStreams/Question.php
Normal file
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\ActivityStreams;
|
||||
|
||||
class Question extends ASObject
|
||||
{
|
||||
public $oneOf;
|
||||
public $anyOf;
|
||||
public $closed;
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getOneOf()
|
||||
{
|
||||
return $this->oneOf;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $oneOf
|
||||
* @return Question
|
||||
*/
|
||||
public function setOneOf($oneOf)
|
||||
{
|
||||
$this->oneOf = $oneOf;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getAnyOf()
|
||||
{
|
||||
return $this->anyOf;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $anyOf
|
||||
* @return Question
|
||||
*/
|
||||
public function setAnyOf($anyOf)
|
||||
{
|
||||
$this->anyOf = $anyOf;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getClosed()
|
||||
{
|
||||
return $this->closed;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $closed
|
||||
* @return Question
|
||||
*/
|
||||
public function setClosed($closed)
|
||||
{
|
||||
$this->closed = $closed;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
67
Zotlabs/ActivityStreams/Relationship.php
Normal file
67
Zotlabs/ActivityStreams/Relationship.php
Normal file
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\ActivityStreams;
|
||||
|
||||
class Relationship extends ASObject
|
||||
{
|
||||
public $subject;
|
||||
public $object;
|
||||
public $relationship;
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getSubject()
|
||||
{
|
||||
return $this->subject;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $subject
|
||||
* @return Relationship
|
||||
*/
|
||||
public function setSubject($subject)
|
||||
{
|
||||
$this->subject = $subject;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getObject()
|
||||
{
|
||||
return $this->object;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $object
|
||||
* @return Relationship
|
||||
*/
|
||||
public function setObject($object)
|
||||
{
|
||||
$this->object = $object;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getRelationship()
|
||||
{
|
||||
return $this->relationship;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $relationship
|
||||
* @return Relationship
|
||||
*/
|
||||
public function setRelationship($relationship)
|
||||
{
|
||||
$this->relationship = $relationship;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
65
Zotlabs/ActivityStreams/Signature.php
Normal file
65
Zotlabs/ActivityStreams/Signature.php
Normal file
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\ActivityStreams;
|
||||
|
||||
class Signature extends ASObject
|
||||
{
|
||||
public $nonce;
|
||||
public $creator;
|
||||
public $signatureValue;
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getCreator()
|
||||
{
|
||||
return $this->creator;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $creator
|
||||
* @return Signature
|
||||
*/
|
||||
public function setCreator($creator)
|
||||
{
|
||||
$this->creator = $creator;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getSignatureValue()
|
||||
{
|
||||
return $this->signatureValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $signatureValue
|
||||
* @return Signature
|
||||
*/
|
||||
public function setSignatureValue($signatureValue)
|
||||
{
|
||||
$this->signatureValue = $signatureValue;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getNonce()
|
||||
{
|
||||
return $this->nonce;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $nonce
|
||||
* @return Signature
|
||||
*/
|
||||
public function setNonce($nonce)
|
||||
{
|
||||
$this->nonce = $nonce;
|
||||
return $this;
|
||||
}
|
||||
|
||||
}
|
||||
48
Zotlabs/ActivityStreams/Tombstone.php
Normal file
48
Zotlabs/ActivityStreams/Tombstone.php
Normal file
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\ActivityStreams;
|
||||
|
||||
class Tombstone extends ASObject
|
||||
{
|
||||
public $formerType;
|
||||
public $deleted;
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getFormerType()
|
||||
{
|
||||
return $this->formerType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $formerType
|
||||
* @return Tombstone
|
||||
*/
|
||||
public function setFormerType($formerType)
|
||||
{
|
||||
$this->formerType = $formerType;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getDeleted()
|
||||
{
|
||||
return $this->deleted;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $deleted
|
||||
* @return Tombstone
|
||||
*/
|
||||
public function setDeleted($deleted)
|
||||
{
|
||||
$this->deleted = $deleted;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
8
Zotlabs/ActivityStreams/UnhandledElementException.php
Normal file
8
Zotlabs/ActivityStreams/UnhandledElementException.php
Normal file
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\ActivityStreams;
|
||||
|
||||
class UnhandledElementException extends \Exception
|
||||
{
|
||||
|
||||
}
|
||||
@@ -7,6 +7,7 @@ class Addon {
|
||||
static public function run($argc, $argv) {
|
||||
|
||||
call_hooks('daemon_addon', $argv);
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -19,8 +19,10 @@ class Cache_embeds {
|
||||
$item = $c[0];
|
||||
|
||||
// bbcode conversion by default processes embeds that aren't already cached.
|
||||
// Ignore the returned html output.
|
||||
// Ignore the returned html output.
|
||||
|
||||
bbcode($item['body']);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace Zotlabs\Daemon;
|
||||
|
||||
use Zotlabs\Lib\Cache;
|
||||
use Zotlabs\Lib\Config;
|
||||
|
||||
class Cache_query {
|
||||
|
||||
@@ -11,26 +12,31 @@ class Cache_query {
|
||||
if(! $argc == 3)
|
||||
return;
|
||||
|
||||
$r = null;
|
||||
$key = $argv[1];
|
||||
|
||||
$pid = get_config('procid', $key, false);
|
||||
$pid = Config::Get('procid', $key, false);
|
||||
if ($pid && (function_exists('posix_kill') ? posix_kill($pid, 0) : true)) {
|
||||
logger($key . ': procedure already run with pid ' . $pid, LOGGER_DEBUG);
|
||||
return;
|
||||
}
|
||||
|
||||
$pid = getmypid();
|
||||
set_config('procid', $key, $pid);
|
||||
Config::Set('procid', $key, $pid);
|
||||
|
||||
array_shift($argv);
|
||||
array_shift($argv);
|
||||
|
||||
|
||||
$arr = json_decode(base64_decode($argv[0]), true);
|
||||
|
||||
$r = call_user_func_array('q', $arr);
|
||||
if($r)
|
||||
Cache::set($key, serialize($r));
|
||||
|
||||
del_config('procid', $key);
|
||||
if(is_array($r)) {
|
||||
Cache::set($key, serialize($r));
|
||||
}
|
||||
|
||||
Config::Delete('procid', $key);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
34
Zotlabs/Daemon/Channel_purge.php
Normal file
34
Zotlabs/Daemon/Channel_purge.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Daemon;
|
||||
|
||||
class Channel_purge {
|
||||
|
||||
static public function run($argc,$argv) {
|
||||
|
||||
cli_startup();
|
||||
|
||||
$channel_id = intval($argv[1]);
|
||||
|
||||
$channel = q("select * from channel where channel_id = %d and channel_removed = 1",
|
||||
intval($channel_id)
|
||||
);
|
||||
|
||||
if (! $channel) {
|
||||
return;
|
||||
}
|
||||
|
||||
do {
|
||||
$r = q("select id from item where uid = %d and item_deleted = 0 limit 1000",
|
||||
intval($channel_id)
|
||||
);
|
||||
if ($r) {
|
||||
foreach ($r as $rv) {
|
||||
drop_item($rv['id'], uid: $channel_id);
|
||||
}
|
||||
}
|
||||
} while ($r);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
namespace Zotlabs\Daemon;
|
||||
|
||||
use Zotlabs\Lib\Config;
|
||||
|
||||
require_once('include/hubloc.php');
|
||||
|
||||
class Checksites {
|
||||
@@ -10,13 +12,16 @@ class Checksites {
|
||||
|
||||
logger('checksites: start');
|
||||
|
||||
$site_id = '';
|
||||
$sql_options = '';
|
||||
|
||||
if (($argc > 1) && ($argv[1]))
|
||||
$site_id = $argv[1];
|
||||
|
||||
if ($site_id)
|
||||
$sql_options = " and site_url = '" . dbesc($argv[1]) . "' ";
|
||||
|
||||
$days = intval(get_config('system', 'sitecheckdays'));
|
||||
$days = intval(Config::Get('system', 'sitecheckdays'));
|
||||
if ($days < 1)
|
||||
$days = 30;
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ class Cli_suggest {
|
||||
static public function run($argc,$argv) {
|
||||
|
||||
update_suggestions();
|
||||
return;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
83
Zotlabs/Daemon/Content_importer.php
Normal file
83
Zotlabs/Daemon/Content_importer.php
Normal file
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Daemon;
|
||||
|
||||
use Zotlabs\Web\HTTPSig;
|
||||
use Zotlabs\Lib\PConfig;
|
||||
|
||||
|
||||
require_once('include/cli_startup.php');
|
||||
require_once('include/attach.php');
|
||||
require_once('include/import.php');
|
||||
|
||||
class Content_importer {
|
||||
|
||||
static public function run($argc,$argv) {
|
||||
cli_startup();
|
||||
|
||||
$page = $argv[1];
|
||||
$since = $argv[2];
|
||||
$until = $argv[3];
|
||||
$channel_address = $argv[4];
|
||||
$hz_server = urldecode($argv[5]);
|
||||
|
||||
$m = parse_url($hz_server);
|
||||
|
||||
$channel = channelx_by_nick($channel_address);
|
||||
if(! $channel) {
|
||||
logger('channel not found');
|
||||
return;
|
||||
}
|
||||
|
||||
$headers = [
|
||||
'X-API-Token' => random_string(),
|
||||
'X-API-Request' => $hz_server . '/api/z/1.0/item/export_page?f=&since=' . urlencode($since) . '&until=' . urlencode($until) . '&page=' . $page ,
|
||||
'Host' => $m['host'],
|
||||
'(request-target)' => 'get /api/z/1.0/item/export_page?f=&since=' . urlencode($since) . '&until=' . urlencode($until) . '&page=' . $page ,
|
||||
];
|
||||
|
||||
$headers = HTTPSig::create_sig($headers,$channel['channel_prvkey'], channel_url($channel),true,'sha512');
|
||||
|
||||
$redirects = 0;
|
||||
$x = z_fetch_url(
|
||||
$hz_server . '/api/z/1.0/item/export_page?f=&since=' . urlencode($since) . '&until=' . urlencode($until) . '&page=' . $page,
|
||||
false,
|
||||
$redirects,
|
||||
[ 'headers' => $headers ]
|
||||
);
|
||||
|
||||
// logger('item fetch: ' . print_r($x,true));
|
||||
|
||||
if(! $x['success']) {
|
||||
logger('no API response',LOGGER_DEBUG);
|
||||
killme();
|
||||
}
|
||||
|
||||
$j = json_decode($x['body'], true);
|
||||
|
||||
if($j && empty($j['item'])) {
|
||||
PConfig::Set($channel['channel_id'], 'import', 'content_completed', 1);
|
||||
return;
|
||||
}
|
||||
|
||||
$saved_notification_flags = notifications_off($channel['channel_id']);
|
||||
|
||||
import_items($channel,$j['item'],false,((array_key_exists('relocate',$j)) ? $j['relocate'] : null));
|
||||
|
||||
notifications_on($channel['channel_id'], $saved_notification_flags);
|
||||
|
||||
PConfig::Set($channel['channel_id'], 'import', 'content_progress', [
|
||||
'items_total' => $j['items_total'],
|
||||
'items_page' => $j['items_page'],
|
||||
'items_current_page' => count($j['item']),
|
||||
'last_page' => $page,
|
||||
'next_cmd' => ['Content_importer', sprintf('%d',$page + 1), $since, $until, $channel['channel_address'], urlencode($hz_server)]
|
||||
]);
|
||||
|
||||
$page++;
|
||||
|
||||
Master::Summon([ 'Content_importer', sprintf('%d',$page), $since, $until, $channel['channel_address'], urlencode($hz_server) ]);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -30,6 +30,7 @@ class Convo {
|
||||
intval($channel_id),
|
||||
dbesc($contact_hash)
|
||||
);
|
||||
|
||||
if (!$r) {
|
||||
return;
|
||||
}
|
||||
@@ -40,19 +41,26 @@ class Convo {
|
||||
|
||||
$messages = $obj->get();
|
||||
|
||||
if ($messages) {
|
||||
foreach ($messages as $message) {
|
||||
if (is_string($message)) {
|
||||
$message = Activity::fetch($message, $channel);
|
||||
}
|
||||
// set client flag because comments will probably just be objects and not full blown activities
|
||||
// and that lets us use implied_create
|
||||
$AS = new ActivityStreams($message);
|
||||
if ($AS->is_valid() && is_array($AS->obj)) {
|
||||
$item = Activity::decode_note($AS);
|
||||
Activity::store($channel, $contact['abook_xchan'], $AS, $item);
|
||||
}
|
||||
if (!$messages) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($messages as $message) {
|
||||
if (is_string($message)) {
|
||||
$message = Activity::fetch($message, $channel);
|
||||
}
|
||||
|
||||
// set client flag because comments will probably just be objects and not full blown activities
|
||||
// and that lets us use implied_create
|
||||
$AS = new ActivityStreams($message);
|
||||
if ($AS->is_valid() && is_array($AS->obj)) {
|
||||
$item = Activity::decode_note($AS);
|
||||
$item['item_fetched'] = true;
|
||||
Activity::store($channel, $contact['abook_xchan'], $AS, $item);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,13 +2,15 @@
|
||||
|
||||
namespace Zotlabs\Daemon;
|
||||
|
||||
use Zotlabs\Lib\Config;
|
||||
use Zotlabs\Lib\Libsync;
|
||||
use Zotlabs\Lib\Libzotdir;
|
||||
|
||||
class Cron {
|
||||
|
||||
static public function run($argc, $argv) {
|
||||
|
||||
$maxsysload = intval(get_config('system', 'maxloadavg'));
|
||||
$maxsysload = intval(Config::Get('system', 'maxloadavg'));
|
||||
if ($maxsysload < 1)
|
||||
$maxsysload = 50;
|
||||
if (function_exists('sys_getloadavg')) {
|
||||
@@ -19,10 +21,11 @@ class Cron {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
// Check for a lockfile. If it exists, but is over an hour old, it's stale. Ignore it.
|
||||
$lockfile = 'store/[data]/cron';
|
||||
if ((file_exists($lockfile)) && (filemtime($lockfile) > (time() - 3600))
|
||||
&& (!get_config('system', 'override_cron_lockfile'))) {
|
||||
&& (!Config::Get('system', 'override_cron_lockfile'))) {
|
||||
logger("cron: Already running");
|
||||
return;
|
||||
}
|
||||
@@ -30,13 +33,24 @@ class Cron {
|
||||
// Create a lockfile. Needs two vars, but $x doesn't need to contain anything.
|
||||
$x = '';
|
||||
file_put_contents($lockfile, $x);
|
||||
*/
|
||||
|
||||
logger('cron: start');
|
||||
|
||||
// If this is a directory server, request a sync with an upstream
|
||||
// directory at least once a day, up to once every poll interval.
|
||||
// Pull remote changes and push local changes.
|
||||
// potential issue: how do we keep from creating an endless update loop?
|
||||
|
||||
$dirmode = Config::Get('system', 'directory_mode');
|
||||
|
||||
if ($dirmode == DIRECTORY_MODE_SECONDARY || $dirmode == DIRECTORY_MODE_PRIMARY) {
|
||||
Libzotdir::sync_directories($dirmode);
|
||||
}
|
||||
|
||||
// run queue delivery process in the background
|
||||
|
||||
Master::Summon(array('Queue'));
|
||||
|
||||
Master::Summon(array('Poller'));
|
||||
|
||||
/**
|
||||
@@ -51,23 +65,25 @@ class Cron {
|
||||
require_once('include/account.php');
|
||||
remove_expired_registrations();
|
||||
|
||||
$interval = get_config('system', 'delivery_interval', 3);
|
||||
$interval = Config::Get('queueworker', 'queue_interval', 500000);
|
||||
|
||||
// expire any expired items
|
||||
|
||||
$r = q("select id,item_wall from item where expires > '2001-01-01 00:00:00' and expires < %s
|
||||
$r = q("select id, uid, item_wall from item where expires > '2001-01-01 00:00:00' and expires < %s
|
||||
and item_deleted = 0 ",
|
||||
db_utcnow()
|
||||
);
|
||||
|
||||
if ($r) {
|
||||
require_once('include/items.php');
|
||||
foreach ($r as $rr) {
|
||||
drop_item($rr['id'], false, (($rr['item_wall']) ? DROPITEM_PHASE1 : DROPITEM_NORMAL));
|
||||
// pass uid of the message for permission check as we are running as a daemon process with no session.
|
||||
drop_item($rr['id'], (($rr['item_wall']) ? DROPITEM_PHASE1 : DROPITEM_NORMAL), uid: intval($rr['uid']));
|
||||
if ($rr['item_wall']) {
|
||||
// The notifier isn't normally invoked unless item_drop is interactive.
|
||||
Master::Summon(['Notifier', 'drop', $rr['id']]);
|
||||
if ($interval)
|
||||
@time_sleep_until(microtime(true) + (float)$interval);
|
||||
if ($interval) {
|
||||
usleep($interval);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -97,8 +113,10 @@ class Cron {
|
||||
if ($r) {
|
||||
foreach ($r as $rr) {
|
||||
Master::Summon(array('Directory', $rr['channel_id'], 'force'));
|
||||
if ($interval)
|
||||
@time_sleep_until(microtime(true) + (float)$interval);
|
||||
|
||||
if ($interval) {
|
||||
usleep($interval);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,13 +125,13 @@ class Cron {
|
||||
$r = q("SELECT DISTINCT xchan, content FROM photo WHERE photo_usage = %d AND expires < %s - INTERVAL %s",
|
||||
intval(PHOTO_CACHE),
|
||||
db_utcnow(),
|
||||
db_quoteinterval(get_config('system', 'active_expire_days', '30') . ' DAY')
|
||||
db_quoteinterval(Config::Get('system', 'cache_expire_days', 7) . ' DAY')
|
||||
);
|
||||
if ($r) {
|
||||
q("DELETE FROM photo WHERE photo_usage = %d AND expires < %s - INTERVAL %s",
|
||||
intval(PHOTO_CACHE),
|
||||
db_utcnow(),
|
||||
db_quoteinterval(get_config('system', 'active_expire_days', '30') . ' DAY')
|
||||
db_quoteinterval(Config::Get('system', 'cache_expire_days', 7) . ' DAY')
|
||||
);
|
||||
foreach ($r as $rr) {
|
||||
$file = dbunescbin($rr['content']);
|
||||
@@ -129,50 +147,41 @@ class Cron {
|
||||
// (time travel posts). Restrict to items that have come of age in the last
|
||||
// couple of days to limit the query to something reasonable.
|
||||
|
||||
$r = q("select id from item where item_delayed = 1 and created <= %s and created > '%s' ",
|
||||
$r = q("select * from item where item_delayed = 1 and created <= %s and created > '%s' ",
|
||||
db_utcnow(),
|
||||
dbesc(datetime_convert('UTC', 'UTC', 'now - 2 days'))
|
||||
);
|
||||
|
||||
if ($r) {
|
||||
foreach ($r as $rr) {
|
||||
$x = q("update item set item_delayed = 0 where id = %d",
|
||||
intval($rr['id'])
|
||||
);
|
||||
if ($x) {
|
||||
$z = q("select * from item where id = %d",
|
||||
intval($rr['id'])
|
||||
);
|
||||
if ($z) {
|
||||
xchan_query($z);
|
||||
$sync_item = fetch_post_tags($z);
|
||||
Libsync::build_sync_packet($sync_item[0]['uid'],
|
||||
[
|
||||
'item' => [encode_item($sync_item[0], true)]
|
||||
]
|
||||
);
|
||||
xchan_query($r);
|
||||
$items = fetch_post_tags($r);
|
||||
foreach ($items as $item) {
|
||||
$item['item_delayed'] = 0;
|
||||
$post = item_store_update($item);
|
||||
|
||||
if($post['success']) {
|
||||
Master::Summon(['Notifier', 'wall-new', $post['item_id']]);
|
||||
if (!empty($post['approval_id'])) {
|
||||
Master::Summon(['Notifier', 'wall-new', $post['approval_id']]);
|
||||
}
|
||||
Master::Summon(array('Notifier', 'wall-new', $rr['id']));
|
||||
if ($interval)
|
||||
@time_sleep_until(microtime(true) + (float)$interval);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
require_once('include/attach.php');
|
||||
attach_upgrade();
|
||||
|
||||
if ($interval) {
|
||||
usleep($interval);
|
||||
}
|
||||
}
|
||||
}
|
||||
// once daily run birthday_updates and then expire in background
|
||||
|
||||
// FIXME: add birthday updates, both locally and for xprof for use
|
||||
// by directory servers
|
||||
|
||||
$d1 = intval(get_config('system', 'last_expire_day'));
|
||||
$d1 = intval(Config::Get('system', 'last_expire_day'));
|
||||
$d2 = intval(datetime_convert('UTC', 'UTC', 'now', 'd'));
|
||||
|
||||
// Allow somebody to staggger daily activities if they have more than one site on their server,
|
||||
// or if it happens at an inconvenient (busy) hour.
|
||||
|
||||
$h1 = intval(get_config('system', 'cron_hour'));
|
||||
$h1 = intval(Config::Get('system', 'cron_hour'));
|
||||
$h2 = intval(datetime_convert('UTC', 'UTC', 'now', 'G'));
|
||||
|
||||
|
||||
@@ -204,12 +213,11 @@ class Cron {
|
||||
}
|
||||
|
||||
|
||||
// pull in some public posts
|
||||
// pull in some public posts if allowed
|
||||
|
||||
/* $disable_discover_tab = get_config('system', 'disable_discover_tab') || get_config('system', 'disable_discover_tab') === false;
|
||||
if (!$disable_discover_tab)
|
||||
Master::Summon(array('Externals'));
|
||||
*/
|
||||
$disable_externals = Config::Get('system', 'disable_discover_tab') || Config::Get('system', 'disable_discover_tab') === false || Config::Get('system', 'site_firehose');
|
||||
if (!$disable_externals)
|
||||
Master::Summon(['Externals']);
|
||||
|
||||
$restart = false;
|
||||
|
||||
@@ -227,10 +235,10 @@ class Cron {
|
||||
if (!$restart)
|
||||
Master::Summon(array('Cronhooks'));
|
||||
|
||||
set_config('system', 'lastcron', datetime_convert());
|
||||
Config::Set('system', 'lastcron', datetime_convert());
|
||||
|
||||
//All done - clear the lockfile
|
||||
@unlink($lockfile);
|
||||
//@unlink($lockfile);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace Zotlabs\Daemon;
|
||||
|
||||
use Zotlabs\Lib\Config;
|
||||
use Zotlabs\Lib\Libzotdir;
|
||||
|
||||
class Cron_daily {
|
||||
@@ -49,10 +50,26 @@ class Cron_daily {
|
||||
dbesc('sse_id.%')
|
||||
);
|
||||
|
||||
// Clean up emdedded content cache
|
||||
// Mark items seen after X days (default 90)
|
||||
|
||||
$r = dbq("select channel_id from channel where channel_removed = 0");
|
||||
if ($r) {
|
||||
foreach ($r as $rr) {
|
||||
$mark_seen_days = get_pconfig($rr['channel_id'], 'system', 'mark_seen_days', 90);
|
||||
q("UPDATE item SET item_unseen = 0 WHERE
|
||||
uid = %d AND item_unseen = 1
|
||||
AND created < %s - INTERVAL %s",
|
||||
intval($rr['channel_id']),
|
||||
db_utcnow(),
|
||||
db_quoteinterval($mark_seen_days . ' DAY')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up cache
|
||||
q("DELETE FROM cache WHERE updated < %s - INTERVAL %s",
|
||||
db_utcnow(),
|
||||
db_quoteinterval(get_config('system', 'active_expire_days', '30') . ' DAY')
|
||||
db_quoteinterval(Config::Get('system', 'cache_expire_days', 7) . ' DAY')
|
||||
);
|
||||
|
||||
//update statistics in config
|
||||
@@ -66,7 +83,7 @@ class Cron_daily {
|
||||
|
||||
// expire old delivery reports
|
||||
|
||||
$keep_reports = intval(get_config('system', 'expire_delivery_reports'));
|
||||
$keep_reports = intval(Config::Get('system', 'expire_delivery_reports'));
|
||||
if ($keep_reports === 0)
|
||||
$keep_reports = 10;
|
||||
|
||||
@@ -78,17 +95,6 @@ class Cron_daily {
|
||||
// expire any expired accounts
|
||||
downgrade_accounts();
|
||||
|
||||
// If this is a directory server, request a sync with an upstream
|
||||
// directory at least once a day, up to once every poll interval.
|
||||
// Pull remote changes and push local changes.
|
||||
// potential issue: how do we keep from creating an endless update loop?
|
||||
|
||||
$dirmode = get_config('system', 'directory_mode');
|
||||
|
||||
if ($dirmode == DIRECTORY_MODE_SECONDARY || $dirmode == DIRECTORY_MODE_PRIMARY) {
|
||||
Libzotdir::sync_directories($dirmode);
|
||||
}
|
||||
|
||||
Master::Summon(array('Expire'));
|
||||
Master::Summon(array('Cli_suggest'));
|
||||
|
||||
@@ -98,10 +104,12 @@ class Cron_daily {
|
||||
$date = datetime_convert();
|
||||
call_hooks('cron_daily', $date);
|
||||
|
||||
set_config('system', 'last_expire_day', intval(datetime_convert('UTC', 'UTC', 'now', 'd')));
|
||||
Config::Set('system', 'last_expire_day', intval(datetime_convert('UTC', 'UTC', 'now', 'd')));
|
||||
|
||||
/**
|
||||
* End Cron Daily
|
||||
*/
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
namespace Zotlabs\Daemon;
|
||||
|
||||
use Zotlabs\Lib\Config;
|
||||
|
||||
class Cron_weekly {
|
||||
|
||||
static public function run($argc, $argv) {
|
||||
@@ -22,12 +24,12 @@ class Cron_weekly {
|
||||
|
||||
mark_orphan_hubsxchans();
|
||||
|
||||
// Find channels that were removed in the last three weeks, but
|
||||
// Find channels that were removed in the last three weeks, but
|
||||
// haven't been finally cleaned up. These should be older than 10
|
||||
// days to ensure that "purgeall" messages have gone out or bounced
|
||||
// or timed out.
|
||||
// days to ensure that "purgeall" messages have gone out or bounced
|
||||
// or timed out.
|
||||
|
||||
$r = q("select channel_id from channel where channel_removed = 1 and
|
||||
$r = q("select channel_id from channel where channel_removed = 1 and
|
||||
channel_deleted > %s - INTERVAL %s and channel_deleted < %s - INTERVAL %s",
|
||||
db_utcnow(), db_quoteinterval('21 DAY'),
|
||||
db_utcnow(), db_quoteinterval('10 DAY')
|
||||
@@ -44,7 +46,7 @@ class Cron_weekly {
|
||||
db_utcnow(), db_quoteinterval('14 DAY')
|
||||
);
|
||||
|
||||
$dirmode = intval(get_config('system', 'directory_mode'));
|
||||
$dirmode = intval(Config::Get('system', 'directory_mode'));
|
||||
if ($dirmode === DIRECTORY_MODE_SECONDARY || $dirmode === DIRECTORY_MODE_PRIMARY) {
|
||||
logger('regdir: ' . print_r(z_fetch_url(get_directory_primary() . '/regdir?f=&url=' . urlencode(z_root()) . '&realm=' . urlencode(get_directory_realm())), true));
|
||||
}
|
||||
@@ -59,5 +61,6 @@ class Cron_weekly {
|
||||
* End Cron Weekly
|
||||
*/
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,8 @@ class Deliver {
|
||||
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -12,8 +12,12 @@ class Deliver_hooks {
|
||||
$r = q("select * from item where id = '%d'",
|
||||
intval($argv[1])
|
||||
);
|
||||
if ($r)
|
||||
|
||||
if ($r) {
|
||||
call_hooks('notifier_normal', $r[0]);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
25
Zotlabs/Daemon/Delxitems.php
Normal file
25
Zotlabs/Daemon/Delxitems.php
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Daemon;
|
||||
|
||||
require_once('include/connections.php');
|
||||
|
||||
/*
|
||||
* Daemon to remove 'item' resources in the background from a removed connection
|
||||
*/
|
||||
|
||||
class Delxitems {
|
||||
|
||||
static public function run($argc, $argv) {
|
||||
|
||||
cli_startup();
|
||||
|
||||
if($argc != 3) {
|
||||
return;
|
||||
}
|
||||
|
||||
remove_abook_items($argv[1], $argv[2]);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace Zotlabs\Daemon;
|
||||
|
||||
use Zotlabs\Lib\Config;
|
||||
use Zotlabs\Lib\Libzot;
|
||||
use Zotlabs\Lib\Libzotdir;
|
||||
use Zotlabs\Lib\Queue;
|
||||
@@ -25,7 +26,7 @@ class Directory {
|
||||
|
||||
logger('directory update', LOGGER_DEBUG);
|
||||
|
||||
$dirmode = get_config('system', 'directory_mode');
|
||||
$dirmode = Config::Get('system', 'directory_mode');
|
||||
if ($dirmode === false)
|
||||
$dirmode = DIRECTORY_MODE_NORMAL;
|
||||
|
||||
@@ -49,8 +50,9 @@ class Directory {
|
||||
);
|
||||
|
||||
// Now update all the connections
|
||||
if ($pushall)
|
||||
if ($pushall) {
|
||||
Master::Summon(array('Notifier', 'refresh_all', $channel['channel_id']));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -93,8 +95,10 @@ class Directory {
|
||||
}
|
||||
|
||||
// Now update all the connections
|
||||
if ($pushall)
|
||||
if ($pushall) {
|
||||
Master::Summon(array('Notifier', 'refresh_all', $channel['channel_id']));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
namespace Zotlabs\Daemon;
|
||||
|
||||
use Zotlabs\Lib\Config;
|
||||
|
||||
require_once('include/items.php');
|
||||
|
||||
class Expire {
|
||||
@@ -10,42 +12,41 @@ class Expire {
|
||||
|
||||
cli_startup();
|
||||
|
||||
$pid = get_config('procid', 'expire', false);
|
||||
$pid = Config::Get('procid', 'expire', false);
|
||||
if ($pid && (function_exists('posix_kill') ? posix_kill($pid, 0) : true)) {
|
||||
logger('procedure already run with pid ' . $pid, LOGGER_DEBUG);
|
||||
return;
|
||||
}
|
||||
|
||||
$pid = getmypid();
|
||||
set_config('procid', 'expire', $pid);
|
||||
Config::Set('procid', 'expire', $pid);
|
||||
|
||||
// perform final cleanup on previously delete items
|
||||
|
||||
$r = q("select id from item where item_deleted = 1 and item_pending_remove = 0 and changed < %s - INTERVAL %s",
|
||||
$r = q("select id, uid from item where item_deleted = 1 and item_pending_remove = 0 and changed < %s - INTERVAL %s",
|
||||
db_utcnow(),
|
||||
db_quoteinterval('10 DAY')
|
||||
);
|
||||
if ($r) {
|
||||
foreach ($r as $rr) {
|
||||
drop_item($rr['id'], false, DROPITEM_PHASE2);
|
||||
drop_item($rr['id'], DROPITEM_PHASE2, uid: $rr['uid']);
|
||||
}
|
||||
}
|
||||
|
||||
// physically remove anything that has been deleted for more than two months
|
||||
/** @FIXME - this is a wretchedly inefficient query */
|
||||
|
||||
q("delete from item where item_pending_remove = 1 and changed < %s - INTERVAL %s",
|
||||
db_utcnow(),
|
||||
db_quoteinterval('36 DAY')
|
||||
);
|
||||
|
||||
if (intval(get_config('system', 'optimize_items')))
|
||||
if (intval(Config::Get('system', 'optimize_items')))
|
||||
q("optimize table item");
|
||||
|
||||
logger('expire: start with pid ' . $pid, LOGGER_DEBUG);
|
||||
|
||||
$site_expire = intval(get_config('system', 'default_expire_days'));
|
||||
$commented_days = intval(get_config('system', 'active_expire_days'));
|
||||
$site_expire = intval(Config::Get('system', 'default_expire_days', 30));
|
||||
$commented_days = intval(Config::Get('system', 'active_expire_days', 7));
|
||||
|
||||
logger('site_expire: ' . $site_expire);
|
||||
|
||||
@@ -59,8 +60,8 @@ class Expire {
|
||||
continue;
|
||||
|
||||
// service class default (if non-zero) over-rides the site default
|
||||
|
||||
$service_class_expire = service_class_fetch($rr['channel_id'], 'expire_days');
|
||||
|
||||
if (intval($service_class_expire))
|
||||
$channel_expire = $service_class_expire;
|
||||
else
|
||||
@@ -85,8 +86,7 @@ class Expire {
|
||||
|
||||
// this should probably just fetch the channel_expire_days from the sys channel,
|
||||
// but there's no convenient way to set it.
|
||||
|
||||
$expire_days = get_config('system', 'sys_expire_days');
|
||||
$expire_days = Config::Get('system', 'sys_expire_days');
|
||||
if ($expire_days === false)
|
||||
$expire_days = 30;
|
||||
|
||||
@@ -96,12 +96,15 @@ class Expire {
|
||||
|
||||
logger('Expire: sys interval: ' . $expire_days, LOGGER_DEBUG);
|
||||
|
||||
if ($expire_days)
|
||||
if ($expire_days) {
|
||||
item_expire($x['channel_id'], $expire_days, $commented_days);
|
||||
}
|
||||
|
||||
logger('Expire: sys: done', LOGGER_DEBUG);
|
||||
}
|
||||
|
||||
del_config('procid', 'expire');
|
||||
Config::Delete('procid', 'expire');
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace Zotlabs\Daemon;
|
||||
|
||||
use Zotlabs\Lib\Activity;
|
||||
use Zotlabs\Lib\Libzot;
|
||||
use Zotlabs\Lib\ActivityStreams;
|
||||
use Zotlabs\Lib\ASCollection;
|
||||
|
||||
@@ -18,6 +19,7 @@ class Externals {
|
||||
$importer = get_sys_channel();
|
||||
$total = 0;
|
||||
$attempts = 0;
|
||||
$url = '';
|
||||
|
||||
logger('externals: startup', LOGGER_DEBUG);
|
||||
|
||||
@@ -31,25 +33,54 @@ class Externals {
|
||||
$url = $arr['url'];
|
||||
}
|
||||
else {
|
||||
$networks = ['zot6'];
|
||||
|
||||
if (plugin_is_installed('pubcrawl')) {
|
||||
$networks[] = 'activitypub';
|
||||
}
|
||||
|
||||
stringify_array_elms($networks);
|
||||
$networks_str = implode(',', $networks);
|
||||
|
||||
$randfunc = db_getfunc('RAND');
|
||||
|
||||
// fixme this query does not deal with directory realms.
|
||||
//$r = q("select site_url, site_pull from site where site_url != '%s'
|
||||
//and site_flags != %d and site_type = %d
|
||||
//and site_dead = 0 and site_project like '%s' and site_version > '5.3.1' order by $randfunc limit 1",
|
||||
//dbesc(z_root()),
|
||||
//intval(DIRECTORY_MODE_STANDALONE),
|
||||
//intval(SITE_TYPE_ZOT),
|
||||
//dbesc('hubzilla%')
|
||||
//);
|
||||
|
||||
$r = q("select site_url, site_pull from site where site_url != '%s'
|
||||
and site_flags != %d and site_type = %d
|
||||
and site_dead = 0 and site_project like '%s' and site_version > '5.3.1' order by $randfunc limit 1",
|
||||
$r = q("SELECT * FROM hubloc
|
||||
LEFT JOIN abook ON abook_xchan = hubloc_hash
|
||||
LEFT JOIN site ON site_url = hubloc_url WHERE
|
||||
hubloc_network IN ( $networks_str ) AND
|
||||
abook_xchan IS NULL AND
|
||||
hubloc_url != '%s' AND
|
||||
hubloc_updated > '%s' AND
|
||||
hubloc_primary = 1 AND hubloc_deleted = 0 AND
|
||||
site_dead = 0
|
||||
ORDER BY $randfunc LIMIT 1",
|
||||
dbesc(z_root()),
|
||||
intval(DIRECTORY_MODE_STANDALONE),
|
||||
intval(SITE_TYPE_ZOT),
|
||||
dbesc('hubzilla%')
|
||||
datetime_convert('UTC', 'UTC', 'now - 30 days')
|
||||
);
|
||||
if ($r)
|
||||
$url = $r[0]['site_url'];
|
||||
|
||||
if ($r) {
|
||||
$contact = $r[0];
|
||||
$url = $contact['hubloc_id_url'];
|
||||
}
|
||||
}
|
||||
|
||||
if (!$url) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$blacklisted = false;
|
||||
|
||||
if (!check_siteallowed($url)) {
|
||||
if (!check_siteallowed($contact['hubloc_url'])) {
|
||||
logger('blacklisted site: ' . $url);
|
||||
$blacklisted = true;
|
||||
}
|
||||
@@ -59,123 +90,68 @@ class Externals {
|
||||
// make sure we can eventually break out if somebody blacklists all known sites
|
||||
|
||||
if ($blacklisted) {
|
||||
if ($attempts > 20)
|
||||
if ($attempts > 5)
|
||||
break;
|
||||
$attempts--;
|
||||
continue;
|
||||
}
|
||||
|
||||
$cl = Activity::get_actor_collections($contact['hubloc_hash']);
|
||||
if(empty($cl)) {
|
||||
$cl = get_xconfig($contact['hubloc_hash'], 'activitypub', 'collections');
|
||||
}
|
||||
|
||||
if (is_array($cl) && array_key_exists('outbox', $cl)) {
|
||||
$url = $cl['outbox'];
|
||||
}
|
||||
else {
|
||||
$url = str_replace('/channel/', '/outbox/', $contact['hubloc_id_url']);
|
||||
if ($url) {
|
||||
$url .= '?top=1';
|
||||
}
|
||||
}
|
||||
|
||||
if ($url) {
|
||||
logger('fetching outbox: ' . $url);
|
||||
|
||||
$max = intval(get_config('system', 'max_imported_posts', 30));
|
||||
if (intval($max)) {
|
||||
logger('externals: fetching outbox');
|
||||
$obj = new ASCollection($url, $importer, 0, 10);
|
||||
$messages = $obj->get();
|
||||
|
||||
$feed_url = $url . '/zotfeed';
|
||||
$obj = new ASCollection($feed_url, $importer, 0, $max);
|
||||
$messages = $obj->get();
|
||||
if ($messages) {
|
||||
foreach ($messages as $message) {
|
||||
if (is_string($message)) {
|
||||
$message = Activity::fetch($message, $importer);
|
||||
}
|
||||
|
||||
if ($messages) {
|
||||
foreach ($messages as $message) {
|
||||
if (is_string($message)) {
|
||||
$message = Activity::fetch($message, $importer);
|
||||
}
|
||||
$AS = new ActivityStreams($message);
|
||||
if ($AS->is_valid() && is_array($AS->obj)) {
|
||||
$item = Activity::decode_note($AS);
|
||||
Activity::store($importer, $importer['xchan_hash'], $AS, $item, true);
|
||||
$total++;
|
||||
if ($message['type'] !== 'Create') {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($contact['hubloc_network'] === 'zot6') {
|
||||
// make sure we only fetch top level items
|
||||
if (isset($message['object']['inReplyTo'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$obj_id = $message['object']['id'] ?? $message['object'];
|
||||
|
||||
Libzot::fetch_conversation($importer, $obj_id);
|
||||
$total++;
|
||||
continue;
|
||||
}
|
||||
|
||||
$AS = new ActivityStreams($message);
|
||||
if ($AS->is_valid() && is_array($AS->obj)) {
|
||||
$item = Activity::decode_note($AS);
|
||||
$item['item_fetched'] = true;
|
||||
Activity::store($importer, $contact['hubloc_hash'], $AS, $item);
|
||||
$total++;
|
||||
}
|
||||
}
|
||||
logger('externals: import_public_posts: ' . $total . ' messages imported', LOGGER_DEBUG);
|
||||
}
|
||||
logger('fetched messages count: ' . $total);
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
||||
/* $total = 0;
|
||||
$attempts = 0;
|
||||
|
||||
logger('externals: startup', LOGGER_DEBUG);
|
||||
|
||||
// pull in some public posts
|
||||
|
||||
while ($total == 0 && $attempts < 3) {
|
||||
$arr = ['url' => ''];
|
||||
call_hooks('externals_url_select', $arr);
|
||||
|
||||
if ($arr['url']) {
|
||||
$url = $arr['url'];
|
||||
}
|
||||
else {
|
||||
$randfunc = db_getfunc('RAND');
|
||||
|
||||
// fixme this query does not deal with directory realms.
|
||||
|
||||
$r = q("select site_url, site_pull from site where site_url != '%s' and site_flags != %d and site_type = %d and site_dead = 0 order by $randfunc limit 1",
|
||||
dbesc(z_root()),
|
||||
intval(DIRECTORY_MODE_STANDALONE),
|
||||
intval(SITE_TYPE_ZOT)
|
||||
);
|
||||
if ($r)
|
||||
$url = $r[0]['site_url'];
|
||||
}
|
||||
|
||||
$blacklisted = false;
|
||||
|
||||
if (!check_siteallowed($url)) {
|
||||
logger('blacklisted site: ' . $url);
|
||||
$blacklisted = true;
|
||||
}
|
||||
|
||||
$attempts++;
|
||||
|
||||
// make sure we can eventually break out if somebody blacklists all known sites
|
||||
|
||||
if ($blacklisted) {
|
||||
if ($attempts > 20)
|
||||
break;
|
||||
$attempts--;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($url) {
|
||||
if ($r[0]['site_pull'] > NULL_DATE)
|
||||
$mindate = urlencode(datetime_convert('', '', $r[0]['site_pull'] . ' - 1 day'));
|
||||
else {
|
||||
$days = get_config('externals', 'since_days');
|
||||
if ($days === false)
|
||||
$days = 15;
|
||||
$mindate = urlencode(datetime_convert('', '', 'now - ' . intval($days) . ' days'));
|
||||
}
|
||||
|
||||
$feedurl = $url . '/zotfeed?f=&mindate=' . $mindate;
|
||||
|
||||
logger('externals: pulling public content from ' . $feedurl, LOGGER_DEBUG);
|
||||
|
||||
$x = z_fetch_url($feedurl);
|
||||
if (($x) && ($x['success'])) {
|
||||
|
||||
q("update site set site_pull = '%s' where site_url = '%s'",
|
||||
dbesc(datetime_convert()),
|
||||
dbesc($url)
|
||||
);
|
||||
|
||||
$j = json_decode($x['body'], true);
|
||||
if ($j['success'] && $j['messages']) {
|
||||
$sys = get_sys_channel();
|
||||
foreach ($j['messages'] as $message) {
|
||||
// on these posts, clear any route info.
|
||||
$message['route'] = '';
|
||||
process_delivery(['hash' => 'undefined'], get_item_elements($message),
|
||||
[['hash' => $sys['xchan_hash']]], false, true);
|
||||
$total++;
|
||||
}
|
||||
logger('externals: import_public_posts: ' . $total . ' messages imported', LOGGER_DEBUG);
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
42
Zotlabs/Daemon/Fetchparents.php
Normal file
42
Zotlabs/Daemon/Fetchparents.php
Normal file
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Daemon;
|
||||
|
||||
use Zotlabs\Lib\Activity;
|
||||
|
||||
class Fetchparents {
|
||||
|
||||
static public function run($argc, $argv) {
|
||||
|
||||
logger('Fetchparents invoked: ' . print_r($argv, true));
|
||||
|
||||
if ($argc < 4) {
|
||||
return;
|
||||
}
|
||||
|
||||
$channels = explode(',', $argv[1]);
|
||||
if (!$channels) {
|
||||
return;
|
||||
}
|
||||
|
||||
$observer_hash = $argv[2];
|
||||
if (!$observer_hash) {
|
||||
return;
|
||||
}
|
||||
|
||||
$mid = $argv[3];
|
||||
if (!$mid) {
|
||||
return;
|
||||
}
|
||||
|
||||
$force = $argv[4] ?? false;
|
||||
|
||||
foreach ($channels as $channel_id) {
|
||||
$channel = channelx_by_n($channel_id);
|
||||
Activity::fetch_and_store_parents($channel, $observer_hash, $mid, null, $force);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
}
|
||||
77
Zotlabs/Daemon/File_importer.php
Normal file
77
Zotlabs/Daemon/File_importer.php
Normal file
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Daemon;
|
||||
|
||||
use Zotlabs\Web\HTTPSig;
|
||||
use Zotlabs\Lib\PConfig;
|
||||
|
||||
|
||||
require_once('include/cli_startup.php');
|
||||
require_once('include/attach.php');
|
||||
require_once('include/import.php');
|
||||
|
||||
class File_importer {
|
||||
|
||||
static public function run($argc,$argv) {
|
||||
|
||||
cli_startup();
|
||||
|
||||
$page = $argv[1];
|
||||
$channel_address = $argv[2];
|
||||
$hz_server = urldecode($argv[3]);
|
||||
|
||||
$m = parse_url($hz_server);
|
||||
|
||||
$channel = channelx_by_nick($channel_address);
|
||||
if(! $channel) {
|
||||
logger('channel not found');
|
||||
return;
|
||||
}
|
||||
|
||||
$headers = [
|
||||
'X-API-Token' => random_string(),
|
||||
'X-API-Request' => $hz_server . '/api/z/1.0/file/export_page?f=records=1&page=' . $page,
|
||||
'Host' => $m['host'],
|
||||
'(request-target)' => 'get /api/z/1.0/file/export_page?f=records=1&page=' . $page,
|
||||
];
|
||||
|
||||
$headers = HTTPSig::create_sig($headers,$channel['channel_prvkey'],channel_url($channel),true,'sha512');
|
||||
|
||||
// TODO: implement total count
|
||||
$redirects = 0;
|
||||
$x = z_fetch_url(
|
||||
$hz_server . '/api/z/1.0/file/export_page?f=records=1&page=' . $page,
|
||||
false,
|
||||
$redirects,
|
||||
[ 'headers' => $headers ]
|
||||
);
|
||||
// logger('file fetch: ' . print_r($x,true));
|
||||
|
||||
if(! $x['success']) {
|
||||
logger('no API response',LOGGER_DEBUG);
|
||||
killme();
|
||||
}
|
||||
|
||||
$j = json_decode($x['body'],true);
|
||||
|
||||
if(! is_array($j['results'][0]['attach']) || ! count($j['results'][0]['attach'])) {
|
||||
PConfig::Set($channel['channel_id'], 'import', 'files_completed', 1);
|
||||
return;
|
||||
}
|
||||
|
||||
$r = sync_files($channel, $j['results']);
|
||||
|
||||
PConfig::Set($channel['channel_id'], 'import', 'files_progress', [
|
||||
'files_total' => $j['total'],
|
||||
'files_page' => 1, // export page atm returns just one file
|
||||
'last_page' => $page,
|
||||
'next_cmd' => ['File_importer',sprintf('%d',$page + 1), $channel['channel_address'], urlencode($hz_server)]
|
||||
]);
|
||||
|
||||
$page++;
|
||||
|
||||
Master::Summon([ 'File_importer',sprintf('%d',$page), $channel['channel_address'], urlencode($hz_server) ]);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -15,21 +15,32 @@ class Gprobe {
|
||||
return;
|
||||
|
||||
$url = hex2bin($argv[1]);
|
||||
$is_webbie = false;
|
||||
$r = null;
|
||||
|
||||
if (!strpos($url, '@'))
|
||||
return;
|
||||
if (filter_var($url, FILTER_VALIDATE_EMAIL)) {
|
||||
$is_webbie = true;
|
||||
|
||||
$r = q("select * from hubloc where hubloc_addr = '%s' and hubloc_network = 'zot6' limit 1",
|
||||
dbesc($url)
|
||||
);
|
||||
$r = q("select * from hubloc where hubloc_addr = '%s' and hubloc_network = 'zot6' limit 1",
|
||||
dbesc($url)
|
||||
);
|
||||
}
|
||||
elseif (filter_var($url, FILTER_VALIDATE_URL)) {
|
||||
$r = q("select * from hubloc where hubloc_id_url = '%s' and hubloc_network = 'zot6' limit 1",
|
||||
dbesc($url)
|
||||
);
|
||||
}
|
||||
|
||||
if (!$r) {
|
||||
$href = Webfinger::zot_url(punify($url));
|
||||
if ($href) {
|
||||
$zf = Zotfinger::exec($href, null);
|
||||
if ($is_webbie) {
|
||||
$url = Webfinger::zot_url(punify($url));
|
||||
}
|
||||
if (is_array($zf) && array_path_exists('signature/signer', $zf) && $zf['signature']['signer'] === $href && intval($zf['signature']['header_valid'])) {
|
||||
Libzot::import_xchan($zf['data']);
|
||||
|
||||
if ($url) {
|
||||
$zf = Zotfinger::exec($url, null);
|
||||
if (is_array($zf) && array_path_exists('signature/signer', $zf) && $zf['signature']['signer'] === $url && intval($zf['signature']['header_valid'])) {
|
||||
Libzot::import_xchan($zf['data']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,14 +11,35 @@ class Importdoc {
|
||||
|
||||
self::update_docs_dir('doc/*');
|
||||
|
||||
$sys = get_sys_channel();
|
||||
|
||||
// remove old files that weren't updated (indicates they were most likely deleted).
|
||||
$i = q("select id from item where uid = %d and item_type = 5 and edited < %s - INTERVAL %s",
|
||||
intval($sys['channel_id']),
|
||||
db_utcnow(),
|
||||
db_quoteinterval('14 DAY')
|
||||
);
|
||||
|
||||
if ($i) {
|
||||
foreach ($i as $iv) {
|
||||
drop_item($iv['id'], uid: $sys['channel_id']);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
static public function update_docs_dir($s) {
|
||||
$f = basename($s);
|
||||
$d = dirname($s);
|
||||
if ($s === 'doc/html')
|
||||
|
||||
if ($s === 'doc/html') {
|
||||
return;
|
||||
}
|
||||
|
||||
$files = glob("$d/$f");
|
||||
|
||||
if ($files) {
|
||||
foreach ($files as $fi) {
|
||||
if ($fi === 'doc/html') {
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
namespace Zotlabs\Daemon;
|
||||
|
||||
use Zotlabs\Lib\QueueWorker;
|
||||
|
||||
if (array_search(__file__, get_included_files()) === 0) {
|
||||
require_once('include/cli_startup.php');
|
||||
array_shift($argv);
|
||||
@@ -9,6 +11,7 @@ if (array_search(__file__, get_included_files()) === 0) {
|
||||
|
||||
if ($argc)
|
||||
Master::Release($argc, $argv);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -16,6 +19,10 @@ if (array_search(__file__, get_included_files()) === 0) {
|
||||
class Master {
|
||||
|
||||
static public function Summon($arr) {
|
||||
|
||||
QueueWorker::Summon($arr);
|
||||
return;
|
||||
/*
|
||||
$hookinfo = [
|
||||
'argv' => $arr
|
||||
];
|
||||
@@ -30,13 +37,17 @@ class Master {
|
||||
return;
|
||||
}
|
||||
|
||||
$phpbin = get_config('system', 'phpbin', 'php');
|
||||
$phpbin = Config::Get('system', 'phpbin', 'php');
|
||||
proc_run($phpbin, 'Zotlabs/Daemon/Master.php', $arr);
|
||||
*/
|
||||
}
|
||||
|
||||
static public function Release($argc, $argv) {
|
||||
cli_startup();
|
||||
|
||||
QueueWorker::Release($argv);
|
||||
return;
|
||||
/*
|
||||
$hookinfo = [
|
||||
'argv' => $argv
|
||||
];
|
||||
@@ -54,5 +65,6 @@ class Master {
|
||||
logger('Master: release: ' . json_encode($argv), LOGGER_ALL, LOG_DEBUG);
|
||||
$cls = '\\Zotlabs\\Daemon\\' . $argv[0];
|
||||
$cls::run($argc, $argv);
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,9 @@
|
||||
|
||||
namespace Zotlabs\Daemon;
|
||||
|
||||
use Zotlabs\Lib\Libzot;
|
||||
use Zotlabs\Lib\Activity;
|
||||
use Zotlabs\Lib\Config;
|
||||
use Zotlabs\Lib\Libzot;
|
||||
use Zotlabs\Lib\Queue;
|
||||
|
||||
require_once('include/html2plain.php');
|
||||
@@ -79,6 +80,7 @@ class Notifier {
|
||||
static public $channel = null;
|
||||
static public $private = false;
|
||||
|
||||
|
||||
static public function run($argc, $argv) {
|
||||
|
||||
if ($argc < 3) {
|
||||
@@ -88,14 +90,12 @@ class Notifier {
|
||||
logger('notifier: invoked: ' . print_r($argv, true), LOGGER_DEBUG);
|
||||
|
||||
$cmd = $argv[1];
|
||||
|
||||
$item_id = $argv[2];
|
||||
|
||||
if (!$item_id) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
self::$deliveries = [];
|
||||
self::$recipients = [];
|
||||
self::$env_recips = [];
|
||||
@@ -107,6 +107,12 @@ class Notifier {
|
||||
|
||||
$sys = get_sys_channel();
|
||||
$normal_mode = true;
|
||||
$upstream = false;
|
||||
$uplink = false;
|
||||
$target_item = null;
|
||||
$parent_item = null;
|
||||
$top_level_post = false;
|
||||
$relay_to_owner = false;
|
||||
|
||||
if ($cmd === 'keychange') {
|
||||
self::$channel = channelx_by_n($item_id);
|
||||
@@ -170,7 +176,7 @@ class Notifier {
|
||||
elseif ($cmd === 'refresh_all') {
|
||||
logger('notifier: refresh_all: ' . $item_id);
|
||||
|
||||
self::$channel = channelx_by_n($item_id);
|
||||
self::$channel = channelx_by_n($item_id, true);
|
||||
|
||||
$r = q("select abook_xchan from abook where abook_channel = %d",
|
||||
intval($item_id)
|
||||
@@ -180,6 +186,11 @@ class Notifier {
|
||||
self::$recipients[] = $rr['abook_xchan'];
|
||||
}
|
||||
}
|
||||
|
||||
// In case we deleted the channel, our abook entry has already vanished.
|
||||
// In order to be able to update our clones we need to add ourself here.
|
||||
self::$recipients[] = self::$channel['channel_hash'];
|
||||
|
||||
self::$private = false;
|
||||
self::$packet_type = 'refresh';
|
||||
}
|
||||
@@ -190,14 +201,14 @@ class Notifier {
|
||||
return;
|
||||
}
|
||||
|
||||
self::$channel = channelx_by_n($item_id);
|
||||
self::$channel = channelx_by_n($item_id, true);
|
||||
self::$recipients = [$xchan];
|
||||
self::$private = true;
|
||||
self::$packet_type = 'purge';
|
||||
}
|
||||
elseif ($cmd === 'purge_all') {
|
||||
logger('notifier: purge_all: ' . $item_id);
|
||||
self::$channel = channelx_by_n($item_id);
|
||||
self::$channel = channelx_by_n($item_id, true);
|
||||
self::$recipients = [];
|
||||
self::$private = false;
|
||||
self::$packet_type = 'purge';
|
||||
@@ -230,11 +241,6 @@ class Notifier {
|
||||
|
||||
$target_item = $r[0];
|
||||
|
||||
if (in_array($target_item['author']['xchan_network'], ['rss', 'anon'])) {
|
||||
logger('notifier: target item author is not a fetchable actor', LOGGER_DEBUG);
|
||||
return;
|
||||
}
|
||||
|
||||
if (intval($target_item['item_deleted'])) {
|
||||
logger('notifier: target item ITEM_DELETED', LOGGER_DEBUG);
|
||||
}
|
||||
@@ -257,23 +263,9 @@ class Notifier {
|
||||
|
||||
}
|
||||
|
||||
// Check for non published items, but allow an exclusion for transmitting hidden file activities
|
||||
|
||||
if (intval($target_item['item_unpublished']) || intval($target_item['item_delayed']) ||
|
||||
intval($target_item['item_blocked']) ||
|
||||
(intval($target_item['item_hidden']) && ($target_item['obj_type'] !== ACTIVITY_OBJ_FILE))) {
|
||||
logger('notifier: target item not published, so not forwardable', LOGGER_DEBUG);
|
||||
return;
|
||||
}
|
||||
|
||||
// follow/unfollow is for internal use only
|
||||
if (in_array($target_item['verb'], [ACTIVITY_FOLLOW, ACTIVITY_UNFOLLOW])) {
|
||||
logger('not fowarding follow/unfollow note activity');
|
||||
return;
|
||||
}
|
||||
|
||||
if (strpos($target_item['postopts'], 'nodeliver') !== false) {
|
||||
logger('notifier: target item is undeliverable', LOGGER_DEBUG);
|
||||
if (!item_forwardable($target_item)) {
|
||||
//hz_syslog(print_r($target_item,true));
|
||||
logger('notifier: target item not forwardable', LOGGER_DEBUG);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -289,6 +281,11 @@ class Notifier {
|
||||
return;
|
||||
}
|
||||
|
||||
if (in_array($target_item['verb'], [ACTIVITY_SHARE])) {
|
||||
// Provide correct representation across the wire. Internally this is treated as a comment.
|
||||
$target_item['parent_mid'] = $target_item['thr_parent'] = $target_item['mid'];
|
||||
}
|
||||
|
||||
if ($target_item['mid'] === $target_item['parent_mid']) {
|
||||
$parent_item = $target_item;
|
||||
$top_level_post = true;
|
||||
@@ -326,12 +323,7 @@ class Notifier {
|
||||
self::$encoded_item = json_decode($m, true);
|
||||
}
|
||||
else {
|
||||
self::$encoded_item = array_merge(['@context' => [
|
||||
ACTIVITYSTREAMS_JSONLD_REV,
|
||||
'https://w3id.org/security/v1',
|
||||
z_root() . ZOT_APSCHEMA_REV
|
||||
]], Activity::encode_activity($target_item)
|
||||
);
|
||||
self::$encoded_item = Activity::build_packet(Activity::encode_activity($target_item), self::$channel, false);
|
||||
}
|
||||
|
||||
logger('target_item: ' . print_r($target_item, true), LOGGER_DEBUG);
|
||||
@@ -347,8 +339,6 @@ class Notifier {
|
||||
// the hostname in the message_id and provides a second (fallback) opinion.
|
||||
|
||||
$relay_to_owner = (!$top_level_post && intval($target_item['item_origin']) && comment_local_origin($target_item));
|
||||
$uplink = false;
|
||||
$upstream = false;
|
||||
|
||||
// $cmd === 'relay' indicates the owner is sending it to the original recipients
|
||||
// don't allow the item in the relay command to relay to owner under any circumstances, it will loop
|
||||
@@ -380,7 +370,7 @@ class Notifier {
|
||||
logger('normal (downstream) distribution', LOGGER_DEBUG);
|
||||
}
|
||||
|
||||
if ($parent_item && $parent_item['item_private'] !== $target_item['item_private']) {
|
||||
if (($parent_item && $parent_item['item_private'] !== $target_item['item_private']) || (intval($target_item['item_restrict']) & 1)) {
|
||||
logger('conversation privacy mismatch - downstream delivery prevented');
|
||||
return;
|
||||
}
|
||||
@@ -398,9 +388,7 @@ class Notifier {
|
||||
self::$private = false;
|
||||
self::$recipients = collect_recipients($parent_item, self::$private);
|
||||
|
||||
// FIXME add any additional recipients such as mentions, etc.
|
||||
|
||||
if ($top_level_post) {
|
||||
if ($top_level_post && intval($target_item['item_wall'])) {
|
||||
// remove clones who will receive the post via sync
|
||||
self::$recipients = array_values(array_diff(self::$recipients, [$target_item['owner_xchan']]));
|
||||
}
|
||||
@@ -443,7 +431,6 @@ class Notifier {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$narr = [
|
||||
'channel' => self::$channel,
|
||||
'upstream' => $upstream,
|
||||
@@ -485,7 +472,7 @@ class Notifier {
|
||||
// Now we have collected recipients (except for external mentions, FIXME)
|
||||
// Let's reduce this to a set of hubs; checking that the site is not dead.
|
||||
|
||||
$hubs = q("select hubloc.*, site.site_crypto, site.site_flags, site.site_dead from hubloc left join site on site_url = hubloc_url
|
||||
$hubs = dbq("select hubloc.*, site.site_crypto, site.site_flags, site.site_dead from hubloc left join site on site_url = hubloc_url
|
||||
where hubloc_hash in (" . protect_sprintf(implode(',', self::$recipients)) . ")
|
||||
and hubloc_error = 0 and hubloc_deleted = 0"
|
||||
);
|
||||
@@ -493,6 +480,7 @@ class Notifier {
|
||||
// public posts won't make it to the local public stream unless there's a recipient on this site.
|
||||
// This code block sees if it's a public post and localhost is missing, and if so adds an entry for the local sys channel to the $hubs list
|
||||
|
||||
/* sys channel is now added in collect recipients
|
||||
if (!self::$private) {
|
||||
$found_localhost = false;
|
||||
if ($hubs) {
|
||||
@@ -513,6 +501,7 @@ class Notifier {
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
if (!$hubs) {
|
||||
logger('notifier: no hubs', LOGGER_NORMAL, LOG_NOTICE);
|
||||
@@ -526,16 +515,18 @@ class Notifier {
|
||||
*/
|
||||
|
||||
|
||||
$hublist = []; // this provides an easily printable list for the logs
|
||||
$dhubs = []; // delivery hubs where we store our resulting unique array
|
||||
$keys = []; // array of keys to check uniquness for zot hubs
|
||||
$urls = []; // array of urls to check uniqueness of hubs from other networks
|
||||
$hub_env = []; // per-hub envelope so we don't broadcast the entire envelope to all
|
||||
$dead = []; // known dead hubs - report them as undeliverable
|
||||
$hublist = []; // this provides an easily printable list for the logs
|
||||
$dhubs = []; // delivery hubs where we store our resulting unique array
|
||||
$keys = []; // array of keys to check uniquness for zot hubs
|
||||
$urls = []; // array of urls to check uniqueness of hubs from other networks
|
||||
$hub_env = []; // per-hub envelope so we don't broadcast the entire envelope to all
|
||||
$dead_hosts = []; // known dead hubs - report them as undeliverable
|
||||
|
||||
foreach ($hubs as $hub) {
|
||||
if (isset($hub['site_dead']) && intval($hub['site_dead'])) {
|
||||
$dead[] = $hub;
|
||||
if(!in_array($hub['hubloc_host'], $dead_hosts)) {
|
||||
$dead_hosts[] = $hub['hubloc_host'];
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -545,7 +536,9 @@ class Notifier {
|
||||
if (!array_key_exists($hub['hubloc_site_id'], $hub_env)) {
|
||||
$hub_env[$hub['hubloc_site_id']] = [];
|
||||
}
|
||||
$hub_env[$hub['hubloc_site_id']][] = $er;
|
||||
if (!in_array($er, $hub_env[$hub['hubloc_site_id']])) {
|
||||
$hub_env[$hub['hubloc_site_id']][] = $er;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -577,8 +570,6 @@ class Notifier {
|
||||
|
||||
foreach ($dhubs as $hub) {
|
||||
|
||||
logger('notifier_hub: ' . $hub['hubloc_url'], LOGGER_DEBUG);
|
||||
|
||||
if ($hub['hubloc_network'] !== 'zot6') {
|
||||
$narr = [
|
||||
'channel' => self::$channel,
|
||||
@@ -623,9 +614,22 @@ class Notifier {
|
||||
|
||||
// default: zot protocol
|
||||
|
||||
// Prevent zot6 delivery of group comment boosts, which are not required for conversational platforms.
|
||||
// ActivityPub conversational platforms may wish to filter these if they don't want or require them.
|
||||
// We will assume here that if $target_item exists and has a verb that it is an actual item structure
|
||||
// so we won't need to check the existence of the other item fields prior to evaluation.
|
||||
|
||||
// This shouldn't produce false positives on comment boosts that were generated on other platforms
|
||||
// because we won't be delivering them.
|
||||
|
||||
if (isset($target_item['verb']) && $target_item['verb'] === 'Announce' && $target_item['author_xchan'] === $target_item['owner_xchan'] && ! intval($target_item['item_thread_top'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$hash = new_uuid();
|
||||
|
||||
$env = (($hub_env && $hub_env[$hub['hubloc_site_id']]) ? $hub_env[$hub['hubloc_site_id']] : '');
|
||||
$env = $hub_env[$hub['hubloc_site_id']] ?? '';
|
||||
|
||||
if ((self::$private) && (!$env)) {
|
||||
continue;
|
||||
}
|
||||
@@ -644,7 +648,7 @@ class Notifier {
|
||||
);
|
||||
|
||||
// only create delivery reports for normal undeleted items
|
||||
if (is_array($target_item) && (!$target_item['item_deleted']) && (!get_config('system', 'disable_dreport'))) {
|
||||
if (is_array($target_item) && (!$target_item['item_deleted']) && (!Config::Get('system', 'disable_dreport'))) {
|
||||
q("insert into dreport ( dreport_mid, dreport_site, dreport_recip, dreport_name, dreport_result, dreport_time, dreport_xchan, dreport_queue )
|
||||
values ( '%s', '%s','%s','%s','%s','%s','%s','%s' ) ",
|
||||
dbesc($target_item['mid']),
|
||||
@@ -662,7 +666,7 @@ class Notifier {
|
||||
|
||||
}
|
||||
|
||||
if ($normal_mode) {
|
||||
if ($normal_mode && is_array($target_item)) {
|
||||
// This wastes a process if there are no delivery hooks configured, so check this before launching the new process
|
||||
$x = q("select * from hook where hook = 'notifier_normal'");
|
||||
if ($x) {
|
||||
@@ -674,21 +678,19 @@ class Notifier {
|
||||
do_delivery(self::$deliveries);
|
||||
}
|
||||
|
||||
if ($dead) {
|
||||
foreach ($dead as $deceased) {
|
||||
if (is_array($target_item) && (!$target_item['item_deleted']) && (!get_config('system', 'disable_dreport'))) {
|
||||
q("insert into dreport ( dreport_mid, dreport_site, dreport_recip, dreport_name, dreport_result, dreport_time, dreport_xchan, dreport_queue )
|
||||
values ( '%s', '%s','%s','%s','%s','%s','%s','%s' ) ",
|
||||
dbesc($target_item['mid']),
|
||||
dbesc($deceased['hubloc_host']),
|
||||
dbesc($deceased['hubloc_host']),
|
||||
dbesc($deceased['hubloc_host']),
|
||||
dbesc('undeliverable/unresponsive site'),
|
||||
dbesc(datetime_convert()),
|
||||
dbesc(self::$channel['channel_hash']),
|
||||
dbesc(new_uuid())
|
||||
);
|
||||
}
|
||||
if ($dead_hosts && is_array($target_item) && (!$target_item['item_deleted']) && (!Config::Get('system', 'disable_dreport'))) {
|
||||
foreach ($dead_hosts as $deceased_host) {
|
||||
$r = q("insert into dreport ( dreport_mid, dreport_site, dreport_recip, dreport_name, dreport_result, dreport_time, dreport_xchan, dreport_queue )
|
||||
values ( '%s', '%s','%s','%s','%s','%s','%s','%s' ) ",
|
||||
dbesc($target_item['mid']),
|
||||
dbesc($deceased_host),
|
||||
dbesc($deceased_host),
|
||||
dbesc($deceased_host),
|
||||
dbesc('undeliverable/unresponsive site'),
|
||||
dbesc(datetime_convert()),
|
||||
dbesc(self::$channel['channel_hash']),
|
||||
dbesc(new_uuid())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,61 +15,45 @@ class Onedirsync {
|
||||
$update_id = intval($argv[1]);
|
||||
|
||||
if (!$update_id) {
|
||||
logger('onedirsync: no update');
|
||||
logger('onedirsync: no update id');
|
||||
return;
|
||||
}
|
||||
|
||||
$r = q("select * from updates where ud_id = %d limit 1",
|
||||
$r = q("select * from updates where ud_id = %d",
|
||||
intval($update_id)
|
||||
);
|
||||
|
||||
if (!$r)
|
||||
return;
|
||||
|
||||
if (($r[0]['ud_flags'] & UPDATE_FLAGS_UPDATED) || (!$r[0]['ud_addr']))
|
||||
return;
|
||||
|
||||
// Have we probed this channel more recently than the other directory server
|
||||
// (where we received this update from) ?
|
||||
// If we have, we don't need to do anything except mark any older entries updated
|
||||
|
||||
$x = q("select * from updates where ud_addr = '%s' and ud_date > '%s' and ( ud_flags & %d )>0 order by ud_date desc limit 1",
|
||||
dbesc($r[0]['ud_addr']),
|
||||
dbesc($r[0]['ud_date']),
|
||||
intval(UPDATE_FLAGS_UPDATED)
|
||||
);
|
||||
if ($x) {
|
||||
q("update updates set ud_flags = ( ud_flags | %d ) where ud_addr = '%s' and ( ud_flags & %d ) = 0 and ud_date != '%s'",
|
||||
intval(UPDATE_FLAGS_UPDATED),
|
||||
dbesc($r[0]['ud_addr']),
|
||||
intval(UPDATE_FLAGS_UPDATED),
|
||||
dbesc($x[0]['ud_date'])
|
||||
);
|
||||
if (!$r) {
|
||||
logger('onedirsync: update id not found');
|
||||
return;
|
||||
}
|
||||
|
||||
// ignore doing an update if this ud_addr refers to a known dead hubloc
|
||||
|
||||
$h = q("select * from hubloc where hubloc_addr = '%s'",
|
||||
$h = q("select * from hubloc where hubloc_id_url = '%s' order by hubloc_id desc",
|
||||
dbesc($r[0]['ud_addr']),
|
||||
);
|
||||
|
||||
$h = Libzot::zot_record_preferred($h);
|
||||
|
||||
if (($h) && (($h['hubloc_status'] & HUBLOC_OFFLINE) || $h['hubloc_deleted'] || $h['hubloc_error'])) {
|
||||
q("update updates set ud_flags = ( ud_flags | %d ) where ud_addr = '%s' and ( ud_flags & %d ) = 0 ",
|
||||
intval(UPDATE_FLAGS_DELETED),
|
||||
dbesc($r[0]['ud_addr']),
|
||||
intval(UPDATE_FLAGS_UPDATED)
|
||||
);
|
||||
return;
|
||||
|
||||
// 2023-04-12: Try to update anyway since the info is not always correct
|
||||
// This might change after all directory servers run the new code.
|
||||
|
||||
// q("update updates set ud_flags = 9 where ud_hash = '%s' and ud_flags != 9",
|
||||
// dbesc($r[0]['ud_hash'])
|
||||
//);
|
||||
|
||||
// return;
|
||||
}
|
||||
|
||||
// we might have to pull this out some day, but for now update_directory_entry()
|
||||
// runs zot_finger() and is kind of zot specific
|
||||
|
||||
if ($h && $h['hubloc_network'] !== 'zot6')
|
||||
if ($h && $h['hubloc_network'] !== 'zot6') {
|
||||
return;
|
||||
}
|
||||
|
||||
Libzotdir::update_directory_entry($r[0]);
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ namespace Zotlabs\Daemon;
|
||||
use Zotlabs\Lib\Activity;
|
||||
use Zotlabs\Lib\ActivityStreams;
|
||||
use Zotlabs\Lib\ASCollection;
|
||||
use Zotlabs\Lib\Config;
|
||||
use Zotlabs\Lib\Libzot;
|
||||
|
||||
require_once('include/socgraph.php');
|
||||
@@ -25,19 +26,15 @@ class Onepoll {
|
||||
}
|
||||
|
||||
$sql_extra = '';
|
||||
$allow_feeds = get_config('system', 'feed_contacts');
|
||||
$allow_feeds = Config::Get('system', 'feed_contacts');
|
||||
if(!$allow_feeds) {
|
||||
$sql_extra = ' and abook_feed = 0 ';
|
||||
}
|
||||
|
||||
$contacts = q("SELECT abook.*, xchan.*, account.*
|
||||
FROM abook LEFT JOIN account on abook_account = account_id left join xchan on xchan_hash = abook_xchan
|
||||
where abook_id = %d $sql_extra
|
||||
and abook_pending = 0 and abook_archived = 0 and abook_blocked = 0 and abook_ignored = 0
|
||||
AND (( account_flags = %d ) OR ( account_flags = %d )) limit 1",
|
||||
intval($contact_id),
|
||||
intval(ACCOUNT_OK),
|
||||
intval(ACCOUNT_UNVERIFIED)
|
||||
$contacts = q("SELECT abook.*, xchan.* FROM abook
|
||||
LEFT JOIN xchan ON xchan_hash = abook_xchan
|
||||
WHERE abook_id = %d",
|
||||
intval($contact_id)
|
||||
);
|
||||
|
||||
if (!$contacts) {
|
||||
@@ -46,18 +43,15 @@ class Onepoll {
|
||||
}
|
||||
|
||||
$contact = $contacts[0];
|
||||
|
||||
$importer_uid = $contact['abook_channel'];
|
||||
|
||||
$r = q("SELECT * from channel left join xchan on channel_hash = xchan_hash where channel_id = %d limit 1",
|
||||
intval($importer_uid)
|
||||
);
|
||||
$importer = channelx_by_n($importer_uid);
|
||||
|
||||
if (!$r)
|
||||
if (!$importer)
|
||||
return;
|
||||
|
||||
$importer = $r[0];
|
||||
|
||||
logger("onepoll: poll: ({$contact['id']}) IMPORTER: {$importer['xchan_name']}, CONTACT: {$contact['xchan_name']}");
|
||||
logger("onepoll: poll: ($contact_id) IMPORTER: {$importer['xchan_name']}, CONTACT: {$contact['xchan_name']}");
|
||||
|
||||
$last_update = ((($contact['abook_updated'] === $contact['abook_created']) || ($contact['abook_updated'] <= NULL_DATE))
|
||||
? datetime_convert('UTC', 'UTC', 'now - 7 days')
|
||||
@@ -67,12 +61,21 @@ class Onepoll {
|
||||
if ($contact['xchan_network'] === 'rss') {
|
||||
logger('onepoll: processing feed ' . $contact['xchan_name'], LOGGER_DEBUG);
|
||||
$alive = handle_feed($importer['channel_id'], $contact_id, $contact['xchan_hash']);
|
||||
if ($alive) {
|
||||
q("update abook set abook_connected = '%s' where abook_id = %d",
|
||||
|
||||
if (!$alive) {
|
||||
q("update abook set abook_updated = '%s' where abook_id = %d",
|
||||
dbesc(datetime_convert()),
|
||||
intval($contact['abook_id'])
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
q("update abook set abook_updated = '%s', abook_connected = '%s' where abook_id = %d",
|
||||
dbesc(datetime_convert()),
|
||||
dbesc(datetime_convert()),
|
||||
intval($contact['abook_id'])
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -123,7 +126,7 @@ class Onepoll {
|
||||
|
||||
if ($fetch_feed) {
|
||||
|
||||
$max = intval(get_config('system', 'max_imported_posts', 30));
|
||||
$max = intval(Config::Get('system', 'max_imported_posts', 30));
|
||||
|
||||
if (intval($max)) {
|
||||
$cl = Activity::get_actor_collections($contact['abook_xchan']);
|
||||
@@ -135,22 +138,38 @@ class Onepoll {
|
||||
$url = $cl['outbox'];
|
||||
}
|
||||
else {
|
||||
$url = str_replace('/poco/', '/zotfeed/', $contact['xchan_connurl']);
|
||||
$url = str_replace('/poco/', '/outbox/', $contact['xchan_connurl']);
|
||||
}
|
||||
|
||||
if ($url) {
|
||||
logger('fetching outbox');
|
||||
$url = $url . '?date_begin=' . urlencode($last_update);
|
||||
$url = $url . '?date_begin=' . urlencode($last_update);
|
||||
|
||||
if($contact['xchan_network'] === 'zot6') {
|
||||
$url = $url . '&top=1';
|
||||
}
|
||||
|
||||
$obj = new ASCollection($url, $importer, 0, $max);
|
||||
$messages = $obj->get();
|
||||
|
||||
if ($messages) {
|
||||
foreach ($messages as $message) {
|
||||
if (is_string($message)) {
|
||||
$message = Activity::fetch($message, $importer);
|
||||
}
|
||||
|
||||
if ($contact['xchan_network'] === 'zot6') {
|
||||
// make sure we only fetch top level items
|
||||
if ($message['type'] === 'Create' && !isset($message['object']['inReplyTo'])) {
|
||||
Libzot::fetch_conversation($importer, $message['object']['id']);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
$AS = new ActivityStreams($message);
|
||||
if ($AS->is_valid() && is_array($AS->obj)) {
|
||||
$item = Activity::decode_note($AS);
|
||||
$item['item_fetched'] = true;
|
||||
Activity::store($importer, $contact['abook_xchan'], $AS, $item);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,11 +2,13 @@
|
||||
|
||||
namespace Zotlabs\Daemon;
|
||||
|
||||
use Zotlabs\Lib\Config;
|
||||
|
||||
class Poller {
|
||||
|
||||
static public function run($argc, $argv) {
|
||||
|
||||
$maxsysload = intval(get_config('system', 'maxloadavg'));
|
||||
$maxsysload = intval(Config::Get('system', 'maxloadavg'));
|
||||
if ($maxsysload < 1)
|
||||
$maxsysload = 50;
|
||||
if (function_exists('sys_getloadavg')) {
|
||||
@@ -17,21 +19,7 @@ class Poller {
|
||||
}
|
||||
}
|
||||
|
||||
$interval = intval(get_config('system', 'poll_interval'));
|
||||
if (!$interval)
|
||||
$interval = ((get_config('system', 'delivery_interval') === false) ? 3 : intval(get_config('system', 'delivery_interval')));
|
||||
|
||||
// Check for a lockfile. If it exists, but is over an hour old, it's stale. Ignore it.
|
||||
$lockfile = 'store/[data]/poller';
|
||||
if ((file_exists($lockfile)) && (filemtime($lockfile) > (time() - 3600))
|
||||
&& (!get_config('system', 'override_poll_lockfile'))) {
|
||||
logger("poller: Already running");
|
||||
return;
|
||||
}
|
||||
|
||||
// Create a lockfile. Needs two vars, but $x doesn't need to contain anything.
|
||||
$x = '';
|
||||
file_put_contents($lockfile, $x);
|
||||
$interval = Config::Get('queueworker', 'queue_interval', 500000);
|
||||
|
||||
logger('poller: start');
|
||||
|
||||
@@ -57,12 +45,17 @@ class Poller {
|
||||
reload_plugins();
|
||||
|
||||
// Only poll from those with suitable relationships
|
||||
$abandon_days = intval(get_config('system', 'account_abandon_days', 0));
|
||||
$abandon_days = intval(Config::Get('system', 'account_abandon_days', 0));
|
||||
$abandon_sql = (($abandon_days)
|
||||
? sprintf(" AND account_lastlog > %s - INTERVAL %s ", db_utcnow(), db_quoteinterval(intval($abandon_days) . ' DAY'))
|
||||
: ''
|
||||
);
|
||||
|
||||
$allow_feeds = Config::Get('system', 'feed_contacts');
|
||||
if(!$allow_feeds) {
|
||||
$sql_extra .= ' and abook_feed = 0 ';
|
||||
}
|
||||
|
||||
$randfunc = db_getfunc('RAND');
|
||||
|
||||
$contacts = q("SELECT abook.abook_updated, abook.abook_connected, abook.abook_feed,
|
||||
@@ -72,7 +65,7 @@ class Poller {
|
||||
account.account_lastlog, account.account_flags
|
||||
FROM abook LEFT JOIN xchan on abook_xchan = xchan_hash
|
||||
LEFT JOIN account on abook_account = account_id
|
||||
where abook_self = 0
|
||||
where abook_self = 0 and abook_pending = 0 and abook_archived = 0 and abook_blocked = 0 and abook_ignored = 0
|
||||
$sql_extra
|
||||
AND (( account_flags = %d ) OR ( account_flags = %d )) $abandon_sql ORDER BY $randfunc",
|
||||
intval(ACCOUNT_OK),
|
||||
@@ -90,16 +83,27 @@ class Poller {
|
||||
if (intval($contact['abook_feed'])) {
|
||||
$min = service_class_fetch($contact['abook_channel'], 'minimum_feedcheck_minutes');
|
||||
if (!$min)
|
||||
$min = intval(get_config('system', 'minimum_feedcheck_minutes'));
|
||||
$min = intval(Config::Get('system', 'minimum_feedcheck_minutes'));
|
||||
if (!$min)
|
||||
$min = 60;
|
||||
$x = datetime_convert('UTC', 'UTC', "now - $min minutes");
|
||||
if ($c < $x) {
|
||||
Master::Summon(['Onepoll', $contact['abook_id']]);
|
||||
if ($interval)
|
||||
@time_sleep_until(microtime(true) + (float)$interval);
|
||||
|
||||
if ($t !== $c) {
|
||||
// if the last fetch failed only attempt fetch once a day
|
||||
$min = 60 * 24;
|
||||
}
|
||||
|
||||
$x = datetime_convert('UTC', 'UTC', "now - $min minutes");
|
||||
|
||||
if ($t < $x) {
|
||||
Master::Summon(['Onepoll', $contact['abook_id']]);
|
||||
|
||||
if ($interval) {
|
||||
usleep($interval);
|
||||
}
|
||||
}
|
||||
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
if ($contact['xchan_network'] !== 'zot6')
|
||||
@@ -158,20 +162,22 @@ class Poller {
|
||||
continue;
|
||||
|
||||
Master::Summon(['Onepoll', $contact['abook_id']]);
|
||||
if ($interval)
|
||||
@time_sleep_until(microtime(true) + (float)$interval);
|
||||
|
||||
if ($interval) {
|
||||
usleep($interval);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$dirmode = intval(get_config('system', 'directory_mode'));
|
||||
$dirmode = intval(Config::Get('system', 'directory_mode'));
|
||||
|
||||
if ($dirmode == DIRECTORY_MODE_SECONDARY || $dirmode == DIRECTORY_MODE_PRIMARY) {
|
||||
$r = q("SELECT u.ud_addr, u.ud_id, u.ud_last FROM updates AS u INNER JOIN (SELECT ud_addr, max(ud_id) AS ud_id FROM updates WHERE ( ud_flags & %d ) = 0 AND ud_addr != '' AND ( ud_last <= '%s' OR ud_last > %s - INTERVAL %s ) GROUP BY ud_addr) AS s ON s.ud_id = u.ud_id ",
|
||||
intval(UPDATE_FLAGS_UPDATED),
|
||||
$r = q("SELECT * FROM updates WHERE ud_update = 1 AND (ud_last = '%s' OR ud_last > %s - INTERVAL %s)",
|
||||
dbesc(NULL_DATE),
|
||||
db_utcnow(), db_quoteinterval('7 DAY')
|
||||
db_utcnow(),
|
||||
db_quoteinterval('7 DAY')
|
||||
);
|
||||
|
||||
if ($r) {
|
||||
foreach ($r as $rr) {
|
||||
|
||||
@@ -181,18 +187,17 @@ class Poller {
|
||||
if ($rr['ud_last'] > NULL_DATE)
|
||||
if ($rr['ud_last'] > datetime_convert('UTC', 'UTC', 'now - 1 day'))
|
||||
continue;
|
||||
|
||||
Master::Summon(['Onedirsync', $rr['ud_id']]);
|
||||
if ($interval)
|
||||
@time_sleep_until(microtime(true) + (float)$interval);
|
||||
|
||||
if ($interval) {
|
||||
usleep($interval);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
set_config('system', 'lastpoll', datetime_convert());
|
||||
|
||||
//All done - clear the lockfile
|
||||
|
||||
@unlink($lockfile);
|
||||
Config::Set('system', 'lastpoll', datetime_convert());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -7,77 +7,59 @@ use Zotlabs\Lib\Queue as LibQueue;
|
||||
class Queue {
|
||||
|
||||
static public function run($argc, $argv) {
|
||||
|
||||
require_once('include/items.php');
|
||||
require_once('include/bbcode.php');
|
||||
|
||||
if ($argc > 1)
|
||||
$queue_id = $argv[1];
|
||||
else
|
||||
$queue_id = EMPTY_STR;
|
||||
$queue_id = ($argc > 1) ? $argv[1] : '';
|
||||
|
||||
logger('queue: start');
|
||||
|
||||
// delete all queue items more than 3 days old
|
||||
// but first mark these sites dead if we haven't heard from them in a month
|
||||
|
||||
$r = q("select outq_posturl from outq where outq_created < %s - INTERVAL %s",
|
||||
db_utcnow(), db_quoteinterval('3 DAY')
|
||||
$oldqItems = q("select outq_posturl, outq_hash from outq where outq_created < %s - INTERVAL %s",
|
||||
db_utcnow(),
|
||||
db_quoteinterval('3 DAY')
|
||||
);
|
||||
if ($r) {
|
||||
foreach ($r as $rr) {
|
||||
$h = parse_url($rr['outq_posturl']);
|
||||
$desturl = $h['scheme'] . '://' . $h['host'] . (isset($h['port']) ? ':' . $h['port'] : '');
|
||||
|
||||
if ($oldqItems) {
|
||||
foreach ($oldqItems as $qItem) {
|
||||
$h = parse_url($qItem['outq_posturl']);
|
||||
$site_url = $h['scheme'] . '://' . $h['host'] . ((!empty($h['port'])) ? ':' . $h['port'] : '');
|
||||
q("update site set site_dead = 1 where site_dead = 0 and site_url = '%s' and site_update < %s - INTERVAL %s",
|
||||
dbesc($desturl),
|
||||
db_utcnow(), db_quoteinterval('1 MONTH')
|
||||
dbesc($site_url),
|
||||
db_utcnow(),
|
||||
db_quoteinterval('1 MONTH')
|
||||
);
|
||||
}
|
||||
|
||||
$old_hashes = ids_to_querystr($oldqItems, 'outq_hash', true);
|
||||
|
||||
logger('Removing ' . count($oldqItems) . ' old queue entries');
|
||||
dbq("DELETE FROM outq WHERE outq_hash IN ($old_hashes)");
|
||||
|
||||
}
|
||||
|
||||
q("DELETE FROM outq WHERE outq_created < %s - INTERVAL %s",
|
||||
db_utcnow(), db_quoteinterval('3 DAY')
|
||||
);
|
||||
$deliveries = [];
|
||||
|
||||
if ($queue_id) {
|
||||
$r = q("SELECT * FROM outq WHERE outq_hash = '%s' LIMIT 1",
|
||||
$qItems = q("SELECT * FROM outq WHERE outq_hash = '%s' LIMIT 1",
|
||||
dbesc($queue_id)
|
||||
);
|
||||
logger('queue deliver: ' . $qItems[0]['outq_hash'] . ' to ' . $qItems[0]['outq_posturl'], LOGGER_DEBUG);
|
||||
LibQueue::deliver($qItems[0]);
|
||||
}
|
||||
else {
|
||||
|
||||
// For the first 12 hours we'll try to deliver every 15 minutes
|
||||
// After that, we'll only attempt delivery once per hour.
|
||||
// This currently only handles the default queue drivers ('zot' or '') which we will group by posturl
|
||||
// so that we don't start off a thousand deliveries for a couple of dead hubs.
|
||||
// The zot driver will deliver everything destined for a single hub once contact is made (*if* contact is made).
|
||||
// Other drivers will have to do something different here and may need their own query.
|
||||
|
||||
// Note: this requires some tweaking as new posts to long dead hubs once a day will keep them in the
|
||||
// "every 15 minutes" category. We probably need to prioritise them when inserted into the queue
|
||||
// or just prior to this query based on recent and long-term delivery history. If we have good reason to believe
|
||||
// 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.
|
||||
|
||||
$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",
|
||||
$qItems = q("SELECT outq_hash FROM outq WHERE outq_scheduled < %s ",
|
||||
db_utcnow()
|
||||
);
|
||||
while ($r) {
|
||||
foreach ($r as $rv) {
|
||||
LibQueue::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;
|
||||
|
||||
foreach ($r as $rv) {
|
||||
LibQueue::deliver($rv);
|
||||
}
|
||||
if ($qItems) {
|
||||
foreach ($qItems as $qItem) {
|
||||
$deliveries[] = $qItem['outq_hash'];
|
||||
}
|
||||
|
||||
shuffle($deliveries);
|
||||
do_delivery($deliveries, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace Zotlabs\Daemon;
|
||||
|
||||
use Zotlabs\Lib\Config;
|
||||
|
||||
class Thumbnail {
|
||||
|
||||
@@ -19,9 +20,9 @@ class Thumbnail {
|
||||
|
||||
$attach = $c[0];
|
||||
|
||||
$preview_style = intval(get_config('system', 'thumbnail_security', 0));
|
||||
$preview_width = intval(get_config('system', 'thumbnail_width', 300));
|
||||
$preview_height = intval(get_config('system', 'thumbnail_height', 300));
|
||||
$preview_style = intval(Config::Get('system', 'thumbnail_security', 0));
|
||||
$preview_width = intval(Config::Get('system', 'thumbnail_width', 300));
|
||||
$preview_height = intval(Config::Get('system', 'thumbnail_height', 300));
|
||||
|
||||
$p = [
|
||||
'attach' => $attach,
|
||||
@@ -73,5 +74,7 @@ class Thumbnail {
|
||||
|| (filectime(dbunescbin($attach['content']) . 'thumb') < (time() - 60)))) {
|
||||
$default_controller->Thumb($attach, $preview_style, $preview_width, $preview_height);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
37
Zotlabs/Daemon/Xchan_photo.php
Normal file
37
Zotlabs/Daemon/Xchan_photo.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
/** @file */
|
||||
|
||||
namespace Zotlabs\Daemon;
|
||||
|
||||
class Xchan_photo {
|
||||
|
||||
static public function run($argc, $argv) {
|
||||
|
||||
if ($argc < 3) {
|
||||
return;
|
||||
}
|
||||
|
||||
$url = hex2bin($argv[1]);
|
||||
$xchan = hex2bin($argv[2]);
|
||||
$force = $argv[3];
|
||||
|
||||
$photos = import_xchan_photo($url, $xchan, false, $force);
|
||||
if ($photos) {
|
||||
$result = q("update xchan set xchan_photo_date = '%s', xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s' where xchan_hash = '%s'",
|
||||
dbescdate(datetime_convert()),
|
||||
dbesc($photos[0]),
|
||||
dbesc($photos[1]),
|
||||
dbesc($photos[2]),
|
||||
dbesc($photos[3]),
|
||||
dbesc($xchan)
|
||||
);
|
||||
|
||||
if (! $result) {
|
||||
logger("xchan photo update failed for $url");
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
37
Zotlabs/Daemon/Zotconvo.php
Normal file
37
Zotlabs/Daemon/Zotconvo.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Daemon;
|
||||
|
||||
use Zotlabs\Lib\Libzot;
|
||||
|
||||
class Zotconvo {
|
||||
|
||||
static public function run($argc, $argv) {
|
||||
|
||||
logger('Zotconvo invoked: ' . print_r($argv, true));
|
||||
|
||||
if ($argc < 3) {
|
||||
return;
|
||||
}
|
||||
|
||||
$channels = explode(',', $argv[1]);
|
||||
if (!$channels) {
|
||||
return;
|
||||
}
|
||||
|
||||
$mid = $argv[2];
|
||||
if (!$mid) {
|
||||
return;
|
||||
}
|
||||
|
||||
$force = $argv[3] ?? false;
|
||||
|
||||
foreach ($channels as $channel_id) {
|
||||
$channel = channelx_by_n($channel_id);
|
||||
Libzot::fetch_conversation($channel, $mid, $force);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
}
|
||||
352
Zotlabs/Entity/Account.php
Normal file
352
Zotlabs/Entity/Account.php
Normal file
@@ -0,0 +1,352 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Entity;
|
||||
|
||||
use Zotlabs\Lib\BaseObject;
|
||||
|
||||
class Account extends BaseObject
|
||||
{
|
||||
public $account_id;
|
||||
public $account_parent;
|
||||
public $account_default_channel;
|
||||
public $account_salt;
|
||||
public $account_password;
|
||||
public $account_email;
|
||||
public $account_external;
|
||||
public $account_language;
|
||||
public $account_created;
|
||||
public $account_lastlog;
|
||||
public $account_flags;
|
||||
public $account_roles;
|
||||
public $account_reset;
|
||||
public $account_expires;
|
||||
public $account_expire_notified;
|
||||
public $account_service_class;
|
||||
public $account_level;
|
||||
public $account_password_change;
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return $this->account_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $account_id
|
||||
* @return Account
|
||||
*/
|
||||
public function setId($account_id)
|
||||
{
|
||||
$this->account_id = $account_id;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getParent()
|
||||
{
|
||||
return $this->account_parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $account_parent
|
||||
* @return Account
|
||||
*/
|
||||
public function setParent($account_parent)
|
||||
{
|
||||
$this->account_parent = $account_parent;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getDefaultChannel()
|
||||
{
|
||||
return $this->account_default_channel;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $account_default_channel
|
||||
* @return Account
|
||||
*/
|
||||
public function setDefaultChannel($account_default_channel)
|
||||
{
|
||||
$this->account_default_channel = $account_default_channel;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getSalt()
|
||||
{
|
||||
return $this->account_salt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $account_salt
|
||||
* @return Account
|
||||
*/
|
||||
public function setSalt($account_salt)
|
||||
{
|
||||
$this->account_salt = $account_salt;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getPassword()
|
||||
{
|
||||
return $this->account_password;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $account_password
|
||||
* @return Account
|
||||
*/
|
||||
public function setPassword($account_password)
|
||||
{
|
||||
$this->account_password = $account_password;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getEmail()
|
||||
{
|
||||
return $this->account_email;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $account_email
|
||||
* @return Account
|
||||
*/
|
||||
public function setEmail($account_email)
|
||||
{
|
||||
$this->account_email = $account_email;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getExternal()
|
||||
{
|
||||
return $this->account_external;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $account_external
|
||||
* @return Account
|
||||
*/
|
||||
public function setExternal($account_external)
|
||||
{
|
||||
$this->account_external = $account_external;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getLanguage()
|
||||
{
|
||||
return $this->account_language;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $account_language
|
||||
* @return Account
|
||||
*/
|
||||
public function setLanguage($account_language)
|
||||
{
|
||||
$this->account_language = $account_language;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getCreated()
|
||||
{
|
||||
return $this->account_created;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $account_created
|
||||
* @return Account
|
||||
*/
|
||||
public function setCreated($account_created)
|
||||
{
|
||||
$this->account_created = $account_created;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getLastlog()
|
||||
{
|
||||
return $this->account_lastlog;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $account_lastlog
|
||||
* @return Account
|
||||
*/
|
||||
public function setLastlog($account_lastlog)
|
||||
{
|
||||
$this->account_lastlog = $account_lastlog;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getFlags()
|
||||
{
|
||||
return $this->account_flags;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $account_flags
|
||||
* @return Account
|
||||
*/
|
||||
public function setFlags($account_flags)
|
||||
{
|
||||
$this->account_flags = $account_flags;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getRoles()
|
||||
{
|
||||
return $this->account_roles;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $account_roles
|
||||
* @return Account
|
||||
*/
|
||||
public function setRoles($account_roles)
|
||||
{
|
||||
$this->account_roles = $account_roles;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getReset()
|
||||
{
|
||||
return $this->account_reset;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $account_reset
|
||||
* @return Account
|
||||
*/
|
||||
public function setReset($account_reset)
|
||||
{
|
||||
$this->account_reset = $account_reset;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getExpires()
|
||||
{
|
||||
return $this->account_expires;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $account_expires
|
||||
* @return Account
|
||||
*/
|
||||
public function setExpires($account_expires)
|
||||
{
|
||||
$this->account_expires = $account_expires;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getExpireNotified()
|
||||
{
|
||||
return $this->account_expire_notified;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $account_expire_notified
|
||||
* @return Account
|
||||
*/
|
||||
public function setExpireNotified($account_expire_notified)
|
||||
{
|
||||
$this->account_expire_notified = $account_expire_notified;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getServiceClass()
|
||||
{
|
||||
return $this->account_service_class;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $account_service_class
|
||||
* @return Account
|
||||
*/
|
||||
public function setServiceClass($account_service_class)
|
||||
{
|
||||
$this->account_service_class = $account_service_class;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getLevel()
|
||||
{
|
||||
return $this->account_level;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $account_level
|
||||
* @return Account
|
||||
*/
|
||||
public function setLevel($account_level)
|
||||
{
|
||||
$this->account_level = $account_level;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getPasswordChange()
|
||||
{
|
||||
return $this->account_password_change;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $account_password_change
|
||||
* @return Account
|
||||
*/
|
||||
public function setPasswordChange($account_password_change)
|
||||
{
|
||||
$this->account_password_change = $account_password_change;
|
||||
return $this;
|
||||
}
|
||||
|
||||
}
|
||||
714
Zotlabs/Entity/Channel.php
Normal file
714
Zotlabs/Entity/Channel.php
Normal file
@@ -0,0 +1,714 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Entity;
|
||||
|
||||
use Zotlabs\Lib\BaseObject;
|
||||
|
||||
class Channel extends BaseObject
|
||||
{
|
||||
public $channel_id;
|
||||
public $channel_account_id;
|
||||
public $channel_primary;
|
||||
public $channel_name;
|
||||
public $channel_parent;
|
||||
public $channel_address;
|
||||
public $channel_guid;
|
||||
public $channel_guid_sig;
|
||||
public $channel_hash;
|
||||
public $channel_timezone;
|
||||
public $channel_location;
|
||||
public $channel_theme;
|
||||
public $channel_startpage;
|
||||
public $channel_pubkey;
|
||||
public $channel_prvkey;
|
||||
public $channel_epubkey;
|
||||
public $channel_eprvkey;
|
||||
public $channel_notifyflags;
|
||||
public $channel_pageflags;
|
||||
public $channel_dirdate;
|
||||
public $channel_lastpost;
|
||||
public $channel_deleted;
|
||||
public $channel_active;
|
||||
public $channel_max_anon_mail;
|
||||
public $channel_max_friend_req;
|
||||
public $channel_expire_days;
|
||||
public $channel_passwd_reset;
|
||||
public $channel_default_group;
|
||||
public $channel_allow_cid;
|
||||
public $channel_allow_gid;
|
||||
public $channel_deny_cid;
|
||||
public $channel_deny_gid;
|
||||
public $channel_removed;
|
||||
public $channel_system;
|
||||
public $channel_moved;
|
||||
public $channel_password;
|
||||
public $channel_salt;
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return $this->channel_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $channel_id
|
||||
* @return Channel
|
||||
*/
|
||||
public function setId($channel_id)
|
||||
{
|
||||
$this->channel_id = $channel_id;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getAccountId()
|
||||
{
|
||||
return $this->channel_account_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $channel_account_id
|
||||
* @return Channel
|
||||
*/
|
||||
public function setAccountId($channel_account_id)
|
||||
{
|
||||
$this->channel_account_id = $channel_account_id;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getPrimary()
|
||||
{
|
||||
return $this->channel_primary;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $channel_primary
|
||||
* @return Channel
|
||||
*/
|
||||
public function setPrimary($channel_primary)
|
||||
{
|
||||
$this->channel_primary = $channel_primary;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return $this->channel_name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $channel_name
|
||||
* @return Channel
|
||||
*/
|
||||
public function setName($channel_name)
|
||||
{
|
||||
$this->channel_name = $channel_name;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getParent()
|
||||
{
|
||||
return $this->channel_parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $channel_parent
|
||||
* @return Channel
|
||||
*/
|
||||
public function setParent($channel_parent)
|
||||
{
|
||||
$this->channel_parent = $channel_parent;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getAddress()
|
||||
{
|
||||
return $this->channel_address;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $channel_address
|
||||
* @return Channel
|
||||
*/
|
||||
public function setAddress($channel_address)
|
||||
{
|
||||
$this->channel_address = $channel_address;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getGuid()
|
||||
{
|
||||
return $this->channel_guid;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $channel_guid
|
||||
* @return Channel
|
||||
*/
|
||||
public function setGuid($channel_guid)
|
||||
{
|
||||
$this->channel_guid = $channel_guid;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getGuidSig()
|
||||
{
|
||||
return $this->channel_guid_sig;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $channel_guid_sig
|
||||
* @return Channel
|
||||
*/
|
||||
public function setGuidSig($channel_guid_sig)
|
||||
{
|
||||
$this->channel_guid_sig = $channel_guid_sig;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getHash()
|
||||
{
|
||||
return $this->channel_hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $channel_hash
|
||||
* @return Channel
|
||||
*/
|
||||
public function setHash($channel_hash)
|
||||
{
|
||||
$this->channel_hash = $channel_hash;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getTimezone()
|
||||
{
|
||||
return $this->channel_timezone;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $channel_timezone
|
||||
* @return Channel
|
||||
*/
|
||||
public function setTimezone($channel_timezone)
|
||||
{
|
||||
$this->channel_timezone = $channel_timezone;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getLocation()
|
||||
{
|
||||
return $this->channel_location;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $channel_location
|
||||
* @return Channel
|
||||
*/
|
||||
public function setLocation($channel_location)
|
||||
{
|
||||
$this->channel_location = $channel_location;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getTheme()
|
||||
{
|
||||
return $this->channel_theme;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $channel_theme
|
||||
* @return Channel
|
||||
*/
|
||||
public function setTheme($channel_theme)
|
||||
{
|
||||
$this->channel_theme = $channel_theme;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getStartpage()
|
||||
{
|
||||
return $this->channel_startpage;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $channel_startpage
|
||||
* @return Channel
|
||||
*/
|
||||
public function setStartpage($channel_startpage)
|
||||
{
|
||||
$this->channel_startpage = $channel_startpage;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getPubkey()
|
||||
{
|
||||
return $this->channel_pubkey;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $channel_pubkey
|
||||
* @return Channel
|
||||
*/
|
||||
public function setPubkey($channel_pubkey)
|
||||
{
|
||||
$this->channel_pubkey = $channel_pubkey;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getPrvkey()
|
||||
{
|
||||
return $this->channel_prvkey;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $channel_prvkey
|
||||
* @return Channel
|
||||
*/
|
||||
public function setPrvkey($channel_prvkey)
|
||||
{
|
||||
$this->channel_prvkey = $channel_prvkey;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getEpubkey()
|
||||
{
|
||||
return $this->channel_epubkey;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $channel_epubkey
|
||||
* @return Channel
|
||||
*/
|
||||
public function setEpubkey($channel_epubkey)
|
||||
{
|
||||
$this->channel_epubkey = $channel_epubkey;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getEprvkey()
|
||||
{
|
||||
return $this->channel_eprvkey;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $channel_eprvkey
|
||||
* @return Channel
|
||||
*/
|
||||
public function setEprvkey($channel_eprvkey)
|
||||
{
|
||||
$this->channel_eprvkey = $channel_eprvkey;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getNotifyflags()
|
||||
{
|
||||
return $this->channel_notifyflags;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $channel_notifyflags
|
||||
* @return Channel
|
||||
*/
|
||||
public function setNotifyflags($channel_notifyflags)
|
||||
{
|
||||
$this->channel_notifyflags = $channel_notifyflags;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getPageflags()
|
||||
{
|
||||
return $this->channel_pageflags;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $channel_pageflags
|
||||
* @return Channel
|
||||
*/
|
||||
public function setPageflags($channel_pageflags)
|
||||
{
|
||||
$this->channel_pageflags = $channel_pageflags;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getDirdate()
|
||||
{
|
||||
return $this->channel_dirdate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $channel_dirdate
|
||||
* @return Channel
|
||||
*/
|
||||
public function setDirdate($channel_dirdate)
|
||||
{
|
||||
$this->channel_dirdate = $channel_dirdate;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getLastpost()
|
||||
{
|
||||
return $this->channel_lastpost;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $channel_lastpost
|
||||
* @return Channel
|
||||
*/
|
||||
public function setLastpost($channel_lastpost)
|
||||
{
|
||||
$this->channel_lastpost = $channel_lastpost;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getDeleted()
|
||||
{
|
||||
return $this->channel_deleted;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $channel_deleted
|
||||
* @return Channel
|
||||
*/
|
||||
public function setDeleted($channel_deleted)
|
||||
{
|
||||
$this->channel_deleted = $channel_deleted;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getActive()
|
||||
{
|
||||
return $this->channel_active;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $channel_active
|
||||
* @return Channel
|
||||
*/
|
||||
public function setActive($channel_active)
|
||||
{
|
||||
$this->channel_active = $channel_active;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getMaxAnonMail()
|
||||
{
|
||||
return $this->channel_max_anon_mail;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $channel_max_anon_mail
|
||||
* @return Channel
|
||||
*/
|
||||
public function setMaxAnonMail($channel_max_anon_mail)
|
||||
{
|
||||
$this->channel_max_anon_mail = $channel_max_anon_mail;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getMaxFriendReq()
|
||||
{
|
||||
return $this->channel_max_friend_req;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $channel_max_friend_req
|
||||
* @return Channel
|
||||
*/
|
||||
public function setMaxFriendReq($channel_max_friend_req)
|
||||
{
|
||||
$this->channel_max_friend_req = $channel_max_friend_req;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getExpireDays()
|
||||
{
|
||||
return $this->channel_expire_days;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $channel_expire_days
|
||||
* @return Channel
|
||||
*/
|
||||
public function setExpireDays($channel_expire_days)
|
||||
{
|
||||
$this->channel_expire_days = $channel_expire_days;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getPasswdReset()
|
||||
{
|
||||
return $this->channel_passwd_reset;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $channel_passwd_reset
|
||||
* @return Channel
|
||||
*/
|
||||
public function setPasswdReset($channel_passwd_reset)
|
||||
{
|
||||
$this->channel_passwd_reset = $channel_passwd_reset;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getDefaultGroup()
|
||||
{
|
||||
return $this->channel_default_group;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $channel_default_group
|
||||
* @return Channel
|
||||
*/
|
||||
public function setDefaultGroup($channel_default_group)
|
||||
{
|
||||
$this->channel_default_group = $channel_default_group;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getAllowCid()
|
||||
{
|
||||
return $this->channel_allow_cid;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $channel_allow_cid
|
||||
* @return Channel
|
||||
*/
|
||||
public function setAllowCid($channel_allow_cid)
|
||||
{
|
||||
$this->channel_allow_cid = $channel_allow_cid;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getAllowGid()
|
||||
{
|
||||
return $this->channel_allow_gid;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $channel_allow_gid
|
||||
* @return Channel
|
||||
*/
|
||||
public function setAllowGid($channel_allow_gid)
|
||||
{
|
||||
$this->channel_allow_gid = $channel_allow_gid;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getDenyCid()
|
||||
{
|
||||
return $this->channel_deny_cid;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $channel_deny_cid
|
||||
* @return Channel
|
||||
*/
|
||||
public function setDenyCid($channel_deny_cid)
|
||||
{
|
||||
$this->channel_deny_cid = $channel_deny_cid;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getDenyGid()
|
||||
{
|
||||
return $this->channel_deny_gid;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $channel_deny_gid
|
||||
* @return Channel
|
||||
*/
|
||||
public function setDenyGid($channel_deny_gid)
|
||||
{
|
||||
$this->channel_deny_gid = $channel_deny_gid;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getRemoved()
|
||||
{
|
||||
return $this->channel_removed;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $channel_removed
|
||||
* @return Channel
|
||||
*/
|
||||
public function setRemoved($channel_removed)
|
||||
{
|
||||
$this->channel_removed = $channel_removed;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getSystem()
|
||||
{
|
||||
return $this->channel_system;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $channel_system
|
||||
* @return Channel
|
||||
*/
|
||||
public function setSystem($channel_system)
|
||||
{
|
||||
$this->channel_system = $channel_system;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getMoved()
|
||||
{
|
||||
return $this->channel_moved;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $channel_moved
|
||||
* @return Channel
|
||||
*/
|
||||
public function setMoved($channel_moved)
|
||||
{
|
||||
$this->channel_moved = $channel_moved;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getPassword()
|
||||
{
|
||||
return $this->channel_password;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $channel_password
|
||||
* @return Channel
|
||||
*/
|
||||
public function setPassword($channel_password)
|
||||
{
|
||||
$this->channel_password = $channel_password;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getSalt()
|
||||
{
|
||||
return $this->channel_salt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $channel_salt
|
||||
* @return Channel
|
||||
*/
|
||||
public function setSalt($channel_salt)
|
||||
{
|
||||
$this->channel_salt = $channel_salt;
|
||||
return $this;
|
||||
}
|
||||
|
||||
}
|
||||
1498
Zotlabs/Entity/Item.php
Normal file
1498
Zotlabs/Entity/Item.php
Normal file
File diff suppressed because it is too large
Load Diff
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace Zotlabs\Extend;
|
||||
|
||||
use Zotlabs\Lib\Config;
|
||||
|
||||
class Route {
|
||||
|
||||
@@ -38,11 +39,11 @@ class Route {
|
||||
}
|
||||
|
||||
static function get() {
|
||||
return get_config('system','routes',[]);
|
||||
return Config::Get('system','routes',[]);
|
||||
}
|
||||
|
||||
static function set($r) {
|
||||
return set_config('system','routes',$r);
|
||||
return Config::Set('system','routes',$r);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace Zotlabs\Extend;
|
||||
|
||||
use Zotlabs\Lib\Config;
|
||||
|
||||
class Widget {
|
||||
|
||||
@@ -38,10 +39,10 @@ class Widget {
|
||||
}
|
||||
|
||||
static function get() {
|
||||
return get_config('system','widgets',[]);
|
||||
return Config::Get('system','widgets',[]);
|
||||
}
|
||||
|
||||
static function set($r) {
|
||||
return set_config('system','widgets',$r);
|
||||
return Config::Set('system','widgets',$r);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
namespace Zotlabs\Identity;
|
||||
|
||||
use Zotlabs\Lib\Config;
|
||||
|
||||
class OAuth2Server extends \OAuth2\Server {
|
||||
|
||||
public function __construct(OAuth2Storage $storage, $config = null) {
|
||||
@@ -24,8 +26,8 @@ class OAuth2Server extends \OAuth2\Server {
|
||||
|
||||
$keyStorage = new \OAuth2\Storage\Memory( [
|
||||
'keys' => [
|
||||
'public_key' => get_config('system', 'pubkey'),
|
||||
'private_key' => get_config('system', 'prvkey')
|
||||
'public_key' => Config::Get('system', 'pubkey'),
|
||||
'private_key' => Config::Get('system', 'prvkey')
|
||||
]
|
||||
]);
|
||||
|
||||
|
||||
33
Zotlabs/Lib/ASCache.php
Normal file
33
Zotlabs/Lib/ASCache.php
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php /** @file */
|
||||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
/**
|
||||
* A wrapper for the cache api
|
||||
*/
|
||||
|
||||
class ASCache {
|
||||
public static function isEnabled() {
|
||||
return Config::Get('system', 'as_object_cache_enabled', true);
|
||||
}
|
||||
|
||||
public static function getAge() {
|
||||
return Config::Get('system', 'as_object_cache_time', '10 MINUTE');
|
||||
}
|
||||
|
||||
public static function Get($key) {
|
||||
if (!self::isEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
return Cache::get($key, self::getAge());
|
||||
}
|
||||
|
||||
public static function Set($key, $value) {
|
||||
if (!self::isEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Cache::set($key, $value);
|
||||
}
|
||||
}
|
||||
@@ -24,6 +24,8 @@ class ASCollection {
|
||||
$this->direction = $direction;
|
||||
$this->limit = $limit;
|
||||
|
||||
$data = null;
|
||||
|
||||
if (is_array($obj)) {
|
||||
$data = $obj;
|
||||
}
|
||||
@@ -147,4 +149,4 @@ class ASCollection {
|
||||
}
|
||||
logger('nextpage: ' . $this->nextpage, LOGGER_DEBUG);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,12 +6,17 @@ namespace Zotlabs\Lib;
|
||||
class AbConfig {
|
||||
|
||||
static public function Load($chan,$xhash,$family = '') {
|
||||
if($family)
|
||||
$where = '';
|
||||
|
||||
if($family) {
|
||||
$where = sprintf(" and cat = '%s' ",dbesc($family));
|
||||
}
|
||||
|
||||
$r = q("select * from abconfig where chan = %d and xchan = '%s' $where",
|
||||
intval($chan),
|
||||
dbesc($xhash)
|
||||
);
|
||||
|
||||
return $r;
|
||||
}
|
||||
|
||||
@@ -21,7 +26,7 @@ class AbConfig {
|
||||
intval($chan),
|
||||
dbesc($xhash),
|
||||
dbesc($family),
|
||||
dbesc($key)
|
||||
dbesc($key)
|
||||
);
|
||||
if($r) {
|
||||
return ((preg_match('|^a:[0-9]+:{.*}$|s', $r[0]['v'])) ? unserialize($r[0]['v']) : $r[0]['v']);
|
||||
@@ -41,19 +46,19 @@ class AbConfig {
|
||||
dbesc($xhash),
|
||||
dbesc($family),
|
||||
dbesc($key),
|
||||
dbesc($dbvalue)
|
||||
dbesc($dbvalue)
|
||||
);
|
||||
}
|
||||
else {
|
||||
$r = q("update abconfig set v = '%s' where chan = %d and xchan = '%s' and cat = '%s' and k = '%s' ",
|
||||
dbesc($dbvalue),
|
||||
dbesc($dbvalue),
|
||||
dbesc($chan),
|
||||
dbesc($xhash),
|
||||
dbesc($family),
|
||||
dbesc($key)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
if($r)
|
||||
return $value;
|
||||
return false;
|
||||
|
||||
@@ -1,38 +1,37 @@
|
||||
<?php
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
use Zotlabs\Lib\Libsync;
|
||||
|
||||
|
||||
class AccessList {
|
||||
|
||||
static function add($uid,$name,$public = 0) {
|
||||
|
||||
$ret = false;
|
||||
static function add($uid, $name, $public = 0) {
|
||||
|
||||
$ret = false;
|
||||
$hash = '';
|
||||
if ($uid && $name) {
|
||||
$r = self::byname($uid,$name); // check for dups
|
||||
$r = self::by_name($uid, $name); // check for dups
|
||||
if ($r !== false) {
|
||||
|
||||
// This could be a problem.
|
||||
// This could be a problem.
|
||||
// Let's assume we've just created a list which we once deleted
|
||||
// all the old members are gone, but the list remains so we don't break any security
|
||||
// access lists. What we're doing here is reviving the dead list, but old content which
|
||||
// was restricted to this list may now be seen by the new list members.
|
||||
// was restricted to this list may now be seen by the new list members.
|
||||
|
||||
$z = q("SELECT * FROM pgrp WHERE id = %d LIMIT 1",
|
||||
intval($r)
|
||||
);
|
||||
if(($z) && $z[0]['deleted']) {
|
||||
if (($z) && $z[0]['deleted']) {
|
||||
q('UPDATE pgrp SET deleted = 0 WHERE id = %d', intval($z[0]['id']));
|
||||
notice( t('A deleted list with this name was revived. Existing item permissions <strong>may</strong> apply to this list and any future members. If this is not what you intended, please create another list with a different name.') . EOL);
|
||||
notice(t('A deleted privacy group with this name was revived. Existing item permissions <strong>may</strong> apply to this privacy group and any future members. If this is not what you intended, please create another privacy group with a different name.') . EOL);
|
||||
}
|
||||
return true;
|
||||
$hash = self::by_id($uid, $r);
|
||||
return $hash;
|
||||
}
|
||||
|
||||
$hash = new_uuid();
|
||||
|
||||
$r = q("INSERT INTO pgrp ( hash, uid, visible, gname )
|
||||
$r = q("INSERT INTO pgrp ( hash, uid, visible, gname )
|
||||
VALUES( '%s', %d, %d, '%s' ) ",
|
||||
dbesc($hash),
|
||||
intval($uid),
|
||||
@@ -42,12 +41,12 @@ class AccessList {
|
||||
$ret = $r;
|
||||
}
|
||||
|
||||
Libsync::build_sync_packet($uid,null,true);
|
||||
return $ret;
|
||||
Libsync::build_sync_packet($uid, null, true);
|
||||
|
||||
return (($ret) ? $hash : $ret);
|
||||
}
|
||||
|
||||
|
||||
static function remove($uid,$name) {
|
||||
static function remove($uid, $name) {
|
||||
$ret = false;
|
||||
if ($uid && $name) {
|
||||
$r = q("SELECT id, hash FROM pgrp WHERE uid = %d AND gname = '%s' LIMIT 1",
|
||||
@@ -55,36 +54,36 @@ class AccessList {
|
||||
dbesc($name)
|
||||
);
|
||||
if ($r) {
|
||||
$group_id = $r[0]['id'];
|
||||
$group_id = $r[0]['id'];
|
||||
$group_hash = $r[0]['hash'];
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// remove group from default posting lists
|
||||
$r = q("SELECT channel_default_group, channel_allow_gid, channel_deny_gid FROM channel WHERE channel_id = %d LIMIT 1",
|
||||
intval($uid)
|
||||
intval($uid)
|
||||
);
|
||||
if ($r) {
|
||||
$user_info = array_shift($r);
|
||||
$change = false;
|
||||
$change = false;
|
||||
|
||||
if ($user_info['channel_default_group'] == $group_hash) {
|
||||
$user_info['channel_default_group'] = '';
|
||||
$change = true;
|
||||
$change = true;
|
||||
}
|
||||
if (strpos($user_info['channel_allow_gid'], '<' . $group_hash . '>') !== false) {
|
||||
$user_info['channel_allow_gid'] = str_replace('<' . $group_hash . '>', '', $user_info['channel_allow_gid']);
|
||||
$change = true;
|
||||
$change = true;
|
||||
}
|
||||
if (strpos($user_info['channel_deny_gid'], '<' . $group_hash . '>') !== false) {
|
||||
$user_info['channel_deny_gid'] = str_replace('<' . $group_hash . '>', '', $user_info['channel_deny_gid']);
|
||||
$change = true;
|
||||
$change = true;
|
||||
}
|
||||
|
||||
if ($change) {
|
||||
q("UPDATE channel SET channel_default_group = '%s', channel_allow_gid = '%s', channel_deny_gid = '%s'
|
||||
q("UPDATE channel SET channel_default_group = '%s', channel_allow_gid = '%s', channel_deny_gid = '%s'
|
||||
WHERE channel_id = %d",
|
||||
intval($user_info['channel_default_group']),
|
||||
dbesc($user_info['channel_allow_gid']),
|
||||
@@ -110,16 +109,16 @@ class AccessList {
|
||||
|
||||
}
|
||||
|
||||
Libsync::build_sync_packet($uid,null,true);
|
||||
Libsync::build_sync_packet($uid, null, true);
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
// returns the integer id of an access group owned by $uid and named $name
|
||||
// or false.
|
||||
|
||||
static function byname($uid,$name) {
|
||||
if (! ($uid && $name)) {
|
||||
|
||||
static function by_name($uid, $name) {
|
||||
if (!($uid && $name)) {
|
||||
return false;
|
||||
}
|
||||
$r = q("SELECT id FROM pgrp WHERE uid = %d AND gname = '%s' LIMIT 1",
|
||||
@@ -132,11 +131,11 @@ class AccessList {
|
||||
return false;
|
||||
}
|
||||
|
||||
static function by_id($uid,$id) {
|
||||
if (! ($uid && $id)) {
|
||||
static function by_id($uid, $id) {
|
||||
if (!($uid && $id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
$r = q("SELECT * FROM pgrp WHERE uid = %d AND id = %d and deleted = 0",
|
||||
intval($uid),
|
||||
intval($id)
|
||||
@@ -147,10 +146,8 @@ class AccessList {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static function rec_byhash($uid,$hash) {
|
||||
if (! ( $uid && $hash)) {
|
||||
static function by_hash($uid, $hash) {
|
||||
if (!($uid && $hash)) {
|
||||
return false;
|
||||
}
|
||||
$r = q("SELECT * FROM pgrp WHERE uid = %d AND hash = '%s' LIMIT 1",
|
||||
@@ -163,46 +160,46 @@ class AccessList {
|
||||
return false;
|
||||
}
|
||||
|
||||
static function member_remove($uid, $name, $member, $gid = 0) {
|
||||
if (!$gid) {
|
||||
$gid = self::by_name($uid, $name);
|
||||
}
|
||||
|
||||
static function member_remove($uid,$name,$member) {
|
||||
$gid = self::byname($uid,$name);
|
||||
if (! $gid) {
|
||||
return false;
|
||||
}
|
||||
if (! ($uid && $gid && $member)) {
|
||||
if (!($uid && $gid && $member)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$r = q("DELETE FROM pgrp_member WHERE uid = %d AND gid = %d AND xchan = '%s' ",
|
||||
intval($uid),
|
||||
intval($gid),
|
||||
dbesc($member)
|
||||
);
|
||||
|
||||
Libsync::build_sync_packet($uid,null,true);
|
||||
Libsync::build_sync_packet($uid, null, true);
|
||||
|
||||
return $r;
|
||||
}
|
||||
|
||||
|
||||
static function member_add($uid,$name,$member,$gid = 0) {
|
||||
if (! $gid) {
|
||||
$gid = self::byname($uid,$name);
|
||||
static function member_add($uid, $name, $member, $gid = 0) {
|
||||
if (!$gid) {
|
||||
$gid = self::by_name($uid, $name);
|
||||
}
|
||||
if (! ($gid && $uid && $member)) {
|
||||
if (!($gid && $uid && $member)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$r = q("SELECT * FROM pgrp_member WHERE uid = %d AND gid = %d AND xchan = '%s' LIMIT 1",
|
||||
$r = q("SELECT * FROM pgrp_member WHERE uid = %d AND gid = %d AND xchan = '%s' LIMIT 1",
|
||||
intval($uid),
|
||||
intval($gid),
|
||||
dbesc($member)
|
||||
);
|
||||
if ($r) {
|
||||
return true; // You might question this, but
|
||||
// we indicate success because the group member was in fact created
|
||||
// -- It was just created at another time
|
||||
return true;
|
||||
// You might question this, but
|
||||
// we indicate success because the group member was in fact created
|
||||
// -- It was just created at another time
|
||||
}
|
||||
else {
|
||||
else {
|
||||
$r = q("INSERT INTO pgrp_member (uid, gid, xchan)
|
||||
VALUES( %d, %d, '%s' ) ",
|
||||
intval($uid),
|
||||
@@ -210,15 +207,14 @@ class AccessList {
|
||||
dbesc($member)
|
||||
);
|
||||
}
|
||||
Libsync::build_sync_packet($uid,null,true);
|
||||
Libsync::build_sync_packet($uid, null, true);
|
||||
return $r;
|
||||
}
|
||||
|
||||
|
||||
static function members($uid, $gid) {
|
||||
$ret = [];
|
||||
if (intval($gid)) {
|
||||
$r = q("SELECT * FROM pgrp_member
|
||||
$r = q("SELECT * FROM pgrp_member
|
||||
LEFT JOIN abook ON abook_xchan = pgrp_member.xchan left join xchan on xchan_hash = abook_xchan
|
||||
WHERE gid = %d AND abook_channel = %d and pgrp_member.uid = %d and xchan_deleted = 0 and abook_self = 0 and abook_blocked = 0 and abook_pending = 0 ORDER BY xchan_name ASC ",
|
||||
intval($gid),
|
||||
@@ -232,7 +228,7 @@ class AccessList {
|
||||
return $ret;
|
||||
}
|
||||
|
||||
static function members_xchan($uid,$gid) {
|
||||
static function members_xchan($uid, $gid) {
|
||||
$ret = [];
|
||||
if (intval($gid)) {
|
||||
$r = q("SELECT xchan FROM pgrp_member WHERE gid = %d AND uid = %d",
|
||||
@@ -248,99 +244,75 @@ class AccessList {
|
||||
return $ret;
|
||||
}
|
||||
|
||||
static function members_profile_xchan($uid,$gid) {
|
||||
static function profile_members_xchan($uid,$gid) {
|
||||
$ret = [];
|
||||
if (intval($gid)) {
|
||||
|
||||
if(intval($gid)) {
|
||||
$r = q("SELECT abook_xchan as xchan from abook left join profile on abook_profile = profile_guid where profile.id = %d and profile.uid = %d",
|
||||
intval($gid),
|
||||
intval($uid)
|
||||
);
|
||||
if ($r) {
|
||||
foreach($r as $rv) {
|
||||
$ret[] = $rv['xchan'];
|
||||
if($r) {
|
||||
foreach($r as $rr) {
|
||||
$ret[] = $rr['xchan'];
|
||||
}
|
||||
}
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
static function select($uid, $options) {
|
||||
|
||||
$selected = $options['selected'] ?? '';
|
||||
$form_id = $options['form_id'] ?? 'accesslist_select';
|
||||
$label = $options['label'] ?? t('Select a privacy group');
|
||||
$before = $options['before'] ?? [];
|
||||
$after = $options['after'] ?? [];
|
||||
|
||||
|
||||
static function select($uid,$group = '') {
|
||||
|
||||
$grps = [];
|
||||
$o = '';
|
||||
|
||||
$grps[] = [
|
||||
'name' => '',
|
||||
'id' => '0',
|
||||
'selected' => false
|
||||
];
|
||||
|
||||
if ($before) {
|
||||
$grps[] = $before;
|
||||
}
|
||||
|
||||
$r = q("SELECT * FROM pgrp WHERE deleted = 0 AND uid = %d ORDER BY gname ASC",
|
||||
intval($uid)
|
||||
);
|
||||
$grps[] = [ 'name' => '', 'hash' => '0', 'selected' => '' ];
|
||||
if ($r) {
|
||||
foreach ($r as $rr) {
|
||||
$grps[] = [ 'name' => $rr['gname'], 'id' => $rr['hash'], 'selected' => (($group == $rr['hash']) ? 'true' : '') ];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return replace_macros(get_markup_template('group_selection.tpl'), [
|
||||
'$label' => t('Add new connections to this access list'),
|
||||
'$groups' => $grps
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
static function widget($every="connections",$each="lists",$edit = false, $group_id = 0, $cid = '',$mode = 1) {
|
||||
|
||||
$o = '';
|
||||
|
||||
$groups = [];
|
||||
|
||||
$r = q("SELECT * FROM pgrp WHERE deleted = 0 AND uid = %d ORDER BY gname ASC",
|
||||
intval($_SESSION['uid'])
|
||||
);
|
||||
$member_of = [];
|
||||
if ($cid) {
|
||||
$member_of = self::containing(local_channel(),$cid);
|
||||
}
|
||||
|
||||
if ($r) {
|
||||
foreach ($r as $rr) {
|
||||
$selected = (($group_id == $rr['id']) ? ' group-selected' : '');
|
||||
|
||||
if ($edit) {
|
||||
$groupedit = [ 'href' => "lists/".$rr['id'], 'title' => t('edit') ];
|
||||
}
|
||||
else {
|
||||
$groupedit = null;
|
||||
}
|
||||
|
||||
$groups[] = [
|
||||
'id' => $rr['id'],
|
||||
'enc_cid' => base64url_encode($cid),
|
||||
'cid' => $cid,
|
||||
'text' => $rr['gname'],
|
||||
'selected' => $selected,
|
||||
'href' => (($mode == 0) ? $each.'?f=&gid='.$rr['id'] : $each."/".$rr['id']) . ((x($_GET,'new')) ? '&new=' . $_GET['new'] : '') . ((x($_GET,'order')) ? '&order=' . $_GET['order'] : ''),
|
||||
'edit' => $groupedit,
|
||||
'ismember' => in_array($rr['id'],$member_of),
|
||||
if($r) {
|
||||
foreach($r as $rr) {
|
||||
$grps[] = [
|
||||
'name' => $rr['gname'],
|
||||
'id' => $rr['hash'],
|
||||
'selected' => ($selected == $rr['hash'])
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return replace_macros(get_markup_template('group_side.tpl'), [
|
||||
'$title' => t('Lists'),
|
||||
'$edittext' => t('Edit list'),
|
||||
'$createtext' => t('Create new list'),
|
||||
'$ungrouped' => (($every === 'contacts') ? t('Channels not in any access list') : ''),
|
||||
'$groups' => $groups,
|
||||
'$add' => t('add'),
|
||||
]);
|
||||
|
||||
if ($after) {
|
||||
$grps[] = $after;
|
||||
}
|
||||
|
||||
logger('select: ' . print_r($grps,true), LOGGER_DATA);
|
||||
|
||||
$o = replace_macros(get_markup_template('group_selection.tpl'), array(
|
||||
'$label' => $label,
|
||||
'$form_id' => $form_id,
|
||||
'$groups' => $grps
|
||||
));
|
||||
|
||||
return $o;
|
||||
}
|
||||
|
||||
|
||||
static function expand($g) {
|
||||
if (! (is_array($g) && count($g))) {
|
||||
if (!(is_array($g) && count($g))) {
|
||||
return [];
|
||||
}
|
||||
|
||||
@@ -350,8 +322,8 @@ class AccessList {
|
||||
// private profile linked virtual groups
|
||||
|
||||
foreach ($g as $gv) {
|
||||
if (substr($gv,0,3) === 'vp.') {
|
||||
$profile_hash = substr($gv,3);
|
||||
if (substr($gv, 0, 3) === 'vp.') {
|
||||
$profile_hash = substr($gv, 3);
|
||||
if ($profile_hash) {
|
||||
$r = q("select abook_xchan from abook where abook_profile = '%s'",
|
||||
dbesc($profile_hash)
|
||||
@@ -366,10 +338,10 @@ class AccessList {
|
||||
else {
|
||||
$x[] = $gv;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($x) {
|
||||
stringify_array_elms($x,true);
|
||||
stringify_array_elms($x, true);
|
||||
$groups = implode(',', $x);
|
||||
if ($groups) {
|
||||
$r = q("SELECT xchan FROM pgrp_member WHERE gid IN ( select id from pgrp where hash in ( $groups ))");
|
||||
@@ -383,9 +355,8 @@ class AccessList {
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
static function member_of($c) {
|
||||
$r = q("SELECT pgrp.gname, pgrp.id FROM pgrp LEFT JOIN pgrp_member ON pgrp_member.gid = pgrp.id
|
||||
$r = q("SELECT pgrp.gname, pgrp.id FROM pgrp LEFT JOIN pgrp_member ON pgrp_member.gid = pgrp.id
|
||||
WHERE pgrp_member.xchan = '%s' AND pgrp.deleted = 0 ORDER BY pgrp.gname ASC ",
|
||||
dbesc($c)
|
||||
);
|
||||
@@ -393,7 +364,7 @@ class AccessList {
|
||||
return $r;
|
||||
}
|
||||
|
||||
static function containing($uid,$c) {
|
||||
static function containing($uid, $c) {
|
||||
|
||||
$r = q("SELECT gid FROM pgrp_member WHERE uid = %d AND pgrp_member.xchan = '%s' ",
|
||||
intval($uid),
|
||||
@@ -405,7 +376,8 @@ class AccessList {
|
||||
foreach ($r as $rv)
|
||||
$ret[] = $rv['gid'];
|
||||
}
|
||||
|
||||
|
||||
return $ret;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -11,8 +11,10 @@ class ActivityStreams {
|
||||
|
||||
public $raw = null;
|
||||
public $data = null;
|
||||
public $meta = null;
|
||||
public $valid = false;
|
||||
public $deleted = false;
|
||||
public $portable_id = null;
|
||||
public $id = '';
|
||||
public $parent_id = '';
|
||||
public $type = '';
|
||||
@@ -22,10 +24,11 @@ class ActivityStreams {
|
||||
public $origin = null;
|
||||
public $owner = null;
|
||||
public $signer = null;
|
||||
public $ldsig = null;
|
||||
public $sig = null;
|
||||
public $sigok = false;
|
||||
public $recips = null;
|
||||
public $raw_recips = null;
|
||||
public $saved_recips = null;
|
||||
|
||||
/**
|
||||
* @brief Constructor for ActivityStreams.
|
||||
@@ -34,12 +37,17 @@ class ActivityStreams {
|
||||
*
|
||||
* @param string $string
|
||||
*/
|
||||
function __construct($string) {
|
||||
function __construct($string, $portable_id = null) {
|
||||
|
||||
if(!$string)
|
||||
return;
|
||||
|
||||
$this->raw = $string;
|
||||
$this->portable_id = $portable_id;
|
||||
|
||||
if (is_array($string)) {
|
||||
$this->data = $string;
|
||||
$this->raw = json_encode($string, JSON_UNESCAPED_SLASHES);
|
||||
}
|
||||
else {
|
||||
$this->data = json_decode($string, true);
|
||||
@@ -56,18 +64,21 @@ class ActivityStreams {
|
||||
if ($ret['signer']) {
|
||||
$saved = json_encode($this->data, JSON_UNESCAPED_SLASHES);
|
||||
$this->data = $tmp;
|
||||
$this->data['signer'] = $ret['signer'];
|
||||
$this->data['signed_data'] = $saved;
|
||||
$this->meta['signer'] = $ret['signer'];
|
||||
$this->meta['signed_data'] = $saved;
|
||||
if ($ret['hubloc']) {
|
||||
$this->data['hubloc'] = $ret['hubloc'];
|
||||
$this->meta['hubloc'] = $ret['hubloc'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This indicates only that we have sucessfully decoded JSON.
|
||||
$this->valid = true;
|
||||
|
||||
if (array_key_exists('type', $this->data) && array_key_exists('actor', $this->data) && array_key_exists('object', $this->data)) {
|
||||
// Special handling for Mastodon "delete actor" activities which will often fail to verify
|
||||
// because the key cannot be fetched. We will catch this condition elsewhere.
|
||||
if (is_array($this->data) && 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;
|
||||
@@ -76,8 +87,18 @@ class ActivityStreams {
|
||||
|
||||
}
|
||||
|
||||
// Attempt to assemble an Activity from what we were given.
|
||||
if ($this->is_valid()) {
|
||||
$this->id = $this->get_property_obj('id');
|
||||
$this->id = $this->get_property_obj('id');
|
||||
|
||||
if (!$this->id) {
|
||||
logger('Data with mmissing id: ' . print_r($this->data, true));
|
||||
return;
|
||||
}
|
||||
|
||||
// cache for future use
|
||||
ASCache::Set($this->id, 'json:' . $this->raw);
|
||||
|
||||
$this->type = $this->get_primary_type();
|
||||
$this->actor = $this->get_actor('actor', '', '');
|
||||
$this->obj = $this->get_compound_property('object');
|
||||
@@ -85,11 +106,19 @@ class ActivityStreams {
|
||||
$this->origin = $this->get_compound_property('origin');
|
||||
$this->recips = $this->collect_recips();
|
||||
|
||||
$this->ldsig = $this->get_compound_property('signature');
|
||||
if ($this->ldsig) {
|
||||
$this->signer = $this->get_compound_property('creator', $this->ldsig);
|
||||
if ($this->signer && is_array($this->signer) && array_key_exists('publicKey', $this->signer) && is_array($this->signer['publicKey']) && $this->signer['publicKey']['publicKeyPem']) {
|
||||
$this->sigok = LDSignatures::verify($this->data, $this->signer['publicKey']['publicKeyPem']);
|
||||
$this->sig = $this->get_compound_property('proof');
|
||||
if ($this->sig) {
|
||||
$this->checkEddsaSignature(); // will set signer and sigok if everything works out
|
||||
}
|
||||
|
||||
// Try LDSignatures if edsig failed
|
||||
if (!$this->sigok) {
|
||||
$this->sig = $this->get_compound_property('signature');
|
||||
if ($this->sig) {
|
||||
$this->signer = $this->get_actor('creator', $this->sig);
|
||||
if ($this->signer && is_array($this->signer) && array_key_exists('publicKey', $this->signer) && is_array($this->signer['publicKey']) && $this->signer['publicKey']['publicKeyPem']) {
|
||||
$this->sigok = LDSignatures::verify($this->data, $this->signer['publicKey']['publicKeyPem']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,25 +130,34 @@ class ActivityStreams {
|
||||
}
|
||||
}
|
||||
|
||||
// fetch recursive or embedded activities
|
||||
// Fetch recursive or embedded activities
|
||||
|
||||
if ($this->obj && is_array($this->obj) && array_key_exists('object', $this->obj)) {
|
||||
$this->obj['object'] = $this->get_compound_property($this->obj['object']);
|
||||
$this->obj['object'] = $this->get_compound_property('object', $this->obj);
|
||||
}
|
||||
|
||||
if ($this->obj && is_array($this->obj) && $this->obj['actor'])
|
||||
// Enumerate and store actors in referenced objects
|
||||
|
||||
if ($this->obj && is_array($this->obj) && isset($this->obj['actor'])) {
|
||||
$this->obj['actor'] = $this->get_actor('actor', $this->obj);
|
||||
if ($this->tgt && is_array($this->tgt) && $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)) {
|
||||
|
||||
if ($this->tgt && is_array($this->tgt) && isset($this->tgt['actor'])) {
|
||||
$this->tgt['actor'] = $this->get_actor('actor', $this->tgt);
|
||||
}
|
||||
|
||||
// Determine if this is a followup or response activity
|
||||
|
||||
$this->parent_id = ((is_array($this->get_property_obj('inReplyTo'))) ? $this->get_property_obj('inReplyTo')['id'] : $this->get_property_obj('inReplyTo'));
|
||||
|
||||
if (!$this->parent_id && isset($this->obj['inReplyTo'])) {
|
||||
$this->parent_id = ((is_array($this->obj['inReplyTo'])) ? $this->obj['inReplyTo']['id'] : $this->obj['inReplyTo']);
|
||||
}
|
||||
|
||||
if (!$this->parent_id && isset($this->obj['id'])) {
|
||||
$this->parent_id = $this->obj['id'];
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,36 +174,59 @@ class ActivityStreams {
|
||||
$this->saved_recips = $arr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief get single property from Activity object
|
||||
*
|
||||
* @param string $property
|
||||
* @param mixed $default return value if property or object not set
|
||||
* or object is a string id which could not be fetched.
|
||||
* @return mixed
|
||||
*/
|
||||
public function objprop(string $property, mixed $default = false): mixed {
|
||||
$x = $this->get_property_obj($property, $this->obj);
|
||||
return (isset($x)) ? $x : $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Collects all recipients.
|
||||
*
|
||||
* @param string $base
|
||||
* @param mixed $base
|
||||
* @param string $namespace (optional) default empty
|
||||
* @return array
|
||||
*/
|
||||
function collect_recips($base = '', $namespace = '') {
|
||||
$x = [];
|
||||
public function collect_recips(mixed $base = '', string $namespace = ''): array {
|
||||
$result = [];
|
||||
$tmp = [];
|
||||
|
||||
$fields = ['to', 'cc', 'bto', 'bcc', 'audience'];
|
||||
foreach ($fields as $f) {
|
||||
$y = $this->get_compound_property($f, $base, $namespace);
|
||||
if ($y) {
|
||||
if (!is_array($this->raw_recips)) {
|
||||
$this->raw_recips = [];
|
||||
}
|
||||
|
||||
if (!is_array($y)) {
|
||||
$y = [$y];
|
||||
}
|
||||
$this->raw_recips[$f] = $y;
|
||||
$x = array_merge($x, $y);
|
||||
foreach ($fields as $field) {
|
||||
// don't expand these yet
|
||||
$values = $this->get_property_obj($field, $base, $namespace);
|
||||
if ($values) {
|
||||
$values = force_array($values);
|
||||
$tmp[$field] = $values;
|
||||
$result = array_values(array_unique(array_merge($result, $values)));
|
||||
}
|
||||
// Merge the object recipients if they exist.
|
||||
$values = $this->objprop($field);
|
||||
if ($values) {
|
||||
$values = force_array($values);
|
||||
$tmp[$field] = ((isset($tmp[$field])) ? array_merge($tmp[$field], $values) : $values);
|
||||
$result = array_values(array_unique(array_merge($result, $values)));
|
||||
}
|
||||
// remove duplicates
|
||||
if (isset($tmp[$field])) {
|
||||
$tmp[$field] = array_values(array_unique($tmp[$field]));
|
||||
}
|
||||
}
|
||||
// not yet ready for prime time
|
||||
// $x = $this->expand($x,$base,$namespace);
|
||||
return $x;
|
||||
$this->raw_recips = $tmp;
|
||||
|
||||
// not yet ready for prime time
|
||||
// $result = $this->expand($result,$base,$namespace);
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
function expand($arr, $base = '', $namespace = '') {
|
||||
$ret = [];
|
||||
|
||||
@@ -269,12 +330,27 @@ class ActivityStreams {
|
||||
* @return NULL|mixed
|
||||
*/
|
||||
|
||||
function fetch_property($url) {
|
||||
return self::fetch($url);
|
||||
}
|
||||
function fetch_property($url, $channel = null) {
|
||||
$x = null;
|
||||
|
||||
static function fetch($url, $channel = null) {
|
||||
return Activity::fetch($url, $channel);
|
||||
if (str_starts_with($url, z_root() . '/item/')) {
|
||||
$x = Activity::fetch_local($url, $this->portable_id ?? '');
|
||||
logger('local: ' . print_r($x,true));
|
||||
}
|
||||
|
||||
if (!$x) {
|
||||
$x = Activity::fetch($url, $channel);
|
||||
if ($x === null && strpos($url, '/channel/')) {
|
||||
// look for other nomadic channels which might be alive
|
||||
$zf = Zotfinger::exec($url, $channel);
|
||||
if ($zf) {
|
||||
$url = $zf['signature']['signer'];
|
||||
$x = Activity::fetch($url, $channel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $x;
|
||||
}
|
||||
|
||||
static function is_an_actor($s) {
|
||||
@@ -285,7 +361,7 @@ class ActivityStreams {
|
||||
if (!$s) {
|
||||
return false;
|
||||
}
|
||||
return (in_array($s, ['Like', 'Dislike', 'Flag', 'Block', 'Accept', 'Reject', 'TentativeAccept', 'TentativeReject', 'emojiReaction', 'EmojiReaction', 'EmojiReact']));
|
||||
return (in_array($s, ['Announce', 'Like', 'Dislike', 'Flag', 'Block', 'Accept', 'Reject', 'TentativeAccept', 'TentativeReject', 'emojiReaction', 'EmojiReaction', 'EmojiReact']));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -299,20 +375,25 @@ class ActivityStreams {
|
||||
|
||||
function get_actor($property, $base = '', $namespace = '') {
|
||||
$x = $this->get_property_obj($property, $base, $namespace);
|
||||
|
||||
if ($this->is_url($x)) {
|
||||
$y = Activity::get_cached_actor($x);
|
||||
$y = Activity::get_actor($x);
|
||||
if ($y) {
|
||||
return $y;
|
||||
}
|
||||
}
|
||||
|
||||
$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;
|
||||
|
||||
return Activity::get_unknown_actor($this->data);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -327,13 +408,26 @@ class ActivityStreams {
|
||||
*/
|
||||
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);
|
||||
$cached = ASCache::Get($x);
|
||||
if ($cached) {
|
||||
// logger('AS cached: ' . $x);
|
||||
$y = unserialise($cached);
|
||||
}
|
||||
else {
|
||||
// logger('AS fetching: ' . $x);
|
||||
$y = $this->fetch_property($x);
|
||||
if ($y) {
|
||||
ASCache::Set($x, serialise($y));
|
||||
}
|
||||
}
|
||||
if (is_array($y)) {
|
||||
$x = $y;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// verify and unpack JSalmon signature if present
|
||||
|
||||
if (is_array($x) && array_key_exists('signed', $x)) {
|
||||
@@ -343,10 +437,10 @@ class ActivityStreams {
|
||||
if ($ret['signer']) {
|
||||
$saved = json_encode($x, JSON_UNESCAPED_SLASHES);
|
||||
$x = $tmp;
|
||||
$x['signer'] = $ret['signer'];
|
||||
$x['signed_data'] = $saved;
|
||||
$x['meta']['signer'] = $ret['signer'];
|
||||
$x['meta']['signed_data'] = $saved;
|
||||
if ($ret['hubloc']) {
|
||||
$x['hubloc'] = $ret['hubloc'];
|
||||
$x['meta']['hubloc'] = $ret['hubloc'];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -417,16 +511,74 @@ class ActivityStreams {
|
||||
|
||||
static function get_accept_header_string($channel = null) {
|
||||
|
||||
$ret = '';
|
||||
|
||||
$hookdata = [];
|
||||
if ($channel)
|
||||
$hookdata['channel'] = $channel;
|
||||
|
||||
$hookdata['data'] = 'application/x-zot-activity+json';
|
||||
$hookdata['data'] = ['application/x-zot-activity+json'];
|
||||
|
||||
call_hooks('get_accept_header_string', $hookdata);
|
||||
|
||||
return $hookdata['data'];
|
||||
$ret = implode(', ', $hookdata['data']);
|
||||
|
||||
return $ret;
|
||||
|
||||
}
|
||||
|
||||
public function checkEddsaSignature() {
|
||||
$signer = $this->get_property_obj('verificationMethod', $this->sig);
|
||||
|
||||
$parseUrl = parse_url($signer);
|
||||
|
||||
if (isset($parseUrl['fragment'])) {
|
||||
if (str_starts_with($parseUrl['fragment'], 'z6Mk')) {
|
||||
$publicKey = $parseUrl['fragment'];
|
||||
}
|
||||
unset($parseUrl['fragment']);
|
||||
}
|
||||
|
||||
if (isset($parseUrl['query'])) {
|
||||
unset($parseUrl['query']);
|
||||
}
|
||||
|
||||
$url = unparse_url($parseUrl);
|
||||
|
||||
$hublocs = Activity::get_actor_hublocs($url);
|
||||
|
||||
$hasStoredKey = false;
|
||||
if ($hublocs) {
|
||||
foreach ($hublocs as $hubloc) {
|
||||
if ($publicKey && $hubloc['xchan_epubkey'] === $publicKey) {
|
||||
$hasStoredKey = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!$hasStoredKey) {
|
||||
$this->signer = Activity::get_actor($url);
|
||||
|
||||
if (isset($this->signer['assertionMethod'])) {
|
||||
if (!isset($this->signer['assertionMethod'][0])) {
|
||||
$this->signer['assertionMethod'] = [$this->signer['assertionMethod']];
|
||||
}
|
||||
|
||||
foreach($this->signer['assertionMethod'] as $am) {
|
||||
if ($url === $am['controller'] &&
|
||||
$am['type'] === 'Multikey' &&
|
||||
str_starts_with($am['publicKeyMultibase'], 'z6Mk')
|
||||
) {
|
||||
$publicKey = $am['publicKeyMultibase'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($publicKey) {
|
||||
$this->sigok = (new JcsEddsa2022)->verify($this->data, $publicKey);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
use App;
|
||||
use Zotlabs\Lib\Libsync;
|
||||
use Zotlabs\Lib\Config;
|
||||
|
||||
require_once('include/plugin.php');
|
||||
require_once('include/channel.php');
|
||||
@@ -22,9 +22,10 @@ class Apps {
|
||||
* @brief
|
||||
*
|
||||
* @param boolean $translate (optional) default true
|
||||
* @param boolean $sync (optional) default false used if called from sync_sysapps()
|
||||
* @return array
|
||||
*/
|
||||
static public function get_system_apps($translate = true) {
|
||||
static public function get_system_apps($translate = true, $sync = false) {
|
||||
$ret = [];
|
||||
|
||||
if(is_dir('apps'))
|
||||
@@ -34,7 +35,7 @@ class Apps {
|
||||
|
||||
if($files) {
|
||||
foreach($files as $f) {
|
||||
$x = self::parse_app_description($f,$translate);
|
||||
$x = self::parse_app_description($f, $translate, $sync);
|
||||
if($x) {
|
||||
$ret[] = $x;
|
||||
}
|
||||
@@ -46,7 +47,7 @@ class Apps {
|
||||
$path = explode('/',$f);
|
||||
$plugin = trim($path[1]);
|
||||
if(plugin_is_installed($plugin)) {
|
||||
$x = self::parse_app_description($f,$translate);
|
||||
$x = self::parse_app_description($f, $translate, $sync);
|
||||
if($x) {
|
||||
$x['plugin'] = $plugin;
|
||||
$ret[] = $x;
|
||||
@@ -65,19 +66,17 @@ class Apps {
|
||||
}
|
||||
|
||||
static public function get_base_apps() {
|
||||
$x = get_config('system','base_apps',[
|
||||
$x = Config::Get('system','base_apps',[
|
||||
'Connections',
|
||||
'Contact Roles',
|
||||
'Network',
|
||||
'Settings',
|
||||
'Files',
|
||||
'Channel Home',
|
||||
'View Profile',
|
||||
'Channel',
|
||||
'Photos',
|
||||
'Calendar',
|
||||
'Directory',
|
||||
'Search',
|
||||
'Help',
|
||||
'Profile Photo',
|
||||
'HQ',
|
||||
'Post'
|
||||
]);
|
||||
@@ -161,7 +160,7 @@ class Apps {
|
||||
foreach(self::$available_apps as $iapp) {
|
||||
if($iapp['app_id'] == hash('whirlpool',$app['name'])) {
|
||||
$notfound = false;
|
||||
if(($iapp['app_version'] !== $app['version'])
|
||||
if((isset($app['version']) && $iapp['app_version'] !== $app['version'])
|
||||
|| ($app['plugin'] && (! $iapp['app_plugin']))) {
|
||||
return intval($iapp['app_id']);
|
||||
}
|
||||
@@ -210,9 +209,10 @@ class Apps {
|
||||
*
|
||||
* @param string $f filename
|
||||
* @param boolean $translate (optional) default true
|
||||
* @param boolean $sync (optional) default false
|
||||
* @return boolean|array
|
||||
*/
|
||||
static public function parse_app_description($f, $translate = true) {
|
||||
static public function parse_app_description($f, $translate = true, $sync = false) {
|
||||
$ret = [];
|
||||
$matches = [];
|
||||
|
||||
@@ -237,6 +237,7 @@ class Apps {
|
||||
$ret['photo'] = $baseurl . '/' . get_default_profile_photo(80);
|
||||
|
||||
$ret['type'] = 'system';
|
||||
$ret['plugin'] = '';
|
||||
|
||||
foreach($ret as $k => $v) {
|
||||
if(strpos($v,'http') === 0) {
|
||||
@@ -258,7 +259,7 @@ class Apps {
|
||||
if(array_key_exists('categories',$ret))
|
||||
$ret['categories'] = str_replace(array('\'','"'),array(''','&dquot;'),$ret['categories']);
|
||||
|
||||
if(array_key_exists('requires',$ret)) {
|
||||
if(array_key_exists('requires',$ret) && !$sync) {
|
||||
$requires = explode(',',$ret['requires']);
|
||||
foreach($requires as $require) {
|
||||
$require = trim(strtolower($require));
|
||||
@@ -301,7 +302,7 @@ class Apps {
|
||||
break;
|
||||
default:
|
||||
if($config)
|
||||
$unset = ((get_config('system', $require[0]) == $require[1]) ? false : true);
|
||||
$unset = ((Config::Get('system', $require[0]) == $require[1]) ? false : true);
|
||||
else
|
||||
$unset = ((local_channel() && feature_enabled(local_channel(),$require)) ? false : true);
|
||||
if($unset)
|
||||
@@ -310,14 +311,16 @@ class Apps {
|
||||
}
|
||||
}
|
||||
}
|
||||
if(isset($ret)) {
|
||||
if($translate)
|
||||
self::translate_system_apps($ret);
|
||||
|
||||
return $ret;
|
||||
if(empty($ret)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
if($translate) {
|
||||
self::translate_system_apps($ret);
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -343,15 +346,13 @@ class Apps {
|
||||
'Files' => t('Files'),
|
||||
'Webpages' => t('Webpages'),
|
||||
'Wiki' => t('Wiki'),
|
||||
'Channel Home' => t('Channel Home'),
|
||||
'Channel' => t('Channel'),
|
||||
'View Profile' => t('View Profile'),
|
||||
'Photos' => t('Photos'),
|
||||
'Calendar' => t('Calendar'),
|
||||
'Directory' => t('Directory'),
|
||||
'Help' => t('Help'),
|
||||
'Mail' => t('Mail'),
|
||||
'Mood' => t('Mood'),
|
||||
'Poke' => t('Poke'),
|
||||
'Chat' => t('Chat'),
|
||||
'Search' => t('Search'),
|
||||
'Probe' => t('Probe'),
|
||||
@@ -374,10 +375,10 @@ class Apps {
|
||||
'OAuth Apps Manager' => t('OAuth Apps Manager'),
|
||||
'OAuth2 Apps Manager' => t('OAuth2 Apps Manager'),
|
||||
'PDL Editor' => t('PDL Editor'),
|
||||
'Permission Categories' => t('Permission Categories'),
|
||||
'Contact Roles' => t('Contact Roles'),
|
||||
'Public Stream' => t('Public Stream'),
|
||||
'My Chatrooms' => t('My Chatrooms'),
|
||||
'Channel Export' => t('Channel Export'),
|
||||
'Channel Export' => t('Channel Export')
|
||||
);
|
||||
|
||||
if(array_key_exists('name',$arr)) {
|
||||
@@ -417,15 +418,32 @@ class Apps {
|
||||
static public function app_render($papp, $mode = 'view') {
|
||||
$installed = false;
|
||||
|
||||
if(! $papp)
|
||||
if(!$papp) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(! $papp['photo'])
|
||||
/**
|
||||
* @hooks app_render_before
|
||||
* Hook to manipulate the papp array before rendering
|
||||
*/
|
||||
|
||||
$hookinfo = [
|
||||
'name' => $papp['name'],
|
||||
'photo' => $papp['photo']
|
||||
];
|
||||
|
||||
call_hooks('app_render_manipulate_photo', $hookinfo);
|
||||
|
||||
// We will only allow to manipulate the photo
|
||||
$papp['photo'] = $hookinfo['photo'];
|
||||
|
||||
if(!$papp['photo']) {
|
||||
$papp['photo'] = 'icon:gear';
|
||||
}
|
||||
|
||||
self::translate_system_apps($papp);
|
||||
|
||||
if(trim($papp['plugin']) && (! plugin_is_installed(trim($papp['plugin']))))
|
||||
if(isset($papp['plugin']) && trim($papp['plugin']) && (! plugin_is_installed(trim($papp['plugin']))))
|
||||
return '';
|
||||
|
||||
$papp['papp'] = self::papp_encode($papp);
|
||||
@@ -506,7 +524,7 @@ class Apps {
|
||||
break;
|
||||
default:
|
||||
if($config)
|
||||
$unset = ((get_config('system', $require[0]) === $require[1]) ? false : true);
|
||||
$unset = ((Config::Get('system', $require[0]) === $require[1]) ? false : true);
|
||||
else
|
||||
$unset = ((local_channel() && feature_enabled(local_channel(),$require)) ? false : true);
|
||||
if($unset)
|
||||
@@ -520,8 +538,13 @@ class Apps {
|
||||
$hosturl = '';
|
||||
|
||||
if(local_channel()) {
|
||||
if(self::app_installed(local_channel(),$papp) && !$papp['deleted'])
|
||||
if(self::app_installed(local_channel(),$papp)) {
|
||||
$installed = true;
|
||||
}
|
||||
|
||||
if ($installed && isset($papp['deleted']) && $papp['deleted']) {
|
||||
$installed = false;
|
||||
}
|
||||
|
||||
$hosturl = z_root() . '/';
|
||||
}
|
||||
@@ -594,12 +617,12 @@ class Apps {
|
||||
'$edit' => ((local_channel() && $installed && $mode == 'edit') ? t('Edit') : ''),
|
||||
'$delete' => ((local_channel() && $mode == 'edit') ? t('Delete') : ''),
|
||||
'$undelete' => ((local_channel() && $mode == 'edit') ? t('Undelete') : ''),
|
||||
'$settings_url' => ((local_channel() && $installed && $mode == 'list') ? $papp['settings_url'] : ''),
|
||||
'$deleted' => $papp['deleted'],
|
||||
'$settings_url' => ((local_channel() && $installed && $mode == 'list' && isset($papp['settings_url'])) ? $papp['settings_url'] : ''),
|
||||
'$deleted' => $papp['deleted'] ?? false,
|
||||
'$feature' => ((isset($papp['embed']) || $mode == 'edit') ? false : true),
|
||||
'$pin' => ((isset($papp['embed']) || $mode == 'edit') ? false : true),
|
||||
'$featured' => ((strpos($papp['categories'], 'nav_featured_app') === false) ? false : true),
|
||||
'$pinned' => ((strpos($papp['categories'], 'nav_pinned_app') === false) ? false : true),
|
||||
'$featured' => ((isset($papp['categories']) && strpos($papp['categories'], 'nav_featured_app') !== false) ? true : false),
|
||||
'$pinned' => ((isset($papp['categories']) && strpos($papp['categories'], 'nav_pinned_app') !== false) ? true : false),
|
||||
'$mode' => $mode,
|
||||
'$add' => t('Add to app-tray'),
|
||||
'$remove' => t('Remove from app-tray'),
|
||||
@@ -624,10 +647,12 @@ class Apps {
|
||||
|
||||
$app['uid'] = $uid;
|
||||
|
||||
if(self::app_installed($uid,$app,true))
|
||||
if(self::app_installed($uid,$app,true)) {
|
||||
$x = self::app_update($app);
|
||||
else
|
||||
}
|
||||
else {
|
||||
$x = self::app_store($app);
|
||||
}
|
||||
|
||||
if($x['success']) {
|
||||
$r = q("select * from app where app_id = '%s' and app_channel = %d limit 1",
|
||||
@@ -635,13 +660,12 @@ class Apps {
|
||||
intval($uid)
|
||||
);
|
||||
if($r) {
|
||||
if(($app['uid']) && (! $r[0]['app_system'])) {
|
||||
if($app['categories'] && (! $app['term'])) {
|
||||
if($app['uid']) {
|
||||
if((isset($app['categories']) && $app['categories']) && !(isset($app['term']) && $app['term'])) {
|
||||
$r[0]['term'] = q("select * from term where otype = %d and oid = %d",
|
||||
intval(TERM_OBJ_APP),
|
||||
intval($r[0]['id'])
|
||||
);
|
||||
Libsync::build_sync_packet($uid,array('app' => $r[0]));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -670,6 +694,7 @@ class Apps {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -681,38 +706,35 @@ class Apps {
|
||||
dbesc($app['guid']),
|
||||
intval($uid)
|
||||
);
|
||||
if($x) {
|
||||
if(! intval($x[0]['app_deleted'])) {
|
||||
$x[0]['app_deleted'] = 1;
|
||||
if(self::can_delete($uid,$app)) {
|
||||
q("delete from app where app_id = '%s' and app_channel = %d",
|
||||
dbesc($app['guid']),
|
||||
intval($uid)
|
||||
);
|
||||
q("delete from term where otype = %d and oid = %d",
|
||||
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 {
|
||||
q("update app set app_deleted = 1 where app_id = '%s' and app_channel = %d",
|
||||
dbesc($app['guid']),
|
||||
intval($uid)
|
||||
);
|
||||
}
|
||||
if(! intval($x[0]['app_system'])) {
|
||||
Libsync::build_sync_packet($uid,array('app' => $x));
|
||||
}
|
||||
}
|
||||
else {
|
||||
self::app_undestroy($uid,$app);
|
||||
}
|
||||
|
||||
if($x && intval($x[0]['app_deleted'])) {
|
||||
self::app_undestroy($uid, $app);
|
||||
return;
|
||||
}
|
||||
|
||||
if(self::can_delete($uid,$app)) {
|
||||
q("delete from app where app_id = '%s' and app_channel = %d",
|
||||
dbesc($app['guid']),
|
||||
intval($uid)
|
||||
);
|
||||
|
||||
q("delete from term where otype = %d and oid = %d",
|
||||
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 {
|
||||
q("update app set app_deleted = 1 where app_id = '%s' and app_channel = %d",
|
||||
dbesc($app['guid']),
|
||||
intval($uid)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -729,13 +751,11 @@ class Apps {
|
||||
dbesc($app['guid']),
|
||||
intval($uid)
|
||||
);
|
||||
if($x) {
|
||||
if($x[0]['app_system']) {
|
||||
q("update app set app_deleted = 0 where app_id = '%s' and app_channel = %d",
|
||||
dbesc($app['guid']),
|
||||
intval($uid)
|
||||
);
|
||||
}
|
||||
if($x && intval($x[0]['app_deleted']) && $x[0]['app_system']) {
|
||||
q("update app set app_deleted = 0 where app_id = '%s' and app_channel = %d",
|
||||
dbesc($app['guid']),
|
||||
intval($uid)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -941,7 +961,7 @@ class Apps {
|
||||
|
||||
$conf = (($menu === 'nav_featured_app') ? 'app_order' : 'app_pin_order');
|
||||
|
||||
$x = (($uid) ? get_pconfig($uid,'system',$conf) : get_config('system',$conf));
|
||||
$x = (($uid) ? get_pconfig($uid,'system',$conf) : Config::Get('system',$conf));
|
||||
if(($x) && (! is_array($x))) {
|
||||
$y = explode(',',$x);
|
||||
$y = array_map('trim',$y);
|
||||
@@ -1186,7 +1206,7 @@ class Apps {
|
||||
$ret['success'] = true;
|
||||
$ret['app_id'] = $darray['app_id'];
|
||||
}
|
||||
if($arr['categories']) {
|
||||
if(isset($arr['categories']) && $arr['categories']) {
|
||||
$x = q("select id from app where app_id = '%s' and app_channel = %d limit 1",
|
||||
dbesc($darray['app_id']),
|
||||
intval($darray['app_channel'])
|
||||
@@ -1194,9 +1214,9 @@ class Apps {
|
||||
$y = explode(',',$arr['categories']);
|
||||
if($y) {
|
||||
foreach($y as $t) {
|
||||
$t = trim($t);
|
||||
$t = escape_tags(trim($t));
|
||||
if($t) {
|
||||
store_item_tag($darray['app_channel'],$x[0]['id'],TERM_OBJ_APP,TERM_CATEGORY,escape_tags($t),escape_tags(z_root() . '/apps/?f=&cat=' . escape_tags($t)));
|
||||
store_item_tag($darray['app_channel'], $x[0]['id'], TERM_OBJ_APP, TERM_CATEGORY, $t, z_root() . '/apps/?f=&cat=' . $t);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1284,7 +1304,7 @@ class Apps {
|
||||
intval(TERM_OBJ_APP),
|
||||
intval($x[0]['id'])
|
||||
);
|
||||
if($arr['categories']) {
|
||||
if(isset($arr['categories']) && $arr['categories']) {
|
||||
$y = explode(',',$arr['categories']);
|
||||
if($y) {
|
||||
foreach($y as $t) {
|
||||
|
||||
80
Zotlabs/Lib/BaseObject.php
Normal file
80
Zotlabs/Lib/BaseObject.php
Normal file
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
use Zotlabs\ActivityStreams\UnhandledElementException;
|
||||
|
||||
class BaseObject
|
||||
{
|
||||
|
||||
public $string;
|
||||
public $ldContext;
|
||||
|
||||
/**
|
||||
* @param $input
|
||||
* @param $strict
|
||||
* @throws UnhandledElementException if $strict
|
||||
*/
|
||||
|
||||
public function __construct($input = null, $strict = false)
|
||||
{
|
||||
if (isset($input)) {
|
||||
if (is_string($input)) {
|
||||
$this->string = $input;
|
||||
}
|
||||
elseif(is_array($input)) {
|
||||
foreach ($input as $key => $value) {
|
||||
$key = ($key === '@context') ? 'ldContext' : $key;
|
||||
if ($strict && !property_exists($this, $key)) {
|
||||
throw new UnhandledElementException("Unhandled element: $key");
|
||||
}
|
||||
$this->{$key} = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getDataType($element, $object = null)
|
||||
{
|
||||
$object = $object ?? $this;
|
||||
$type = gettype($object[$element]);
|
||||
if ($type === 'array' && array_is_list($object[$element])) {
|
||||
return 'list';
|
||||
}
|
||||
return $type;
|
||||
}
|
||||
|
||||
public function toArray()
|
||||
{
|
||||
if ($this->string) {
|
||||
return $this->string;
|
||||
}
|
||||
$returnValue = [];
|
||||
foreach ((array) $this as $key => $value) {
|
||||
if (isset($value)) {
|
||||
$key = ($key === 'ldContext') ? '@context' : $key;
|
||||
$returnValue[$key] = (($value instanceof BaseObject) ? $value->toArray() : $value);
|
||||
}
|
||||
}
|
||||
return $returnValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getLdContext()
|
||||
{
|
||||
return $this->ldContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $ldContext
|
||||
* @return BaseObject
|
||||
*/
|
||||
public function setLdContext($ldContext)
|
||||
{
|
||||
$this->ldContext = $ldContext;
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
@@ -2,53 +2,56 @@
|
||||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
/**
|
||||
* cache api
|
||||
*/
|
||||
|
||||
use Zotlabs\Lib\Config;
|
||||
|
||||
/**
|
||||
* cache api
|
||||
*/
|
||||
class Cache {
|
||||
|
||||
|
||||
/**
|
||||
* @brief Returns cached content
|
||||
*
|
||||
*
|
||||
* @param string $key
|
||||
* @param string $age in SQL format, default is '30 DAY'
|
||||
* @return string
|
||||
*/
|
||||
|
||||
public static function get($key, $age = '') {
|
||||
|
||||
$hash = hash('whirlpool',$key);
|
||||
public static function get($key, $age = '') {
|
||||
// $hash = hash('whirlpool',$key);
|
||||
$hash = uuid_from_url($key);
|
||||
|
||||
$r = q("SELECT v FROM cache WHERE k = '%s' AND updated > %s - INTERVAL %s LIMIT 1",
|
||||
dbesc($hash),
|
||||
db_utcnow(),
|
||||
db_quoteinterval(($age ? $age : get_config('system','object_cache_days', '30') . ' DAY'))
|
||||
db_quoteinterval(($age ? $age : Config::Get('system','object_cache_days', '30') . ' DAY'))
|
||||
);
|
||||
|
||||
|
||||
if ($r)
|
||||
return $r[0]['v'];
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public static function set($key,$value) {
|
||||
// $hash = hash('whirlpool',$key);
|
||||
$hash = uuid_from_url($key);
|
||||
|
||||
$hash = hash('whirlpool',$key);
|
||||
|
||||
$r = q("SELECT * FROM cache WHERE k = '%s' limit 1",
|
||||
$r = q("SELECT * FROM cache WHERE k = '%s' LIMIT 1",
|
||||
dbesc($hash)
|
||||
);
|
||||
if($r) {
|
||||
q("UPDATE cache SET v = '%s', updated = '%s' WHERE k = '%s'",
|
||||
dbesc($value),
|
||||
dbesc(datetime_convert()),
|
||||
dbesc($hash));
|
||||
dbesc($hash)
|
||||
);
|
||||
}
|
||||
else {
|
||||
q("INSERT INTO cache ( k, v, updated) VALUES ('%s','%s','%s')",
|
||||
q("INSERT INTO cache (k, v, updated) VALUES ('%s', '%s', '%s')",
|
||||
dbesc($hash),
|
||||
dbesc($value),
|
||||
dbesc(datetime_convert()));
|
||||
dbesc(datetime_convert())
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -181,7 +181,7 @@ class Chatroom {
|
||||
}
|
||||
|
||||
|
||||
function leave($observer_xchan, $room_id, $client) {
|
||||
public static function leave($observer_xchan, $room_id, $client) {
|
||||
if(! $room_id || ! $observer_xchan)
|
||||
return;
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
use App;
|
||||
|
||||
class Config {
|
||||
|
||||
@@ -14,20 +15,41 @@ class Config {
|
||||
* @param string $family
|
||||
* The category of the configuration value
|
||||
*/
|
||||
static public function Load($family) {
|
||||
if(! array_key_exists($family, \App::$config))
|
||||
\App::$config[$family] = array();
|
||||
public static function Load($family, $recursionCounter = 0) {
|
||||
if (! array_key_exists($family, App::$config)) {
|
||||
App::$config[$family] = [];
|
||||
}
|
||||
|
||||
if(! array_key_exists('config_loaded', \App::$config[$family])) {
|
||||
// We typically continue when presented with minor DB issues,
|
||||
// but loading the site configuration is more important.
|
||||
|
||||
// Check for query returning false and give it approx 30 seconds
|
||||
// to recover if there's a problem. This is intended to fix a
|
||||
// rare issue on Galera where temporary sync issues were causing
|
||||
// the site encryption keys to be regenerated, which was causing
|
||||
// communication issues for members.
|
||||
|
||||
// This code probably belongs at the database layer, but we don't
|
||||
// necessarily want to shut the site down for problematic queries
|
||||
// caused by bad data. That could be used in a denial of service
|
||||
// attack. Those do need to be (and they are) logged.
|
||||
|
||||
if (! array_key_exists('config_loaded', App::$config[$family])) {
|
||||
$r = q("SELECT * FROM config WHERE cat = '%s'", dbesc($family));
|
||||
if($r !== false) {
|
||||
if($r) {
|
||||
foreach($r as $rr) {
|
||||
$k = $rr['k'];
|
||||
\App::$config[$family][$k] = $rr['v'];
|
||||
}
|
||||
if ($r === false && !App::$install) {
|
||||
sleep(3);
|
||||
$recursionCounter ++;
|
||||
if ($recursionCounter > 10) {
|
||||
system_unavailable();
|
||||
}
|
||||
\App::$config[$family]['config_loaded'] = true;
|
||||
self::Load($family, $recursionCounter);
|
||||
}
|
||||
elseif (is_array($r)) {
|
||||
foreach ($r as $rr) {
|
||||
$k = $rr['k'];
|
||||
App::$config[$family][$k] = $rr['v'];
|
||||
}
|
||||
App::$config[$family]['config_loaded'] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -46,19 +68,19 @@ class Config {
|
||||
* @return mixed
|
||||
* Return the set value, or false if the database update failed
|
||||
*/
|
||||
static public function Set($family, $key, $value) {
|
||||
public static function Set($family, $key, $value) {
|
||||
// manage array value
|
||||
$dbvalue = ((is_array($value)) ? serialize($value) : $value);
|
||||
$dbvalue = ((is_array($value)) ? 'json:' . json_encode($value) : $value);
|
||||
$dbvalue = ((is_bool($dbvalue)) ? intval($dbvalue) : $dbvalue);
|
||||
|
||||
if(self::Get($family, $key) === false || (! self::get_from_storage($family, $key))) {
|
||||
if (self::Get($family, $key) === false || (! self::get_from_storage($family, $key))) {
|
||||
$ret = q("INSERT INTO config ( cat, k, v ) VALUES ( '%s', '%s', '%s' ) ",
|
||||
dbesc($family),
|
||||
dbesc($key),
|
||||
dbesc($dbvalue)
|
||||
);
|
||||
if($ret) {
|
||||
\App::$config[$family][$key] = $value;
|
||||
if ($ret) {
|
||||
App::$config[$family][$key] = $value;
|
||||
$ret = $value;
|
||||
}
|
||||
return $ret;
|
||||
@@ -70,8 +92,8 @@ class Config {
|
||||
dbesc($key)
|
||||
);
|
||||
|
||||
if($ret) {
|
||||
\App::$config[$family][$key] = $value;
|
||||
if ($ret) {
|
||||
App::$config[$family][$key] = $value;
|
||||
$ret = $value;
|
||||
}
|
||||
|
||||
@@ -93,21 +115,37 @@ class Config {
|
||||
* The category of the configuration value
|
||||
* @param string $key
|
||||
* The configuration key to query
|
||||
* @param string $default (optional) default false
|
||||
* @param mixed $default (optional) default false
|
||||
* @return mixed Return value or false on error or if not set
|
||||
*/
|
||||
static public function Get($family, $key, $default = false) {
|
||||
if((! array_key_exists($family, \App::$config)) || (! array_key_exists('config_loaded', \App::$config[$family])))
|
||||
self::Load($family);
|
||||
public static function Get($family, $key, $default = false) {
|
||||
|
||||
if(array_key_exists('config_loaded', \App::$config[$family])) {
|
||||
if(! array_key_exists($key, \App::$config[$family])) {
|
||||
if ((! array_key_exists($family, App::$config)) || (! array_key_exists('config_loaded', App::$config[$family]))) {
|
||||
self::Load($family);
|
||||
}
|
||||
|
||||
if (array_key_exists('config_loaded', App::$config[$family])) {
|
||||
if (! array_key_exists($key, App::$config[$family])) {
|
||||
return $default;
|
||||
}
|
||||
return ((! is_array(\App::$config[$family][$key])) && (preg_match('|^a:[0-9]+:{.*}$|s', \App::$config[$family][$key]))
|
||||
? unserialize(\App::$config[$family][$key])
|
||||
: \App::$config[$family][$key]
|
||||
);
|
||||
|
||||
$value = App::$config[$family][$key];
|
||||
|
||||
if (! is_array($value)) {
|
||||
if (substr($value, 0, 5) == 'json:') {
|
||||
return json_decode(substr($value, 5), true);
|
||||
} else if (preg_match('|^a:[0-9]+:{.*}$|s', $value)) {
|
||||
// Unserialize in inherently unsafe. Try to mitigate by not
|
||||
// allowing unserializing objects. Only kept for backwards
|
||||
// compatibility. JSON serialization should be prefered.
|
||||
return unserialize($value, array('allowed_classes' => false));
|
||||
} else {
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
|
||||
return $default;
|
||||
@@ -125,12 +163,13 @@ class Config {
|
||||
* The configuration key to delete
|
||||
* @return mixed
|
||||
*/
|
||||
static public function Delete($family, $key) {
|
||||
public static function Delete($family, $key) {
|
||||
|
||||
$ret = false;
|
||||
|
||||
if(array_key_exists($family, \App::$config) && array_key_exists($key, \App::$config[$family]))
|
||||
unset(\App::$config[$family][$key]);
|
||||
if (array_key_exists($family, App::$config) && array_key_exists($key, App::$config[$family])) {
|
||||
unset(App::$config[$family][$key]);
|
||||
}
|
||||
|
||||
$ret = q("DELETE FROM config WHERE cat = '%s' AND k = '%s'",
|
||||
dbesc($family),
|
||||
@@ -153,7 +192,7 @@ class Config {
|
||||
* The configuration key to query
|
||||
* @return mixed
|
||||
*/
|
||||
static private function get_from_storage($family,$key) {
|
||||
private static function get_from_storage($family, $key) {
|
||||
$ret = q("SELECT * FROM config WHERE cat = '%s' AND k = '%s' LIMIT 1",
|
||||
dbesc($family),
|
||||
dbesc($key)
|
||||
@@ -161,5 +200,4 @@ class Config {
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -5,8 +5,7 @@ namespace Zotlabs\Lib;
|
||||
use App;
|
||||
use Zotlabs\Access\Permissions;
|
||||
use Zotlabs\Daemon\Master;
|
||||
|
||||
|
||||
use Zotlabs\Lib\Config;
|
||||
|
||||
class Connect {
|
||||
|
||||
@@ -25,10 +24,16 @@ class Connect {
|
||||
|
||||
$uid = $channel['channel_id'];
|
||||
|
||||
if (strpos($url,'@') === false && strpos($url,'/') === false) {
|
||||
// If we get just a channel name and it is not an URL turn it into a local webbie
|
||||
if (!str_contains($url, '@') && strpos($url,'/') === false) {
|
||||
$url = $url . '@' . App::get_hostname();
|
||||
}
|
||||
|
||||
// Remove a possible leading @
|
||||
if (str_starts_with($url, '@')) {
|
||||
$url = ltrim($url, '@');
|
||||
}
|
||||
|
||||
$result = [ 'success' => false, 'message' => '' ];
|
||||
|
||||
$my_perms = false;
|
||||
@@ -69,7 +74,8 @@ class Connect {
|
||||
$xchan_hash = '';
|
||||
$sql_options = (($protocol) ? " and xchan_network = '" . dbesc($protocol) . "' " : '');
|
||||
|
||||
$r = q("select * from xchan where ( xchan_hash = '%s' or xchan_url = '%s' or xchan_addr = '%s') $sql_options ",
|
||||
// We need both, the xchan and the hubloc here hence use JOIN instead of LEFT JOIN
|
||||
$r = q("SELECT * FROM xchan JOIN hubloc ON xchan_hash = hubloc_hash WHERE ( xchan_hash = '%s' or xchan_url = '%s' or xchan_addr = '%s') $sql_options ORDER BY hubloc_id DESC",
|
||||
dbesc($url),
|
||||
dbesc($url),
|
||||
dbesc($url)
|
||||
@@ -80,12 +86,13 @@ class Connect {
|
||||
// reset results to the best record or the first if we don't have the best
|
||||
// note: this is a single record and not an array of results
|
||||
|
||||
$r = Libzot::zot_record_preferred($r,'xchan_network');
|
||||
$r = Libzot::zot_record_preferred($r, 'xchan_network');
|
||||
|
||||
}
|
||||
|
||||
$singleton = false;
|
||||
$d = false;
|
||||
$wf = false;
|
||||
|
||||
if (! $r) {
|
||||
|
||||
@@ -94,7 +101,7 @@ class Connect {
|
||||
$wf = discover_by_webbie($url,$protocol);
|
||||
|
||||
if (! $wf) {
|
||||
$feeds = get_config('system','feed_contacts');
|
||||
$feeds = Config::Get('system','feed_contacts');
|
||||
|
||||
if (($feeds) && (in_array($protocol, [ '', 'feed', 'rss' ]))) {
|
||||
$d = discover_by_url($url);
|
||||
@@ -108,10 +115,12 @@ class Connect {
|
||||
|
||||
if ($wf || $d) {
|
||||
|
||||
$xchan_hash = (($wf) ? $wf : $url);
|
||||
|
||||
// something was discovered - find the record which was just created.
|
||||
|
||||
$r = q("select * from xchan where ( xchan_hash = '%s' or xchan_url = '%s' or xchan_addr = '%s' ) $sql_options",
|
||||
dbesc(($wf) ? $wf : $url),
|
||||
dbesc($xchan_hash),
|
||||
dbesc($url),
|
||||
dbesc($url)
|
||||
);
|
||||
@@ -119,7 +128,7 @@ class Connect {
|
||||
// convert to a single record (once again preferring a zot solution in the case of multiples)
|
||||
|
||||
if ($r) {
|
||||
$r = Libzot::zot_record_preferred($r,'xchan_network');
|
||||
$r = Libzot::zot_record_preferred($r, 'xchan_network');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -261,7 +270,8 @@ class Connect {
|
||||
'abook_feed' => intval(($xchan['xchan_network'] === 'rss') ? 1 : 0),
|
||||
'abook_created' => datetime_convert(),
|
||||
'abook_updated' => datetime_convert(),
|
||||
'abook_instance' => (($singleton) ? z_root() : '')
|
||||
'abook_instance' => (($singleton) ? z_root() : ''),
|
||||
'abook_role' => get_pconfig($uid, 'system', 'default_permcat', 'default')
|
||||
]
|
||||
);
|
||||
}
|
||||
@@ -300,7 +310,7 @@ class Connect {
|
||||
/** If there is a default group for this channel, add this connection to it */
|
||||
|
||||
if ($default_group) {
|
||||
$g = AccessList::rec_byhash($uid,$default_group);
|
||||
$g = AccessList::by_hash($uid,$default_group);
|
||||
if ($g) {
|
||||
AccessList::member_add($uid,'',$xchan_hash,$g['id']);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
use Exception;
|
||||
use Zotlabs\Lib\Config;
|
||||
|
||||
class Crypto {
|
||||
|
||||
@@ -44,7 +45,7 @@ class Crypto {
|
||||
'encrypt_key' => false
|
||||
];
|
||||
|
||||
$conf = get_config('system', 'openssl_conf_file');
|
||||
$conf = Config::Get('system', 'openssl_conf_file');
|
||||
|
||||
if ($conf) {
|
||||
$openssl_options['config'] = $conf;
|
||||
@@ -87,6 +88,10 @@ class Crypto {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$alg) {
|
||||
$alg = 'sha256';
|
||||
}
|
||||
|
||||
try {
|
||||
$verify = openssl_verify($data, $sig, $key, $alg);
|
||||
} catch (Exception $e) {
|
||||
|
||||
@@ -1,21 +1,39 @@
|
||||
<?php
|
||||
/**
|
||||
* A class to handle database schema upgrades.
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2024 Hubzilla Community
|
||||
* SPDX-FileContributor: Harald Eilertsen
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
use Zotlabs\Lib\Config;
|
||||
|
||||
/**
|
||||
* Upgrade the database schema if necessary.
|
||||
*
|
||||
* Compares the currently active database schema version with the version
|
||||
* required for this version of Hubzilla, and performs the upgrade if needed.
|
||||
*
|
||||
* If the difference consists of more than one revision of the schema, each of
|
||||
* the intermediate upgrades are performed in turn.
|
||||
*/
|
||||
class DB_Upgrade {
|
||||
|
||||
public $config_name = '';
|
||||
public $func_prefix = '';
|
||||
/**
|
||||
* Check the installed and required schema versions and perform the upgrade
|
||||
* if necessary.
|
||||
*
|
||||
* @param int $db_version The required DB schema version.
|
||||
*/
|
||||
public static function run(int $db_revision): void {
|
||||
|
||||
function __construct($db_revision) {
|
||||
|
||||
$this->config_name = 'db_version';
|
||||
$this->func_prefix = '_';
|
||||
|
||||
$build = get_config('system', 'db_version', 0);
|
||||
$build = Config::Get('system', 'db_version', 0);
|
||||
if(! intval($build))
|
||||
$build = set_config('system', 'db_version', $db_revision);
|
||||
$build = Config::Set('system', 'db_version', $db_revision);
|
||||
|
||||
if($build == $db_revision) {
|
||||
// Nothing to be done.
|
||||
@@ -27,7 +45,7 @@ class DB_Upgrade {
|
||||
logger('Critical: check_config unable to determine database schema version');
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
$current = intval($db_revision);
|
||||
|
||||
if($stored < $current) {
|
||||
@@ -38,7 +56,7 @@ class DB_Upgrade {
|
||||
for($x = $stored + 1; $x <= $current; $x ++) {
|
||||
$s = '_' . $x;
|
||||
$cls = '\\Zotlabs\Update\\' . $s ;
|
||||
if(! class_exists($cls)) {
|
||||
if(! class_exists($cls)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -52,10 +70,10 @@ class DB_Upgrade {
|
||||
|
||||
Config::Load('database');
|
||||
|
||||
if(get_config('database', $s))
|
||||
if(Config::Get('database', $s))
|
||||
break;
|
||||
set_config('database',$s, '1');
|
||||
|
||||
Config::Set('database',$s, '1');
|
||||
|
||||
|
||||
$c = new $cls();
|
||||
|
||||
@@ -65,10 +83,10 @@ class DB_Upgrade {
|
||||
|
||||
|
||||
$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.
|
||||
// a lockfile.
|
||||
|
||||
$lockfile = 'store/[data]/mailsent';
|
||||
|
||||
@@ -77,7 +95,7 @@ class DB_Upgrade {
|
||||
@unlink($lockfile);
|
||||
//send the administrator an e-mail
|
||||
file_put_contents($lockfile, $x);
|
||||
|
||||
|
||||
$r = q("select account_language from account where account_email = '%s' limit 1",
|
||||
dbesc(\App::$config['system']['admin_email'])
|
||||
);
|
||||
@@ -86,7 +104,7 @@ class DB_Upgrade {
|
||||
[
|
||||
'toEmail' => \App::$config['system']['admin_email'],
|
||||
'messageSubject' => sprintf( t('Update Error at %s'), z_root()),
|
||||
'textVersion' => replace_macros(get_intltext_template('update_fail_eml.tpl'),
|
||||
'textVersion' => replace_macros(get_intltext_template('update_fail_eml.tpl'),
|
||||
[
|
||||
'$sitename' => \App::$config['system']['sitename'],
|
||||
'$siteurl' => z_root(),
|
||||
@@ -104,11 +122,11 @@ class DB_Upgrade {
|
||||
pop_lang();
|
||||
}
|
||||
else {
|
||||
set_config('database',$s, 'success');
|
||||
Config::Set('database',$s, 'success');
|
||||
}
|
||||
}
|
||||
}
|
||||
set_config('system', 'db_version', $db_revision);
|
||||
Config::Set('system', 'db_version', $db_revision);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,28 +1,33 @@
|
||||
<?php
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
use Zotlabs\Lib\Config;
|
||||
|
||||
class DReport {
|
||||
|
||||
private $location;
|
||||
private $sender;
|
||||
private $recipient;
|
||||
private $name;
|
||||
private $message_id;
|
||||
private $message_uuid;
|
||||
private $status;
|
||||
private $date;
|
||||
|
||||
function __construct($location,$sender,$recipient,$message_id,$status = 'deliver') {
|
||||
$this->location = $location;
|
||||
$this->sender = $sender;
|
||||
$this->recipient = $recipient;
|
||||
$this->name = EMPTY_STR;
|
||||
$this->message_id = $message_id;
|
||||
$this->status = $status;
|
||||
$this->date = datetime_convert();
|
||||
function __construct($location, $sender, $recipient, $message_id, $message_uuid = '', $status = 'deliver') {
|
||||
$this->location = $location;
|
||||
$this->sender = $sender;
|
||||
$this->recipient = $recipient;
|
||||
$this->name = EMPTY_STR;
|
||||
$this->message_id = $message_id;
|
||||
$this->message_uuid = $message_uuid;
|
||||
$this->status = $status;
|
||||
$this->date = datetime_convert();
|
||||
}
|
||||
|
||||
function update($status) {
|
||||
$this->status = $status;
|
||||
$this->date = datetime_convert();
|
||||
$this->status = $status;
|
||||
$this->date = datetime_convert();
|
||||
}
|
||||
|
||||
function set_name($name) {
|
||||
@@ -35,24 +40,26 @@ class DReport {
|
||||
|
||||
|
||||
function set($arr) {
|
||||
$this->location = $arr['location'];
|
||||
$this->sender = $arr['sender'];
|
||||
$this->recipient = $arr['recipient'];
|
||||
$this->name = $arr['name'];
|
||||
$this->message_id = $arr['message_id'];
|
||||
$this->status = $arr['status'];
|
||||
$this->date = $arr['date'];
|
||||
$this->location = $arr['location'];
|
||||
$this->sender = $arr['sender'];
|
||||
$this->recipient = $arr['recipient'];
|
||||
$this->name = $arr['name'];
|
||||
$this->message_id = $arr['message_id'];
|
||||
$this->message_uuid = $arr['message_uuid'] ?? '';
|
||||
$this->status = $arr['status'];
|
||||
$this->date = $arr['date'];
|
||||
}
|
||||
|
||||
function get() {
|
||||
return array(
|
||||
'location' => $this->location,
|
||||
'sender' => $this->sender,
|
||||
'recipient' => $this->recipient,
|
||||
'name' => $this->name,
|
||||
'message_id' => $this->message_id,
|
||||
'status' => $this->status,
|
||||
'date' => $this->date
|
||||
'location' => $this->location,
|
||||
'sender' => $this->sender,
|
||||
'recipient' => $this->recipient,
|
||||
'name' => $this->name,
|
||||
'message_id' => $this->message_id,
|
||||
'message_uuid' => $this->message_uuid,
|
||||
'status' => $this->status,
|
||||
'date' => $this->date
|
||||
);
|
||||
}
|
||||
|
||||
@@ -65,7 +72,7 @@ class DReport {
|
||||
|
||||
static function is_storable($dr) {
|
||||
|
||||
if(get_config('system', 'disable_dreport'))
|
||||
if(Config::Get('system', 'disable_dreport'))
|
||||
return false;
|
||||
|
||||
/**
|
||||
@@ -94,19 +101,6 @@ class DReport {
|
||||
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');
|
||||
@@ -117,7 +111,7 @@ class DReport {
|
||||
// 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'))
|
||||
if(($dr['location'] !== z_root()) && ($dr['sender'] === $dr['recipient']) && ($dr['status'] === 'recipient not found'))
|
||||
return false;
|
||||
|
||||
// If you have a private post with a recipient list, every single site is going to report
|
||||
@@ -126,14 +120,14 @@ class DReport {
|
||||
// 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['recipient']),
|
||||
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),
|
||||
dbesc($dr['recipient']),
|
||||
intval($c[0]['channel_id'])
|
||||
);
|
||||
if($r)
|
||||
|
||||
@@ -6,6 +6,7 @@ namespace Zotlabs\Lib;
|
||||
* @brief File with functions and a class for generating system and email notifications.
|
||||
*/
|
||||
|
||||
use Zotlabs\Lib\Config;
|
||||
|
||||
class Enotify {
|
||||
|
||||
@@ -61,7 +62,7 @@ class Enotify {
|
||||
$product = t('$projectname'); // PLATFORM_NAME;
|
||||
$siteurl = z_root();
|
||||
$thanks = t('Thank You,');
|
||||
$sitename = get_config('system','sitename');
|
||||
$sitename = Config::Get('system','sitename');
|
||||
$site_admin = sprintf( t('%s Administrator'), $sitename);
|
||||
$opt_out1 = sprintf( t('This email was sent by %1$s at %2$s.'), t('$Projectname'), \App::get_hostname());
|
||||
$opt_out2 = sprintf( t('To stop receiving these messages, please adjust your Notification Settings at %s'), z_root() . '/settings');
|
||||
@@ -73,15 +74,15 @@ class Enotify {
|
||||
|
||||
// Do not translate 'noreply' as it must be a legal 7-bit email address
|
||||
|
||||
$reply_email = get_config('system', 'reply_address');
|
||||
$reply_email = Config::Get('system', 'reply_address');
|
||||
if(! $reply_email)
|
||||
$reply_email = 'noreply' . '@' . $hostname;
|
||||
|
||||
$sender_email = get_config('system', 'from_email');
|
||||
$sender_email = Config::Get('system', 'from_email');
|
||||
if(! $sender_email)
|
||||
$sender_email = 'Administrator' . '@' . $hostname;
|
||||
|
||||
$sender_name = get_config('system', 'from_email_name');
|
||||
$sender_name = Config::Get('system', 'from_email_name');
|
||||
if(! $sender_name)
|
||||
$sender_name = \Zotlabs\Lib\System::get_site_name();
|
||||
|
||||
@@ -122,12 +123,15 @@ class Enotify {
|
||||
// e.g. "your post", "David's photo", etc.
|
||||
$possess_desc = t('%s <!item_type!>');
|
||||
|
||||
$parent_mid = '';
|
||||
$parent_item = [];
|
||||
|
||||
// @@TODO: consider using switch instead of those elseif
|
||||
if ($params['type'] == NOTIFY_MAIL) {
|
||||
if (isset($params['type']) && $params['type'] == NOTIFY_MAIL) {
|
||||
logger('notification: mail');
|
||||
$subject = sprintf( t('[$Projectname:Notify] New direct message received at %s'), $sitename);
|
||||
|
||||
$preamble = sprintf( t('%1$s sent you a new direct message at %2$s.'), $sender['xchan_name'], $sitename);
|
||||
$preamble = sprintf( t('%1$s sent you a new direct message at %2$s'), $sender['xchan_name'], $sitename);
|
||||
$epreamble = sprintf( t('%1$s sent you %2$s.'), '[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]', '[zrl=$itemlink]' . t('a direct message') . '[/zrl]');
|
||||
$sitelink = t('Please visit %s to view and/or reply to your direct messages.');
|
||||
$tsitelink = sprintf( $sitelink, $siteurl . '/hq/' . gen_link_id($params['item']['mid']));
|
||||
@@ -135,18 +139,18 @@ class Enotify {
|
||||
$itemlink = $siteurl . '/hq/' . gen_link_id($params['item']['mid']);
|
||||
}
|
||||
|
||||
elseif ($params['type'] === NOTIFY_COMMENT) {
|
||||
elseif (isset($params['type']) && $params['type'] === NOTIFY_COMMENT) {
|
||||
//logger("notification: params = " . print_r($params, true), LOGGER_DEBUG);
|
||||
|
||||
$moderated = (($params['item']['item_blocked'] == ITEM_MODERATED) ? true : false);
|
||||
|
||||
$itemlink = $params['link'];
|
||||
|
||||
$action = t('commented on');
|
||||
$action = (($moderated) ? t('requested to comment on') : t('commented on'));
|
||||
|
||||
if(array_key_exists('item',$params)) {
|
||||
|
||||
if(in_array($params['item']['verb'], [ACTIVITY_LIKE, ACTIVITY_DISLIKE])) {
|
||||
if(in_array($params['item']['verb'], ['Like', 'Dislike', ACTIVITY_LIKE, ACTIVITY_DISLIKE, ACTIVITY_SHARE])) {
|
||||
|
||||
if(! $always_show_in_notices || !($vnotify & VNOTIFY_LIKE)) {
|
||||
logger('notification: not a visible activity. Ignoring.');
|
||||
@@ -154,11 +158,14 @@ class Enotify {
|
||||
return;
|
||||
}
|
||||
|
||||
if(activity_match($params['verb'], ACTIVITY_LIKE))
|
||||
$action = t('liked');
|
||||
if(activity_match($params['verb'], ['Like', ACTIVITY_LIKE]))
|
||||
$action = (($moderated) ? t('requested to like') : t('liked'));
|
||||
|
||||
if(activity_match($params['verb'], ACTIVITY_DISLIKE))
|
||||
$action = t('disliked');
|
||||
if(activity_match($params['verb'], ['Dislike', ACTIVITY_DISLIKE]))
|
||||
$action = (($moderated) ? t('requested to dislike') : t('disliked'));
|
||||
|
||||
if(activity_match($params['verb'], ACTIVITY_SHARE))
|
||||
$action = t('repeated');
|
||||
|
||||
}
|
||||
|
||||
@@ -167,7 +174,7 @@ class Enotify {
|
||||
|
||||
}
|
||||
|
||||
$parent_mid = $params['parent_mid'];
|
||||
$parent_mid = $params['parent_mid'] ?? '';
|
||||
|
||||
// Check to see if there was already a notify for this post.
|
||||
// If so don't create a second notification
|
||||
@@ -206,28 +213,36 @@ class Enotify {
|
||||
//$possess_desc = str_replace('<!item_type!>',$possess_desc);
|
||||
|
||||
// "a post"
|
||||
$dest_str = sprintf(t('%1$s %2$s [zrl=%3$s]a %4$s[/zrl]'),
|
||||
$dest_str = sprintf(
|
||||
t('%1$s %2$s [zrl=%3$s]a %4$s[/zrl]'),
|
||||
'[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]',
|
||||
$action,
|
||||
$itemlink,
|
||||
$item_post_type);
|
||||
$item_post_type
|
||||
);
|
||||
|
||||
// "George Bull's post"
|
||||
if($p)
|
||||
$dest_str = sprintf(t('%1$s %2$s [zrl=%3$s]%4$s\'s %5$s[/zrl]'),
|
||||
if($p) {
|
||||
$dest_str = sprintf(
|
||||
t('%1$s %2$s [zrl=%3$s]%4$s\'s %5$s[/zrl]'),
|
||||
'[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]',
|
||||
$action,
|
||||
$itemlink,
|
||||
$p[0]['author']['xchan_name'],
|
||||
$item_post_type);
|
||||
$parent_item['author']['xchan_name'],
|
||||
$item_post_type
|
||||
);
|
||||
}
|
||||
|
||||
// "your post"
|
||||
if($p[0]['owner']['xchan_name'] == $p[0]['author']['xchan_name'] && intval($p[0]['item_wall']))
|
||||
$dest_str = sprintf(t('%1$s %2$s [zrl=%3$s]your %4$s[/zrl]'),
|
||||
if ($parent_item['owner']['xchan_hash'] === $recip['channel_hash'] && intval($parent_item['item_wall'])) {
|
||||
$dest_str = sprintf(
|
||||
t('%1$s %2$s [zrl=%3$s]your %4$s[/zrl]'),
|
||||
'[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]',
|
||||
$action,
|
||||
$itemlink,
|
||||
$item_post_type);
|
||||
$item_post_type
|
||||
);
|
||||
}
|
||||
|
||||
// Some mail softwares relies on subject field for threading.
|
||||
// So, we cannot have different subjects for notifications of the same thread.
|
||||
@@ -238,7 +253,7 @@ class Enotify {
|
||||
$subject = sprintf( t('[$Projectname:Notify] Moderated Comment to conversation #%1$d by %2$s'), $parent_id, $sender['xchan_name']);
|
||||
else
|
||||
$subject = sprintf( t('[$Projectname:Notify] Comment to conversation #%1$d by %2$s'), $parent_id, $sender['xchan_name']);
|
||||
$preamble = sprintf( t('%1$s commented on an item/conversation you have been following.'), $sender['xchan_name']);
|
||||
$preamble = sprintf( t('%1$s commented on an item/conversation you have been following'), $sender['xchan_name']);
|
||||
$epreamble = $dest_str;
|
||||
|
||||
$sitelink = t('Please visit %s to view and/or reply to the conversation.');
|
||||
@@ -251,20 +266,20 @@ class Enotify {
|
||||
|
||||
}
|
||||
|
||||
elseif ($params['type'] === NOTIFY_LIKE) {
|
||||
elseif (isset($params['type']) && $params['type'] === NOTIFY_LIKE) {
|
||||
// logger("notification: params = " . print_r($params, true), LOGGER_DEBUG);
|
||||
|
||||
$itemlink = $params['link'];
|
||||
|
||||
if (array_key_exists('item',$params) && (! activity_match($params['item']['verb'],ACTIVITY_LIKE))) {
|
||||
if(! $always_show_in_notices || !($vnotify & VNOTIFY_LIKE)) {
|
||||
if (array_key_exists('item',$params) && (activity_match($params['item']['verb'], ['Like', 'Dislike', ACTIVITY_LIKE, ACTIVITY_DISLIKE]))) {
|
||||
if(! $always_show_in_notices || !($vnotify & VNOTIFY_LIKE) || !feature_enabled($recip['channel_id'], 'dislike')) {
|
||||
logger('notification: not a visible activity. Ignoring.');
|
||||
pop_lang();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$parent_mid = $params['parent_mid'];
|
||||
$parent_mid = $params['parent_mid'] ?? '';
|
||||
|
||||
// Check to see if there was already a notify for this post.
|
||||
// If so don't create a second notification
|
||||
@@ -291,22 +306,36 @@ class Enotify {
|
||||
);
|
||||
}
|
||||
|
||||
if (!$p) {
|
||||
pop_lang();
|
||||
return;
|
||||
}
|
||||
|
||||
xchan_query($p);
|
||||
|
||||
//@@FIXME $p can be null (line 285)
|
||||
$item_post_type = item_post_type($p[0]);
|
||||
// $private = $p[0]['item_private'];
|
||||
$parent_id = $p[0]['id'];
|
||||
|
||||
$parent_item = $p[0];
|
||||
|
||||
//$verb = ((activity_match($params['item']['verb'], ACTIVITY_DISLIKE)) ? t('disliked') : t('liked'));
|
||||
$moderated = (($params['item']['item_blocked'] == ITEM_MODERATED) ? true : false);
|
||||
|
||||
if(activity_match($params['item']['verb'], ['Like', ACTIVITY_LIKE]))
|
||||
$verb = (($moderated) ? t('requested to like') : t('liked'));
|
||||
|
||||
if(activity_match($params['item']['verb'], ['Dislike', ACTIVITY_DISLIKE]))
|
||||
$verb = (($moderated) ? t('requested to dislike') : t('disliked'));
|
||||
|
||||
// "your post"
|
||||
if($p[0]['owner']['xchan_name'] === $p[0]['author']['xchan_name'] && intval($p[0]['item_wall']))
|
||||
$dest_str = sprintf(t('%1$s liked [zrl=%2$s]your %3$s[/zrl]'),
|
||||
if ($parent_item['author']['xchan_hash'] === $recip['channel_hash']) {
|
||||
$dest_str = sprintf(t('%1$s %2$s [zrl=%3$s]your %4$s[/zrl]'),
|
||||
'[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]',
|
||||
$verb,
|
||||
$itemlink,
|
||||
$item_post_type);
|
||||
$item_post_type
|
||||
);
|
||||
}
|
||||
else {
|
||||
pop_lang();
|
||||
return;
|
||||
@@ -318,7 +347,7 @@ class Enotify {
|
||||
// differents subjects for messages on the same thread.
|
||||
|
||||
$subject = sprintf( t('[$Projectname:Notify] Like received to conversation #%1$d by %2$s'), $parent_id, $sender['xchan_name']);
|
||||
$preamble = sprintf( t('%1$s liked an item/conversation you created.'), $sender['xchan_name']);
|
||||
$preamble = sprintf( t('%1$s liked an item/conversation you created'), $sender['xchan_name']);
|
||||
$epreamble = $dest_str;
|
||||
|
||||
$sitelink = t('Please visit %s to view and/or reply to the conversation.');
|
||||
@@ -328,7 +357,7 @@ class Enotify {
|
||||
|
||||
|
||||
|
||||
elseif($params['type'] === NOTIFY_WALL) {
|
||||
elseif(isset($params['type']) && $params['type'] === NOTIFY_WALL) {
|
||||
$subject = sprintf( t('[$Projectname:Notify] %s posted to your profile wall') , $sender['xchan_name']);
|
||||
|
||||
$preamble = sprintf( t('%1$s posted to your profile wall at %2$s') , $sender['xchan_name'], $sitename);
|
||||
@@ -343,7 +372,7 @@ class Enotify {
|
||||
$itemlink = $params['link'];
|
||||
}
|
||||
|
||||
elseif ($params['type'] === NOTIFY_TAGSELF) {
|
||||
elseif (isset($params['type']) && $params['type'] === NOTIFY_TAGSELF) {
|
||||
|
||||
$p = q("select id from notify where link = '%s' and uid = %d limit 1",
|
||||
dbesc($params['link']),
|
||||
@@ -367,7 +396,7 @@ class Enotify {
|
||||
$itemlink = $params['link'];
|
||||
}
|
||||
|
||||
elseif ($params['type'] === NOTIFY_POKE) {
|
||||
elseif (isset($params['type']) && $params['type'] === NOTIFY_POKE) {
|
||||
$subject = sprintf( t('[$Projectname:Notify] %1$s poked you') , $sender['xchan_name']);
|
||||
$preamble = sprintf( t('%1$s poked you at %2$s') , $sender['xchan_name'], $sitename);
|
||||
$epreamble = sprintf( t('%1$s [zrl=%2$s]poked you[/zrl].') ,
|
||||
@@ -384,7 +413,8 @@ class Enotify {
|
||||
$itemlink = $params['link'];
|
||||
}
|
||||
|
||||
elseif ($params['type'] === NOTIFY_TAGSHARE) {
|
||||
elseif (isset($params['type']) && $params['type'] === NOTIFY_TAGSHARE) {
|
||||
$itemlink = $params['link'];
|
||||
$subject = sprintf( t('[$Projectname:Notify] %s tagged your post') , $sender['xchan_name']);
|
||||
$preamble = sprintf( t('%1$s tagged your post at %2$s'),$sender['xchan_name'], $sitename);
|
||||
$epreamble = sprintf( t('%1$s tagged [zrl=%2$s]your post[/zrl]') ,
|
||||
@@ -394,10 +424,9 @@ class Enotify {
|
||||
$sitelink = t('Please visit %s to view and/or reply to the conversation.');
|
||||
$tsitelink = sprintf( $sitelink, $siteurl );
|
||||
$hsitelink = sprintf( $sitelink, '<a href="' . $siteurl . '">' . $sitename . '</a>');
|
||||
$itemlink = $params['link'];
|
||||
}
|
||||
|
||||
elseif ($params['type'] === NOTIFY_INTRO) {
|
||||
elseif (isset($params['type']) && $params['type'] === NOTIFY_INTRO) {
|
||||
$subject = sprintf( t('[$Projectname:Notify] Introduction received'));
|
||||
$preamble = sprintf( t('You\'ve received an new connection request from \'%1$s\' at %2$s'), $sender['xchan_name'], $sitename);
|
||||
$epreamble = sprintf( t('You\'ve received [zrl=%1$s]a new connection request[/zrl] from %2$s.'),
|
||||
@@ -411,7 +440,8 @@ class Enotify {
|
||||
$itemlink = $params['link'];
|
||||
}
|
||||
|
||||
elseif ($params['type'] === NOTIFY_SUGGEST) {
|
||||
elseif (isset($params['type']) && $params['type'] === NOTIFY_SUGGEST) {
|
||||
$itemlink = $params['link'];
|
||||
$subject = sprintf( t('[$Projectname:Notify] Friend suggestion received'));
|
||||
$preamble = sprintf( t('You\'ve received a friend suggestion from \'%1$s\' at %2$s'), $sender['xchan_name'], $sitename);
|
||||
$epreamble = sprintf( t('You\'ve received [zrl=%1$s]a friend suggestion[/zrl] for %2$s from %3$s.'),
|
||||
@@ -426,14 +456,13 @@ class Enotify {
|
||||
$sitelink = t('Please visit %s to approve or reject the suggestion.');
|
||||
$tsitelink = sprintf( $sitelink, $siteurl );
|
||||
$hsitelink = sprintf( $sitelink, '<a href="' . $siteurl . '">' . $sitename . '</a>');
|
||||
$itemlink = $params['link'];
|
||||
}
|
||||
|
||||
elseif ($params['type'] === NOTIFY_CONFIRM) {
|
||||
elseif (isset($params['type']) && $params['type'] === NOTIFY_CONFIRM) {
|
||||
// ?
|
||||
}
|
||||
|
||||
elseif ($params['type'] === NOTIFY_SYSTEM) {
|
||||
elseif (isset($params['type']) && $params['type'] === NOTIFY_SYSTEM) {
|
||||
// ?
|
||||
}
|
||||
|
||||
@@ -466,6 +495,8 @@ class Enotify {
|
||||
|
||||
require_once('include/html2bbcode.php');
|
||||
|
||||
/*
|
||||
|
||||
do {
|
||||
$dups = false;
|
||||
$hash = random_string();
|
||||
@@ -474,10 +505,12 @@ class Enotify {
|
||||
if ($r)
|
||||
$dups = true;
|
||||
} while ($dups === true);
|
||||
*/
|
||||
|
||||
|
||||
|
||||
$datarray = [];
|
||||
$datarray['hash'] = $hash;
|
||||
$datarray['hash'] = $params['item']['uuid'] ?? new_uuid();
|
||||
$datarray['sender_hash'] = $sender['xchan_hash'];
|
||||
$datarray['xname'] = $sender['xchan_name'];
|
||||
$datarray['url'] = $sender['xchan_url'];
|
||||
@@ -488,12 +521,13 @@ class Enotify {
|
||||
$datarray['link'] = $itemlink;
|
||||
$datarray['parent'] = $parent_mid;
|
||||
$datarray['parent_item'] = $parent_item;
|
||||
$datarray['ntype'] = $params['type'];
|
||||
$datarray['verb'] = $params['verb'];
|
||||
$datarray['otype'] = $params['otype'];
|
||||
$datarray['ntype'] = $params['type'] ?? 0;
|
||||
$datarray['verb'] = $params['verb'] ?? '';
|
||||
$datarray['otype'] = $params['otype'] ?? '';
|
||||
$datarray['abort'] = false;
|
||||
$datarray['seen'] = 0;
|
||||
|
||||
$datarray['item'] = $params['item'];
|
||||
$datarray['item'] = $params['item'] ?? [];
|
||||
|
||||
call_hooks('enotify_store', $datarray);
|
||||
|
||||
@@ -504,7 +538,6 @@ class Enotify {
|
||||
|
||||
|
||||
// create notification entry in DB
|
||||
$seen = 0;
|
||||
|
||||
// Mark some notifications as seen right away
|
||||
// Note! The notification have to be created, because they are used to send emails
|
||||
@@ -514,7 +547,7 @@ class Enotify {
|
||||
|
||||
if (!$always_show_in_notices) {
|
||||
if (($params['type'] === NOTIFY_WALL) || ($params['type'] === NOTIFY_MAIL) || ($params['type'] === NOTIFY_INTRO)) {
|
||||
$seen = 1;
|
||||
$datarray['seen'] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -530,14 +563,15 @@ class Enotify {
|
||||
intval($datarray['uid']),
|
||||
dbesc($datarray['link']),
|
||||
dbesc($datarray['parent']),
|
||||
intval($seen),
|
||||
intval($datarray['seen']),
|
||||
intval($datarray['ntype']),
|
||||
dbesc($datarray['verb']),
|
||||
dbesc($datarray['otype'])
|
||||
);
|
||||
|
||||
$r = q("select id from notify where hash = '%s' and uid = %d limit 1",
|
||||
dbesc($hash),
|
||||
$r = q("select id from notify where hash = '%s' and ntype = %d and uid = %d limit 1",
|
||||
dbesc($datarray['hash']),
|
||||
intval($datarray['ntype']),
|
||||
intval($recip['channel_id'])
|
||||
);
|
||||
if ($r) {
|
||||
@@ -569,7 +603,7 @@ class Enotify {
|
||||
|
||||
// send email notification if notification preferences permit
|
||||
|
||||
require_once('bbcode.php');
|
||||
require_once('include/bbcode.php');
|
||||
if ((intval($recip['channel_notifyflags']) & intval($params['type'])) || $params['type'] == NOTIFY_SYSTEM) {
|
||||
|
||||
logger('notification: sending notification email');
|
||||
@@ -606,8 +640,8 @@ class Enotify {
|
||||
$datarray['preamble'] = $preamble;
|
||||
$datarray['sitename'] = $sitename;
|
||||
$datarray['siteurl'] = $siteurl;
|
||||
$datarray['type'] = $params['type'];
|
||||
$datarray['parent'] = $params['parent_mid'];
|
||||
$datarray['type'] = $params['type'] ?? '';
|
||||
$datarray['parent'] = $params['parent_mid'] ?? '';
|
||||
$datarray['source_name'] = $sender['xchan_name'];
|
||||
$datarray['source_link'] = $sender['xchan_url'];
|
||||
$datarray['source_photo'] = $sender['xchan_photo_s'];
|
||||
@@ -674,7 +708,6 @@ class Enotify {
|
||||
'$source_name' => $datarray['source_name'],
|
||||
'$source_link' => $datarray['source_link'],
|
||||
'$source_photo' => $datarray['source_photo'],
|
||||
'$username' => $datarray['to_name'],
|
||||
'$hsitelink' => $datarray['hsitelink'],
|
||||
'$hitemlink' => $datarray['hitemlink'],
|
||||
'$thanks' => $datarray['thanks'],
|
||||
@@ -696,7 +729,6 @@ class Enotify {
|
||||
'$source_name' => $datarray['source_name'],
|
||||
'$source_link' => $datarray['source_link'],
|
||||
'$source_photo' => $datarray['source_photo'],
|
||||
'$username' => $datarray['to_name'],
|
||||
'$tsitelink' => $datarray['tsitelink'],
|
||||
'$titemlink' => $datarray['titemlink'],
|
||||
'$thanks' => $datarray['thanks'],
|
||||
@@ -808,10 +840,10 @@ class Enotify {
|
||||
|
||||
localize_item($item);
|
||||
|
||||
if($item['shortlocalize']) {
|
||||
if(isset($item['shortlocalize'])) {
|
||||
$itemem_text = $item['shortlocalize'];
|
||||
}
|
||||
elseif($item['localize']) {
|
||||
elseif(isset($item['localize'])) {
|
||||
$itemem_text = $item['localize'];
|
||||
}
|
||||
else {
|
||||
@@ -820,10 +852,6 @@ class Enotify {
|
||||
: (($item['obj_type'] === 'Answer') ? sprintf( t('voted on %s\'s poll'), '[bdi]' . $item['owner']['xchan_name'] . '[/bdi]') : sprintf( t('commented on %s\'s post'), '[bdi]' . $item['owner']['xchan_name'] . '[/bdi]'))
|
||||
);
|
||||
|
||||
if($item['verb'] === ACTIVITY_SHARE) {
|
||||
$itemem_text = sprintf( t('repeated %s\'s post'), '[bdi]' . $item['author']['xchan_name'] . '[/bdi]');
|
||||
}
|
||||
|
||||
if(in_array($item['obj_type'], ['Document', 'Video', 'Audio', 'Image'])) {
|
||||
$itemem_text = t('shared a file with you');
|
||||
}
|
||||
@@ -844,23 +872,27 @@ class Enotify {
|
||||
|
||||
// convert this logic into a json array just like the system notifications
|
||||
|
||||
$who = (($item['verb'] === ACTIVITY_SHARE) ? 'owner' : 'author');
|
||||
$body = html2plain(bbcode($item['body'], ['drop_media' => true, 'tryoembed' => false]), 75, true);
|
||||
if ($body) {
|
||||
$body = htmlentities($body, ENT_QUOTES, 'UTF-8', false);
|
||||
}
|
||||
|
||||
$x = array(
|
||||
'notify_link' => $item['llink'],
|
||||
'name' => $item[$who]['xchan_name'],
|
||||
'addr' => (($item[$who]['xchan_addr']) ? $item[$who]['xchan_addr'] : $item[$who]['xchan_url']),
|
||||
'url' => $item[$who]['xchan_url'],
|
||||
'photo' => $item[$who]['xchan_photo_s'],
|
||||
'name' => $item['author']['xchan_name'],
|
||||
'addr' => $item['author']['xchan_addr'] ? $item['author']['xchan_addr'] : $item['author']['xchan_url'],
|
||||
'url' => $item['author']['xchan_url'],
|
||||
'photo' => $item['author']['xchan_photo_s'],
|
||||
'when' => (($edit) ? datetime_convert('UTC', date_default_timezone_get(), $item['edited']) : datetime_convert('UTC', date_default_timezone_get(), $item['created'])),
|
||||
'class' => (intval($item['item_unseen']) ? 'notify-unseen' : 'notify-seen'),
|
||||
'b64mid' => (($item['mid']) ? gen_link_id($item['mid']) : ''),
|
||||
// 'b64mid' => (($item['mid']) ? gen_link_id($item['mid']) : ''),
|
||||
'b64mid' => (($item['uuid']) ? $item['uuid'] : ''),
|
||||
//'b64mid' => ((in_array($item['verb'], [ACTIVITY_LIKE, ACTIVITY_DISLIKE])) ? gen_link_id($item['thr_parent']) : gen_link_id($item['mid'])),
|
||||
'thread_top' => (($item['item_thread_top']) ? true : false),
|
||||
'message' => bbcode(escape_tags($itemem_text)),
|
||||
'body' => htmlentities(html2plain(bbcode($item['body'], ['drop_media', true]), 75, true), ENT_QUOTES, 'UTF-8', false),
|
||||
'body' => $body,
|
||||
// these are for the superblock addon
|
||||
'hash' => $item[$who]['xchan_hash'],
|
||||
'hash' => $item['author']['xchan_hash'],
|
||||
'uid' => $item['uid'],
|
||||
'display' => true
|
||||
);
|
||||
@@ -880,9 +912,6 @@ class Enotify {
|
||||
if(strpos($message, $tt['xname']) === 0)
|
||||
$message = substr($message, strlen($tt['xname']) + 1);
|
||||
|
||||
$mid = basename($tt['link']);
|
||||
|
||||
$b64mid = gen_link_id($mid);
|
||||
$x = [
|
||||
'notify_link' => (($tt['ntype'] === NOTIFY_MAIL) ? $tt['link'] : z_root() . '/notify/view/' . $tt['id']),
|
||||
'name' => $tt['xname'],
|
||||
@@ -890,7 +919,7 @@ class Enotify {
|
||||
'photo' => $tt['photo'],
|
||||
'when' => datetime_convert('UTC', date_default_timezone_get(), $tt['created']),
|
||||
'hclass' => (($tt['seen']) ? 'notify-seen' : 'notify-unseen'),
|
||||
'b64mid' => (($tt['otype'] == 'item') ? $b64mid : ''),
|
||||
'b64mid' => (($tt['otype'] == 'item') ? $tt['hash'] : ''),
|
||||
'notify_id' => (($tt['otype'] == 'item') ? $tt['id'] : ''),
|
||||
'message' => $message
|
||||
];
|
||||
@@ -902,7 +931,7 @@ class Enotify {
|
||||
static public function format_intros($rr) {
|
||||
|
||||
return [
|
||||
'notify_link' => z_root() . '/connections/ifpending',
|
||||
'notify_link' => z_root() . '/connections#' . $rr['abook_id'],
|
||||
'name' => $rr['xchan_name'],
|
||||
'addr' => $rr['xchan_addr'],
|
||||
'url' => $rr['xchan_url'],
|
||||
|
||||
@@ -1,405 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
use Zotlabs\Lib\Libsync;
|
||||
|
||||
|
||||
class Group {
|
||||
|
||||
static function add($uid,$name,$public = 0) {
|
||||
|
||||
$ret = false;
|
||||
if(x($uid) && x($name)) {
|
||||
$r = self::byname($uid,$name); // check for dups
|
||||
if($r !== false) {
|
||||
|
||||
// This could be a problem.
|
||||
// Let's assume we've just created a group which we once deleted
|
||||
// all the old members are gone, but the group remains so we don't break any security
|
||||
// access lists. What we're doing here is reviving the dead group, but old content which
|
||||
// was restricted to this group may now be seen by the new group members.
|
||||
|
||||
$z = q("SELECT * FROM pgrp WHERE id = %d LIMIT 1",
|
||||
intval($r)
|
||||
);
|
||||
if(($z) && $z[0]['deleted']) {
|
||||
q('UPDATE pgrp SET deleted = 0 WHERE id = %d', intval($z[0]['id']));
|
||||
notice( t('A deleted group with this name was revived. Existing item permissions <strong>may</strong> apply to this group and any future members. If this is not what you intended, please create another group with a different name.') . EOL);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
do {
|
||||
$dups = false;
|
||||
$hash = random_string(32) . str_replace(['<','>'],['.','.'], $name);
|
||||
|
||||
$r = q("SELECT id FROM pgrp WHERE hash = '%s' LIMIT 1", dbesc($hash));
|
||||
if($r)
|
||||
$dups = true;
|
||||
} while($dups == true);
|
||||
|
||||
|
||||
$r = q("INSERT INTO pgrp ( hash, uid, visible, gname )
|
||||
VALUES( '%s', %d, %d, '%s' ) ",
|
||||
dbesc($hash),
|
||||
intval($uid),
|
||||
intval($public),
|
||||
dbesc($name)
|
||||
);
|
||||
$ret = $r;
|
||||
}
|
||||
|
||||
Libsync::build_sync_packet($uid,null,true);
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
static function remove($uid,$name) {
|
||||
$ret = false;
|
||||
if(x($uid) && x($name)) {
|
||||
$r = q("SELECT id, hash FROM pgrp WHERE uid = %d AND gname = '%s' LIMIT 1",
|
||||
intval($uid),
|
||||
dbesc($name)
|
||||
);
|
||||
if($r) {
|
||||
$group_id = $r[0]['id'];
|
||||
$group_hash = $r[0]['hash'];
|
||||
}
|
||||
|
||||
if(! $group_id)
|
||||
return false;
|
||||
|
||||
// remove group from default posting lists
|
||||
$r = q("SELECT channel_default_group, channel_allow_gid, channel_deny_gid FROM channel WHERE channel_id = %d LIMIT 1",
|
||||
intval($uid)
|
||||
);
|
||||
if($r) {
|
||||
$user_info = $r[0];
|
||||
$change = false;
|
||||
|
||||
if($user_info['channel_default_group'] == $group_hash) {
|
||||
$user_info['channel_default_group'] = '';
|
||||
$change = true;
|
||||
}
|
||||
if(strpos($user_info['channel_allow_gid'], '<' . $group_hash . '>') !== false) {
|
||||
$user_info['channel_allow_gid'] = str_replace('<' . $group_hash . '>', '', $user_info['channel_allow_gid']);
|
||||
$change = true;
|
||||
}
|
||||
if(strpos($user_info['channel_deny_gid'], '<' . $group_hash . '>') !== false) {
|
||||
$user_info['channel_deny_gid'] = str_replace('<' . $group_hash . '>', '', $user_info['channel_deny_gid']);
|
||||
$change = true;
|
||||
}
|
||||
|
||||
if($change) {
|
||||
q("UPDATE channel SET channel_default_group = '%s', channel_allow_gid = '%s', channel_deny_gid = '%s'
|
||||
WHERE channel_id = %d",
|
||||
intval($user_info['channel_default_group']),
|
||||
dbesc($user_info['channel_allow_gid']),
|
||||
dbesc($user_info['channel_deny_gid']),
|
||||
intval($uid)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// remove all members
|
||||
$r = q("DELETE FROM pgrp_member WHERE uid = %d AND gid = %d ",
|
||||
intval($uid),
|
||||
intval($group_id)
|
||||
);
|
||||
|
||||
// remove group
|
||||
$r = q("UPDATE pgrp SET deleted = 1 WHERE uid = %d AND gname = '%s'",
|
||||
intval($uid),
|
||||
dbesc($name)
|
||||
);
|
||||
|
||||
$ret = $r;
|
||||
|
||||
}
|
||||
|
||||
Libsync::build_sync_packet($uid,null,true);
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
static function byname($uid,$name) {
|
||||
if((! $uid) || (! strlen($name)))
|
||||
return false;
|
||||
$r = q("SELECT * FROM pgrp WHERE uid = %d AND gname = '%s' LIMIT 1",
|
||||
intval($uid),
|
||||
dbesc($name)
|
||||
);
|
||||
if($r)
|
||||
return $r[0]['id'];
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static function rec_byhash($uid,$hash) {
|
||||
if((! $uid) || (! strlen($hash)))
|
||||
return false;
|
||||
$r = q("SELECT * FROM pgrp WHERE uid = %d AND hash = '%s' LIMIT 1",
|
||||
intval($uid),
|
||||
dbesc($hash)
|
||||
);
|
||||
if($r)
|
||||
return $r[0];
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static function member_remove($uid,$name,$member) {
|
||||
$gid = self::byname($uid,$name);
|
||||
if(! $gid)
|
||||
return false;
|
||||
if(! ( $uid && $gid && $member))
|
||||
return false;
|
||||
$r = q("DELETE FROM pgrp_member WHERE uid = %d AND gid = %d AND xchan = '%s' ",
|
||||
intval($uid),
|
||||
intval($gid),
|
||||
dbesc($member)
|
||||
);
|
||||
|
||||
Libsync::build_sync_packet($uid,null,true);
|
||||
|
||||
return $r;
|
||||
}
|
||||
|
||||
|
||||
static function member_add($uid,$name,$member,$gid = 0) {
|
||||
if(! $gid)
|
||||
$gid = self::byname($uid,$name);
|
||||
if((! $gid) || (! $uid) || (! $member))
|
||||
return false;
|
||||
|
||||
$r = q("SELECT * FROM pgrp_member WHERE uid = %d AND gid = %d AND xchan = '%s' LIMIT 1",
|
||||
intval($uid),
|
||||
intval($gid),
|
||||
dbesc($member)
|
||||
);
|
||||
if($r)
|
||||
return true; // You might question this, but
|
||||
// we indicate success because the group member was in fact created
|
||||
// -- It was just created at another time
|
||||
if(! $r)
|
||||
$r = q("INSERT INTO pgrp_member (uid, gid, xchan)
|
||||
VALUES( %d, %d, '%s' ) ",
|
||||
intval($uid),
|
||||
intval($gid),
|
||||
dbesc($member)
|
||||
);
|
||||
|
||||
Libsync::build_sync_packet($uid,null,true);
|
||||
|
||||
return $r;
|
||||
}
|
||||
|
||||
|
||||
static function members($gid) {
|
||||
$ret = array();
|
||||
if(intval($gid)) {
|
||||
$r = q("SELECT * FROM pgrp_member
|
||||
LEFT JOIN abook ON abook_xchan = pgrp_member.xchan left join xchan on xchan_hash = abook_xchan
|
||||
WHERE gid = %d AND abook_channel = %d and pgrp_member.uid = %d and xchan_deleted = 0 and abook_self = 0 and abook_blocked = 0 and abook_pending = 0 ORDER BY xchan_name ASC ",
|
||||
intval($gid),
|
||||
intval(local_channel()),
|
||||
intval(local_channel())
|
||||
);
|
||||
if($r)
|
||||
$ret = $r;
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
static function members_xchan($gid) {
|
||||
$ret = [];
|
||||
if(intval($gid)) {
|
||||
$r = q("SELECT xchan FROM pgrp_member WHERE gid = %d AND uid = %d",
|
||||
intval($gid),
|
||||
intval(local_channel())
|
||||
);
|
||||
if($r) {
|
||||
foreach($r as $rr) {
|
||||
$ret[] = $rr['xchan'];
|
||||
}
|
||||
}
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
static function members_profile_xchan($uid,$gid) {
|
||||
$ret = [];
|
||||
|
||||
if(intval($gid)) {
|
||||
$r = q("SELECT abook_xchan as xchan from abook left join profile on abook_profile = profile_guid where profile.id = %d and profile.uid = %d",
|
||||
intval($gid),
|
||||
intval($uid)
|
||||
);
|
||||
if($r) {
|
||||
foreach($r as $rr) {
|
||||
$ret[] = $rr['xchan'];
|
||||
}
|
||||
}
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static function select($uid,$group = '') {
|
||||
|
||||
$grps = [];
|
||||
$o = '';
|
||||
|
||||
$r = q("SELECT * FROM pgrp WHERE deleted = 0 AND uid = %d ORDER BY gname ASC",
|
||||
intval($uid)
|
||||
);
|
||||
$grps[] = array('name' => '', 'hash' => '0', 'selected' => '');
|
||||
if($r) {
|
||||
foreach($r as $rr) {
|
||||
$grps[] = array('name' => $rr['gname'], 'id' => $rr['hash'], 'selected' => (($group == $rr['hash']) ? 'true' : ''));
|
||||
}
|
||||
|
||||
}
|
||||
logger('select: ' . print_r($grps,true), LOGGER_DATA);
|
||||
|
||||
$o = replace_macros(get_markup_template('group_selection.tpl'), array(
|
||||
'$label' => t('Add new connections to this privacy group'),
|
||||
'$groups' => $grps
|
||||
));
|
||||
return $o;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static function widget($every="connections",$each="group",$edit = false, $group_id = 0, $cid = '',$mode = 1) {
|
||||
|
||||
$o = '';
|
||||
|
||||
if(! (local_channel() && feature_enabled(local_channel(),'groups'))) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$groups = array();
|
||||
|
||||
$r = q("SELECT * FROM pgrp WHERE deleted = 0 AND uid = %d ORDER BY gname ASC",
|
||||
intval($_SESSION['uid'])
|
||||
);
|
||||
$member_of = array();
|
||||
if($cid) {
|
||||
$member_of = self::containing(local_channel(),$cid);
|
||||
}
|
||||
|
||||
if($r) {
|
||||
foreach($r as $rr) {
|
||||
$selected = (($group_id == $rr['id']) ? ' group-selected' : '');
|
||||
|
||||
if ($edit) {
|
||||
$groupedit = [ 'href' => "group/".$rr['id'], 'title' => t('edit') ];
|
||||
}
|
||||
else {
|
||||
$groupedit = null;
|
||||
}
|
||||
|
||||
$groups[] = [
|
||||
'id' => $rr['id'],
|
||||
'enc_cid' => base64url_encode($cid),
|
||||
'cid' => $cid,
|
||||
'text' => $rr['gname'],
|
||||
'selected' => $selected,
|
||||
'href' => (($mode == 0) ? $each.'?f=&gid='.$rr['id'] : $each."/".$rr['id']) . ((x($_GET,'new')) ? '&new=' . $_GET['new'] : '') . ((x($_GET,'order')) ? '&order=' . $_GET['order'] : ''),
|
||||
'edit' => $groupedit,
|
||||
'ismember' => in_array($rr['id'],$member_of),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$tpl = get_markup_template("group_side.tpl");
|
||||
$o = replace_macros($tpl, array(
|
||||
'$title' => t('Privacy Groups'),
|
||||
'$edittext' => t('Edit group'),
|
||||
'$createtext' => t('Add privacy group'),
|
||||
'$ungrouped' => (($every === 'contacts') ? t('Channels not in any privacy group') : ''),
|
||||
'$groups' => $groups,
|
||||
'$add' => t('add'),
|
||||
));
|
||||
|
||||
|
||||
return $o;
|
||||
}
|
||||
|
||||
|
||||
static function expand($g) {
|
||||
if(! (is_array($g) && count($g)))
|
||||
return array();
|
||||
|
||||
$ret = [];
|
||||
$x = [];
|
||||
|
||||
// private profile linked virtual groups
|
||||
|
||||
foreach($g as $gv) {
|
||||
if(substr($gv,0,3) === 'vp.') {
|
||||
$profile_hash = substr($gv,3);
|
||||
if($profile_hash) {
|
||||
$r = q("select abook_xchan from abook where abook_profile = '%s'",
|
||||
dbesc($profile_hash)
|
||||
);
|
||||
if($r) {
|
||||
foreach($r as $rv) {
|
||||
$ret[] = $rv['abook_xchan'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
$x[] = $gv;
|
||||
}
|
||||
}
|
||||
|
||||
if($x) {
|
||||
stringify_array_elms($x,true);
|
||||
$groups = implode(',', $x);
|
||||
if($groups) {
|
||||
$r = q("SELECT xchan FROM pgrp_member WHERE gid IN ( select id from pgrp where hash in ( $groups ))");
|
||||
if($r) {
|
||||
foreach($r as $rr) {
|
||||
$ret[] = $rr['xchan'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
static function member_of($c) {
|
||||
$r = q("SELECT pgrp.gname, pgrp.id FROM pgrp LEFT JOIN pgrp_member ON pgrp_member.gid = pgrp.id WHERE pgrp_member.xchan = '%s' AND pgrp.deleted = 0 ORDER BY pgrp.gname ASC ",
|
||||
dbesc($c)
|
||||
);
|
||||
|
||||
return $r;
|
||||
|
||||
}
|
||||
|
||||
static function containing($uid,$c) {
|
||||
|
||||
$r = q("SELECT gid FROM pgrp_member WHERE uid = %d AND pgrp_member.xchan = '%s' ",
|
||||
intval($uid),
|
||||
dbesc($c)
|
||||
);
|
||||
|
||||
$ret = array();
|
||||
if($r) {
|
||||
foreach($r as $rr)
|
||||
$ret[] = $rr['gid'];
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,7 @@ class IConfig {
|
||||
static public function Get(&$item, $family, $key, $default = false) {
|
||||
|
||||
$is_item = false;
|
||||
|
||||
|
||||
if(is_array($item)) {
|
||||
$is_item = true;
|
||||
if((! array_key_exists('iconfig',$item)) || (! is_array($item['iconfig'])))
|
||||
@@ -22,7 +22,7 @@ class IConfig {
|
||||
if(array_key_exists('item_id',$item))
|
||||
$iid = $item['item_id'];
|
||||
else
|
||||
$iid = $item['id'];
|
||||
$iid = $item['id'] ?? 0;
|
||||
}
|
||||
elseif(intval($item))
|
||||
$iid = $item;
|
||||
@@ -36,7 +36,7 @@ class IConfig {
|
||||
return $c['v'];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$r = q("select * from iconfig where iid = %d and cat = '%s' and k = '%s' limit 1",
|
||||
intval($iid),
|
||||
dbesc($family),
|
||||
@@ -63,11 +63,11 @@ class IConfig {
|
||||
* $value - value of meta variable
|
||||
* $sharing - boolean (default false); if true the meta information is propagated with the item
|
||||
* to other sites/channels, mostly useful when $item is an array and has not yet been stored/delivered.
|
||||
* If the meta information is added after delivery and you wish it to be shared, it may be necessary to
|
||||
* alter the item edited timestamp and invoke the delivery process on the updated item. The edited
|
||||
* If the meta information is added after delivery and you wish it to be shared, it may be necessary to
|
||||
* alter the item edited timestamp and invoke the delivery process on the updated item. The edited
|
||||
* timestamp needs to be altered in order to trigger an item_store_update() at the receiving end.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
static public function Set(&$item, $family, $key, $value, $sharing = false) {
|
||||
|
||||
@@ -162,4 +162,4 @@ class IConfig {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ class JSalmon {
|
||||
. base64url_encode($x['alg'],true);
|
||||
|
||||
$key = HTTPSig::get_key(EMPTY_STR,'zot6',base64url_decode($x['sigs']['key_id']));
|
||||
logger('key: ' . print_r($key,true));
|
||||
logger('key: ' . print_r($key,true), LOGGER_DATA);
|
||||
if($key['portable_id'] && $key['public_key']) {
|
||||
if(Crypto::verify($signed_data,base64url_decode($x['sigs']['value']),$key['public_key'])) {
|
||||
logger('verified');
|
||||
|
||||
92
Zotlabs/Lib/JcsEddsa2022.php
Normal file
92
Zotlabs/Lib/JcsEddsa2022.php
Normal file
@@ -0,0 +1,92 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
use Mmccook\JsonCanonicalizator\JsonCanonicalizatorFactory;
|
||||
use StephenHill\Base58;
|
||||
|
||||
class JcsEddsa2022 {
|
||||
|
||||
public function __construct() {
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function sign($data, $channel): array {
|
||||
$base58 = new Base58();
|
||||
$pubkey = (new Multibase())->publicKey($channel['channel_epubkey']);
|
||||
$options = [
|
||||
'type' => 'DataIntegrityProof',
|
||||
'cryptosuite' => 'eddsa-jcs-2022',
|
||||
'created' => datetime_convert('UTC', 'UTC', 'now', ATOM_TIME),
|
||||
'verificationMethod' => channel_url($channel) . '#' . $pubkey,
|
||||
'proofPurpose' => 'assertionMethod',
|
||||
];
|
||||
|
||||
$optionsHash = $this->hash($this->signableOptions($options), true);
|
||||
$dataHash = $this->hash($this->signableData($data), true);
|
||||
|
||||
$options['proofValue'] = 'z' . $base58->encode(sodium_crypto_sign_detached($optionsHash . $dataHash,
|
||||
sodium_base642bin($channel['channel_eprvkey'], SODIUM_BASE64_VARIANT_ORIGINAL_NO_PADDING)));
|
||||
|
||||
return $options;
|
||||
}
|
||||
|
||||
public function verify($data, $publicKey) {
|
||||
$base58 = new Base58();
|
||||
$encodedSignature = $data['proof']['proofValue'] ?? '';
|
||||
if (!str_starts_with($encodedSignature,'z')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$encodedSignature = substr($encodedSignature, 1);
|
||||
$optionsHash = $this->hash($this->signableOptions($data['proof']), true);
|
||||
$dataHash = $this->hash($this->signableData($data),true);
|
||||
|
||||
try {
|
||||
$result = sodium_crypto_sign_verify_detached($base58->decode($encodedSignature), $optionsHash . $dataHash,
|
||||
(new Multibase())->decode($publicKey, true));
|
||||
}
|
||||
catch (\Exception $e) {
|
||||
logger('verify exception:' . $e->getMessage());
|
||||
}
|
||||
|
||||
logger('SignatureVerify (eddsa-jcs-2022) ' . (($result) ? 'true' : 'false'));
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function signableData($data) {
|
||||
$signableData = [];
|
||||
if ($data) {
|
||||
foreach ($data as $k => $v) {
|
||||
if (!in_array($k, ['proof', 'signature'])) {
|
||||
$signableData[$k] = $v;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $signableData;
|
||||
}
|
||||
|
||||
public function signableOptions($options) {
|
||||
$signableOptions = [];
|
||||
|
||||
if ($options) {
|
||||
foreach ($options as $k => $v) {
|
||||
if ($k !== 'proofValue') {
|
||||
$signableOptions[$k] = $v;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $signableOptions;
|
||||
}
|
||||
|
||||
public function hash($obj, $binary = false) {
|
||||
return hash('sha256', $this->canonicalize($obj), $binary);
|
||||
}
|
||||
|
||||
public function canonicalize($data) {
|
||||
$canonicalization = JsonCanonicalizatorFactory::getInstance();
|
||||
return $canonicalization->canonicalize($data);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -75,22 +75,23 @@ class LDSignatures {
|
||||
}
|
||||
|
||||
static function hash($obj) {
|
||||
|
||||
return hash('sha256',self::normalise($obj));
|
||||
return hash('sha256', self::normalise($obj));
|
||||
}
|
||||
|
||||
static function normalise($data) {
|
||||
$ret = '';
|
||||
|
||||
if(is_string($data)) {
|
||||
$data = json_decode($data);
|
||||
}
|
||||
|
||||
if(! is_object($data))
|
||||
return '';
|
||||
return $ret;
|
||||
|
||||
jsonld_set_document_loader('jsonld_document_loader');
|
||||
|
||||
try {
|
||||
$d = jsonld_normalize($data,[ 'algorithm' => 'URDNA2015', 'format' => 'application/nquads' ]);
|
||||
$ret = jsonld_normalize($data,[ 'algorithm' => 'URDNA2015', 'format' => 'application/nquads' ]);
|
||||
}
|
||||
catch (\Exception $e) {
|
||||
// Don't log the exception - this can exhaust memory
|
||||
@@ -98,7 +99,7 @@ class LDSignatures {
|
||||
logger('normalise error: ' . print_r($data,true));
|
||||
}
|
||||
|
||||
return $d;
|
||||
return $ret;
|
||||
}
|
||||
|
||||
static function salmon_sign($data,$channel) {
|
||||
|
||||
@@ -5,6 +5,7 @@ namespace Zotlabs\Lib;
|
||||
|
||||
use App;
|
||||
use Zotlabs\Daemon\Master;
|
||||
use Zotlabs\Lib\Config;
|
||||
|
||||
class Libsync {
|
||||
|
||||
@@ -135,15 +136,13 @@ class Libsync {
|
||||
$info['collection_members'] = $r;
|
||||
}
|
||||
|
||||
$interval = ((get_config('system', 'delivery_interval') !== false)
|
||||
? intval(get_config('system', 'delivery_interval')) : 2);
|
||||
$interval = Config::Get('queueworker', 'queue_interval', 500000);
|
||||
|
||||
logger('Packet: ' . print_r($info, true), LOGGER_DATA, LOG_DEBUG);
|
||||
|
||||
$total = count($synchubs);
|
||||
|
||||
foreach ($synchubs as $hub) {
|
||||
$hash = random_string();
|
||||
$hash = new_uuid();
|
||||
$n = Libzot::build_packet($channel, 'sync', $env_recips, json_encode($info), 'hz', $hub['hubloc_sitekey'], $hub['site_crypto']);
|
||||
Queue::insert([
|
||||
'hash' => $hash,
|
||||
@@ -156,19 +155,26 @@ class Libsync {
|
||||
]);
|
||||
|
||||
|
||||
/*
|
||||
$x = q("select count(outq_hash) as total from outq where outq_delivered = 0");
|
||||
if (intval($x[0]['total']) > intval(get_config('system', 'force_queue_threshold', 3000))) {
|
||||
|
||||
if (intval($x[0]['total']) > intval(Config::Get('system', 'force_queue_threshold', 3000))) {
|
||||
logger('immediate delivery deferred.', LOGGER_DEBUG, LOG_INFO);
|
||||
Queue::update($hash);
|
||||
continue;
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
Master::Summon(['Deliver', $hash]);
|
||||
$total = $total - 1;
|
||||
|
||||
if ($interval && $total)
|
||||
@time_sleep_until(microtime(true) + (float)$interval);
|
||||
/*
|
||||
$total = $total - 1;
|
||||
*/
|
||||
|
||||
if ($interval) {
|
||||
usleep($interval);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -186,7 +192,6 @@ class Libsync {
|
||||
require_once('include/import.php');
|
||||
|
||||
$result = [];
|
||||
|
||||
$keychange = ((array_key_exists('keychange', $arr)) ? true : false);
|
||||
|
||||
foreach ($deliveries as $d) {
|
||||
@@ -194,7 +199,10 @@ class Libsync {
|
||||
dbesc($sender)
|
||||
);
|
||||
|
||||
$DR = new DReport(z_root(), $sender, $d, 'sync');
|
||||
$mid = 'sync';
|
||||
|
||||
|
||||
$DR = new DReport(z_root(), $sender, $d, $mid);
|
||||
|
||||
if (!$r) {
|
||||
$DR->update('recipient not found');
|
||||
@@ -204,6 +212,7 @@ class Libsync {
|
||||
|
||||
$channel = $r[0];
|
||||
|
||||
|
||||
$DR->set_name($channel['channel_name'] . ' <' . channel_reddress($channel) . '>');
|
||||
|
||||
$max_friends = service_class_fetch($channel['channel_id'], 'total_channels');
|
||||
@@ -232,8 +241,35 @@ class Libsync {
|
||||
|
||||
if (array_key_exists('config', $arr) && is_array($arr['config']) && count($arr['config'])) {
|
||||
foreach ($arr['config'] as $cat => $k) {
|
||||
foreach ($arr['config'][$cat] as $k => $v)
|
||||
set_pconfig($channel['channel_id'], $cat, $k, $v);
|
||||
$pconfig_updated = [];
|
||||
|
||||
foreach($arr['config'][$cat] as $k => $v) {
|
||||
if ($cat === 'hz_delpconfig' && strpos($k, 'b64.') === 0) {
|
||||
$delpconfig = explode(':', unpack_link_id($k));
|
||||
|
||||
// delete the provided pconfig
|
||||
del_pconfig($channel['channel_id'], $delpconfig[0], $delpconfig[1], $v);
|
||||
|
||||
// delete the messenger pconfig
|
||||
del_pconfig($channel['channel_id'], 'hz_delpconfig', $k);
|
||||
}
|
||||
|
||||
if (strpos($k,'pcfgud:') === 0) {
|
||||
$realk = substr($k,7);
|
||||
$pconfig_updated[$realk] = $v;
|
||||
unset($arr['config'][$cat][$k]);
|
||||
}
|
||||
}
|
||||
|
||||
foreach($arr['config'][$cat] as $k => $v) {
|
||||
if (!isset($pconfig_updated[$k])) {
|
||||
$pconfig_updated[$k] = NULL;
|
||||
}
|
||||
|
||||
if ($cat !== 'hz_delpconfig') {
|
||||
set_pconfig($channel['channel_id'], $cat, $k, $v, $pconfig_updated[$k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -246,6 +282,10 @@ class Libsync {
|
||||
if (array_key_exists('app', $arr) && $arr['app'])
|
||||
sync_apps($channel, $arr['app']);
|
||||
|
||||
if (array_key_exists('sysapp',$arr) && $arr['sysapp']) {
|
||||
sync_sysapps($channel, $arr['sysapp']);
|
||||
}
|
||||
|
||||
if (array_key_exists('addressbook', $arr) && $arr['addressbook'])
|
||||
sync_addressbook($channel, $arr['addressbook']);
|
||||
|
||||
@@ -255,8 +295,8 @@ class Libsync {
|
||||
if (array_key_exists('chatroom', $arr) && $arr['chatroom'])
|
||||
sync_chatrooms($channel, $arr['chatroom']);
|
||||
|
||||
if (array_key_exists('mail', $arr) && $arr['mail'])
|
||||
sync_mail($channel, $arr['mail']);
|
||||
//if (array_key_exists('mail', $arr) && $arr['mail'])
|
||||
// sync_mail($channel, $arr['mail']);
|
||||
|
||||
if (array_key_exists('event', $arr) && $arr['event'])
|
||||
sync_events($channel, $arr['event']);
|
||||
@@ -264,14 +304,16 @@ class Libsync {
|
||||
if (array_key_exists('event_item', $arr) && $arr['event_item'])
|
||||
sync_items($channel, $arr['event_item'], ((array_key_exists('relocate', $arr)) ? $arr['relocate'] : null));
|
||||
|
||||
if (array_key_exists('item', $arr) && $arr['item'])
|
||||
if (array_key_exists('item', $arr) && $arr['item']) {
|
||||
sync_items($channel, $arr['item'], ((array_key_exists('relocate', $arr)) ? $arr['relocate'] : null));
|
||||
$mid = $arr['item'][0]['message_id'] . '#sync';
|
||||
}
|
||||
|
||||
// deprecated, maintaining for a few months for upward compatibility
|
||||
// this should sync webpages, but the logic is a bit subtle
|
||||
|
||||
if (array_key_exists('item_id', $arr) && $arr['item_id'])
|
||||
sync_items($channel, $arr['item_id']);
|
||||
//if (array_key_exists('item_id', $arr) && $arr['item_id'])
|
||||
// sync_items($channel, $arr['item_id']);
|
||||
|
||||
if (array_key_exists('menu', $arr) && $arr['menu'])
|
||||
sync_menus($channel, $arr['menu']);
|
||||
@@ -284,10 +326,7 @@ class Libsync {
|
||||
|
||||
if (array_key_exists('channel', $arr) && is_array($arr['channel']) && count($arr['channel'])) {
|
||||
|
||||
$remote_channel = $arr['channel'];
|
||||
$remote_channel['channel_id'] = $channel['channel_id'];
|
||||
|
||||
if (array_key_exists('channel_pageflags', $arr['channel']) && intval($arr['channel']['channel_pageflags'])) {
|
||||
if (array_key_exists('channel_pageflags', $arr['channel'])) {
|
||||
|
||||
// Several pageflags are site-specific and cannot be sync'd.
|
||||
// Only allow those bits which are shareable from the remote and then
|
||||
@@ -298,6 +337,8 @@ class Libsync {
|
||||
|
||||
}
|
||||
|
||||
$columns = db_columns('channel');
|
||||
|
||||
$disallowed = [
|
||||
'channel_id', 'channel_account_id', 'channel_primary', 'channel_prvkey',
|
||||
'channel_address', 'channel_notifyflags', 'channel_removed', 'channel_deleted',
|
||||
@@ -308,16 +349,21 @@ class Libsync {
|
||||
'channel_a_delegate'
|
||||
];
|
||||
|
||||
$clean = [];
|
||||
foreach ($arr['channel'] as $k => $v) {
|
||||
if (in_array($k, $disallowed))
|
||||
continue;
|
||||
$clean[$k] = $v;
|
||||
if (empty($channel['channel_epubkey']) && empty($channel['channel_eprvkey'])) {
|
||||
$eckey = sodium_crypto_sign_keypair();
|
||||
$channel['channel_epubkey'] = sodium_bin2base64(sodium_crypto_sign_publickey($eckey), SODIUM_BASE64_VARIANT_ORIGINAL_NO_PADDING);
|
||||
$channel['channel_eprvkey'] = sodium_bin2base64(sodium_crypto_sign_secretkey($eckey), SODIUM_BASE64_VARIANT_ORIGINAL_NO_PADDING);
|
||||
}
|
||||
if (count($clean)) {
|
||||
foreach ($clean as $k => $v) {
|
||||
dbq("UPDATE channel set " . dbesc($k) . " = '" . dbesc($v) . "' where channel_id = " . intval($channel['channel_id']));
|
||||
|
||||
foreach ($arr['channel'] as $k => $v) {
|
||||
if (in_array($k, $disallowed)) {
|
||||
continue;
|
||||
}
|
||||
if (!in_array($k, $columns)) {
|
||||
continue;
|
||||
}
|
||||
$r = dbq("UPDATE channel set " . dbesc($k) . " = '" . dbesc($v)
|
||||
. "' where channel_id = " . intval($channel['channel_id']));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -382,19 +428,42 @@ class Libsync {
|
||||
// This relies on the undocumented behaviour that red sites send xchan info with the abook
|
||||
// and import_author_xchan will look them up on all federated networks
|
||||
|
||||
if ($abook['abook_xchan'] && $abook['xchan_addr']) {
|
||||
$found = false;
|
||||
if ($abook['abook_xchan'] && $abook['xchan_addr'] && (! in_array($abook['xchan_network'], [ 'token', 'unknown' ]))) {
|
||||
$h = Libzot::get_hublocs($abook['abook_xchan']);
|
||||
if (!$h) {
|
||||
if ($h) {
|
||||
$found = true;
|
||||
}
|
||||
else {
|
||||
$xhash = import_author_xchan(encode_item_xchan($abook));
|
||||
if (!$xhash) {
|
||||
if ($xhash) {
|
||||
$found = true;
|
||||
}
|
||||
else {
|
||||
logger('Import of ' . $abook['xchan_addr'] . ' failed.');
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!$found && !in_array($abook['xchan_network'], ['zot6', 'activitypub', 'diaspora'])) {
|
||||
// just import the record.
|
||||
$xc = [];
|
||||
foreach ($abook as $k => $v) {
|
||||
if (strpos($k,'xchan_') === 0) {
|
||||
$xc[$k] = $v;
|
||||
}
|
||||
}
|
||||
$r = q("select * from xchan where xchan_hash = '%s'",
|
||||
dbesc($xc['xchan_hash'])
|
||||
);
|
||||
if (! $r) {
|
||||
xchan_store_lowlevel($xc);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
foreach ($abook as $k => $v) {
|
||||
if (in_array($k, $disallowed) || (strpos($k, 'abook') !== 0)) {
|
||||
if (in_array($k, $disallowed) || (strpos($k, 'abook_') !== 0)) {
|
||||
continue;
|
||||
}
|
||||
if (!in_array($k, $fields)) {
|
||||
@@ -408,6 +477,13 @@ class Libsync {
|
||||
|
||||
if (array_key_exists('abook_instance', $clean) && $clean['abook_instance'] && strpos($clean['abook_instance'], z_root()) === false) {
|
||||
$clean['abook_not_here'] = 1;
|
||||
|
||||
// guest pass or access token - don't try to probe since it is one-way
|
||||
// we are relying on the undocumented behaviour that the abook record also contains the xchan
|
||||
if ($abook['xchan_network'] === 'token') {
|
||||
$clean['abook_instance'] .= ',';
|
||||
$clean['abook_instance'] .= z_root();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -681,13 +757,12 @@ class Libsync {
|
||||
*/
|
||||
call_hooks('process_channel_sync_delivery', $addon);
|
||||
|
||||
$DR = new DReport(z_root(), $d, $d, 'sync', 'channel sync delivered');
|
||||
$DR = new DReport(z_root(), $d, $d, $mid, 'channel sync processed');
|
||||
|
||||
$DR->set_name($channel['channel_name'] . ' <' . channel_reddress($channel) . '>');
|
||||
|
||||
$result[] = $DR->get();
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
@@ -696,20 +771,32 @@ class Libsync {
|
||||
*
|
||||
* @param array $sender
|
||||
* @param array $arr
|
||||
* @param boolean $absolute (optional) default false
|
||||
* @return array
|
||||
*/
|
||||
|
||||
static function sync_locations($sender, $arr, $absolute = false) {
|
||||
static function sync_locations($sender, $arr) {
|
||||
|
||||
$ret = [];
|
||||
$ret = [
|
||||
'change_message' => '',
|
||||
'changed' => false,
|
||||
'message' => ''
|
||||
];
|
||||
|
||||
if ($arr['locations']) {
|
||||
$what = '';
|
||||
$changed = false;
|
||||
|
||||
if ($absolute)
|
||||
Libzot::check_location_move($sender['hash'], $arr['locations']);
|
||||
// If a sender reports that the channel has been deleted, delete its hubloc
|
||||
if (isset($arr['deleted_locally']) && intval($arr['deleted_locally'])) {
|
||||
q("UPDATE hubloc SET hubloc_deleted = 1, hubloc_updated = '%s' WHERE hubloc_hash = '%s' AND hubloc_url = '%s'",
|
||||
dbesc(datetime_convert()),
|
||||
dbesc($sender['hash']),
|
||||
dbesc($sender['site']['url'])
|
||||
);
|
||||
}
|
||||
|
||||
$xisting = q("select * from hubloc where hubloc_hash = '%s'",
|
||||
if (isset($arr['locations']) && $arr['locations']) {
|
||||
|
||||
$xisting = q("select * from hubloc where hubloc_hash = '%s' and hubloc_deleted = 0",
|
||||
dbesc($sender['hash'])
|
||||
);
|
||||
|
||||
@@ -757,14 +844,13 @@ class Libsync {
|
||||
|
||||
// match as many fields as possible in case anything at all changed.
|
||||
|
||||
$r = q("select * from hubloc where hubloc_hash = '%s' and hubloc_guid = '%s' and hubloc_guid_sig = '%s' and hubloc_id_url = '%s' and hubloc_url = '%s' and hubloc_url_sig = '%s' and hubloc_site_id = '%s' and hubloc_host = '%s' and hubloc_addr = '%s' and hubloc_callback = '%s' and hubloc_sitekey = '%s' ",
|
||||
$r = q("select * from hubloc where hubloc_hash = '%s' and hubloc_guid = '%s' and hubloc_guid_sig = '%s' and hubloc_id_url = '%s' and hubloc_url = '%s' and hubloc_url_sig = '%s' and hubloc_host = '%s' and hubloc_addr = '%s' and hubloc_callback = '%s' and hubloc_sitekey = '%s' ",
|
||||
dbesc($sender['hash']),
|
||||
dbesc($sender['id']),
|
||||
dbesc($sender['id_sig']),
|
||||
dbesc($location['id_url']),
|
||||
dbesc($location['url']),
|
||||
dbesc($location['url_sig']),
|
||||
dbesc($location['site_id']),
|
||||
dbesc($location['host']),
|
||||
dbesc($location['address']),
|
||||
dbesc($location['callback']),
|
||||
@@ -773,7 +859,18 @@ class Libsync {
|
||||
if ($r) {
|
||||
logger('Hub exists: ' . $location['url'], LOGGER_DEBUG);
|
||||
|
||||
// update connection timestamp if this is the site we're talking to
|
||||
// generate a new hubloc_site_id if it's wrong due to historical bugs 2021-11-30
|
||||
|
||||
if ($r[0]['hubloc_site_id'] !== $location['site_id']) {
|
||||
q("update hubloc set hubloc_site_id = '%s' where hubloc_id = %d",
|
||||
dbesc(Libzot::make_xchan_hash($location['url'], $location['sitekey'])),
|
||||
intval($r[0]['hubloc_id'])
|
||||
);
|
||||
}
|
||||
|
||||
// Update connection timestamp if this is the site we're talking to.
|
||||
// Also mark all entries from the current site with different sitekeys
|
||||
// deleted (the site has been re-installed)
|
||||
// This only happens when called from import_xchan
|
||||
|
||||
$current_site = false;
|
||||
@@ -787,6 +884,12 @@ class Libsync {
|
||||
intval($r[0]['hubloc_id']),
|
||||
dbesc($t)
|
||||
);
|
||||
|
||||
q("update hubloc set hubloc_error = 1, hubloc_deleted = 1 where hubloc_url = '%s' and hubloc_sitekey != '%s' and hubloc_network = 'zot6'",
|
||||
dbesc($r[0]['hubloc_url']),
|
||||
dbesc($r[0]['hubloc_sitekey'])
|
||||
);
|
||||
|
||||
$current_site = true;
|
||||
}
|
||||
|
||||
@@ -836,14 +939,7 @@ class Libsync {
|
||||
$what .= 'primary_hub ';
|
||||
$changed = true;
|
||||
}
|
||||
elseif ($absolute) {
|
||||
// Absolute sync - make sure the current primary is correctly reflected in the xchan
|
||||
$pr = hubloc_change_primary($r[0]);
|
||||
if ($pr) {
|
||||
$what .= 'xchan_primary ';
|
||||
$changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (intval($r[0]['hubloc_deleted']) && (!intval($location['deleted']))) {
|
||||
q("update hubloc set hubloc_deleted = 0, hubloc_updated = '%s' where hubloc_id_url = '%s'",
|
||||
dbesc(datetime_convert()),
|
||||
@@ -861,6 +957,7 @@ class Libsync {
|
||||
$what .= 'delete_hub ';
|
||||
$changed = true;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -911,9 +1008,9 @@ class Libsync {
|
||||
}
|
||||
}
|
||||
|
||||
// get rid of any hubs we have for this channel which weren't reported.
|
||||
// get rid of any hublocs we have for this channel which weren't reported.
|
||||
|
||||
if ($absolute && $xisting) {
|
||||
if ($xisting) {
|
||||
foreach ($xisting as $x) {
|
||||
if (!array_key_exists('updated', $x)) {
|
||||
logger('Deleting unreferenced hub location ' . $x['hubloc_addr']);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
use Zotlabs\Lib\Config;
|
||||
use Zotlabs\Lib\Libzot;
|
||||
use Zotlabs\Lib\Zotfinger;
|
||||
use Zotlabs\Lib\Webfinger;
|
||||
@@ -20,7 +21,7 @@ class Libzotdir {
|
||||
|
||||
static function find_upstream_directory($dirmode) {
|
||||
|
||||
$preferred = get_config('system','directory_server');
|
||||
$preferred = Config::Get('system','directory_server');
|
||||
|
||||
// Thwart attempts to use a private directory
|
||||
|
||||
@@ -47,17 +48,17 @@ class Libzotdir {
|
||||
|
||||
$directory_fallback_servers = get_directory_fallback_servers();
|
||||
|
||||
$dirmode = intval(get_config('system','directory_mode'));
|
||||
$dirmode = intval(Config::Get('system','directory_mode'));
|
||||
if ($dirmode == DIRECTORY_MODE_NORMAL) {
|
||||
$toss = mt_rand(0,count($directory_fallback_servers));
|
||||
$preferred = $directory_fallback_servers[$toss];
|
||||
if(! $preferred) {
|
||||
$preferred = DIRECTORY_FALLBACK_MASTER;
|
||||
}
|
||||
set_config('system','directory_server',$preferred);
|
||||
Config::Set('system','directory_server',$preferred);
|
||||
}
|
||||
else {
|
||||
set_config('system','directory_server',z_root());
|
||||
Config::Set('system','directory_server',z_root());
|
||||
}
|
||||
}
|
||||
if($preferred) {
|
||||
@@ -77,7 +78,7 @@ class Libzotdir {
|
||||
|
||||
static function check_upstream_directory() {
|
||||
|
||||
$directory = get_config('system', 'directory_server');
|
||||
$directory = Config::Get('system', 'directory_server');
|
||||
|
||||
// it's possible there is no directory server configured and the local hub is being used.
|
||||
// If so, default to preserving the absence of a specific server setting.
|
||||
@@ -94,7 +95,7 @@ class Libzotdir {
|
||||
}
|
||||
|
||||
if (! $isadir)
|
||||
set_config('system', 'directory_server', '');
|
||||
Config::Set('system', 'directory_server', '');
|
||||
}
|
||||
|
||||
|
||||
@@ -106,7 +107,7 @@ class Libzotdir {
|
||||
$ret = ((array_key_exists($setting,$_SESSION)) ? intval($_SESSION[$setting]) : false);
|
||||
|
||||
if($ret === false)
|
||||
$ret = get_config('directory', $setting);
|
||||
$ret = Config::Get('directory', $setting);
|
||||
|
||||
|
||||
// 'safemode' is the default if there is no observer or no established preference.
|
||||
@@ -114,7 +115,7 @@ class Libzotdir {
|
||||
if($setting === 'safemode' && $ret === false)
|
||||
$ret = 1;
|
||||
|
||||
if($setting === 'globaldir' && intval(get_config('system','localdir_hide')))
|
||||
if($setting === 'globaldir' && intval(Config::Get('system','localdir_hide')))
|
||||
$ret = 1;
|
||||
|
||||
return $ret;
|
||||
@@ -133,7 +134,7 @@ class Libzotdir {
|
||||
$globaldir = self::get_directory_setting($observer, 'globaldir');
|
||||
$pubforums = self::get_directory_setting($observer, 'pubforums');
|
||||
|
||||
$hide_local = intval(get_config('system','localdir_hide'));
|
||||
$hide_local = intval(Config::Get('system','localdir_hide'));
|
||||
if($hide_local)
|
||||
$globaldir = 1;
|
||||
|
||||
@@ -141,12 +142,12 @@ class Libzotdir {
|
||||
// Build urls without order and pubforums so it's easy to tack on the changed value
|
||||
// Probably there's an easier way to do this
|
||||
|
||||
$directory_sort_order = get_config('system','directory_sort_order');
|
||||
$directory_sort_order = Config::Get('system','directory_sort_order');
|
||||
if(! $directory_sort_order)
|
||||
$directory_sort_order = 'date';
|
||||
|
||||
$current_order = (($_REQUEST['order']) ? $_REQUEST['order'] : $directory_sort_order);
|
||||
$suggest = (($_REQUEST['suggest']) ? '&suggest=' . $_REQUEST['suggest'] : '');
|
||||
$current_order = $_REQUEST['order'] ?? $directory_sort_order;
|
||||
$suggest = ((isset($_REQUEST['suggest'])) ? '&suggest=' . $_REQUEST['suggest'] : '');
|
||||
|
||||
$url = 'directory?f=';
|
||||
|
||||
@@ -172,13 +173,12 @@ class Libzotdir {
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Checks the directory mode of this hub.
|
||||
* @brief fetches updates from known directories
|
||||
*
|
||||
* Checks the directory mode of this hub to see if it is some form of directory server. If it is,
|
||||
* get the directory realm of this hub. Fetch a list of all other directory servers in this realm and request
|
||||
* a directory sync packet. This will contain both directory updates and new ratings. Store these all in the DB.
|
||||
* In the case of updates, we will query each of them asynchronously from a poller task. Ratings are stored
|
||||
* directly if the rater's signature matches.
|
||||
* a directory sync packet. Store these all in the DB.
|
||||
* In the case of updates, we will query each of them asynchronously from a poller task.
|
||||
*
|
||||
* @param int $dirmode;
|
||||
*/
|
||||
@@ -233,6 +233,8 @@ class Libzotdir {
|
||||
if (! $r)
|
||||
return;
|
||||
|
||||
$dir_trusted_hosts = array_merge(get_directory_fallback_servers(), Config::Get('system', 'trusted_directory_servers', []));
|
||||
|
||||
foreach ($r as $rr) {
|
||||
if (! $rr['site_directory'])
|
||||
continue;
|
||||
@@ -243,7 +245,7 @@ class Libzotdir {
|
||||
// It will take about a month for a new directory to obtain the full current repertoire of channels.
|
||||
/** @FIXME Go back and pick up earlier ratings if this is a new directory server. These do not get refreshed. */
|
||||
|
||||
$token = get_config('system','realm_token');
|
||||
$token = Config::Get('system','realm_token');
|
||||
|
||||
$syncdate = (($rr['site_sync'] <= NULL_DATE) ? datetime_convert('UTC','UTC','now - 2 days') : $rr['site_sync']);
|
||||
$x = z_fetch_url($rr['site_directory'] . '?f=&sync=' . urlencode($syncdate) . (($token) ? '&t=' . $token : ''));
|
||||
@@ -264,31 +266,65 @@ class Libzotdir {
|
||||
|
||||
if (is_array($j['transactions']) && count($j['transactions'])) {
|
||||
foreach ($j['transactions'] as $t) {
|
||||
|
||||
if (empty($t['hash']) || empty($t['transaction_id']) || empty($t['address'])) {
|
||||
if (empty($t['hash']) || empty($t['host']) || empty($t['address'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$r = q("select * from updates where ud_guid = '%s' limit 1",
|
||||
dbesc($t['transaction_id'])
|
||||
$r = q("select * from updates where ud_hash = '%s' limit 1",
|
||||
dbesc($t['hash'])
|
||||
);
|
||||
if($r)
|
||||
continue;
|
||||
|
||||
$ud_flags = 0;
|
||||
if (is_array($t['flags']) && in_array('deleted',$t['flags']))
|
||||
$ud_flags |= UPDATE_FLAGS_DELETED;
|
||||
if (is_array($t['flags']) && in_array('forced',$t['flags']))
|
||||
$ud_flags |= UPDATE_FLAGS_FORCED;
|
||||
if ($r) {
|
||||
$update = 0;
|
||||
|
||||
$z = q("insert into updates ( ud_hash, ud_guid, ud_date, ud_flags, ud_addr )
|
||||
values ( '%s', '%s', '%s', %d, '%s' ) ",
|
||||
dbesc($t['hash']),
|
||||
dbesc($t['transaction_id']),
|
||||
dbesc($t['timestamp']),
|
||||
intval($ud_flags),
|
||||
dbesc($t['address'])
|
||||
);
|
||||
// no need to look at updates that originated from our own site
|
||||
if ($t['host'] === z_root()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// there is more recent xchan information
|
||||
if ($r[0]['ud_date'] <= $t['timestamp']) {
|
||||
$update = 1;
|
||||
}
|
||||
|
||||
// the host is trusted and flags have changed - update flags immediately
|
||||
if (in_array($t['host'], $dir_trusted_hosts) &&
|
||||
$rr['site_url'] === $t['host'] &&
|
||||
intval($r[0]['ud_flags']) !== intval($t['flags'])) {
|
||||
|
||||
q("UPDATE updates SET ud_update = %d, ud_flags = %d WHERE ud_id = %d",
|
||||
intval($update),
|
||||
intval($t['flags']),
|
||||
dbesc($r[0]['ud_id'])
|
||||
);
|
||||
|
||||
q("UPDATE xchan SET xchan_censored = %d WHERE xchan_hash = '%s'",
|
||||
intval($t['flags']),
|
||||
dbesc($r[0]['ud_hash'])
|
||||
);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!$update) {
|
||||
continue;
|
||||
}
|
||||
|
||||
q("UPDATE updates SET ud_update = %d WHERE ud_id = %d",
|
||||
intval($update),
|
||||
dbesc($r[0]['ud_id'])
|
||||
);
|
||||
}
|
||||
else {
|
||||
q("insert into updates ( ud_hash, ud_host, ud_date, ud_addr, ud_update, ud_flags )
|
||||
values ( '%s', '%s', '%s', '%s', 1, %d) ",
|
||||
dbesc($t['hash']),
|
||||
dbesc($t['host']),
|
||||
dbesc($t['timestamp']),
|
||||
dbesc($t['address']),
|
||||
dbesc(in_array($t['host'], $dir_trusted_hosts) ? $t['flags'] : 0)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -303,8 +339,9 @@ class Libzotdir {
|
||||
*
|
||||
* Ignore updating records marked as deleted.
|
||||
*
|
||||
* If successful, sets ud_last in the DB to the current datetime for this
|
||||
* If successful, sets ud_updated in the DB to the current datetime for this
|
||||
* reddress/webbie.
|
||||
* Else update ud_last so we can stop trying after 7 days (Daemon/Poller.php)
|
||||
*
|
||||
* @param array $ud Entry from update table
|
||||
*/
|
||||
@@ -313,32 +350,44 @@ class Libzotdir {
|
||||
|
||||
logger('update_directory_entry: ' . print_r($ud,true), LOGGER_DATA);
|
||||
|
||||
if ($ud['ud_addr'] && (! ($ud['ud_flags'] & UPDATE_FLAGS_DELETED))) {
|
||||
$success = false;
|
||||
$zf = [];
|
||||
// TODO: remove this check after all directory servers have version > 8.4
|
||||
// ud_addr will always be the channel url at that time
|
||||
$href = ((strpos($ud['ud_addr'], '://') === false) ? Webfinger::zot_url(punify($ud['ud_addr'])) : punify($ud['ud_addr']));
|
||||
if($href) {
|
||||
$zf = Zotfinger::exec($href);
|
||||
if($zf && array_path_exists('signature/signer',$zf) && $zf['signature']['signer'] === $href && intval($zf['signature']['header_valid'])) {
|
||||
$xc = Libzot::import_xchan($zf['data']);
|
||||
|
||||
// xchan_hash mismatch - this can happen after a site re-install at the same url
|
||||
if ($xc['success'] && $xc['hash'] !== $ud['ud_hash']) {
|
||||
self::delete_by_hash($ud['ud_hash']);
|
||||
}
|
||||
|
||||
// if the channel was deleted - delete the entry in updates
|
||||
if (!empty($zf['data']['deleted_locally'])) {
|
||||
self::delete_by_hash($ud['ud_hash']);
|
||||
}
|
||||
|
||||
$href = Webfinger::zot_url(punify($ud['ud_addr']));
|
||||
if($href) {
|
||||
$zf = Zotfinger::exec($href);
|
||||
}
|
||||
if(array_path_exists('signature/signer',$zf) && $zf['signature']['signer'] === $href && intval($zf['signature']['header_valid'])) {
|
||||
$xc = Libzot::import_xchan($zf['data'], 0, $ud);
|
||||
// This is a workaround for a missing xchan_updated column
|
||||
// TODO: implement xchan_updated in the xchan table and update this column instead
|
||||
if($zf['data']['primary_location']['address'] && $zf['data']['primary_location']['url']) {
|
||||
if(!empty($zf['data']['primary_location']['url'])) {
|
||||
q("UPDATE hubloc SET hubloc_updated = '%s' WHERE hubloc_id_url = '%s' AND hubloc_primary = 1",
|
||||
dbesc(datetime_convert()),
|
||||
dbesc($zf['data']['primary_location']['url'])
|
||||
);
|
||||
}
|
||||
}
|
||||
else {
|
||||
q("update updates set ud_last = '%s' where ud_addr = '%s'",
|
||||
dbesc(datetime_convert()),
|
||||
dbesc($ud['ud_addr'])
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
q("UPDATE updates SET ud_addr = '%s', ud_last = '%s' WHERE ud_hash = '%s'",
|
||||
dbesc($href ? $href : $ud['ud_addr']),
|
||||
dbesc(datetime_convert()),
|
||||
dbesc($ud['ud_hash'])
|
||||
);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -353,85 +402,78 @@ class Libzotdir {
|
||||
*/
|
||||
|
||||
static function local_dir_update($uid, $force) {
|
||||
logger('local_dir_update uid: ' . $uid, LOGGER_DEBUG);
|
||||
|
||||
|
||||
logger('local_dir_update: uid: ' . $uid, LOGGER_DEBUG);
|
||||
|
||||
$p = q("select channel.channel_hash, channel_address, channel_timezone, profile.* from profile left join channel on channel_id = uid where uid = %d and is_default = 1",
|
||||
$p = q("select channel.channel_hash, channel_address, channel_timezone, profile.*, xchan.xchan_hidden, xchan.xchan_url from profile left join channel on channel_id = uid left join xchan on channel_hash = xchan_hash where profile.uid = %d and profile.is_default = 1",
|
||||
intval($uid)
|
||||
);
|
||||
|
||||
$profile = array();
|
||||
$profile['encoding'] = 'zot';
|
||||
|
||||
if ($p) {
|
||||
$hash = $p[0]['channel_hash'];
|
||||
|
||||
$profile['description'] = $p[0]['pdesc'];
|
||||
$profile['birthday'] = $p[0]['dob'];
|
||||
if ($age = age($p[0]['dob'],$p[0]['channel_timezone'],''))
|
||||
$profile['age'] = $age;
|
||||
|
||||
$profile['gender'] = $p[0]['gender'];
|
||||
$profile['marital'] = $p[0]['marital'];
|
||||
$profile['sexual'] = $p[0]['sexual'];
|
||||
$profile['locale'] = $p[0]['locality'];
|
||||
$profile['region'] = $p[0]['region'];
|
||||
$profile['postcode'] = $p[0]['postal_code'];
|
||||
$profile['country'] = $p[0]['country_name'];
|
||||
$profile['about'] = $p[0]['about'];
|
||||
$profile['homepage'] = $p[0]['homepage'];
|
||||
$profile['hometown'] = $p[0]['hometown'];
|
||||
|
||||
if ($p[0]['keywords']) {
|
||||
$tags = array();
|
||||
$k = explode(' ', $p[0]['keywords']);
|
||||
if ($k)
|
||||
foreach ($k as $kk)
|
||||
if (trim($kk))
|
||||
$tags[] = trim($kk);
|
||||
|
||||
if ($tags)
|
||||
$profile['keywords'] = $tags;
|
||||
}
|
||||
|
||||
$hidden = (1 - intval($p[0]['publish']));
|
||||
|
||||
logger('hidden: ' . $hidden);
|
||||
|
||||
$r = q("select xchan_hidden from xchan where xchan_hash = '%s'",
|
||||
dbesc($p[0]['channel_hash'])
|
||||
);
|
||||
|
||||
if(intval($r[0]['xchan_hidden']) != $hidden) {
|
||||
$r = q("update xchan set xchan_hidden = %d where xchan_hash = '%s'",
|
||||
intval($hidden),
|
||||
dbesc($hash)
|
||||
);
|
||||
}
|
||||
|
||||
$arr = [ 'channel_id' => $uid, 'hash' => $hash, 'profile' => $profile ];
|
||||
call_hooks('local_dir_update', $arr);
|
||||
|
||||
$address = channel_reddress($p[0]);
|
||||
|
||||
if (perm_is_allowed($uid, '', 'view_profile')) {
|
||||
self::import_directory_profile($hash, $arr['profile'], $address, 0);
|
||||
}
|
||||
else {
|
||||
// they may have made it private
|
||||
q("delete from xprof where xprof_hash = '%s'",
|
||||
dbesc($hash)
|
||||
);
|
||||
q("delete from xtag where xtag_hash = '%s'",
|
||||
dbesc($hash)
|
||||
);
|
||||
}
|
||||
|
||||
if (!$p) {
|
||||
logger('profile not found');
|
||||
return;
|
||||
}
|
||||
|
||||
$ud_hash = random_string() . '@' . \App::get_hostname();
|
||||
self::update_modtime($hash, $ud_hash, channel_reddress($p[0]),(($force) ? UPDATE_FLAGS_FORCED : UPDATE_FLAGS_UPDATED));
|
||||
$profile = [];
|
||||
$profile['encoding'] = 'zot';
|
||||
|
||||
$hash = $p[0]['channel_hash'];
|
||||
|
||||
$profile['description'] = $p[0]['pdesc'];
|
||||
$profile['birthday'] = $p[0]['dob'];
|
||||
if ($age = age($p[0]['dob'],$p[0]['channel_timezone'],''))
|
||||
$profile['age'] = $age;
|
||||
|
||||
$profile['gender'] = $p[0]['gender'];
|
||||
$profile['marital'] = $p[0]['marital'];
|
||||
$profile['sexual'] = $p[0]['sexual'];
|
||||
$profile['locale'] = $p[0]['locality'];
|
||||
$profile['region'] = $p[0]['region'];
|
||||
$profile['postcode'] = $p[0]['postal_code'];
|
||||
$profile['country'] = $p[0]['country_name'];
|
||||
$profile['about'] = $p[0]['about'];
|
||||
$profile['homepage'] = $p[0]['homepage'];
|
||||
$profile['hometown'] = $p[0]['hometown'];
|
||||
|
||||
if ($p[0]['keywords']) {
|
||||
$tags = array();
|
||||
$k = explode(' ', $p[0]['keywords']);
|
||||
if ($k)
|
||||
foreach ($k as $kk)
|
||||
if (trim($kk))
|
||||
$tags[] = trim($kk);
|
||||
|
||||
if ($tags)
|
||||
$profile['keywords'] = $tags;
|
||||
}
|
||||
|
||||
$hidden = (1 - intval($p[0]['publish']));
|
||||
|
||||
logger('hidden: ' . $hidden);
|
||||
|
||||
if(intval($p[0]['xchan_hidden']) !== $hidden) {
|
||||
q("update xchan set xchan_hidden = %d where xchan_hash = '%s'",
|
||||
intval($hidden),
|
||||
dbesc($hash)
|
||||
);
|
||||
}
|
||||
|
||||
$arr = [ 'channel_id' => $uid, 'hash' => $hash, 'profile' => $profile ];
|
||||
call_hooks('local_dir_update', $arr);
|
||||
|
||||
if (perm_is_allowed($uid, '', 'view_profile')) {
|
||||
self::import_directory_profile($hash, $arr['profile']);
|
||||
}
|
||||
else {
|
||||
// they may have made it private
|
||||
q("delete from xprof where xprof_hash = '%s'",
|
||||
dbesc($hash)
|
||||
);
|
||||
q("delete from xtag where xtag_hash = '%s'",
|
||||
dbesc($hash)
|
||||
);
|
||||
}
|
||||
|
||||
self::update($hash, $p[0]['xchan_url']);
|
||||
}
|
||||
|
||||
|
||||
@@ -441,39 +483,48 @@ class Libzotdir {
|
||||
*
|
||||
* @param string $hash
|
||||
* @param array $profile
|
||||
* @param string $addr
|
||||
* @param number $ud_flags (optional) UPDATE_FLAGS_UPDATED
|
||||
* @param number $suppress_update (optional) default 0
|
||||
* @return boolean $updated if something changed
|
||||
*/
|
||||
|
||||
static function import_directory_profile($hash, $profile, $addr, $ud_flags = UPDATE_FLAGS_UPDATED, $suppress_update = 0) {
|
||||
static function import_directory_profile($hash, $profile) {
|
||||
|
||||
logger('import_directory_profile', LOGGER_DEBUG);
|
||||
if (! $hash)
|
||||
return false;
|
||||
|
||||
$arr = array();
|
||||
$arr = [];
|
||||
|
||||
$arr['xprof_hash'] = $hash;
|
||||
$arr['xprof_dob'] = (($profile['birthday'] === '0000-00-00') ? $profile['birthday'] : datetime_convert('','',$profile['birthday'],'Y-m-d')); // !!!! check this for 0000 year
|
||||
$arr['xprof_age'] = (($profile['age']) ? intval($profile['age']) : 0);
|
||||
$arr['xprof_desc'] = (($profile['description']) ? htmlspecialchars($profile['description'], ENT_COMPAT,'UTF-8',false) : '');
|
||||
$arr['xprof_gender'] = (($profile['gender']) ? htmlspecialchars($profile['gender'], ENT_COMPAT,'UTF-8',false) : '');
|
||||
$arr['xprof_marital'] = (($profile['marital']) ? htmlspecialchars($profile['marital'], ENT_COMPAT,'UTF-8',false) : '');
|
||||
$arr['xprof_sexual'] = (($profile['sexual']) ? htmlspecialchars($profile['sexual'], ENT_COMPAT,'UTF-8',false) : '');
|
||||
$arr['xprof_locale'] = (($profile['locale']) ? htmlspecialchars($profile['locale'], ENT_COMPAT,'UTF-8',false) : '');
|
||||
$arr['xprof_region'] = (($profile['region']) ? htmlspecialchars($profile['region'], ENT_COMPAT,'UTF-8',false) : '');
|
||||
$arr['xprof_postcode'] = (($profile['postcode']) ? htmlspecialchars($profile['postcode'], ENT_COMPAT,'UTF-8',false) : '');
|
||||
$arr['xprof_country'] = (($profile['country']) ? htmlspecialchars($profile['country'], ENT_COMPAT,'UTF-8',false) : '');
|
||||
$arr['xprof_about'] = (($profile['about']) ? htmlspecialchars($profile['about'], ENT_COMPAT,'UTF-8',false) : '');
|
||||
$arr['xprof_homepage'] = (($profile['homepage']) ? htmlspecialchars($profile['homepage'], ENT_COMPAT,'UTF-8',false) : '');
|
||||
$arr['xprof_hometown'] = (($profile['hometown']) ? htmlspecialchars($profile['hometown'], ENT_COMPAT,'UTF-8',false) : '');
|
||||
$arr['xprof_hash'] = $hash;
|
||||
$arr['xprof_dob'] = '0000-00-00';
|
||||
|
||||
if (isset($profile['birthday'])) {
|
||||
$arr['xprof_dob'] = (($profile['birthday'] === '0000-00-00')
|
||||
? $profile['birthday']
|
||||
: datetime_convert('', '', $profile['birthday'], 'Y-m-d')); // !!!! check this for 0000 year
|
||||
}
|
||||
|
||||
$arr['xprof_age'] = ((isset($profile['age']) && $profile['age']) ? intval($profile['age']) : 0);
|
||||
$arr['xprof_desc'] = ((isset($profile['description']) && $profile['description']) ? htmlspecialchars($profile['description'], ENT_COMPAT,'UTF-8',false) : '');
|
||||
$arr['xprof_gender'] = ((isset($profile['gender']) && $profile['gender']) ? htmlspecialchars($profile['gender'], ENT_COMPAT,'UTF-8',false) : '');
|
||||
$arr['xprof_marital'] = ((isset($profile['marital']) && $profile['marital']) ? htmlspecialchars($profile['marital'], ENT_COMPAT,'UTF-8',false) : '');
|
||||
$arr['xprof_sexual'] = ((isset($profile['sexual']) && $profile['sexual']) ? htmlspecialchars($profile['sexual'], ENT_COMPAT,'UTF-8',false) : '');
|
||||
$arr['xprof_locale'] = ((isset($profile['locale']) && $profile['locale']) ? htmlspecialchars($profile['locale'], ENT_COMPAT,'UTF-8',false) : '');
|
||||
$arr['xprof_region'] = ((isset($profile['region']) && $profile['region']) ? htmlspecialchars($profile['region'], ENT_COMPAT,'UTF-8',false) : '');
|
||||
$arr['xprof_postcode'] = ((isset($profile['postcode']) && $profile['postcode']) ? htmlspecialchars($profile['postcode'], ENT_COMPAT,'UTF-8',false) : '');
|
||||
$arr['xprof_country'] = ((isset($profile['country']) && $profile['country']) ? htmlspecialchars($profile['country'], ENT_COMPAT,'UTF-8',false) : '');
|
||||
$arr['xprof_about'] = ((isset($profile['about']) && $profile['about']) ? htmlspecialchars($profile['about'], ENT_COMPAT,'UTF-8',false) : '');
|
||||
$arr['xprof_homepage'] = ((isset($profile['homepage']) && $profile['homepage']) ? htmlspecialchars($profile['homepage'], ENT_COMPAT,'UTF-8',false) : '');
|
||||
$arr['xprof_hometown'] = ((isset($profile['hometown']) && $profile['hometown']) ? htmlspecialchars($profile['hometown'], ENT_COMPAT,'UTF-8',false) : '');
|
||||
|
||||
$clean = array();
|
||||
if (array_key_exists('keywords', $profile) and is_array($profile['keywords'])) {
|
||||
self::import_directory_keywords($hash,$profile['keywords']);
|
||||
|
||||
foreach ($profile['keywords'] as $kw) {
|
||||
if (in_array($kw, $clean)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$kw = trim(htmlspecialchars($kw,ENT_COMPAT, 'UTF-8', false));
|
||||
$kw = trim($kw, ',');
|
||||
$clean[] = $kw;
|
||||
@@ -580,9 +631,6 @@ class Libzotdir {
|
||||
*/
|
||||
call_hooks('import_directory_profile', $d);
|
||||
|
||||
if (($d['update']) && (! $suppress_update))
|
||||
self::update_modtime($arr['xprof_hash'],random_string() . '@' . \App::get_hostname(), $addr, $ud_flags);
|
||||
|
||||
return $d['update'];
|
||||
}
|
||||
|
||||
@@ -600,6 +648,10 @@ class Libzotdir {
|
||||
dbesc($hash)
|
||||
);
|
||||
|
||||
$xchan = q("select xchan_censored from xchan where xchan_hash = '%s'",
|
||||
dbesc($hash)
|
||||
);
|
||||
|
||||
if($r) {
|
||||
foreach($r as $rr)
|
||||
$existing[] = $rr['xtag_term'];
|
||||
@@ -607,6 +659,10 @@ class Libzotdir {
|
||||
|
||||
$clean = array();
|
||||
foreach($keywords as $kw) {
|
||||
if (in_array($kw, $clean)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$kw = trim(htmlspecialchars($kw,ENT_COMPAT, 'UTF-8', false));
|
||||
$kw = trim($kw, ',');
|
||||
$clean[] = $kw;
|
||||
@@ -621,9 +677,10 @@ class Libzotdir {
|
||||
}
|
||||
foreach($clean as $x) {
|
||||
if(! in_array($x, $existing)) {
|
||||
$r = q("insert into xtag ( xtag_hash, xtag_term, xtag_flags) values ( '%s' ,'%s', 0 )",
|
||||
$r = q("insert into xtag ( xtag_hash, xtag_term, xtag_flags) values ( '%s' ,'%s', %d )",
|
||||
dbesc($hash),
|
||||
dbesc($x)
|
||||
dbesc($x),
|
||||
intval($xchan[0]['xchan_censored'])
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -633,40 +690,83 @@ class Libzotdir {
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @param string $hash
|
||||
* @param string $guid
|
||||
* @param string $addr
|
||||
* @param int $flags (optional) default 0
|
||||
* @param string $hash the channel hash
|
||||
* @param string $addr the channel url
|
||||
* @param bool $bump_date (optional) default true
|
||||
*/
|
||||
|
||||
static function update_modtime($hash, $guid, $addr, $flags = 0) {
|
||||
static function update($hash, $addr, $bump_date = true, $flag = null) {
|
||||
|
||||
$dirmode = intval(get_config('system', 'directory_mode'));
|
||||
$dirmode = intval(Config::Get('system', 'directory_mode'));
|
||||
|
||||
if($dirmode == DIRECTORY_MODE_NORMAL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (empty($hash) || empty($guid) || empty($addr)) {
|
||||
if (empty($hash) || empty($addr)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if($flags) {
|
||||
q("insert into updates (ud_hash, ud_guid, ud_date, ud_flags, ud_addr ) values ( '%s', '%s', '%s', %d, '%s' )",
|
||||
dbesc($hash),
|
||||
dbesc($guid),
|
||||
dbesc(datetime_convert()),
|
||||
intval($flags),
|
||||
dbesc($addr)
|
||||
);
|
||||
$u = q("SELECT * FROM updates WHERE ud_hash = '%s' LIMIT 1",
|
||||
dbesc($hash)
|
||||
);
|
||||
|
||||
$date_sql = '';
|
||||
if ($bump_date) {
|
||||
$date_sql = "ud_date = '" . dbesc(datetime_convert()) . "',";
|
||||
}
|
||||
else {
|
||||
q("update updates set ud_flags = ( ud_flags | %d ) where ud_addr = '%s' and not (ud_flags & %d)>0 ",
|
||||
intval(UPDATE_FLAGS_UPDATED),
|
||||
|
||||
$flag_sql = '';
|
||||
if ($flag !== null) {
|
||||
$flag_sql = "ud_flags = '" . intval($flag) . "',";
|
||||
}
|
||||
|
||||
|
||||
if ($u) {
|
||||
$x = q("UPDATE updates SET $date_sql $flag_sql ud_last = '%s', ud_host = '%s', ud_addr = '%s', ud_update = 0 WHERE ud_id = %d",
|
||||
dbesc(NULL_DATE),
|
||||
dbesc(z_root()),
|
||||
dbesc($addr),
|
||||
intval(UPDATE_FLAGS_UPDATED)
|
||||
intval($u[0]['ud_id'])
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
q("INSERT INTO updates (ud_hash, ud_host, ud_date, ud_addr, ud_flags) VALUES ( '%s', '%s', '%s', '%s', %d )",
|
||||
dbesc($hash),
|
||||
dbesc(z_root()),
|
||||
dbesc(datetime_convert()),
|
||||
dbesc($addr),
|
||||
intval($flag)
|
||||
);
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief deletes a entry in updates by hash
|
||||
*
|
||||
* @param string $hash the channel hash
|
||||
* @return boolean
|
||||
*/
|
||||
|
||||
static function delete_by_hash($hash) {
|
||||
if (!$hash) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$x = q("DELETE FROM updates WHERE ud_hash = '%s'",
|
||||
dbesc($hash)
|
||||
);
|
||||
|
||||
if ($x) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
86
Zotlabs/Lib/Mailer.php
Normal file
86
Zotlabs/Lib/Mailer.php
Normal file
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
/**
|
||||
* Mailer class for sending emails from Hubzilla.
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2024 Hubzilla Community
|
||||
* SPDX-FileContributor: Harald Eilertsen
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
use App;
|
||||
|
||||
/**
|
||||
* A class for sending emails.
|
||||
*
|
||||
* Based on the previous `z_mail` function, but adaped and made more
|
||||
* robust and usable as a class.
|
||||
*/
|
||||
class Mailer {
|
||||
|
||||
public function __construct(private array $params = []) {
|
||||
}
|
||||
|
||||
public function deliver(): bool {
|
||||
|
||||
if(empty($this->params['fromEmail'])) {
|
||||
$this->params['fromEmail'] = Config::Get('system','from_email');
|
||||
if(empty($this->params['fromEmail'])) {
|
||||
$this->params['fromEmail'] = 'Administrator@' . App::get_hostname();
|
||||
}
|
||||
}
|
||||
|
||||
if(empty($this->params['fromName'])) {
|
||||
$this->params['fromName'] = Config::Get('system','from_email_name');
|
||||
if(empty($this->params['fromName'])) {
|
||||
$this->params['fromName'] = System::get_site_name();
|
||||
}
|
||||
}
|
||||
|
||||
if(empty($this->params['replyTo'])) {
|
||||
$this->params['replyTo'] = Config::Get('system','reply_address');
|
||||
if(empty($this->params['replyTo'])) {
|
||||
$this->params['replyTo'] = 'noreply@' . App::get_hostname();
|
||||
}
|
||||
}
|
||||
|
||||
if (!isset($this->params['additionalMailHeader'])) {
|
||||
$this->params['additionalMailHeader'] = '';
|
||||
}
|
||||
|
||||
$this->params['sent'] = false;
|
||||
$this->params['result'] = false;
|
||||
|
||||
/**
|
||||
* @hooks email_send
|
||||
* * \e params @see z_mail()
|
||||
*/
|
||||
call_hooks('email_send', $this->params);
|
||||
|
||||
if($this->params['sent']) {
|
||||
logger('notification: z_mail returns ' . (($this->params['result']) ? 'success' : 'failure'), LOGGER_DEBUG);
|
||||
return $this->params['result'];
|
||||
}
|
||||
|
||||
$fromName = email_header_encode(html_entity_decode($this->params['fromName'],ENT_QUOTES,'UTF-8'),'UTF-8');
|
||||
$messageSubject = email_header_encode(html_entity_decode($this->params['messageSubject'],ENT_QUOTES,'UTF-8'),'UTF-8');
|
||||
|
||||
$messageHeader =
|
||||
$this->params['additionalMailHeader'] .
|
||||
"From: $fromName <{$this->params['fromEmail']}>" . PHP_EOL .
|
||||
"Reply-To: $fromName <{$this->params['replyTo']}>" . PHP_EOL .
|
||||
"Content-Type: text/plain; charset=UTF-8";
|
||||
|
||||
// send the message
|
||||
$res = mail(
|
||||
$this->params['toEmail'], // send to address
|
||||
$messageSubject, // subject
|
||||
$this->params['textVersion'],
|
||||
$messageHeader // message headers
|
||||
);
|
||||
logger('notification: z_mail returns ' . (($res) ? 'success' : 'failure'), LOGGER_DEBUG);
|
||||
return $res;
|
||||
}
|
||||
}
|
||||
@@ -2,85 +2,120 @@
|
||||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
|
||||
require_once('include/html2plain.php');
|
||||
|
||||
class MessageFilter {
|
||||
|
||||
public static function evaluate($item, $incl, $excl) {
|
||||
|
||||
static public function evaluate($item,$incl,$excl) {
|
||||
|
||||
require_once('include/html2plain.php');
|
||||
|
||||
$text = prepare_text($item['body'],$item['mimetype']);
|
||||
$text = prepare_text($item['body'],((isset($item['mimetype'])) ? $item['mimetype'] : 'text/bbcode'));
|
||||
$text = html2plain(($item['title']) ? $item['title'] . ' ' . $text : $text);
|
||||
|
||||
|
||||
$lang = null;
|
||||
|
||||
if((strpos($incl,'lang=') !== false) || (strpos($excl,'lang=') !== false) || (strpos($incl,'lang!=') !== false) || (strpos($excl,'lang!=') !== false)) {
|
||||
if ((strpos($incl, 'lang=') !== false) || (strpos($excl, 'lang=') !== false) || (strpos($incl, 'lang!=') !== false) || (strpos($excl, 'lang!=') !== false)) {
|
||||
$lang = detect_language($text);
|
||||
}
|
||||
|
||||
$tags = ((is_array($item['term']) && count($item['term'])) ? $item['term'] : false);
|
||||
$tags = ((isset($item['term']) && is_array($item['term']) && count($item['term'])) ? $item['term'] : false);
|
||||
|
||||
// exclude always has priority
|
||||
|
||||
$exclude = (($excl) ? explode("\n",$excl) : null);
|
||||
$exclude = (($excl) ? explode("\n", $excl) : null);
|
||||
|
||||
if($exclude) {
|
||||
foreach($exclude as $word) {
|
||||
$word = trim($word);
|
||||
if(! $word)
|
||||
if ($exclude) {
|
||||
foreach ($exclude as $word) {
|
||||
$word = html_entity_decode(trim($word));
|
||||
if (! $word) {
|
||||
continue;
|
||||
if(substr($word,0,1) === '#' && $tags) {
|
||||
foreach($tags as $t)
|
||||
if((($t['ttype'] == TERM_HASHTAG) || ($t['ttype'] == TERM_COMMUNITYTAG)) && (($t['term'] === substr($word,1)) || (substr($word,1) === '*')))
|
||||
return false;
|
||||
}
|
||||
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;
|
||||
if (isset($lang) && ((strpos($word, 'lang=') === 0) || (strpos($word, 'lang!=') === 0))) {
|
||||
if (!strlen($lang)) {
|
||||
// Result is ambiguous. As we are matching deny rules only at this time, continue tests.
|
||||
// Any matching deny rule concludes testing.
|
||||
continue;
|
||||
}
|
||||
if (strpos($word, 'lang=') === 0 && strcasecmp($lang, trim(substr($word, 5))) == 0) {
|
||||
return false;
|
||||
} elseif (strpos($word, 'lang!=') === 0 && strcasecmp($lang, trim(substr($word, 6))) != 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
elseif((strpos($word,'/') === 0) && preg_match($word,$text))
|
||||
elseif (substr($word, 0, 1) === '#' && $tags) {
|
||||
foreach ($tags as $t) {
|
||||
if ((($t['ttype'] == TERM_HASHTAG) || ($t['ttype'] == TERM_COMMUNITYTAG)) && (($t['term'] === substr($word, 1)) || (substr($word, 1) === '*'))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} 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 (substr($word, 0, 2) === '?+') {
|
||||
if (self::test_condition(substr($word, 2), $item['obj'])) {
|
||||
return false;
|
||||
}
|
||||
} elseif (substr($word, 0, 1) === '?') {
|
||||
if (self::test_condition(substr($word, 1), $item)) {
|
||||
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)
|
||||
} elseif (stristr($text, $word) !== false) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$include = (($incl) ? explode("\n",$incl) : null);
|
||||
$include = (($incl) ? explode("\n", $incl) : null);
|
||||
|
||||
if($include) {
|
||||
foreach($include as $word) {
|
||||
$word = trim($word);
|
||||
if(! $word)
|
||||
if ($include) {
|
||||
foreach ($include as $word) {
|
||||
$word = html_entity_decode(trim($word));
|
||||
if (! $word) {
|
||||
continue;
|
||||
if(substr($word,0,1) === '#' && $tags) {
|
||||
foreach($tags as $t)
|
||||
if((($t['ttype'] == TERM_HASHTAG) || ($t['ttype'] == TERM_COMMUNITYTAG)) && (($t['term'] === substr($word,1)) || (substr($word,1) === '*')))
|
||||
return true;
|
||||
}
|
||||
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;
|
||||
if (isset($lang) && ((strpos($word, 'lang=') === 0) || (strpos($word, 'lang!=') === 0))) {
|
||||
if (!strlen($lang)) {
|
||||
// Result is ambiguous. However we are checking allow rules
|
||||
// and an ambiguous language is always permitted.
|
||||
return true;
|
||||
}
|
||||
if (strpos($word, 'lang=') === 0 && strcasecmp($lang, trim(substr($word, 5))) == 0) {
|
||||
return true;
|
||||
} elseif (strpos($word, 'lang!=') === 0 && strcasecmp($lang, trim(substr($word, 6))) != 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
elseif((strpos($word,'/') === 0) && preg_match($word,$text))
|
||||
elseif (substr($word, 0, 1) === '#' && $tags) {
|
||||
foreach ($tags as $t) {
|
||||
if ((($t['ttype'] == TERM_HASHTAG) || ($t['ttype'] == TERM_COMMUNITYTAG)) && (($t['term'] === substr($word, 1)) || (substr($word, 1) === '*'))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} 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 (substr($word, 0, 2) === '?+') {
|
||||
if (self::test_condition(substr($word, 2), $item['obj'])) {
|
||||
return true;
|
||||
}
|
||||
} elseif (substr($word, 0, 1) === '?') {
|
||||
if (self::test_condition(substr($word, 1), $item)) {
|
||||
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)
|
||||
} elseif (stristr($text, $word) !== false) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -88,4 +123,123 @@ class MessageFilter {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Test for Conditional Execution conditions. Shamelessly ripped off from Code/Render/Comanche
|
||||
*
|
||||
* This is extensible. The first version of variable testing supports tests of the forms:
|
||||
*
|
||||
* - ?foo ~= baz which will check if item.foo contains the string 'baz';
|
||||
* - ?foo == baz which will check if item.foo is the string 'baz';
|
||||
* - ?foo != baz which will check if item.foo is not the string 'baz';
|
||||
* - ?foo >= 3 which will check if item.foo is greater than or equal to 3;
|
||||
* - ?foo > 3 which will check if item.foo is greater than 3;
|
||||
* - ?foo <= 3 which will check if item.foo is less than or equal to 3;
|
||||
* - ?foo < 3 which will check if item.foo is less than 3;
|
||||
*
|
||||
* - ?foo {} baz which will check if 'baz' is an array element in item.foo
|
||||
* - ?foo {*} baz which will check if 'baz' is an array key in item.foo
|
||||
* - ?foo which will check for a return of a true condition for item.foo;
|
||||
* - ?!foo which will check for a return of a false condition for item.foo;
|
||||
*
|
||||
* The values 0, '', an empty array, and an unset value will all evaluate to false.
|
||||
*
|
||||
* @param string $s
|
||||
* @param array $item
|
||||
* @return bool
|
||||
*/
|
||||
|
||||
public static function test_condition($s,$item) {
|
||||
|
||||
if (preg_match('/(.*?)\s\~\=\s(.*?)$/', $s, $matches)) {
|
||||
$x = ((array_key_exists(trim($matches[1]),$item)) ? $item[trim($matches[1])] : EMPTY_STR);
|
||||
if (stripos($x, trim($matches[2])) !== false) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (preg_match('/(.*?)\s\=\=\s(.*?)$/', $s, $matches)) {
|
||||
$x = ((array_key_exists(trim($matches[1]),$item)) ? $item[trim($matches[1])] : EMPTY_STR);
|
||||
if ($x == trim($matches[2])) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (preg_match('/(.*?)\s\!\=\s(.*?)$/', $s, $matches)) {
|
||||
$x = ((array_key_exists(trim($matches[1]),$item)) ? $item[trim($matches[1])] : EMPTY_STR);
|
||||
if ($x != trim($matches[2])) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (preg_match('/(.*?)\s\>\=\s(.*?)$/', $s, $matches)) {
|
||||
$x = ((array_key_exists(trim($matches[1]),$item)) ? $item[trim($matches[1])] : EMPTY_STR);
|
||||
if ($x >= trim($matches[2])) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (preg_match('/(.*?)\s\<\=\s(.*?)$/', $s, $matches)) {
|
||||
$x = ((array_key_exists(trim($matches[1]),$item)) ? $item[trim($matches[1])] : EMPTY_STR);
|
||||
if ($x <= trim($matches[2])) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (preg_match('/(.*?)\s\>\s(.*?)$/', $s, $matches)) {
|
||||
$x = ((array_key_exists(trim($matches[1]),$item)) ? $item[trim($matches[1])] : EMPTY_STR);
|
||||
if ($x > trim($matches[2])) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (preg_match('/(.*?)\s\>\s(.*?)$/', $s, $matches)) {
|
||||
$x = ((array_key_exists(trim($matches[1]),$item)) ? $item[trim($matches[1])] : EMPTY_STR);
|
||||
if ($x < trim($matches[2])) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (preg_match('/[\$](.*?)\s\{\}\s(.*?)$/', $s, $matches)) {
|
||||
$x = ((array_key_exists(trim($matches[1]),$item)) ? $item[trim($matches[1])] : EMPTY_STR);
|
||||
if (is_array($x) && in_array(trim($matches[2]), $x)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (preg_match('/(.*?)\s\{\*\}\s(.*?)$/', $s, $matches)) {
|
||||
$x = ((array_key_exists(trim($matches[1]),$item)) ? $item[trim($matches[1])] : EMPTY_STR);
|
||||
if (is_array($x) && array_key_exists(trim($matches[2]), $x)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Ordering of this check (for falsiness) with relation to the following one (check for truthiness) is important.
|
||||
if (preg_match('/\!(.*?)$/', $s, $matches)) {
|
||||
$x = ((array_key_exists(trim($matches[1]),$item)) ? $item[trim($matches[1])] : EMPTY_STR);
|
||||
if (!$x) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (preg_match('/(.*?)$/', $s, $matches)) {
|
||||
$x = ((array_key_exists(trim($matches[1]),$item)) ? $item[trim($matches[1])] : EMPTY_STR);
|
||||
if ($x) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
34
Zotlabs/Lib/Multibase.php
Normal file
34
Zotlabs/Lib/Multibase.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
use StephenHill\Base58;
|
||||
|
||||
class Multibase {
|
||||
|
||||
protected $key = null;
|
||||
|
||||
public function __construct() {
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function publicKey($key) {
|
||||
$base58 = new Base58();
|
||||
$raw = hex2bin('ed01') . sodium_base642bin($key, SODIUM_BASE64_VARIANT_ORIGINAL_NO_PADDING);
|
||||
return 'z' . $base58->encode($raw);
|
||||
}
|
||||
|
||||
public function secretKey($key) {
|
||||
$base58 = new Base58();
|
||||
$raw = hex2bin('8026') . sodium_base642bin($key, SODIUM_BASE64_VARIANT_ORIGINAL_NO_PADDING);
|
||||
return 'z' . $base58->encode($raw);
|
||||
}
|
||||
|
||||
public function decode($key, $binary = false) {
|
||||
$base58 = new Base58();
|
||||
$key = substr($key,1);
|
||||
$raw = $base58->decode($key);
|
||||
$binaryKey = substr($raw, 2);
|
||||
return $binary ? $binaryKey : sodium_bin2base64($binaryKey, SODIUM_BASE64_VARIANT_ORIGINAL_NO_PADDING);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,324 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
use Zotlabs\Lib\Libsync;
|
||||
|
||||
define ( 'NWIKI_ITEM_RESOURCE_TYPE', 'nwiki' );
|
||||
|
||||
class NativeWiki {
|
||||
|
||||
|
||||
public static function listwikis($channel, $observer_hash) {
|
||||
|
||||
$sql_extra = item_permissions_sql($channel['channel_id'], $observer_hash);
|
||||
$wikis = q("SELECT * FROM item
|
||||
WHERE resource_type = '%s' AND mid = parent_mid AND uid = %d AND item_deleted = 0 $sql_extra",
|
||||
dbesc(NWIKI_ITEM_RESOURCE_TYPE),
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
|
||||
if($wikis) {
|
||||
foreach($wikis as &$w) {
|
||||
|
||||
$w['json_allow_cid'] = acl2json($w['allow_cid']);
|
||||
$w['json_allow_gid'] = acl2json($w['allow_gid']);
|
||||
$w['json_deny_cid'] = acl2json($w['deny_cid']);
|
||||
$w['json_deny_gid'] = acl2json($w['deny_gid']);
|
||||
|
||||
$w['rawName'] = get_iconfig($w, 'wiki', 'rawName');
|
||||
$w['htmlName'] = escape_tags($w['rawName']);
|
||||
//$w['urlName'] = urlencode(urlencode($w['rawName']));
|
||||
$w['urlName'] = self::name_encode($w['rawName']);
|
||||
$w['mimeType'] = get_iconfig($w, 'wiki', 'mimeType');
|
||||
$w['typelock'] = get_iconfig($w, 'wiki', 'typelock');
|
||||
$w['lockstate'] = (($w['allow_cid'] || $w['allow_gid'] || $w['deny_cid'] || $w['deny_gid']) ? 'lock' : 'unlock');
|
||||
}
|
||||
}
|
||||
// TODO: query db for wikis the observer can access. Return with two lists, for read and write access
|
||||
return array('wikis' => $wikis);
|
||||
}
|
||||
|
||||
|
||||
public static function create_wiki($channel, $observer_hash, $wiki, $acl) {
|
||||
|
||||
$resource_id = new_uuid();
|
||||
$uuid = new_uuid();
|
||||
|
||||
$ac = $acl->get();
|
||||
$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;
|
||||
$arr['item_hidden'] = $item_hidden;
|
||||
$arr['resource_type'] = NWIKI_ITEM_RESOURCE_TYPE;
|
||||
$arr['resource_id'] = $resource_id;
|
||||
$arr['owner_xchan'] = $channel['channel_hash'];
|
||||
$arr['author_xchan'] = $observer_hash;
|
||||
$arr['plink'] = z_root() . '/channel/' . $channel['channel_address'] . '/?f=&mid=' . urlencode($arr['mid']);
|
||||
$arr['llink'] = $arr['plink'];
|
||||
$arr['title'] = $wiki['htmlName']; // name of new wiki;
|
||||
$arr['allow_cid'] = $ac['allow_cid'];
|
||||
$arr['allow_gid'] = $ac['allow_gid'];
|
||||
$arr['deny_cid'] = $ac['deny_cid'];
|
||||
$arr['deny_gid'] = $ac['deny_gid'];
|
||||
$arr['item_wall'] = 1;
|
||||
$arr['item_origin'] = 1;
|
||||
$arr['item_thread_top'] = 1;
|
||||
$arr['item_private'] = intval($acl->is_private());
|
||||
$arr['verb'] = ACTIVITY_CREATE;
|
||||
$arr['obj_type'] = 'Document';
|
||||
$arr['body'] = '[table][tr][td][h1]New Wiki[/h1][/td][/tr][tr][td][zrl=' . $wiki_url . ']' . $wiki['htmlName'] . '[/zrl][/td][/tr][/table]';
|
||||
|
||||
$arr['public_policy'] = map_scope(\Zotlabs\Access\PermissionLimits::Get($channel['channel_id'],'view_wiki'),true);
|
||||
|
||||
// Save the wiki name information using iconfig. This is shareable.
|
||||
if(! set_iconfig($arr, 'wiki', 'rawName', $wiki['rawName'], true)) {
|
||||
return array('item' => null, 'success' => false);
|
||||
}
|
||||
if(! set_iconfig($arr, 'wiki', 'mimeType', $wiki['mimeType'], true)) {
|
||||
return array('item' => null, 'success' => false);
|
||||
}
|
||||
|
||||
set_iconfig($arr,'wiki','typelock',$wiki['typelock'],true);
|
||||
|
||||
$post = item_store($arr);
|
||||
|
||||
$item_id = $post['item_id'];
|
||||
|
||||
if($item_id) {
|
||||
\Zotlabs\Daemon\Master::Summon(array('Notifier', 'activity', $item_id));
|
||||
return array('item' => $post['item'], 'item_id' => $item_id, 'success' => true);
|
||||
}
|
||||
else {
|
||||
return array('item' => null, 'success' => false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static function update_wiki($channel_id, $observer_hash, $arr, $acl) {
|
||||
|
||||
$w = self::get_wiki($channel_id, $observer_hash, $arr['resource_id']);
|
||||
$item = $w['wiki'];
|
||||
|
||||
if(! $item) {
|
||||
return array('item' => null, 'success' => false);
|
||||
}
|
||||
|
||||
$x = $acl->get();
|
||||
|
||||
$item['allow_cid'] = $x['allow_cid'];
|
||||
$item['allow_gid'] = $x['allow_gid'];
|
||||
$item['deny_cid'] = $x['deny_cid'];
|
||||
$item['deny_gid'] = $x['deny_gid'];
|
||||
$item['item_private'] = intval($acl->is_private());
|
||||
|
||||
$update_title = false;
|
||||
|
||||
if($item['title'] !== $arr['updateRawName']) {
|
||||
$update_title = true;
|
||||
$item['title'] = $arr['updateRawName'];
|
||||
}
|
||||
|
||||
$update = item_store_update($item);
|
||||
|
||||
$item_id = $update['item_id'];
|
||||
|
||||
// update acl for any existing wiki pages
|
||||
|
||||
q("update item set allow_cid = '%s', allow_gid = '%s', deny_cid = '%s', deny_gid = '%s', item_private = %d where resource_type = 'nwikipage' and resource_id = '%s'",
|
||||
dbesc($item['allow_cid']),
|
||||
dbesc($item['allow_gid']),
|
||||
dbesc($item['deny_cid']),
|
||||
dbesc($item['deny_gid']),
|
||||
dbesc($item['item_private']),
|
||||
dbesc($arr['resource_id'])
|
||||
);
|
||||
|
||||
|
||||
if($update['item_id']) {
|
||||
info( t('Wiki updated successfully'));
|
||||
if($update_title) {
|
||||
// Update the wiki name information using iconfig.
|
||||
if(! set_iconfig($update['item_id'], 'wiki', 'rawName', $arr['updateRawName'], true)) {
|
||||
return array('item' => null, 'success' => false);
|
||||
}
|
||||
}
|
||||
return array('item' => $update['item'], 'item_id' => $update['item_id'], 'success' => $update['success']);
|
||||
}
|
||||
else {
|
||||
return array('item' => null, 'success' => false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static function sync_a_wiki_item($uid,$id,$resource_id) {
|
||||
|
||||
$r = q("SELECT * from item WHERE uid = %d AND ( id = %d OR ( resource_type = '%s' and resource_id = '%s' )) ",
|
||||
intval($uid),
|
||||
intval($id),
|
||||
dbesc(NWIKI_ITEM_RESOURCE_TYPE),
|
||||
dbesc($resource_id)
|
||||
);
|
||||
if($r) {
|
||||
|
||||
$q = q("select * from item where resource_type = 'nwikipage' and resource_id = '%s'",
|
||||
dbesc($r[0]['resource_id'])
|
||||
);
|
||||
if($q) {
|
||||
$r = array_merge($r,$q);
|
||||
}
|
||||
xchan_query($r);
|
||||
$sync_item = fetch_post_tags($r);
|
||||
if($sync_item) {
|
||||
$pkt = [];
|
||||
foreach($sync_item as $w) {
|
||||
$pkt[] = encode_item($w,true);
|
||||
}
|
||||
Libsync::build_sync_packet($uid,array('wiki' => $pkt));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static function delete_wiki($channel_id,$observer_hash,$resource_id) {
|
||||
|
||||
$w = self::get_wiki($channel_id,$observer_hash,$resource_id);
|
||||
if(! $w['wiki']) {
|
||||
return [ 'success' => false ];
|
||||
}
|
||||
else {
|
||||
|
||||
$r = q("SELECT id FROM item WHERE uid = %s AND resource_id = '%s'",
|
||||
intval($channel_id),
|
||||
dbesc($resource_id)
|
||||
);
|
||||
|
||||
$ids = array_column($r, 'id');
|
||||
drop_items($ids, true, DROPITEM_PHASE1);
|
||||
|
||||
info(t('Wiki files deleted successfully'));
|
||||
|
||||
return [ 'success' => true ];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static function get_wiki($channel_id, $observer_hash, $resource_id) {
|
||||
|
||||
$sql_extra = item_permissions_sql($channel_id,$observer_hash);
|
||||
|
||||
$item = q("SELECT * FROM item WHERE uid = %d AND resource_type = '%s' AND resource_id = '%s' AND item_deleted = 0
|
||||
$sql_extra ORDER BY id LIMIT 1",
|
||||
intval($channel_id),
|
||||
dbesc(NWIKI_ITEM_RESOURCE_TYPE),
|
||||
dbesc($resource_id)
|
||||
);
|
||||
if(! $item) {
|
||||
return [ 'wiki' => null ];
|
||||
}
|
||||
else {
|
||||
|
||||
$w = $item[0]; // wiki item table record
|
||||
// Get wiki metadata
|
||||
$rawName = get_iconfig($w, 'wiki', 'rawName');
|
||||
$mimeType = get_iconfig($w, 'wiki', 'mimeType');
|
||||
$typelock = get_iconfig($w, 'wiki', 'typelock');
|
||||
|
||||
return array(
|
||||
'wiki' => $w,
|
||||
'rawName' => $rawName,
|
||||
'htmlName' => escape_tags($rawName),
|
||||
//'urlName' => urlencode(urlencode($rawName)),
|
||||
'urlName' => self::name_encode($rawName),
|
||||
'mimeType' => $mimeType,
|
||||
'typelock' => $typelock
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static function exists_by_name($uid, $urlName) {
|
||||
|
||||
$sql_extra = item_permissions_sql($uid);
|
||||
|
||||
$item = q("SELECT item.id, resource_id FROM item left join iconfig on iconfig.iid = item.id
|
||||
WHERE resource_type = '%s' AND iconfig.v = '%s' AND uid = %d
|
||||
AND item_deleted = 0 $sql_extra limit 1",
|
||||
dbesc(NWIKI_ITEM_RESOURCE_TYPE),
|
||||
//dbesc(urldecode($urlName)),
|
||||
dbesc(self::name_decode($urlName)),
|
||||
intval($uid)
|
||||
);
|
||||
|
||||
if($item) {
|
||||
return array('id' => $item[0]['id'], 'resource_id' => $item[0]['resource_id']);
|
||||
}
|
||||
else {
|
||||
return array('id' => null, 'resource_id' => null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static function get_permissions($resource_id, $owner_id, $observer_hash) {
|
||||
|
||||
// TODO: For now, only the owner can edit
|
||||
$sql_extra = item_permissions_sql($owner_id, $observer_hash);
|
||||
|
||||
if(local_channel() && local_channel() == $owner_id) {
|
||||
return [ 'read' => true, 'write' => true, 'success' => true ];
|
||||
}
|
||||
|
||||
$r = q("SELECT * FROM item WHERE uid = %d and resource_type = '%s' AND resource_id = '%s' $sql_extra LIMIT 1",
|
||||
intval($owner_id),
|
||||
dbesc(NWIKI_ITEM_RESOURCE_TYPE),
|
||||
dbesc($resource_id)
|
||||
);
|
||||
|
||||
if(! $r) {
|
||||
return array('read' => false, 'write' => false, 'success' => true);
|
||||
}
|
||||
else {
|
||||
// TODO: Create a new permission setting for wiki analogous to webpages. Until
|
||||
// then, use webpage permissions
|
||||
$write = perm_is_allowed($owner_id, $observer_hash,'write_wiki');
|
||||
return array('read' => true, 'write' => $write, 'success' => true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static function name_encode ($string) {
|
||||
|
||||
$string = html_entity_decode($string);
|
||||
$encoding = mb_internal_encoding();
|
||||
mb_internal_encoding("UTF-8");
|
||||
$ret = mb_ereg_replace_callback ('[^A-Za-z0-9\-\_\.\~]',function ($char) {
|
||||
$charhex = unpack('H*',$char[0]);
|
||||
$ret = '('.$charhex[1].')';
|
||||
return $ret;
|
||||
}
|
||||
,$string);
|
||||
mb_internal_encoding($encoding);
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
public static function name_decode ($string) {
|
||||
|
||||
$encoding = mb_internal_encoding();
|
||||
mb_internal_encoding("UTF-8");
|
||||
$ret = mb_ereg_replace_callback ('(\(([0-9a-f]+)\))',function ($chars) {
|
||||
return pack('H*',$chars[2]);
|
||||
}
|
||||
,$string);
|
||||
mb_internal_encoding($encoding);
|
||||
return $ret;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,718 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
use \Zotlabs\Lib as Zlib;
|
||||
|
||||
class NativeWikiPage {
|
||||
|
||||
static public function page_list($channel_id,$observer_hash, $resource_id) {
|
||||
|
||||
// TODO: Create item table records for pages so that metadata like title can be applied
|
||||
$w = Zlib\NativeWiki::get_wiki($channel_id,$observer_hash,$resource_id);
|
||||
|
||||
$pages[] = [
|
||||
'resource_id' => '',
|
||||
'title' => 'Home',
|
||||
'url' => 'Home',
|
||||
'link_id' => 'id_wiki_home_0'
|
||||
];
|
||||
|
||||
$sql_extra = item_permissions_sql($channel_id,$observer_hash);
|
||||
|
||||
$r = q("select * from item where resource_type = 'nwikipage' and resource_id = '%s' and uid = %d and item_deleted = 0
|
||||
$sql_extra order by title asc",
|
||||
dbesc($resource_id),
|
||||
intval($channel_id)
|
||||
);
|
||||
if($r) {
|
||||
$x = [];
|
||||
$y = [];
|
||||
|
||||
foreach($r as $rv) {
|
||||
if(! in_array($rv['mid'],$x)) {
|
||||
$y[] = $rv;
|
||||
$x[] = $rv['mid'];
|
||||
}
|
||||
}
|
||||
|
||||
$items = fetch_post_tags($y,true);
|
||||
|
||||
foreach($items as $page_item) {
|
||||
$title = get_iconfig($page_item['id'],'nwikipage','pagetitle',t('(No Title)'));
|
||||
if(urldecode($title) !== 'Home') {
|
||||
$pages[] = [
|
||||
'resource_id' => $resource_id,
|
||||
'title' => escape_tags($title),
|
||||
//'url' => str_replace('%2F','/',urlencode(str_replace('%2F','/',urlencode($title)))),
|
||||
'url' => Zlib\NativeWiki::name_encode($title),
|
||||
'link_id' => 'id_' . substr($resource_id, 0, 10) . '_' . $page_item['id']
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return array('pages' => $pages, 'wiki' => $w);
|
||||
}
|
||||
|
||||
|
||||
static public function create_page($channel_id, $observer_hash, $name, $resource_id, $mimetype = 'text/bbcode') {
|
||||
|
||||
logger('mimetype: ' . $mimetype);
|
||||
|
||||
if(! in_array($mimetype,[ 'text/markdown','text/bbcode','text/plain','text/html' ]))
|
||||
$mimetype = 'text/markdown';
|
||||
|
||||
$w = Zlib\NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
|
||||
|
||||
if (! $w['wiki']) {
|
||||
return array('content' => null, 'message' => 'Error reading wiki', 'success' => false);
|
||||
}
|
||||
|
||||
// backslashes won't work well in the javascript functions
|
||||
$name = str_replace('\\','',$name);
|
||||
|
||||
// create an empty activity
|
||||
|
||||
$arr = [];
|
||||
$arr['uid'] = $channel_id;
|
||||
$arr['author_xchan'] = $observer_hash;
|
||||
$arr['mimetype'] = $mimetype;
|
||||
$arr['title'] = $name;
|
||||
$arr['resource_type'] = 'nwikipage';
|
||||
$arr['resource_id'] = $resource_id;
|
||||
$arr['allow_cid'] = $w['wiki']['allow_cid'];
|
||||
$arr['allow_gid'] = $w['wiki']['allow_gid'];
|
||||
$arr['deny_cid'] = $w['wiki']['deny_cid'];
|
||||
$arr['deny_gid'] = $w['wiki']['deny_gid'];
|
||||
|
||||
$arr['public_policy'] = map_scope(\Zotlabs\Access\PermissionLimits::Get($channel_id,'view_wiki'),true);
|
||||
|
||||
// We may wish to change this some day.
|
||||
$arr['item_unpublished'] = 1;
|
||||
|
||||
set_iconfig($arr,'nwikipage','pagetitle',(($name) ? $name : t('(No Title)')),true);
|
||||
|
||||
$p = post_activity_item($arr, false, false);
|
||||
|
||||
if($p['item_id']) {
|
||||
$page = [
|
||||
'rawName' => $name,
|
||||
'htmlName' => escape_tags($name),
|
||||
//'urlName' => urlencode($name),
|
||||
'urlName' => Zlib\NativeWiki::name_encode($name)
|
||||
|
||||
];
|
||||
|
||||
return array('page' => $page, 'item_id' => $p['item_id'], 'item' => $p['activity'], 'wiki' => $w, 'message' => '', 'success' => true);
|
||||
}
|
||||
return [ 'success' => false, 'message' => t('Wiki page create failed.') ];
|
||||
}
|
||||
|
||||
|
||||
static public function rename_page($arr) {
|
||||
|
||||
$pageUrlName = ((array_key_exists('pageUrlName',$arr)) ? $arr['pageUrlName'] : '');
|
||||
$pageNewName = ((array_key_exists('pageNewName',$arr)) ? $arr['pageNewName'] : '');
|
||||
$resource_id = ((array_key_exists('resource_id',$arr)) ? $arr['resource_id'] : '');
|
||||
$observer_hash = ((array_key_exists('observer_hash',$arr)) ? $arr['observer_hash'] : '');
|
||||
$channel_id = ((array_key_exists('channel_id',$arr)) ? $arr['channel_id'] : 0);
|
||||
|
||||
$w = Zlib\NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
|
||||
if(! $w['wiki']) {
|
||||
return array('message' => t('Wiki not found.'), 'success' => false);
|
||||
}
|
||||
|
||||
|
||||
$ic = q("select * from iconfig left join item on iconfig.iid = item.id
|
||||
where uid = %d and cat = 'nwikipage' and k = 'pagetitle' and v = '%s'",
|
||||
intval($channel_id),
|
||||
dbesc($pageNewName)
|
||||
);
|
||||
|
||||
if($ic) {
|
||||
return [ 'success' => false, 'message' => t('Destination name already exists') ];
|
||||
}
|
||||
|
||||
|
||||
$ids = [];
|
||||
|
||||
$ic = q("select *, item.id as item_id from iconfig left join item on iconfig.iid = item.id
|
||||
where uid = %d and cat = 'nwikipage' and k = 'pagetitle' and v = '%s'",
|
||||
intval($channel_id),
|
||||
dbesc($pageUrlName)
|
||||
);
|
||||
|
||||
if($ic) {
|
||||
foreach($ic as $c) {
|
||||
set_iconfig($c['item_id'],'nwikipage','pagetitle',$pageNewName);
|
||||
$ids[] = $c['item_id'];
|
||||
}
|
||||
|
||||
$str_ids = implode(',', $ids);
|
||||
q("update item set title = '%s' where id in ($str_ids)",
|
||||
dbesc($pageNewName)
|
||||
);
|
||||
|
||||
$page = [
|
||||
'rawName' => $pageNewName,
|
||||
'htmlName' => escape_tags($pageNewName),
|
||||
//'urlName' => urlencode(escape_tags($pageNewName))
|
||||
'urlName' => Zlib\NativeWiki::name_encode($pageNewName)
|
||||
];
|
||||
|
||||
return [ 'success' => true, 'page' => $page ];
|
||||
}
|
||||
|
||||
return [ 'success' => false, 'message' => t('Page not found') ];
|
||||
|
||||
}
|
||||
|
||||
|
||||
static public function get_page_content($arr) {
|
||||
|
||||
$pageUrlName = ((array_key_exists('pageUrlName',$arr)) ? $arr['pageUrlName'] : '');
|
||||
$resource_id = ((array_key_exists('resource_id',$arr)) ? $arr['resource_id'] : '');
|
||||
$observer_hash = ((array_key_exists('observer_hash',$arr)) ? $arr['observer_hash'] : '');
|
||||
$channel_id = ((array_key_exists('channel_id',$arr)) ? intval($arr['channel_id']) : 0);
|
||||
$revision = ((array_key_exists('revision',$arr)) ? intval($arr['revision']) : (-1));
|
||||
|
||||
|
||||
$w = Zlib\NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
|
||||
if (! $w['wiki']) {
|
||||
return array('content' => null, 'message' => 'Error reading wiki', 'success' => false);
|
||||
}
|
||||
|
||||
$item = self::load_page($arr);
|
||||
|
||||
if($item) {
|
||||
$content = $item['body'];
|
||||
|
||||
return [
|
||||
'content' => $content,
|
||||
'mimeType' => $w['mimeType'],
|
||||
'pageMimeType' => $item['mimetype'],
|
||||
'message' => '',
|
||||
'success' => true
|
||||
];
|
||||
}
|
||||
|
||||
return array('content' => null, 'message' => t('Error reading page content'), 'success' => false);
|
||||
|
||||
}
|
||||
|
||||
|
||||
static public function page_history($arr) {
|
||||
|
||||
$pageUrlName = ((array_key_exists('pageUrlName',$arr)) ? $arr['pageUrlName'] : '');
|
||||
$resource_id = ((array_key_exists('resource_id',$arr)) ? $arr['resource_id'] : '');
|
||||
$observer_hash = ((array_key_exists('observer_hash',$arr)) ? $arr['observer_hash'] : '');
|
||||
$channel_id = ((array_key_exists('channel_id',$arr)) ? $arr['channel_id'] : 0);
|
||||
|
||||
$w = Zlib\NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
|
||||
if (!$w['wiki']) {
|
||||
return array('history' => null, 'message' => 'Error reading wiki', 'success' => false);
|
||||
}
|
||||
|
||||
$items = self::load_page_history($arr);
|
||||
|
||||
$history = [];
|
||||
|
||||
if($items) {
|
||||
$processed = 0;
|
||||
foreach($items as $item) {
|
||||
if($processed > 1000)
|
||||
break;
|
||||
$processed ++;
|
||||
$history[] = [
|
||||
'revision' => $item['revision'],
|
||||
'date' => datetime_convert('UTC',date_default_timezone_get(),$item['edited']),
|
||||
'name' => $item['author']['xchan_name'],
|
||||
'title' => get_iconfig($item,'nwikipage','commit_msg')
|
||||
];
|
||||
|
||||
}
|
||||
|
||||
return [ 'success' => true, 'history' => $history ];
|
||||
}
|
||||
|
||||
return [ 'success' => false ];
|
||||
|
||||
}
|
||||
|
||||
|
||||
static public function load_page($arr) {
|
||||
|
||||
$pageUrlName = ((array_key_exists('pageUrlName',$arr)) ? $arr['pageUrlName'] : '');
|
||||
$resource_id = ((array_key_exists('resource_id',$arr)) ? $arr['resource_id'] : '');
|
||||
$observer_hash = ((array_key_exists('observer_hash',$arr)) ? $arr['observer_hash'] : '');
|
||||
$channel_id = ((array_key_exists('channel_id',$arr)) ? $arr['channel_id'] : 0);
|
||||
$revision = ((array_key_exists('revision',$arr)) ? $arr['revision'] : (-1));
|
||||
|
||||
$w = Zlib\NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
|
||||
|
||||
if (! $w['wiki']) {
|
||||
return array('content' => null, 'message' => 'Error reading wiki', 'success' => false);
|
||||
}
|
||||
|
||||
$ids = '';
|
||||
|
||||
$ic = q("select * from iconfig left join item on iconfig.iid = item.id where uid = %d and cat = 'nwikipage' and k = 'pagetitle' and v = '%s'",
|
||||
intval($channel_id),
|
||||
dbesc($pageUrlName)
|
||||
);
|
||||
|
||||
if($ic) {
|
||||
foreach($ic as $c) {
|
||||
if($ids)
|
||||
$ids .= ',';
|
||||
$ids .= intval($c['iid']);
|
||||
}
|
||||
}
|
||||
|
||||
$sql_extra = item_permissions_sql($channel_id,$observer_hash);
|
||||
|
||||
if($revision == (-1))
|
||||
$sql_extra .= " order by revision desc ";
|
||||
elseif($revision)
|
||||
$sql_extra .= " and revision = " . intval($revision) . " ";
|
||||
|
||||
$r = null;
|
||||
|
||||
|
||||
if($ids) {
|
||||
$r = q("select * from item where resource_type = 'nwikipage' and resource_id = '%s' and uid = %d and id in ( $ids ) $sql_extra limit 1",
|
||||
dbesc($resource_id),
|
||||
intval($channel_id)
|
||||
);
|
||||
|
||||
if($r) {
|
||||
$items = fetch_post_tags($r,true);
|
||||
return $items[0];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
static public function load_page_history($arr) {
|
||||
|
||||
$pageUrlName = ((array_key_exists('pageUrlName',$arr)) ? $arr['pageUrlName'] : '');
|
||||
$resource_id = ((array_key_exists('resource_id',$arr)) ? $arr['resource_id'] : '');
|
||||
$observer_hash = ((array_key_exists('observer_hash',$arr)) ? $arr['observer_hash'] : '');
|
||||
$channel_id = ((array_key_exists('channel_id',$arr)) ? $arr['channel_id'] : 0);
|
||||
$revision = ((array_key_exists('revision',$arr)) ? $arr['revision'] : (-1));
|
||||
|
||||
$w = Zlib\NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
|
||||
if (! $w['wiki']) {
|
||||
return array('content' => null, 'message' => 'Error reading wiki', 'success' => false);
|
||||
}
|
||||
|
||||
$ids = '';
|
||||
|
||||
$ic = q("select * from iconfig left join item on iconfig.iid = item.id where uid = %d and cat = 'nwikipage' and k = 'pagetitle' and v = '%s'",
|
||||
intval($channel_id),
|
||||
dbesc($pageUrlName)
|
||||
);
|
||||
|
||||
if($ic) {
|
||||
foreach($ic as $c) {
|
||||
if($ids)
|
||||
$ids .= ',';
|
||||
$ids .= intval($c['iid']);
|
||||
}
|
||||
}
|
||||
|
||||
$sql_extra = item_permissions_sql($channel_id,$observer_hash);
|
||||
|
||||
$sql_extra .= " order by revision desc ";
|
||||
|
||||
$r = null;
|
||||
if($ids) {
|
||||
$r = q("select * from item where resource_type = 'nwikipage' and resource_id = '%s' and uid = %d and id in ( $ids ) and item_deleted = 0 $sql_extra",
|
||||
dbesc($resource_id),
|
||||
intval($channel_id)
|
||||
);
|
||||
if($r) {
|
||||
xchan_query($r);
|
||||
$items = fetch_post_tags($r,true);
|
||||
return $items;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
static public function save_page($arr) {
|
||||
$pageUrlName = ((array_key_exists('pageUrlName',$arr)) ? $arr['pageUrlName'] : '');
|
||||
$content = ((array_key_exists('content',$arr)) ? $arr['content'] : '');
|
||||
$resource_id = ((array_key_exists('resource_id',$arr)) ? $arr['resource_id'] : '');
|
||||
$observer_hash = ((array_key_exists('observer_hash',$arr)) ? $arr['observer_hash'] : '');
|
||||
$channel_id = ((array_key_exists('channel_id',$arr)) ? $arr['channel_id'] : 0);
|
||||
$revision = ((array_key_exists('revision',$arr)) ? $arr['revision'] : 0);
|
||||
|
||||
$w = Zlib\NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
|
||||
|
||||
if (!$w['wiki']) {
|
||||
return array('message' => t('Error reading wiki'), 'success' => false);
|
||||
}
|
||||
|
||||
|
||||
// fetch the most recently saved revision.
|
||||
|
||||
$item = self::load_page($arr);
|
||||
|
||||
if(! $item) {
|
||||
return array('message' => t('Page not found'), 'success' => false);
|
||||
}
|
||||
|
||||
$mimetype = $item['mimetype'];
|
||||
|
||||
// change just the fields we need to change to create a revision;
|
||||
|
||||
unset($item['id']);
|
||||
unset($item['author']);
|
||||
$item['parent'] = 0;
|
||||
$item['body'] = $content;
|
||||
$item['author_xchan'] = $observer_hash;
|
||||
$item['revision'] = (($arr['revision']) ? intval($arr['revision']) + 1 : intval($item['revision']) + 1);
|
||||
$item['edited'] = datetime_convert();
|
||||
$item['mimetype'] = $mimetype;
|
||||
|
||||
if($item['iconfig'] && is_array($item['iconfig']) && count($item['iconfig'])) {
|
||||
for($x = 0; $x < count($item['iconfig']); $x ++) {
|
||||
unset($item['iconfig'][$x]['id']);
|
||||
unset($item['iconfig'][$x]['iid']);
|
||||
}
|
||||
}
|
||||
|
||||
$ret = item_store($item, false, false);
|
||||
|
||||
if($ret['item_id'])
|
||||
return array('message' => '', 'item_id' => $ret['item_id'], 'filename' => $pageUrlName, 'success' => true);
|
||||
else
|
||||
return array('message' => t('Page update failed.'), 'success' => false);
|
||||
}
|
||||
|
||||
|
||||
static public function delete_page($arr) {
|
||||
|
||||
$pageUrlName = (array_key_exists('pageUrlName',$arr) ? $arr['pageUrlName'] : '');
|
||||
$resource_id = (array_key_exists('resource_id',$arr) ? $arr['resource_id'] : '');
|
||||
$observer_hash = (array_key_exists('observer_hash',$arr) ? $arr['observer_hash'] : '');
|
||||
$channel_id = (array_key_exists('channel_id',$arr) ? $arr['channel_id'] : 0);
|
||||
|
||||
$w = Zlib\NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
|
||||
if(! $w['wiki']) {
|
||||
return [ 'success' => false, 'message' => t('Error reading wiki') ];
|
||||
}
|
||||
|
||||
$ids = [];
|
||||
|
||||
$ic = q("select * from iconfig left join item on iconfig.iid = item.id
|
||||
where uid = %d and cat = 'nwikipage' and k = 'pagetitle' and v = '%s'",
|
||||
intval($channel_id),
|
||||
dbesc($pageUrlName)
|
||||
);
|
||||
|
||||
if($ic) {
|
||||
foreach($ic as $c) {
|
||||
$ids[] = intval($c['iid']);
|
||||
}
|
||||
}
|
||||
|
||||
if($ids) {
|
||||
drop_items($ids, true, DROPITEM_PHASE1);
|
||||
return [ 'success' => true ];
|
||||
}
|
||||
|
||||
return [ 'success' => false, 'message' => t('Nothing deleted') ];
|
||||
}
|
||||
|
||||
|
||||
static public function revert_page($arr) {
|
||||
|
||||
$pageUrlName = ((array_key_exists('pageUrlName',$arr)) ? $arr['pageUrlName'] : '');
|
||||
$resource_id = ((array_key_exists('resource_id',$arr)) ? $arr['resource_id'] : '');
|
||||
$commitHash = ((array_key_exists('commitHash',$arr)) ? $arr['commitHash'] : null);
|
||||
$observer_hash = ((array_key_exists('observer_hash',$arr)) ? $arr['observer_hash'] : '');
|
||||
$channel_id = ((array_key_exists('channel_id',$arr)) ? $arr['channel_id'] : 0);
|
||||
|
||||
if (! $commitHash) {
|
||||
return array('message' => 'No commit was provided', 'success' => false);
|
||||
}
|
||||
|
||||
$w = Zlib\NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
|
||||
if (!$w['wiki']) {
|
||||
return array('message' => 'Error reading wiki', 'success' => false);
|
||||
}
|
||||
|
||||
$x = $arr;
|
||||
|
||||
if(intval($commitHash) > 0) {
|
||||
unset($x['commitHash']);
|
||||
$x['revision'] = intval($commitHash) - 1;
|
||||
$loaded = self::load_page($x);
|
||||
|
||||
if($loaded) {
|
||||
$content = $loaded['body'];
|
||||
return [ 'content' => $content, 'success' => true ];
|
||||
}
|
||||
return [ 'success' => false ];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static public function compare_page($arr) {
|
||||
|
||||
$pageUrlName = ((array_key_exists('pageUrlName',$arr)) ? $arr['pageUrlName'] : '');
|
||||
$resource_id = ((array_key_exists('resource_id',$arr)) ? $arr['resource_id'] : '');
|
||||
$currentCommit = ((array_key_exists('currentCommit',$arr)) ? $arr['currentCommit'] : (-1));
|
||||
$compareCommit = ((array_key_exists('compareCommit',$arr)) ? $arr['compareCommit'] : 0);
|
||||
$observer_hash = ((array_key_exists('observer_hash',$arr)) ? $arr['observer_hash'] : '');
|
||||
$channel_id = ((array_key_exists('channel_id',$arr)) ? $arr['channel_id'] : 0);
|
||||
|
||||
$w = Zlib\NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
|
||||
|
||||
if (!$w['wiki']) {
|
||||
return array('message' => t('Error reading wiki'), 'success' => false);
|
||||
}
|
||||
|
||||
$x = $arr;
|
||||
$x['revision'] = (-1);
|
||||
|
||||
$currpage = self::load_page($x);
|
||||
if($currpage)
|
||||
$currentContent = $currpage['body'];
|
||||
|
||||
$x['revision'] = $compareCommit;
|
||||
$comppage = self::load_page($x);
|
||||
if($comppage)
|
||||
$compareContent = $comppage['body'];
|
||||
|
||||
if($currpage && $comppage) {
|
||||
require_once('library/class.Diff.php');
|
||||
$diff = \Diff::toTable(\Diff::compare($currentContent, $compareContent));
|
||||
|
||||
return [ 'success' => true, 'diff' => $diff ];
|
||||
}
|
||||
return [ 'success' => false, 'message' => t('Compare: object not found.') ];
|
||||
|
||||
}
|
||||
|
||||
|
||||
static public function commit($arr) {
|
||||
|
||||
$commit_msg = ((array_key_exists('commit_msg', $arr)) ? $arr['commit_msg'] : t('Page updated'));
|
||||
$observer_hash = ((array_key_exists('observer_hash',$arr)) ? $arr['observer_hash'] : '');
|
||||
$channel_id = ((array_key_exists('channel_id',$arr)) ? $arr['channel_id'] : 0);
|
||||
$pageUrlName = ((array_key_exists('pageUrlName',$arr)) ? $arr['pageUrlName'] : t('Untitled'));
|
||||
|
||||
if(array_key_exists('resource_id', $arr)) {
|
||||
$resource_id = $arr['resource_id'];
|
||||
}
|
||||
else {
|
||||
return array('message' => t('Wiki resource_id required for git commit'), 'success' => false);
|
||||
}
|
||||
|
||||
$w = Zlib\NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
|
||||
if (! $w['wiki']) {
|
||||
return array('message' => t('Error reading wiki'), 'success' => false);
|
||||
}
|
||||
|
||||
|
||||
$page = self::load_page($arr);
|
||||
|
||||
if($page) {
|
||||
set_iconfig($page['id'],'nwikipage','commit_msg',escape_tags($commit_msg),true);
|
||||
return [ 'success' => true, 'item_id' => $page['id'], 'page' => $page ];
|
||||
}
|
||||
|
||||
return [ 'success' => false, 'message' => t('Page not found.') ];
|
||||
|
||||
}
|
||||
|
||||
static public function convert_links($s, $wikiURL) {
|
||||
|
||||
if (strpos($s,'[[') !== false) {
|
||||
preg_match_all("/\[\[(.*?)\]\]/", $s, $match);
|
||||
$pages = $pageURLs = array();
|
||||
foreach ($match[1] as $m) {
|
||||
// TODO: Why do we need to double urlencode for this to work?
|
||||
//$pageURLs[] = urlencode(urlencode(escape_tags($m)));
|
||||
$titleUri = explode('|',$m);
|
||||
$page = $titleUri[0] ?? '';
|
||||
$title = $titleUri[1] ?? $page;
|
||||
$pageURLs[] = Zlib\NativeWiki::name_encode(escape_tags($page));
|
||||
$pages[] = $title;
|
||||
}
|
||||
$idx = 0;
|
||||
while(strpos($s,'[[') !== false) {
|
||||
$replace = '<a href="'.$wikiURL.'/'.$pageURLs[$idx].'">'.$pages[$idx].'</a>';
|
||||
$s = preg_replace("/\[\[(.*?)\]\]/", $replace, $s, 1);
|
||||
$idx++;
|
||||
}
|
||||
}
|
||||
return $s;
|
||||
}
|
||||
|
||||
static public function render_page_history($arr) {
|
||||
|
||||
$pageUrlName = ((array_key_exists('pageUrlName', $arr)) ? $arr['pageUrlName'] : '');
|
||||
$resource_id = ((array_key_exists('resource_id', $arr)) ? $arr['resource_id'] : '');
|
||||
|
||||
$pageHistory = self::page_history([
|
||||
'channel_id' => \App::$profile_uid,
|
||||
'observer_hash' => get_observer_hash(),
|
||||
'resource_id' => $resource_id,
|
||||
'pageUrlName' => $pageUrlName
|
||||
]);
|
||||
|
||||
return replace_macros(get_markup_template('nwiki_page_history.tpl'), array(
|
||||
'$pageHistory' => $pageHistory['history'],
|
||||
'$permsWrite' => $arr['permsWrite'],
|
||||
'$name_lbl' => t('Name'),
|
||||
'$msg_label' => t('Message','wiki_history'),
|
||||
'$date_lbl' => t('Date'),
|
||||
'$revert_btn' => t('Revert'),
|
||||
'$compare_btn' => t('Compare')
|
||||
));
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Replace the instances of the string [toc] with a list element that will be populated by
|
||||
* a table of contents by the JavaScript library
|
||||
* @param string $s
|
||||
* @return string
|
||||
*/
|
||||
static public function generate_toc($s) {
|
||||
if (strpos($s,'[toc]') !== false) {
|
||||
//$toc_md = wiki_toc($s); // Generate Markdown-formatted list prior to HTML render
|
||||
$toc_md = '<ul id="wiki-toc"></ul>'; // use the available jQuery plugin http://ndabas.github.io/toc/
|
||||
$s = preg_replace("/\[toc\]/", $toc_md, $s, -1);
|
||||
}
|
||||
return $s;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Converts a select set of bbcode tags. Much of the code is copied from include/bbcode.php
|
||||
* @param string $s
|
||||
* @return string
|
||||
*/
|
||||
static public function bbcode($s) {
|
||||
|
||||
$s = str_replace(array('[baseurl]', '[sitename]'), array(z_root(), get_config('system', 'sitename')), $s);
|
||||
|
||||
$s = preg_replace_callback("/\[observer\.language\=(.*?)\](.*?)\[\/observer\]/ism",'oblanguage_callback', $s);
|
||||
|
||||
$s = preg_replace_callback("/\[observer\.language\!\=(.*?)\](.*?)\[\/observer\]/ism",'oblanguage_necallback', $s);
|
||||
|
||||
|
||||
$observer = \App::get_observer();
|
||||
if ($observer) {
|
||||
$s1 = '<span class="bb_observer" title="' . t('Different viewers will see this text differently') . '">';
|
||||
$s2 = '</span>';
|
||||
$obsBaseURL = $observer['xchan_connurl'];
|
||||
$obsBaseURL = preg_replace("/\/poco\/.*$/", '', $obsBaseURL);
|
||||
$s = str_replace('[observer.baseurl]', $obsBaseURL, $s);
|
||||
$s = str_replace('[observer.url]', $observer['xchan_url'], $s);
|
||||
$s = str_replace('[observer.name]', $s1 . $observer['xchan_name'] . $s2, $s);
|
||||
$s = str_replace('[observer.address]', $s1 . $observer['xchan_addr'] . $s2, $s);
|
||||
$s = str_replace('[observer.webname]', substr($observer['xchan_addr'], 0, strpos($observer['xchan_addr'], '@')), $s);
|
||||
$s = str_replace('[observer.photo]', '', $s);
|
||||
}
|
||||
else {
|
||||
$s = str_replace('[observer.baseurl]', '', $s);
|
||||
$s = str_replace('[observer.url]', '', $s);
|
||||
$s = str_replace('[observer.name]', '', $s);
|
||||
$s = str_replace('[observer.address]', '', $s);
|
||||
$s = str_replace('[observer.webname]', '', $s);
|
||||
$s = str_replace('[observer.photo]', '', $s);
|
||||
}
|
||||
|
||||
return $s;
|
||||
}
|
||||
|
||||
|
||||
static public function get_file_ext($arr) {
|
||||
|
||||
if($arr['mimetype'] === 'text/bbcode')
|
||||
return '.bb';
|
||||
elseif($arr['mimetype'] === 'text/markdown')
|
||||
return '.md';
|
||||
elseif($arr['mimetype'] === 'text/plain')
|
||||
return '.txt';
|
||||
|
||||
}
|
||||
|
||||
// This function is derived from
|
||||
// http://stackoverflow.com/questions/32068537/generate-table-of-contents-from-markdown-in-php
|
||||
static public function toc($content) {
|
||||
// ensure using only "\n" as line-break
|
||||
$source = str_replace(["\r\n", "\r"], "\n", $content);
|
||||
|
||||
// look for markdown TOC items
|
||||
preg_match_all(
|
||||
'/^(?:=|-|#).*$/m',
|
||||
$source,
|
||||
$matches,
|
||||
PREG_PATTERN_ORDER | PREG_OFFSET_CAPTURE
|
||||
);
|
||||
|
||||
// preprocess: iterate matched lines to create an array of items
|
||||
// where each item is an array(level, text)
|
||||
$file_size = strlen($source);
|
||||
foreach ($matches[0] as $item) {
|
||||
$found_mark = substr($item[0], 0, 1);
|
||||
if ($found_mark == '#') {
|
||||
// text is the found item
|
||||
$item_text = $item[0];
|
||||
$item_level = strrpos($item_text, '#') + 1;
|
||||
$item_text = substr($item_text, $item_level);
|
||||
} else {
|
||||
// text is the previous line (empty if <hr>)
|
||||
$item_offset = $item[1];
|
||||
$prev_line_offset = strrpos($source, "\n", -($file_size - $item_offset + 2));
|
||||
$item_text =
|
||||
substr($source, $prev_line_offset, $item_offset - $prev_line_offset - 1);
|
||||
$item_text = trim($item_text);
|
||||
$item_level = $found_mark == '=' ? 1 : 2;
|
||||
}
|
||||
if (!trim($item_text) OR strpos($item_text, '|') !== FALSE) {
|
||||
// item is an horizontal separator or a table header, don't mind
|
||||
continue;
|
||||
}
|
||||
$raw_toc[] = ['level' => $item_level, 'text' => trim($item_text)];
|
||||
}
|
||||
$o = '';
|
||||
foreach($raw_toc as $t) {
|
||||
$level = intval($t['level']);
|
||||
$text = $t['text'];
|
||||
switch ($level) {
|
||||
case 1:
|
||||
$li = '* ';
|
||||
break;
|
||||
case 2:
|
||||
$li = ' * ';
|
||||
break;
|
||||
case 3:
|
||||
$li = ' * ';
|
||||
break;
|
||||
case 4:
|
||||
$li = ' * ';
|
||||
break;
|
||||
default:
|
||||
$li = '* ';
|
||||
break;
|
||||
}
|
||||
$o .= $li . $text . "\n";
|
||||
}
|
||||
return $o;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
use App;
|
||||
|
||||
/**
|
||||
* @brief Class for handling channel specific configurations.
|
||||
*
|
||||
@@ -32,15 +34,15 @@ class PConfig {
|
||||
if(is_null($uid) || $uid === false)
|
||||
return false;
|
||||
|
||||
if(! is_array(\App::$config)) {
|
||||
if(! is_array(App::$config)) {
|
||||
btlogger('App::$config not an array');
|
||||
}
|
||||
|
||||
if(! array_key_exists($uid, \App::$config)) {
|
||||
\App::$config[$uid] = array();
|
||||
if(! array_key_exists($uid, App::$config)) {
|
||||
App::$config[$uid] = array();
|
||||
}
|
||||
|
||||
if(! is_array(\App::$config[$uid])) {
|
||||
if(! is_array(App::$config[$uid])) {
|
||||
btlogger('App::$config[$uid] not an array: ' . $uid);
|
||||
}
|
||||
|
||||
@@ -52,12 +54,12 @@ class PConfig {
|
||||
foreach($r as $rr) {
|
||||
$k = $rr['k'];
|
||||
$c = $rr['cat'];
|
||||
if(! array_key_exists($c, \App::$config[$uid])) {
|
||||
\App::$config[$uid][$c] = array();
|
||||
\App::$config[$uid][$c]['config_loaded'] = true;
|
||||
if(! array_key_exists($c, App::$config[$uid])) {
|
||||
App::$config[$uid][$c] = array();
|
||||
App::$config[$uid][$c]['config_loaded'] = true;
|
||||
}
|
||||
\App::$config[$uid][$c][$k] = $rr['v'];
|
||||
\App::$config[$uid][$c]['pcfgud:'.$k] = $rr['updated'];
|
||||
App::$config[$uid][$c][$k] = $rr['v'];
|
||||
App::$config[$uid][$c]['pcfgud:'.$k] = $rr['updated'];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -86,15 +88,15 @@ class PConfig {
|
||||
if(is_null($uid) || $uid === false)
|
||||
return $default;
|
||||
|
||||
if(! array_key_exists($uid, \App::$config))
|
||||
if(! array_key_exists($uid, App::$config))
|
||||
self::Load($uid);
|
||||
|
||||
if((! array_key_exists($family, \App::$config[$uid])) || (! array_key_exists($key, \App::$config[$uid][$family])))
|
||||
if((! array_key_exists($family, App::$config[$uid])) || (! array_key_exists($key, App::$config[$uid][$family])))
|
||||
return $default;
|
||||
|
||||
return ((! is_array(\App::$config[$uid][$family][$key])) && (preg_match('|^a:[0-9]+:{.*}$|s', \App::$config[$uid][$family][$key]))
|
||||
? unserialize(\App::$config[$uid][$family][$key])
|
||||
: \App::$config[$uid][$family][$key]
|
||||
return ((! is_array(App::$config[$uid][$family][$key])) && (preg_match('|^a:[0-9]+:{.*}$|s', App::$config[$uid][$family][$key]))
|
||||
? unserialize(App::$config[$uid][$family][$key])
|
||||
: App::$config[$uid][$family][$key]
|
||||
);
|
||||
}
|
||||
|
||||
@@ -133,6 +135,7 @@ class PConfig {
|
||||
$dbvalue = ((is_array($value)) ? serialize($value) : $value);
|
||||
$dbvalue = ((is_bool($dbvalue)) ? intval($dbvalue) : $dbvalue);
|
||||
$new = false;
|
||||
$update = false;
|
||||
|
||||
$now = datetime_convert();
|
||||
if (! $updated) {
|
||||
@@ -143,23 +146,22 @@ class PConfig {
|
||||
$updated = datetime_convert('UTC','UTC','-2 seconds');
|
||||
}
|
||||
|
||||
$hash = hash('sha256',$family.':'.$key);
|
||||
$hash = gen_link_id($family.':'.$key);
|
||||
|
||||
if (self::Get($uid, 'hz_delpconfig', $hash) !== false) {
|
||||
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 {
|
||||
self::Delete($uid,'hz_delpconfig',$hash);
|
||||
self::Delete($uid, 'hz_delpconfig', $hash);
|
||||
}
|
||||
}
|
||||
|
||||
if(self::Get($uid, $family, $key) === false) {
|
||||
if(! array_key_exists($uid, \App::$config))
|
||||
\App::$config[$uid] = array();
|
||||
if(! array_key_exists($family, \App::$config[$uid]))
|
||||
\App::$config[$uid][$family] = array();
|
||||
|
||||
if(! array_key_exists($uid, App::$config))
|
||||
App::$config[$uid] = array();
|
||||
if(! array_key_exists($family, App::$config[$uid]))
|
||||
App::$config[$uid][$family] = array();
|
||||
|
||||
$ret = q("INSERT INTO pconfig ( uid, cat, k, v, updated ) VALUES ( %d, '%s', '%s', '%s', '%s' ) ",
|
||||
intval($uid),
|
||||
@@ -177,13 +179,14 @@ class PConfig {
|
||||
logger("Error: Insert to pconfig failed.",LOGGER_NORMAL, LOG_ERR);
|
||||
}
|
||||
|
||||
\App::$config[$uid][$family]['pcfgud:'.$key] = $updated;
|
||||
$new = true;
|
||||
App::$config[$uid][$family]['pcfgud:'.$key] = $updated;
|
||||
|
||||
}
|
||||
else {
|
||||
$new = (\App::$config[$uid][$family]['pcfgud:'.$key] < $now);
|
||||
$update = (App::$config[$uid][$family]['pcfgud:'.$key] < $now);
|
||||
|
||||
if ($new) {
|
||||
if ($update) {
|
||||
|
||||
// @NOTE There is still a possible race condition under limited circumstances
|
||||
// where a value will be updated by another thread with more current data than
|
||||
@@ -198,7 +201,7 @@ class PConfig {
|
||||
dbesc($key)
|
||||
);
|
||||
|
||||
\App::$config[$uid][$family]['pcfgud:'.$key] = $updated;
|
||||
App::$config[$uid][$family]['pcfgud:'.$key] = $updated;
|
||||
|
||||
} else {
|
||||
logger('Refusing to update pconfig with outdated info.', LOGGER_NORMAL, LOG_ERR);
|
||||
@@ -211,16 +214,16 @@ class PConfig {
|
||||
// set in the life of this page. We need this to
|
||||
// synchronise channel 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(! 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();
|
||||
|
||||
\App::$config[$uid][$family][$key] = $value;
|
||||
App::$config[$uid][$family][$key] = $value;
|
||||
|
||||
if ($new) {
|
||||
\App::$config[$uid]['transient'][$family][$key] = $value;
|
||||
\App::$config[$uid]['transient'][$family]['pcfgud:'.$key] = $updated;
|
||||
if ($new || $update) {
|
||||
App::$config[$uid]['transient'][$family][$key] = $value;
|
||||
App::$config[$uid]['transient'][$family]['pcfgud:'.$key] = $updated;
|
||||
}
|
||||
|
||||
if($ret)
|
||||
@@ -253,7 +256,7 @@ class PConfig {
|
||||
|
||||
$updated = ($updated) ? $updated : datetime_convert('UTC','UTC','-2 seconds');
|
||||
$now = datetime_convert();
|
||||
$newer = (\App::$config[$uid][$family]['pcfgud:'.$key] < $now);
|
||||
$newer = (App::$config[$uid][$family]['pcfgud:'.$key] < $now);
|
||||
|
||||
if (! $newer) {
|
||||
logger('Refusing to delete pconfig with outdated delete request.', LOGGER_NORMAL, LOG_ERR);
|
||||
@@ -262,12 +265,12 @@ class PConfig {
|
||||
|
||||
$ret = false;
|
||||
|
||||
if (isset(\App::$config[$uid][$family][$key])) {
|
||||
unset(\App::$config[$uid][$family][$key]);
|
||||
if (isset(App::$config[$uid][$family][$key])) {
|
||||
unset(App::$config[$uid][$family][$key]);
|
||||
}
|
||||
|
||||
if (isset(\App::$config[$uid][$family]['pcfgud:'.$key])) {
|
||||
unset(\App::$config[$uid][$family]['pcfgud:'.$key]);
|
||||
if (isset(App::$config[$uid][$family]['pcfgud:'.$key])) {
|
||||
unset(App::$config[$uid][$family]['pcfgud:'.$key]);
|
||||
}
|
||||
|
||||
$ret = q("DELETE FROM pconfig WHERE uid = %d AND cat = '%s' AND k = '%s'",
|
||||
@@ -278,9 +281,9 @@ class PConfig {
|
||||
|
||||
// Synchronize delete with clones.
|
||||
|
||||
if ($family != 'hz_delpconfig') {
|
||||
$hash = hash('sha256',$family.':'.$key);
|
||||
set_pconfig($uid,'hz_delpconfig',$hash,$updated);
|
||||
if ($family !== 'hz_delpconfig') {
|
||||
$hash = gen_link_id($family.':'.$key);
|
||||
set_pconfig($uid, 'hz_delpconfig', $hash, $updated);
|
||||
}
|
||||
|
||||
return $ret;
|
||||
|
||||
@@ -4,6 +4,7 @@ namespace Zotlabs\Lib;
|
||||
|
||||
use Zotlabs\Access\PermissionRoles;
|
||||
use Zotlabs\Access\Permissions;
|
||||
use Zotlabs\Daemon\Master;
|
||||
|
||||
/**
|
||||
* @brief Permission Categories. Permission rules for various classes of connections.
|
||||
@@ -38,33 +39,33 @@ class Permcat {
|
||||
|
||||
// first check role perms for a perms_connect setting
|
||||
|
||||
$role = get_pconfig($channel_id,'system','permissions_role');
|
||||
if($role) {
|
||||
$role = get_pconfig($channel_id, 'system', 'permissions_role');
|
||||
if ($role) {
|
||||
$x = PermissionRoles::role_perms($role);
|
||||
if($x['perms_connect']) {
|
||||
if ($x['perms_connect']) {
|
||||
$perms = Permissions::FilledPerms($x['perms_connect']);
|
||||
}
|
||||
}
|
||||
|
||||
// if no role perms it may be a custom role, see if there any autoperms
|
||||
|
||||
if(! $perms) {
|
||||
if (!$perms) {
|
||||
$perms = Permissions::FilledAutoPerms($channel_id);
|
||||
}
|
||||
|
||||
// if no autoperms it may be a custom role with manual perms
|
||||
|
||||
if(! $perms) {
|
||||
if (!$perms) {
|
||||
$r = q("select channel_hash from channel where channel_id = %d",
|
||||
intval($channel_id)
|
||||
);
|
||||
if($r) {
|
||||
if ($r) {
|
||||
$x = q("select * from abconfig where chan = %d and xchan = '%s' and cat = 'my_perms'",
|
||||
intval($channel_id),
|
||||
dbesc($r[0]['channel_hash'])
|
||||
);
|
||||
if($x) {
|
||||
foreach($x as $xv) {
|
||||
if ($x) {
|
||||
foreach ($x as $xv) {
|
||||
$perms[$xv['k']] = intval($xv['v']);
|
||||
}
|
||||
}
|
||||
@@ -73,25 +74,27 @@ class Permcat {
|
||||
|
||||
// nothing was found - create a filled permission array where all permissions are 0
|
||||
|
||||
if(! $perms) {
|
||||
if (!$perms) {
|
||||
$perms = Permissions::FilledPerms([]);
|
||||
}
|
||||
|
||||
$this->permcats[] = [
|
||||
'name' => 'default',
|
||||
'localname' => t('default','permcat'),
|
||||
'localname' => t('Default', 'permcat'),
|
||||
'perms' => Permissions::Operms($perms),
|
||||
'raw_perms' => $perms,
|
||||
'system' => 1
|
||||
];
|
||||
|
||||
|
||||
$p = $this->load_permcats($channel_id);
|
||||
if($p) {
|
||||
for($x = 0; $x < count($p); $x++) {
|
||||
if ($p) {
|
||||
for ($x = 0; $x < count($p); $x++) {
|
||||
$this->permcats[] = [
|
||||
'name' => $p[$x][0],
|
||||
'localname' => $p[$x][1],
|
||||
'perms' => Permissions::Operms(Permissions::FilledPerms($p[$x][2])),
|
||||
'raw_perms' => Permissions::FilledPerms($p[$x][2]),
|
||||
'system' => intval($p[$x][3])
|
||||
];
|
||||
}
|
||||
@@ -116,9 +119,9 @@ class Permcat {
|
||||
* * \e bool \b error if $name not found in permcats true
|
||||
*/
|
||||
public function fetch($name) {
|
||||
if($name && $this->permcats) {
|
||||
foreach($this->permcats as $permcat) {
|
||||
if(strcasecmp($permcat['name'], $name) === 0) {
|
||||
if ($name && $this->permcats) {
|
||||
foreach ($this->permcats as $permcat) {
|
||||
if (strcasecmp($permcat['name'], $name) === 0) {
|
||||
return $permcat;
|
||||
}
|
||||
}
|
||||
@@ -128,31 +131,28 @@ class Permcat {
|
||||
}
|
||||
|
||||
public function load_permcats($uid) {
|
||||
|
||||
/*
|
||||
$permcats = [
|
||||
[ 'follower', t('follower','permcat'),
|
||||
[ 'view_stream','view_profile','view_contacts','view_storage','view_pages','view_wiki',
|
||||
'post_like' ], 1
|
||||
],
|
||||
[ 'contributor', t('contributor','permcat'),
|
||||
[ 'view_stream','view_profile','view_contacts','view_storage','view_pages','view_wiki',
|
||||
'post_wall','post_comments','write_wiki','post_like','tag_deliver','chat' ], 1
|
||||
],
|
||||
[ 'publisher', t('publisher','permcat'),
|
||||
[ 'contributor', t('Contributor','permcat'),
|
||||
[ 'view_stream','view_profile','view_contacts','view_storage','view_pages',
|
||||
'write_storage','post_wall','write_pages','write_wiki','post_comments','post_like','tag_deliver',
|
||||
'chat', 'republish' ], 1
|
||||
]
|
||||
'write_storage','post_wall','write_pages','write_wiki','post_comments', 'post_mail', 'post_like',
|
||||
'chat' ], 1
|
||||
],
|
||||
[ 'muted', t('Muted','permcat'),
|
||||
[ 'view_stream','view_profile','view_contacts','view_storage','view_pages','view_wiki',
|
||||
'post_comments','write_wiki','post_like' ], 1
|
||||
],
|
||||
];
|
||||
|
||||
if($uid) {
|
||||
*/
|
||||
if ($uid) {
|
||||
$x = q("select * from pconfig where uid = %d and cat = 'permcat'",
|
||||
intval($uid)
|
||||
);
|
||||
if($x) {
|
||||
foreach($x as $xv) {
|
||||
$value = ((preg_match('|^a:[0-9]+:{.*}$|s', $xv['v'])) ? unserialize($xv['v']) : $xv['v']);
|
||||
$permcats[] = [ $xv['k'], $xv['k'], $value, 0 ];
|
||||
|
||||
if ($x) {
|
||||
foreach ($x as $xv) {
|
||||
$value = ((preg_match('|^a:[0-9]+:{.*}$|s', $xv['v'])) ? unserialize($xv['v']) : $xv['v']);
|
||||
$permcats[] = [$xv['k'], $xv['k'], $value, 0];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -167,11 +167,11 @@ class Permcat {
|
||||
}
|
||||
|
||||
static public function find_permcat($arr, $name) {
|
||||
if((! $arr) || (! $name))
|
||||
if ((!$arr) || (!$name))
|
||||
return false;
|
||||
|
||||
foreach($arr as $p)
|
||||
if($p['name'] == $name)
|
||||
foreach ($arr as $p)
|
||||
if ($p['name'] == $name)
|
||||
return $p['value'];
|
||||
}
|
||||
|
||||
@@ -183,4 +183,105 @@ class Permcat {
|
||||
PConfig::Delete($channel_id, 'permcat', $name);
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* @brief assign a contact role to contacts
|
||||
*
|
||||
* @param array $channel
|
||||
* @param string $role the name of the role
|
||||
* @param array $contacts an array of contact hashes
|
||||
*/
|
||||
public static function assign($channel, $role, $contacts) {
|
||||
|
||||
if (!isset($channel['channel_id'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!is_array($contacts) || empty($contacts)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$role) {
|
||||
// lookup the default
|
||||
$role = get_pconfig($channel['channel_id'], 'system', 'default_permcat', 'default');
|
||||
}
|
||||
|
||||
|
||||
// Doublecheck that we do not assign a role to ourself.
|
||||
// It does not make a difference but could be confusing.
|
||||
if (in_array($channel['channel_hash'], $contacts)) {
|
||||
$contacts = array_diff($contacts, [$channel['channel_hash']]);
|
||||
}
|
||||
|
||||
$all_perms = Permissions::Perms();
|
||||
$permcats = new Permcat($channel['channel_id']);
|
||||
$role_perms = $permcats->fetch($role);
|
||||
|
||||
if (isset($role_perms['error'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$perms = $role_perms['raw_perms'];
|
||||
|
||||
$values_sql = '';
|
||||
stringify_array_elms($contacts, true);
|
||||
|
||||
if ($all_perms && $perms) {
|
||||
|
||||
foreach ($contacts as $contact) {
|
||||
foreach ($all_perms as $perm => $desc) {
|
||||
if (array_key_exists($perm, $perms)) {
|
||||
$values_sql .= " (" . intval($channel['channel_id']) . ", " . protect_sprintf($contact) . ", 'my_perms', '" . dbesc($perm) . "', " . intval($perms[$perm]) . "),";
|
||||
}
|
||||
else {
|
||||
$values_sql .= " (" . intval($channel['channel_id']) . ", " . protect_sprintf($contact) . ", 'my_perms', '" . dbesc($perm) . "', 0), ";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$values_sql = rtrim($values_sql, ',');
|
||||
|
||||
dbq("DELETE FROM abconfig WHERE chan = " . intval($channel['channel_id']) . " AND cat = 'my_perms' AND xchan IN (" . protect_sprintf(implode(',', $contacts)) . ")");
|
||||
|
||||
dbq("INSERT INTO abconfig ( chan, xchan, cat, k, v ) VALUES $values_sql");
|
||||
|
||||
q("UPDATE abook SET abook_role = '%s'
|
||||
WHERE abook_xchan IN (" . protect_sprintf(implode(',', $contacts)) . ") AND abook_channel = %d",
|
||||
dbesc($role),
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
|
||||
$r = q("SELECT abook.*, xchan.* FROM abook LEFT JOIN xchan ON abook.abook_xchan = xchan.xchan_hash WHERE abook.abook_xchan IN (" . protect_sprintf(implode(',', $contacts)) . ") AND abook.abook_channel = %d AND abook_self = 0",
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
|
||||
foreach ($r as $rr) {
|
||||
|
||||
if (intval($rr['abook_self'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Master::Summon([
|
||||
'Notifier',
|
||||
'permission_update',
|
||||
$rr['abook_id']
|
||||
]);
|
||||
|
||||
$clone = $rr;
|
||||
|
||||
unset($clone['abook_id']);
|
||||
unset($clone['abook_account']);
|
||||
unset($clone['abook_channel']);
|
||||
|
||||
$abconfig = load_abconfig($channel['channel_id'], $clone['abook_xchan']);
|
||||
if ($abconfig)
|
||||
$clone['abconfig'] = $abconfig;
|
||||
|
||||
Libsync::build_sync_packet(0 /* use the current local_channel */, ['abook' => [$clone]]);
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user