mirror of
https://framagit.org/hubzilla/core.git
synced 2026-06-21 09:01:15 -04:00
Compare commits
2147 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
84105c3b05 | ||
|
|
a70db805b7 | ||
|
|
750e0a8d11 | ||
|
|
be3bfa3806 | ||
|
|
4f4d0e416e | ||
|
|
8fde0f01b8 | ||
|
|
757489beb7 | ||
|
|
7773ef0ff4 | ||
|
|
2f5990962c | ||
|
|
81ae0fa252 | ||
|
|
fefc78a849 | ||
|
|
ffe058d48f | ||
|
|
57214fd659 | ||
|
|
5a2b17a1da | ||
|
|
ae3067200b | ||
|
|
568cf2a9e4 | ||
|
|
c2ad28a000 | ||
|
|
f7ad5bbaad | ||
|
|
2a8c4bfbae | ||
|
|
c0f7b8879d | ||
|
|
3a347d7a56 | ||
|
|
c735503f7e | ||
|
|
b0f4929d41 | ||
|
|
10a1569c9a | ||
|
|
301e5383c7 | ||
|
|
66d0b4d0d5 | ||
|
|
94212766cc | ||
|
|
5b436d8fc3 | ||
|
|
cd2d1ff02a | ||
|
|
4ab4224277 | ||
|
|
b5b2e34da5 | ||
|
|
34d28e7ba9 | ||
|
|
259f425050 | ||
|
|
340d437ab2 | ||
|
|
34f576f540 | ||
|
|
64a97d42ff | ||
|
|
beb51040c2 | ||
|
|
8fc9d87b1b | ||
|
|
9845272522 | ||
|
|
7b77e05f3a | ||
|
|
a284e1f9d8 | ||
|
|
ec11ebbd54 | ||
|
|
edf804ea67 | ||
|
|
6f586ae11a | ||
|
|
22c89b6c66 | ||
|
|
cfae618c60 | ||
|
|
7766db40f5 | ||
|
|
18349efccc | ||
|
|
1c5630ef5a | ||
|
|
03d95ec089 | ||
|
|
09d84b5b68 | ||
|
|
9d16666484 | ||
|
|
bb4dcbe89e | ||
|
|
8a8c757327 | ||
|
|
8c75ace6ec | ||
|
|
eb5dfcc9df | ||
|
|
a29c84b522 | ||
|
|
ab3b126ff6 | ||
|
|
6a17da9b08 | ||
|
|
fca405741a | ||
|
|
715847bf74 | ||
|
|
01289048a9 | ||
|
|
dc90f103d4 | ||
|
|
2f026b66a2 | ||
|
|
48db3a189f | ||
|
|
08820fd655 | ||
|
|
66991a0778 | ||
|
|
814dfcd4ac | ||
|
|
48be6ad5c4 | ||
|
|
fbc2bb02b4 | ||
|
|
861bd15c72 | ||
|
|
b8fcfc7698 | ||
|
|
494ce9b872 | ||
|
|
a984cd2b27 | ||
|
|
7a7bfd9de7 | ||
|
|
d0956eb39d | ||
|
|
4d7acdd44d | ||
|
|
5b1ef760a0 | ||
|
|
4859e6e11a | ||
|
|
c2990964f0 | ||
|
|
d4bb6c17d1 | ||
|
|
fca1a7506e | ||
|
|
27bc5fa4b0 | ||
|
|
ad6cb63e07 | ||
|
|
adec67d5fa | ||
|
|
85b7c90637 | ||
|
|
e9ae51cfbc | ||
|
|
3dac1a8d4a | ||
|
|
d326e7a75c | ||
|
|
4c08d7c480 | ||
|
|
ffaab27e77 | ||
|
|
9ba72a06b3 | ||
|
|
a604236d89 | ||
|
|
5024fe3e2d | ||
|
|
44cb68a356 | ||
|
|
157966eb11 | ||
|
|
b7ca2b41cc | ||
|
|
8451ee20c9 | ||
|
|
d4acf41192 | ||
|
|
24d256e253 | ||
|
|
cb39d9435d | ||
|
|
0305983360 | ||
|
|
11c703cb4b | ||
|
|
657ec75c3d | ||
|
|
a79b268438 | ||
|
|
5c12b56e87 | ||
|
|
11b03ca4d2 | ||
|
|
91e3c5c34e | ||
|
|
1c821640ce | ||
|
|
7ed80bf443 | ||
|
|
1c32c5fd2a | ||
|
|
ba547c2257 | ||
|
|
dae0107dd0 | ||
|
|
d5763ba476 | ||
|
|
8a8689c191 | ||
|
|
dd2c4c37ff | ||
|
|
0afdb3ed4d | ||
|
|
9a04b49585 | ||
|
|
dcad9ce26a | ||
|
|
3b6d7e3066 | ||
|
|
3d8de8cf0a | ||
|
|
19ec8488e0 | ||
|
|
0e8e0b48b3 | ||
|
|
cc0d53e695 | ||
|
|
cce2b08e6b | ||
|
|
a68e2999f1 | ||
|
|
fc5b688716 | ||
|
|
6b327f9f4c | ||
|
|
d59c1bb6bf | ||
|
|
6a4050cc93 | ||
|
|
5abcb8c978 | ||
|
|
aa7f6111a6 | ||
|
|
b1f82257e8 | ||
|
|
bc0f4b4fa5 | ||
|
|
e6a59ad36f | ||
|
|
e375224dfe | ||
|
|
f55ef7e728 | ||
|
|
bf1ec44186 | ||
|
|
e47c08ed72 | ||
|
|
e1a209a3da | ||
|
|
76703dee84 | ||
|
|
df45c13f62 | ||
|
|
455720ae93 | ||
|
|
8073be87da | ||
|
|
8d3bf59b7b | ||
|
|
d5c56c0f5d | ||
|
|
f3c0e212bf | ||
|
|
7092458945 | ||
|
|
56772e4807 | ||
|
|
3e7ab8e113 | ||
|
|
53fca8a248 | ||
|
|
1c712ce93e | ||
|
|
dc53573975 | ||
|
|
1ad1b74512 | ||
|
|
0e91810ed6 | ||
|
|
063654373d | ||
|
|
ee929752e3 | ||
|
|
88ebfe6edb | ||
|
|
e1fdac3278 | ||
|
|
d65740311b | ||
|
|
55868ad02d | ||
|
|
014b629928 | ||
|
|
4bffa49add | ||
|
|
fe37b03757 | ||
|
|
4b2bd871b7 | ||
|
|
2108173e74 | ||
|
|
08900b730b | ||
|
|
9dd545f420 | ||
|
|
fda5231a71 | ||
|
|
b03545f899 | ||
|
|
e327b8cb9a | ||
|
|
64c81ed174 | ||
|
|
87eaa6d8e5 | ||
|
|
874cff1a87 | ||
|
|
3bb0efd2cb | ||
|
|
a99ebd42ec | ||
|
|
0cfe2ecd7b | ||
|
|
14f1292743 | ||
|
|
c96f1dbbe2 | ||
|
|
8fcf16ee63 | ||
|
|
4fc8416c3c | ||
|
|
6c178d4485 | ||
|
|
8bd8af7d16 | ||
|
|
b4f8f4df7b | ||
|
|
98e2b2a60b | ||
|
|
eb69f6c346 | ||
|
|
2cb3ccbf14 | ||
|
|
fb1e3cba8b | ||
|
|
94d6461568 | ||
|
|
09f1e4bdfb | ||
|
|
8dceb8e3a7 | ||
|
|
d942818bd9 | ||
|
|
1acef2e242 | ||
|
|
e2814f5d80 | ||
|
|
542d9130b5 | ||
|
|
159d6469fd | ||
|
|
53445ba6bd | ||
|
|
1810edae93 | ||
|
|
7f9ab491f2 | ||
|
|
77190cca92 | ||
|
|
d2e3e3003a | ||
|
|
56d981c8ef | ||
|
|
250d758d74 | ||
|
|
e32f9e0354 | ||
|
|
0325efeb35 | ||
|
|
9ab33f1e13 | ||
|
|
66c0ac591c | ||
|
|
6241967112 | ||
|
|
250d947667 | ||
|
|
6a49e3124e | ||
|
|
16f584608f | ||
|
|
88d0bf94d8 | ||
|
|
241a0829dc | ||
|
|
66a0b4790e | ||
|
|
46ab7ca786 | ||
|
|
3efe144fa0 | ||
|
|
744960d36d | ||
|
|
727b49c8ab | ||
|
|
0aa01740d1 | ||
|
|
1c75e71eb3 | ||
|
|
fbc57fa8e3 | ||
|
|
60fcb5f4f2 | ||
|
|
eb1e9edd33 | ||
|
|
6b6c2ccfa3 | ||
|
|
8a4ee0506c | ||
|
|
ee2ba21246 | ||
|
|
8e6ebd4f7b | ||
|
|
76af8fa754 | ||
|
|
601ebee969 | ||
|
|
becd5f1446 | ||
|
|
ab363e3132 | ||
|
|
7c655c8d61 | ||
|
|
7386fa57c8 | ||
|
|
3f2b7d756c | ||
|
|
cba602bf64 | ||
|
|
78c9f752af | ||
|
|
d13a6180be | ||
|
|
d479ed00e4 | ||
|
|
67b6d41d57 | ||
|
|
601f1eb624 | ||
|
|
301b41eaa4 | ||
|
|
ed0d7890ab | ||
|
|
f50ae07560 | ||
|
|
8e53491867 | ||
|
|
3c3c0ed342 | ||
|
|
8d9c47acdf | ||
|
|
9d69792e08 | ||
|
|
5b4aa71878 | ||
|
|
240db7b602 | ||
|
|
aff476d0d4 | ||
|
|
d5ff82bbe4 | ||
|
|
c8dbcf8a2a | ||
|
|
d893eb67b8 | ||
|
|
5dad444026 | ||
|
|
217a684e5f | ||
|
|
1ef558d7e6 | ||
|
|
7b6ddeb859 | ||
|
|
b12dc89bb1 | ||
|
|
a387868540 | ||
|
|
1ac35dd047 | ||
|
|
458f2e748d | ||
|
|
b62dee4c90 | ||
|
|
6ea7ef43e0 | ||
|
|
3838472a8e | ||
|
|
064464a553 | ||
|
|
9bf366b7d4 | ||
|
|
4668f36ddd | ||
|
|
a68308b164 | ||
|
|
f7e3d0dbf6 | ||
|
|
bd3bc503ed | ||
|
|
e2eb36ded6 | ||
|
|
4ac3cec66e | ||
|
|
823729d2c1 | ||
|
|
34b38f06e0 | ||
|
|
0fef599341 | ||
|
|
124e08efde | ||
|
|
66338a5757 | ||
|
|
ebee3e208c | ||
|
|
f8cf68ab53 | ||
|
|
28c85cf3ae | ||
|
|
cf4e2b2953 | ||
|
|
f3d3ec5744 | ||
|
|
29829eb011 | ||
|
|
129e6bddde | ||
|
|
8260817cf7 | ||
|
|
47d15f3bf4 | ||
|
|
96d439bcee | ||
|
|
47fab97210 | ||
|
|
5dec3ff18e | ||
|
|
bd3e5156c4 | ||
|
|
fccc1da666 | ||
|
|
55995b0494 | ||
|
|
eb17598254 | ||
|
|
0d512dffc3 | ||
|
|
988028577b | ||
|
|
6cf3ebb7db | ||
|
|
c571ca40d7 | ||
|
|
3a17225546 | ||
|
|
5e541ff53b | ||
|
|
9b19e40a74 | ||
|
|
766a7fb1b4 | ||
|
|
40a7446e3e | ||
|
|
fc96cd3710 | ||
|
|
40c625158f | ||
|
|
7dad842f35 | ||
|
|
909f67fb3a | ||
|
|
e7d20efb1b | ||
|
|
a8d527f1cd | ||
|
|
e5f3296c6b | ||
|
|
9d584fc720 | ||
|
|
92e0c502f7 | ||
|
|
b5d4acf10a | ||
|
|
47fbdda409 | ||
|
|
1bb6dfc9a0 | ||
|
|
549866c090 | ||
|
|
7b69dc574b | ||
|
|
5376a734d4 | ||
|
|
3f1a4b6559 | ||
|
|
11a7a08b9d | ||
|
|
d16bbfb224 | ||
|
|
48959d5606 | ||
|
|
94e548b07a | ||
|
|
4be48b8d8b | ||
|
|
9cd715bbbf | ||
|
|
04d66ba7f4 | ||
|
|
7efcb3c75f | ||
|
|
359bfb76f6 | ||
|
|
0e1c628066 | ||
|
|
65bc146afa | ||
|
|
9630d2ef2c | ||
|
|
6e9d5a03c2 | ||
|
|
839c154869 | ||
|
|
6995d54a3c | ||
|
|
d31df715fb | ||
|
|
26fa091aa2 | ||
|
|
cfbeb1655d | ||
|
|
39c194c5c3 | ||
|
|
9dfb471c0b | ||
|
|
f51a7225c8 | ||
|
|
1d903655af | ||
|
|
9abb061e71 | ||
|
|
6e48c36519 | ||
|
|
d450fc61c4 | ||
|
|
a899ce1c22 | ||
|
|
1a737be2b4 | ||
|
|
fae9c23637 | ||
|
|
1159dd59ed | ||
|
|
0ce7358f0f | ||
|
|
41749f5eda | ||
|
|
1567b7b383 | ||
|
|
e70bd0054c | ||
|
|
b450b6a435 | ||
|
|
0403738981 | ||
|
|
0d7062ffdf | ||
|
|
8f59b2d3e0 | ||
|
|
1b290f573a | ||
|
|
b77169f1d8 | ||
|
|
00d8783e45 | ||
|
|
cf5beafcfd | ||
|
|
cdaf5f3fc0 | ||
|
|
bdf50a824e | ||
|
|
f23c8e7597 | ||
|
|
52657b6215 | ||
|
|
28cd2759d7 | ||
|
|
12f33d2cd4 | ||
|
|
11cdc36bcc | ||
|
|
22d45a8d1e | ||
|
|
7d9d1e0cdb | ||
|
|
98b53801e0 | ||
|
|
bff1e215cc | ||
|
|
6efef3922b | ||
|
|
caec565de5 | ||
|
|
16a2bfa95b | ||
|
|
60da235efb | ||
|
|
71e0e55b0b | ||
|
|
b28ff509b1 | ||
|
|
8467ecb1d7 | ||
|
|
1f47f4ff96 | ||
|
|
4fef29e61c | ||
|
|
56c3d5dbcb | ||
|
|
ceed0f7a1b | ||
|
|
906d91d4d1 | ||
|
|
e539a9e7bd | ||
|
|
1be98d7b7f | ||
|
|
66832c41e9 | ||
|
|
8e4c5db766 | ||
|
|
1dc3253d4a | ||
|
|
feebe7d4c6 | ||
|
|
9a8071e014 | ||
|
|
9ce817bb6e | ||
|
|
fe2a937cf2 | ||
|
|
1cf90dd14d | ||
|
|
6823f0aa52 | ||
|
|
f2efa8c753 | ||
|
|
e5cfb8a0cd | ||
|
|
4a3149d1ba | ||
|
|
dafe0a5547 | ||
|
|
fe5f1e4d67 | ||
|
|
5cf06a679c | ||
|
|
859195d07a | ||
|
|
344aa13c64 | ||
|
|
69b22e3f79 | ||
|
|
a782c9944c | ||
|
|
39055c919c | ||
|
|
bc890d3038 | ||
|
|
e424ae0473 | ||
|
|
780abe7dd4 | ||
|
|
a3fc9e3742 | ||
|
|
325cbfcdb3 | ||
|
|
69e7a7594a | ||
|
|
c489f734db | ||
|
|
60a54e9aac | ||
|
|
280baf7c82 | ||
|
|
a23f8b6231 | ||
|
|
ccc8ff107e | ||
|
|
59a9f6bf02 | ||
|
|
2aff3a1a05 | ||
|
|
25988ddefa | ||
|
|
c99962106d | ||
|
|
52c1f79f2e | ||
|
|
2c07a92ad7 | ||
|
|
e67ff5c122 | ||
|
|
37b7b2f1a8 | ||
|
|
fd5764e166 | ||
|
|
c49eec71f0 | ||
|
|
812d904c98 | ||
|
|
a4fdf3fbbb | ||
|
|
9090bfd1c3 | ||
|
|
8c57ed64d0 | ||
|
|
b58bf75f21 | ||
|
|
189a15fe37 | ||
|
|
c7d9a5ac91 | ||
|
|
d0bc81f8d2 | ||
|
|
0dc777bc45 | ||
|
|
4f39119e37 | ||
|
|
8aa4af372d | ||
|
|
d5e90d678a | ||
|
|
0061ac8584 | ||
|
|
f648809856 | ||
|
|
687114b407 | ||
|
|
40f805c94a | ||
|
|
9751d03a4d | ||
|
|
36678d1b90 | ||
|
|
8f465e3097 | ||
|
|
c80f4feb62 | ||
|
|
2d06e86b5b | ||
|
|
400441d56b | ||
|
|
7d92e9026e | ||
|
|
42416aad22 | ||
|
|
9d51318c53 | ||
|
|
cdb1bc9be6 | ||
|
|
52183f8bf8 | ||
|
|
00dc7c916d | ||
|
|
5fd6e36be7 | ||
|
|
c2714262b3 | ||
|
|
a58f386831 | ||
|
|
e61b44ddbb | ||
|
|
f3c374b6ff | ||
|
|
21b2c0afa3 | ||
|
|
ca4c725d57 | ||
|
|
fe1aa90304 | ||
|
|
656ec585b2 | ||
|
|
64a49eb54a | ||
|
|
b106b53d05 | ||
|
|
a791809a84 | ||
|
|
71c3a0a197 | ||
|
|
9497c6c0f7 | ||
|
|
18279234fd | ||
|
|
4dd05dc4e8 | ||
|
|
cf7481da53 | ||
|
|
b8a9390f49 | ||
|
|
61c86212b9 | ||
|
|
a33562144b | ||
|
|
9b94ad2ffe | ||
|
|
70b39e829b | ||
|
|
29a29f277e | ||
|
|
e5f1bcacc8 | ||
|
|
ccbc532c1a | ||
|
|
e6c166a182 | ||
|
|
26bd532bc5 | ||
|
|
c89b2ac3b7 | ||
|
|
6acd96fd33 | ||
|
|
a652e546cc | ||
|
|
ee307729fc | ||
|
|
48d2b3afa8 | ||
|
|
491856fa79 | ||
|
|
56a675f713 | ||
|
|
05c8d4819d | ||
|
|
c8d5390512 | ||
|
|
f3cf708c85 | ||
|
|
24d1d752fe | ||
|
|
ba55400f14 | ||
|
|
0c5918f290 | ||
|
|
0216dc733d | ||
|
|
ff8ee6fb22 | ||
|
|
1a7ccc462b | ||
|
|
769da564e2 | ||
|
|
09b4660c7d | ||
|
|
69394c1680 | ||
|
|
4203d43c58 | ||
|
|
f273815d8f | ||
|
|
6a2c5e0731 | ||
|
|
07ae431950 | ||
|
|
0c4a1fb9be | ||
|
|
e6f1fb3d95 | ||
|
|
030d703a05 | ||
|
|
edc262f5af | ||
|
|
41cf846ee3 | ||
|
|
335536bbbf | ||
|
|
89aa9a80c4 | ||
|
|
d636ff586d | ||
|
|
8797049144 | ||
|
|
623dfa1384 | ||
|
|
cc1ffff7cd | ||
|
|
5698462588 | ||
|
|
f99c007187 | ||
|
|
54a0690323 | ||
|
|
23812e5b48 | ||
|
|
c37908f344 | ||
|
|
4011dd18f0 | ||
|
|
52b1ea10a1 | ||
|
|
09009d4b32 | ||
|
|
ec173e7eb2 | ||
|
|
bcf4cb519a | ||
|
|
27bc8294ae | ||
|
|
5cc6c6c1e9 | ||
|
|
991db280be | ||
|
|
6f709a6f57 | ||
|
|
71c206fdb9 | ||
|
|
4c0e8a61ae | ||
|
|
dc2c6d00fe | ||
|
|
e7c8012794 | ||
|
|
9bd30eb8bf | ||
|
|
b883b9c983 | ||
|
|
5468ebbb43 | ||
|
|
27f8320353 | ||
|
|
e15307747f | ||
|
|
f427b4a325 | ||
|
|
a6835f4e71 | ||
|
|
052ed1f88b | ||
|
|
34a0ec4089 | ||
|
|
2ed77b5986 | ||
|
|
d70e6f273b | ||
|
|
d2e22d8c2f | ||
|
|
7c501ef60f | ||
|
|
a0eb628526 | ||
|
|
0ddc3e4af2 | ||
|
|
5be9477f21 | ||
|
|
4ab21edba8 | ||
|
|
2862baeee1 | ||
|
|
15b9a67c01 | ||
|
|
80ca99fe5b | ||
|
|
6f88d5e92b | ||
|
|
295ed07d40 | ||
|
|
d6b1eff70e | ||
|
|
7fb02752de | ||
|
|
d88d4b3c3a | ||
|
|
58155864cb | ||
|
|
9cf9217686 | ||
|
|
fa93114804 | ||
|
|
66511d8f07 | ||
|
|
f52e5d90b0 | ||
|
|
f571b753b6 | ||
|
|
40e747ecde | ||
|
|
9e24b28376 | ||
|
|
5abdee73ee | ||
|
|
2feb6795b0 | ||
|
|
c200808fbb | ||
|
|
1f8b705a6a | ||
|
|
a3c2ef4084 | ||
|
|
9dcbef4cb1 | ||
|
|
8bd4e004ff | ||
|
|
47b2959486 | ||
|
|
f70d27b793 | ||
|
|
7c845aafa2 | ||
|
|
16b57a2b28 | ||
|
|
89457c8390 | ||
|
|
ea4d1b5101 | ||
|
|
dd38fad9ee | ||
|
|
c61853ff0b | ||
|
|
bdecb61bfa | ||
|
|
c9231785ab | ||
|
|
f79d5ec18e | ||
|
|
98e0534984 | ||
|
|
617f2863c4 | ||
|
|
0f36916fb4 | ||
|
|
1fd2b6f5b6 | ||
|
|
7d386c2777 | ||
|
|
fb60eeaa9a | ||
|
|
9625d940a5 | ||
|
|
b8a0bc0b0b | ||
|
|
cee41bb1e5 | ||
|
|
4a270d10d1 | ||
|
|
ea5262a0df | ||
|
|
86e888e5eb | ||
|
|
9d7a88b40d | ||
|
|
be8061b64b | ||
|
|
d91a82430a | ||
|
|
b9664f6980 | ||
|
|
66334374af | ||
|
|
741af8c164 | ||
|
|
137f5b3dbc | ||
|
|
e1cd51d8d9 | ||
|
|
237aca32e3 | ||
|
|
906a810735 | ||
|
|
808605cd65 | ||
|
|
06a674775e | ||
|
|
b195407028 | ||
|
|
1650d79862 | ||
|
|
e8a888caab | ||
|
|
3648f9952c | ||
|
|
8b7ab90836 | ||
|
|
866dc9a9b3 | ||
|
|
0e76cec28f | ||
|
|
2988e33b57 | ||
|
|
aef239f421 | ||
|
|
3456c192fe | ||
|
|
ae5a1362a7 | ||
|
|
fefc2290a1 | ||
|
|
6bd35ef740 | ||
|
|
b772a5f564 | ||
|
|
234e9476fb | ||
|
|
a7d339be5a | ||
|
|
b745a143c3 | ||
|
|
6e9e267b27 | ||
|
|
2e9336beb5 | ||
|
|
5951fa56ae | ||
|
|
4372e1fcda | ||
|
|
24a9c3ba79 | ||
|
|
c4261b9c4b | ||
|
|
7b060dff68 | ||
|
|
90f759412b | ||
|
|
15691d3ced | ||
|
|
6f2dd5d325 | ||
|
|
9e46472ca2 | ||
|
|
61d9b34929 | ||
|
|
00fe4e747f | ||
|
|
b0cdec0c35 | ||
|
|
373af6d4f4 | ||
|
|
4ae503bef7 | ||
|
|
72a19a14af | ||
|
|
a7d0c45606 | ||
|
|
dbc0cc8c92 | ||
|
|
a1be6f11ed | ||
|
|
143e389695 | ||
|
|
962a3f7945 | ||
|
|
bced63e823 | ||
|
|
51e40add66 | ||
|
|
4500faf463 | ||
|
|
66fb0fdcd7 | ||
|
|
105e7626fc | ||
|
|
c6bcea0f82 | ||
|
|
4fbebe7b2d | ||
|
|
e812836a60 | ||
|
|
d11d36040d | ||
|
|
c3b3f41a21 | ||
|
|
46daaa11fd | ||
|
|
cca2b1621f | ||
|
|
807776cb15 | ||
|
|
9914e171b1 | ||
|
|
b3c805d7d0 | ||
|
|
d31c91c9d3 | ||
|
|
bf252d2388 | ||
|
|
5c379b4d35 | ||
|
|
4d3b0577c9 | ||
|
|
d37e6b9271 | ||
|
|
654139933f | ||
|
|
1d9e0f17a6 | ||
|
|
9120a82ab4 | ||
|
|
ca24bfdc46 | ||
|
|
aaa83ae5d2 | ||
|
|
8123a62302 | ||
|
|
e84281b620 | ||
|
|
6239a27288 | ||
|
|
0b272264ea | ||
|
|
d5ffa5508d | ||
|
|
991db80646 | ||
|
|
cb3fb0049f | ||
|
|
eef1fcbb07 | ||
|
|
186dd9dee0 | ||
|
|
373651c3db | ||
|
|
663802e699 | ||
|
|
4c5722c766 | ||
|
|
6734854776 | ||
|
|
1c0ece8411 | ||
|
|
cf120b2351 | ||
|
|
6481722fd9 | ||
|
|
b1876ac14f | ||
|
|
d7ec6865b4 | ||
|
|
46b6415f5f | ||
|
|
5aa0fe2bf0 | ||
|
|
f43f38c054 | ||
|
|
235ba81f25 | ||
|
|
55aaabc2f1 | ||
|
|
5be132f877 | ||
|
|
b5966041be | ||
|
|
62d6bada4c | ||
|
|
e8e61c83d5 | ||
|
|
13788af908 | ||
|
|
d5bd5cda97 | ||
|
|
29b0ed87d6 | ||
|
|
0e6d84e207 | ||
|
|
796228b7ad | ||
|
|
7489a4442e | ||
|
|
5e99295bf6 | ||
|
|
4ff89a5862 | ||
|
|
87ca60b0b1 | ||
|
|
525d554a35 | ||
|
|
4c121aff30 | ||
|
|
d77872de50 | ||
|
|
91ed3b357d | ||
|
|
d4e53bb86f | ||
|
|
471449f539 | ||
|
|
187fc9a51b | ||
|
|
abbf245d14 | ||
|
|
20ae69ab7b | ||
|
|
67024c023a | ||
|
|
2f76d63835 | ||
|
|
754329097f | ||
|
|
c5950c0370 | ||
|
|
e2e7bee3cc | ||
|
|
edada2b786 | ||
|
|
ccc9cc8202 | ||
|
|
84c86f01c8 | ||
|
|
9b542c5bcf | ||
|
|
108bb7649b | ||
|
|
1104e2652f | ||
|
|
f2dc55244c | ||
|
|
048a8c5f44 | ||
|
|
1fbb1e6c2a | ||
|
|
7e9162ef06 | ||
|
|
f09fe8da78 | ||
|
|
4d794103be | ||
|
|
61f339a874 | ||
|
|
7b3aa92b5a | ||
|
|
27e9b5618b | ||
|
|
4d1f5c1752 | ||
|
|
23e774db8e | ||
|
|
4190a40de8 | ||
|
|
6143f49042 | ||
|
|
607c414634 | ||
|
|
d65007b230 | ||
|
|
41e0d5f664 | ||
|
|
fa7a6203fb | ||
|
|
5877e28d72 | ||
|
|
318643cf9a | ||
|
|
ab9b82e778 | ||
|
|
fee65f0c69 | ||
|
|
643f515eaf | ||
|
|
1305584d77 | ||
|
|
0a7364d494 | ||
|
|
2cce599fd7 | ||
|
|
7dc99cb4a4 | ||
|
|
45eb61bcf0 | ||
|
|
80400d7191 | ||
|
|
9ca7cc565b | ||
|
|
6147f819ce | ||
|
|
842a041a88 | ||
|
|
68a91ec3ea | ||
|
|
d58f965b9a | ||
|
|
83d0e48ebe | ||
|
|
ca58ef80ae | ||
|
|
0956dcadd3 | ||
|
|
304c393f38 | ||
|
|
05654e4980 | ||
|
|
c8000fca1f | ||
|
|
48547f5f9e | ||
|
|
b4f8136315 | ||
|
|
06f1910ac0 | ||
|
|
03b31932d1 | ||
|
|
e4b0e31a28 | ||
|
|
ba4f75ba19 | ||
|
|
fc62f07a08 | ||
|
|
3d0a7f4fc5 | ||
|
|
47ef41695a | ||
|
|
4adf2caaa6 | ||
|
|
db82d303e2 | ||
|
|
0fac35686b | ||
|
|
5ae2d15dc0 | ||
|
|
dc18440c18 | ||
|
|
499b7de0d2 | ||
|
|
1a0cf2666a | ||
|
|
7bff60edac | ||
|
|
e935473c5c | ||
|
|
3af3b36db3 | ||
|
|
9333503600 | ||
|
|
7a42aed1f6 | ||
|
|
5bffae6219 | ||
|
|
ae8cdc3b42 | ||
|
|
b413beeb36 | ||
|
|
0cf5536e90 | ||
|
|
5e767144c9 | ||
|
|
6d87311394 | ||
|
|
0ee2378cec | ||
|
|
28d6b9ce16 | ||
|
|
f3c0db0f39 | ||
|
|
3a52af6327 | ||
|
|
aec92e0e17 | ||
|
|
c364bff0c1 | ||
|
|
74f55d1504 | ||
|
|
f436ec6f21 | ||
|
|
be097bf415 | ||
|
|
f1b014b7eb | ||
|
|
ad637b5b50 | ||
|
|
5abc9ef10b | ||
|
|
d47df8663f | ||
|
|
77267e049a | ||
|
|
e2b6464f83 | ||
|
|
973f15438a | ||
|
|
1f42d23332 | ||
|
|
b80f0b8960 | ||
|
|
06be21af05 | ||
|
|
ab5e7ad7a2 | ||
|
|
0d3c378e10 | ||
|
|
471031390c | ||
|
|
8517e7e798 | ||
|
|
e70bf97508 | ||
|
|
6385d11b54 | ||
|
|
d0d0a2df3a | ||
|
|
99ca2a7cc6 | ||
|
|
acacea5efe | ||
|
|
187f19b170 | ||
|
|
49b38bd71b | ||
|
|
75f3e9202e | ||
|
|
0098dce597 | ||
|
|
cff5e360fd | ||
|
|
45c033b9aa | ||
|
|
5c92337821 | ||
|
|
341386a95b | ||
|
|
bd84a3ee08 | ||
|
|
383b7928cf | ||
|
|
9cb856d5fd | ||
|
|
2d5768b71c | ||
|
|
90ec3340e4 | ||
|
|
cf2609530f | ||
|
|
cdccf60132 | ||
|
|
df2725a360 | ||
|
|
592cf893c0 | ||
|
|
85f24c292f | ||
|
|
1c4629f5e1 | ||
|
|
af8ed605f8 | ||
|
|
186f85483f | ||
|
|
e157e3bec8 | ||
|
|
4450170790 | ||
|
|
66b032823b | ||
|
|
c9745a4129 | ||
|
|
bf7b0b11ef | ||
|
|
e778815605 | ||
|
|
f2e802229a | ||
|
|
64cf36a2b5 | ||
|
|
8873fbfee9 | ||
|
|
89df4551aa | ||
|
|
ecfc7b8f4c | ||
|
|
3b68df1be6 | ||
|
|
9518dc0e4e | ||
|
|
e084b776ee | ||
|
|
6c38857502 | ||
|
|
41ff8fdd37 | ||
|
|
182f94a9ac | ||
|
|
92077725c3 | ||
|
|
9f37dbc6dc | ||
|
|
33528c616a | ||
|
|
894f0156af | ||
|
|
9d5b6858ea | ||
|
|
7a405da3b7 | ||
|
|
49cc952825 | ||
|
|
31e62bd19e | ||
|
|
52c6ea5115 | ||
|
|
f15d96bebe | ||
|
|
18c57eeaa0 | ||
|
|
2b898537d7 | ||
|
|
081bff605a | ||
|
|
8a5c23fd50 | ||
|
|
830f1bcd50 | ||
|
|
17e81095b3 | ||
|
|
ed71afa6c7 | ||
|
|
4cafa6280d | ||
|
|
b488034352 | ||
|
|
944cd883bb | ||
|
|
f9dd4188b4 | ||
|
|
557aa18526 | ||
|
|
b18f3f4f7a | ||
|
|
4111ba8dee | ||
|
|
035449e4a3 | ||
|
|
2a2abf14bb | ||
|
|
b553ecbb18 | ||
|
|
d87a270e2c | ||
|
|
3443416540 | ||
|
|
f2589cc820 | ||
|
|
691fadc93d | ||
|
|
65a320c509 | ||
|
|
b0f2c22000 | ||
|
|
ef8a251115 | ||
|
|
4a7384bc0c | ||
|
|
90bc21f2d5 | ||
|
|
1c5629263b | ||
|
|
6adfbabbb7 | ||
|
|
2a48222393 | ||
|
|
4addde782e | ||
|
|
9b87940ed2 | ||
|
|
8000d6b5d4 | ||
|
|
e9679d251c | ||
|
|
68f6043d44 | ||
|
|
f560a88ff3 | ||
|
|
4b0d0df781 | ||
|
|
05453ce493 | ||
|
|
af7ea07b43 | ||
|
|
289161aad1 | ||
|
|
6a3919587f | ||
|
|
80e7337984 | ||
|
|
6cea5ddfad | ||
|
|
ba08555efc | ||
|
|
f99b62b516 | ||
|
|
2f45182b48 | ||
|
|
9da1439a4d | ||
|
|
57602647ef | ||
|
|
4848dc5ec8 | ||
|
|
8b5a190d71 | ||
|
|
a4804ff977 | ||
|
|
998bd585bb | ||
|
|
0123a28186 | ||
|
|
ff1d900ccb | ||
|
|
1808ffcdf2 | ||
|
|
86c4743ed9 | ||
|
|
1408e3da3b | ||
|
|
5f6eedcc1a | ||
|
|
7cec3f4dbf | ||
|
|
80ff7fa353 | ||
|
|
7892ed9e77 | ||
|
|
0e3b5536e2 | ||
|
|
6c55e44f4c | ||
|
|
5b88e9574f | ||
|
|
ecfb608518 | ||
|
|
9411732c1b | ||
|
|
acb8eeb853 | ||
|
|
d1c7e78990 | ||
|
|
0a96cdd950 | ||
|
|
5686901869 | ||
|
|
6531cbd1d2 | ||
|
|
09da109eba | ||
|
|
fa2de77abe | ||
|
|
8ab3a4ebd7 | ||
|
|
8eb6dafe31 | ||
|
|
ca11d7b9a7 | ||
|
|
a7a73a5150 | ||
|
|
83b5bbfeea | ||
|
|
59108b18ae | ||
|
|
037e1edb1f | ||
|
|
c00796d553 | ||
|
|
23f9f8bc3b | ||
|
|
88a4889780 | ||
|
|
bac297cf31 | ||
|
|
3c73228d80 | ||
|
|
0085b64b2b | ||
|
|
1c0c01ccfe | ||
|
|
b0d1fa09c1 | ||
|
|
68b32cd8f4 | ||
|
|
d5dcaacf2c | ||
|
|
03ca0bfa69 | ||
|
|
3aa22c29fd | ||
|
|
06a211704f | ||
|
|
913046aa28 | ||
|
|
b4707705f1 | ||
|
|
a618f70f56 | ||
|
|
05444f92f9 | ||
|
|
9566eab934 | ||
|
|
d704832ff6 | ||
|
|
3c1dff3039 | ||
|
|
4edf580ebf | ||
|
|
7b177be271 | ||
|
|
d183e47dc9 | ||
|
|
dc7c3f70eb | ||
|
|
d06ce6294d | ||
|
|
21ee29e46d | ||
|
|
bee09a6d8b | ||
|
|
a100c47f11 | ||
|
|
ba62f14482 | ||
|
|
2a34a497d5 | ||
|
|
4ea4a036ef | ||
|
|
2dbf8a5e00 | ||
|
|
9359f9fe4d | ||
|
|
01526a9a79 | ||
|
|
01fc590938 | ||
|
|
6e9fb9b9fd | ||
|
|
a97b09210e | ||
|
|
acddf5aa8d | ||
|
|
6614d465d6 | ||
|
|
2ba2187c2e | ||
|
|
2ea482d163 | ||
|
|
599b395e24 | ||
|
|
1416b81877 | ||
|
|
aa766b53d6 | ||
|
|
4e2a050afb | ||
|
|
cf437c6a33 | ||
|
|
8b6a24c67d | ||
|
|
a72b549aa7 | ||
|
|
46d8cf3f94 | ||
|
|
91d19a3326 | ||
|
|
a510c91d48 | ||
|
|
2f8c5cf7d0 | ||
|
|
1f2482f6ab | ||
|
|
9476c631b0 | ||
|
|
10e459140b | ||
|
|
b66cd8363e | ||
|
|
376b05bcc9 | ||
|
|
a4a99d2d46 | ||
|
|
2fcbbfe3d4 | ||
|
|
2095937c60 | ||
|
|
d33974cec4 | ||
|
|
9ec995dbf0 | ||
|
|
79a806f328 | ||
|
|
445fa6825a | ||
|
|
e3c8e4f483 | ||
|
|
8f3a99ad1f | ||
|
|
a3fef34a3f | ||
|
|
17618be14d | ||
|
|
3faca10efc | ||
|
|
280f52f007 | ||
|
|
126e06b32a | ||
|
|
988371be0b | ||
|
|
b4efe8ad8d | ||
|
|
964a02d684 | ||
|
|
40effa4417 | ||
|
|
35c05a3180 | ||
|
|
4a071b9a1c | ||
|
|
ead80481b9 | ||
|
|
297057d2bd | ||
|
|
11cdd0033d | ||
|
|
06bd540cfa | ||
|
|
3451fe2d40 | ||
|
|
2ee0f769d9 | ||
|
|
8161ec88e5 | ||
|
|
7b992decd4 | ||
|
|
9b9fe39839 | ||
|
|
1f57a59618 | ||
|
|
5a1b850dd6 | ||
|
|
c4e0e20eb3 | ||
|
|
eedee6d0a1 | ||
|
|
e316494e06 | ||
|
|
4585e35b3e | ||
|
|
9717d4502f | ||
|
|
f9b342c87d | ||
|
|
222113ee57 | ||
|
|
5f7b2e7c17 | ||
|
|
179478a940 | ||
|
|
53570de5a3 | ||
|
|
41a6300d3c | ||
|
|
1376e59d00 | ||
|
|
d623228cf6 | ||
|
|
75d63684b8 | ||
|
|
d3d184192d | ||
|
|
9be4c4d6d1 | ||
|
|
d3a5911932 | ||
|
|
dbbae4bac8 | ||
|
|
9132b9c026 | ||
|
|
769f697ae3 | ||
|
|
7d891a54e7 | ||
|
|
e71cdf02a8 | ||
|
|
7d82b5f28d | ||
|
|
eec2871680 | ||
|
|
029cf6395d | ||
|
|
08f15a6fc6 | ||
|
|
c24cfbc62a | ||
|
|
caf077cbf8 | ||
|
|
5cc8837fb6 | ||
|
|
ddecbf052e | ||
|
|
6a7fa6bf54 | ||
|
|
5ed4ed2246 | ||
|
|
72ed290ccd | ||
|
|
16067db718 | ||
|
|
363d872326 | ||
|
|
f4a4d70149 | ||
|
|
4335e49381 | ||
|
|
992f8272d3 | ||
|
|
27678a523c | ||
|
|
1bdcfe5219 | ||
|
|
89d21c0873 | ||
|
|
23e2b3be09 | ||
|
|
a346399fe6 | ||
|
|
8e5c56dcc2 | ||
|
|
77b58ec02f | ||
|
|
ceeb9836b9 | ||
|
|
df7f0eb9a4 | ||
|
|
6103c30184 | ||
|
|
b52a968c74 | ||
|
|
82aa87c190 | ||
|
|
1af844e474 | ||
|
|
c664a4bdcd | ||
|
|
229f95d555 | ||
|
|
ac6ebeee47 | ||
|
|
8896ebf7cb | ||
|
|
9bd11afc62 | ||
|
|
08c0d78296 | ||
|
|
9daa3b85c8 | ||
|
|
d8c93c0d13 | ||
|
|
42abc2201c | ||
|
|
27257de995 | ||
|
|
15e836b7dd | ||
|
|
0d062251b6 | ||
|
|
ecb1515e5d | ||
|
|
4728e72d18 | ||
|
|
c352047228 | ||
|
|
1aedf22228 | ||
|
|
5408264559 | ||
|
|
b7d92d3a09 | ||
|
|
bd17dc52f2 | ||
|
|
e6315d252a | ||
|
|
ce3be598bb | ||
|
|
e891199a23 | ||
|
|
b1d4e97699 | ||
|
|
16dcaaa3a8 | ||
|
|
fd5c92822c | ||
|
|
77f71303f2 | ||
|
|
266dab1b59 | ||
|
|
2d119c81a4 | ||
|
|
88bb61018d | ||
|
|
c940d8d7ca | ||
|
|
aa70cbbf21 | ||
|
|
6db717a1a0 | ||
|
|
ad9990e100 | ||
|
|
403e90861c | ||
|
|
2d63bbb91e | ||
|
|
271ed82d0d | ||
|
|
c47439fca4 | ||
|
|
e3734328eb | ||
|
|
ddc454bd82 | ||
|
|
799d4ad549 | ||
|
|
8dcdcd55e5 | ||
|
|
1fca442828 | ||
|
|
d077f15270 | ||
|
|
31d1a72854 | ||
|
|
f9a989fe1b | ||
|
|
46e079beea | ||
|
|
4048cb67d2 | ||
|
|
b16e4c558f | ||
|
|
2d6e87fb17 | ||
|
|
024d2737d0 | ||
|
|
b2e5b6c977 | ||
|
|
75f058e15e | ||
|
|
7fb849ab87 | ||
|
|
fca8e0aa6a | ||
|
|
8dd9ab05a9 | ||
|
|
c3b93de099 | ||
|
|
27c8c74988 | ||
|
|
80352dab5f | ||
|
|
00a49b42e4 | ||
|
|
f5735fb67b | ||
|
|
fb5b588349 | ||
|
|
9e497cde40 | ||
|
|
f3816836e5 | ||
|
|
038c928b9b | ||
|
|
c596248f40 | ||
|
|
6ae3a92f53 | ||
|
|
fbf868e976 | ||
|
|
5e0bb6ecd5 | ||
|
|
a34d8773f1 | ||
|
|
4bc94c0ee9 | ||
|
|
bf1a21e46f | ||
|
|
d18427a522 | ||
|
|
76850a7340 | ||
|
|
d096106824 | ||
|
|
562124c29f | ||
|
|
48063fa5ef | ||
|
|
41111bcdad | ||
|
|
133292e241 | ||
|
|
64cad0a041 | ||
|
|
b73c844d1a | ||
|
|
da1b10b741 | ||
|
|
c7b4a53af2 | ||
|
|
024809f970 | ||
|
|
126af3a24a | ||
|
|
b91d95d241 | ||
|
|
8ca5a65dcf | ||
|
|
798a03c2ab | ||
|
|
34c4775916 | ||
|
|
c5cff7d637 | ||
|
|
c2af370282 | ||
|
|
118fed29b5 | ||
|
|
4c50bfebc2 | ||
|
|
dab00a98e0 | ||
|
|
2b2ea40bce | ||
|
|
1273ac67f4 | ||
|
|
676481de58 | ||
|
|
54c5e03b4f | ||
|
|
a8374b25f1 | ||
|
|
4d81c498e2 | ||
|
|
b0dd824dbc | ||
|
|
5dc638c5b3 | ||
|
|
7f982a0778 | ||
|
|
28a1be4d36 | ||
|
|
c456e01219 | ||
|
|
ef53db0b91 | ||
|
|
21542d1f9e | ||
|
|
07d6472eea | ||
|
|
6c771f84ce | ||
|
|
02b7bc0803 | ||
|
|
681d6ca1dd | ||
|
|
3b4f70ae83 | ||
|
|
0e100a864b | ||
|
|
dc14f8bf2c | ||
|
|
37b9a809a6 | ||
|
|
5f1a1db30f | ||
|
|
99ff808b8a | ||
|
|
08c0729f5f | ||
|
|
7e4e2f28db | ||
|
|
08d9316d76 | ||
|
|
0233e9ad2a | ||
|
|
31e0812711 | ||
|
|
76e9809169 | ||
|
|
07a8151ae6 | ||
|
|
075ced80a6 | ||
|
|
4c96b9778e | ||
|
|
1b31c9f8a8 | ||
|
|
b858eec644 | ||
|
|
5af9923e29 | ||
|
|
e122901e49 | ||
|
|
aed1373b70 | ||
|
|
3b5e1c05b7 | ||
|
|
1472f85b16 | ||
|
|
3d6255ae24 | ||
|
|
f25e0c3829 | ||
|
|
b0a6a5a91e | ||
|
|
b917cf1ecc | ||
|
|
4d5469f27e | ||
|
|
1848a22118 | ||
|
|
b429576349 | ||
|
|
bb9557a9ae | ||
|
|
0d7e7ac657 | ||
|
|
b8c77bbcfc | ||
|
|
327b22d24e | ||
|
|
8b3d2c02e1 | ||
|
|
1ac799f629 | ||
|
|
234c64574b | ||
|
|
7b948bdd29 | ||
|
|
1f075d92bc | ||
|
|
fe02665f54 | ||
|
|
ec74b57000 | ||
|
|
3f488e9842 | ||
|
|
54e07389fa | ||
|
|
28906bf50a | ||
|
|
70e912736f | ||
|
|
ec1156d37a | ||
|
|
dcbc65a796 | ||
|
|
8eccd7d47d | ||
|
|
5530833bf8 | ||
|
|
2f8fb2b663 | ||
|
|
5d2035b729 | ||
|
|
7c36331042 | ||
|
|
36cfdd529b | ||
|
|
3e13568f91 | ||
|
|
e84ed1cb9a | ||
|
|
f1fd672d7b | ||
|
|
02b0472058 | ||
|
|
5854a226d7 | ||
|
|
bdf8940040 | ||
|
|
2b9a8fa1ac | ||
|
|
45137a55a4 | ||
|
|
d6dd2c5bd6 | ||
|
|
d4330ceacc | ||
|
|
364da7a57e | ||
|
|
05eeb8432e | ||
|
|
fce68f1a39 | ||
|
|
7f374fe69f | ||
|
|
836cb16455 | ||
|
|
dd8feac540 | ||
|
|
f526b9fcfb | ||
|
|
8bf9b1311d | ||
|
|
5b3e863323 | ||
|
|
6ce9eedb5f | ||
|
|
6f78183b74 | ||
|
|
1d96544c9d | ||
|
|
69f6a5c08c | ||
|
|
38b4f6a391 | ||
|
|
425e13843e | ||
|
|
f28fa0ab5a | ||
|
|
f162993001 | ||
|
|
af774a7269 | ||
|
|
d82cfdf581 | ||
|
|
b84818a334 | ||
|
|
9c26ee122e | ||
|
|
f27047dd2e | ||
|
|
643a62038e | ||
|
|
fbb83d831b | ||
|
|
2a4032d71a | ||
|
|
42c9f853a7 | ||
|
|
3389df77cc | ||
|
|
97732f7006 | ||
|
|
8f2457855c | ||
|
|
7e4c880e1e | ||
|
|
2a21285037 | ||
|
|
61bf77f668 | ||
|
|
cf583168dd | ||
|
|
236b528552 | ||
|
|
f730e476f0 | ||
|
|
3563568f6f | ||
|
|
912be5a792 | ||
|
|
30358100ab | ||
|
|
492665a8a1 | ||
|
|
005baea319 | ||
|
|
4f3b1edf9d | ||
|
|
2e692fca93 | ||
|
|
9dbd997141 | ||
|
|
416a82bf12 | ||
|
|
2e35dc648f | ||
|
|
55836e8ca6 | ||
|
|
a17acfb04f | ||
|
|
e9fe258b5e | ||
|
|
79e618415a | ||
|
|
bea0a491cf | ||
|
|
108b052e4e | ||
|
|
f5b593ff42 | ||
|
|
cdfd42053d | ||
|
|
36d4086673 | ||
|
|
01b541d8b0 | ||
|
|
928fce875e | ||
|
|
1d3c6e7420 | ||
|
|
c96fe2931a | ||
|
|
8a11dc0c90 | ||
|
|
324d427ac7 | ||
|
|
84c04cfe1c | ||
|
|
1925f2dec2 | ||
|
|
5235a72bca | ||
|
|
80c65ea8f3 | ||
|
|
3a2a7d0508 | ||
|
|
59002cb873 | ||
|
|
f49ce500a1 | ||
|
|
40b9130c63 | ||
|
|
e917b94929 | ||
|
|
abce12ccd9 | ||
|
|
83f8f8ebb8 | ||
|
|
4bd825e778 | ||
|
|
2fea5ff889 | ||
|
|
a94a42d609 | ||
|
|
4784f847c9 | ||
|
|
867d8510ca | ||
|
|
d53fb9d1b5 | ||
|
|
58b5c4cc16 | ||
|
|
10ecb6d368 | ||
|
|
e7c3ca9bd8 | ||
|
|
e8a4e9a31f | ||
|
|
43914852e5 | ||
|
|
c7f097ec84 | ||
|
|
7562f77bdf | ||
|
|
c4ed04fc82 | ||
|
|
f3061651d4 | ||
|
|
0b740826c5 | ||
|
|
e2d028fb97 | ||
|
|
e0913dc8e6 | ||
|
|
56f3b12171 | ||
|
|
927313968a | ||
|
|
2e54024b92 | ||
|
|
cdfcb1ed24 | ||
|
|
e6581aa09c | ||
|
|
8ebb000650 | ||
|
|
fc98bd1563 | ||
|
|
7ccf47f4c6 | ||
|
|
35debe46bc | ||
|
|
98c18f416a | ||
|
|
ea19971285 | ||
|
|
47d55694a4 | ||
|
|
f0e615dee5 | ||
|
|
5376b478b8 | ||
|
|
909e618f6c | ||
|
|
c492573429 | ||
|
|
8ae97b556e | ||
|
|
dfc0d4cf59 | ||
|
|
bfad624528 | ||
|
|
062b9ecbf3 | ||
|
|
d3cad5a651 | ||
|
|
a7ecf51915 | ||
|
|
893ae17b99 | ||
|
|
e48d5383ce | ||
|
|
9675acdf87 | ||
|
|
14229d0dd3 | ||
|
|
2b5d19924b | ||
|
|
3f658cc2ea | ||
|
|
6962bc5147 | ||
|
|
321957781e | ||
|
|
fd91513832 | ||
|
|
4fcfcc8117 | ||
|
|
11cecea597 | ||
|
|
e549833077 | ||
|
|
b15a5f03e6 | ||
|
|
7738083f3e | ||
|
|
98fe474276 | ||
|
|
03b8ecd0de | ||
|
|
bb669ccd2c | ||
|
|
e9d924b5d7 | ||
|
|
143601374c | ||
|
|
586c72fbe5 | ||
|
|
8bb832e23f | ||
|
|
184f522d5f | ||
|
|
0f0e23445a | ||
|
|
1b75e4de0d | ||
|
|
2deafa0dea | ||
|
|
938a621810 | ||
|
|
583a047e83 | ||
|
|
57edfa7ae8 | ||
|
|
b4da2d35bf | ||
|
|
fd357f87be | ||
|
|
df8c69f73b | ||
|
|
8ce98e38dc | ||
|
|
3a00140797 | ||
|
|
bf580fcc06 | ||
|
|
31d9208172 | ||
|
|
508ea9153c | ||
|
|
6ff16e2651 | ||
|
|
da682717ab | ||
|
|
647b5d098f | ||
|
|
3a9e5f0f98 | ||
|
|
50c9aec436 | ||
|
|
ec7ecc285e | ||
|
|
dea0d07b9a | ||
|
|
357e7af6ad | ||
|
|
53057830e0 | ||
|
|
7ae0317b6a | ||
|
|
547df2219a | ||
|
|
1c8c7479b8 | ||
|
|
36a960adec | ||
|
|
07ee4984cb | ||
|
|
e4448423fb | ||
|
|
50e9d02458 | ||
|
|
45233dd53c | ||
|
|
1a9fdc565c | ||
|
|
e32e616031 | ||
|
|
b14fb1759d | ||
|
|
abd757d356 | ||
|
|
28645b492e | ||
|
|
3919c8f79f | ||
|
|
803be11bbc | ||
|
|
335de94343 | ||
|
|
b62463107c | ||
|
|
93ce1661af | ||
|
|
f59ed38a38 | ||
|
|
3fad69e5ca | ||
|
|
005db13c45 | ||
|
|
d7ddafb39f | ||
|
|
3fe7bf27de | ||
|
|
4b718929df | ||
|
|
a44c908147 | ||
|
|
1bf37305a8 | ||
|
|
ed4d589077 | ||
|
|
47a080d79c | ||
|
|
66a8e5ddbb | ||
|
|
8c39ed61a9 | ||
|
|
a12d403981 | ||
|
|
ccf0274d13 | ||
|
|
21103f8bc4 | ||
|
|
a1ba44db72 | ||
|
|
3c22a7b482 | ||
|
|
d056b13e14 | ||
|
|
7a39ccf7bb | ||
|
|
3be90c2e45 | ||
|
|
60caecffdd | ||
|
|
df3eb562f0 | ||
|
|
c4b247e75e | ||
|
|
d9fdd0ce36 | ||
|
|
226fcac72e | ||
|
|
5c8a911c93 | ||
|
|
2cc1844d97 | ||
|
|
3916d5c567 | ||
|
|
ef51c1c2b2 | ||
|
|
f637faf0d2 | ||
|
|
d010f4fcae | ||
|
|
d5e436d15b | ||
|
|
18ee1ba589 | ||
|
|
795b39250f | ||
|
|
ae89f1b3b3 | ||
|
|
cbe600369c | ||
|
|
1de1b58a08 | ||
|
|
4f577cbdeb | ||
|
|
c2bd7d1e56 | ||
|
|
e501289a55 | ||
|
|
1ebc9de1e6 | ||
|
|
f34b060e23 | ||
|
|
84064b90a6 | ||
|
|
08e21fd0b8 | ||
|
|
1077686bda | ||
|
|
582d075c45 | ||
|
|
b60f1085db | ||
|
|
a3bdfc1580 | ||
|
|
76a8711570 | ||
|
|
87b424123b | ||
|
|
9a66d47d54 | ||
|
|
5a0712f766 | ||
|
|
660ea89521 | ||
|
|
60204becf4 | ||
|
|
032216153f | ||
|
|
dac4447e33 | ||
|
|
fa94c0a65b | ||
|
|
76d78571d6 | ||
|
|
556407408f | ||
|
|
a862bf488c | ||
|
|
f629dc51aa | ||
|
|
96cc6a916d | ||
|
|
6c0e0b3eae | ||
|
|
8a129610da | ||
|
|
8688753522 | ||
|
|
9a0400c93a | ||
|
|
13b5eb0ad8 | ||
|
|
e059efb4c4 | ||
|
|
0be74c6551 | ||
|
|
6fe6e1596f | ||
|
|
0e7c3951a6 | ||
|
|
40c8549cf5 | ||
|
|
a7ea370ec3 | ||
|
|
b6c6f06537 | ||
|
|
2e531c103f | ||
|
|
1a05939e0b | ||
|
|
acb8e85b61 | ||
|
|
8c38841a4d | ||
|
|
2c2ee706ac | ||
|
|
b7df4de4b7 | ||
|
|
b237425c94 | ||
|
|
bd3708870d | ||
|
|
2aa699d03e | ||
|
|
1d20b2603a | ||
|
|
6576f9c0c3 | ||
|
|
f840082aae | ||
|
|
f162508ad1 | ||
|
|
3ccefa20e8 | ||
|
|
00b19ccee0 | ||
|
|
54d55fb62f | ||
|
|
dcc8a94d07 | ||
|
|
5dd501e0ea | ||
|
|
af7a3fc2ea | ||
|
|
4b4b06bec5 | ||
|
|
54259593ea | ||
|
|
73cb270b14 | ||
|
|
3d1df8337e | ||
|
|
f08001a5a6 | ||
|
|
ecbba93784 | ||
|
|
47ebddf99f | ||
|
|
c70ac572fa | ||
|
|
f0a2747d80 | ||
|
|
67918033f9 | ||
|
|
93335cdb0e | ||
|
|
e308c3d34a | ||
|
|
977677d005 | ||
|
|
faf9814788 | ||
|
|
eeb9103e26 | ||
|
|
1f6386bd60 | ||
|
|
5c7acf4807 | ||
|
|
a92b9b7adb | ||
|
|
b4529229d2 | ||
|
|
bc776a9534 | ||
|
|
45c64c2d2e | ||
|
|
73f41023f3 | ||
|
|
139c1a956f | ||
|
|
b08af13872 | ||
|
|
1e59d9ade5 | ||
|
|
519aef7ff5 | ||
|
|
05cbdc6915 | ||
|
|
8d5e028b5b | ||
|
|
153ffbe558 | ||
|
|
394352d882 | ||
|
|
c0edfee224 | ||
|
|
06d2d31777 | ||
|
|
535691a05c | ||
|
|
d2058ee151 | ||
|
|
263cfe2538 | ||
|
|
717190975f | ||
|
|
d6a3f7765a | ||
|
|
f9d40adb18 | ||
|
|
087f9784e3 | ||
|
|
3bd74aabaa | ||
|
|
4933aef543 | ||
|
|
0e5d824bff | ||
|
|
b2d2dcc7fe | ||
|
|
7acb068590 | ||
|
|
80ec92ce8d | ||
|
|
83c4dd6bda | ||
|
|
e332d1074f | ||
|
|
42ed73ed4a | ||
|
|
5ed5c76d3f | ||
|
|
fe2288a88f | ||
|
|
8f0a0add1e | ||
|
|
3645eb18f8 | ||
|
|
610e80a19b | ||
|
|
d8460f147b | ||
|
|
71e508c7cd | ||
|
|
d3fcef43f8 | ||
|
|
cbc906c438 | ||
|
|
d57169fcf6 | ||
|
|
fdf639e1fb | ||
|
|
25760e30f9 | ||
|
|
3cdcb121c5 | ||
|
|
968209471e | ||
|
|
d71a53f24e | ||
|
|
c845d20352 | ||
|
|
11e888fb7c | ||
|
|
230617208b | ||
|
|
e99be61d49 | ||
|
|
635b8ff73a | ||
|
|
c9daafc887 | ||
|
|
033cf61380 | ||
|
|
70e17f9194 | ||
|
|
89e7e5e4fb | ||
|
|
ab32372f8f | ||
|
|
2778e63d6c | ||
|
|
d16fbda0f8 | ||
|
|
e8ea8d203d | ||
|
|
ac670856f6 | ||
|
|
88149f56bb | ||
|
|
6fcfab3488 | ||
|
|
dab3e90353 | ||
|
|
1c304eb8ba | ||
|
|
d1c84ad9f0 | ||
|
|
c39a680096 | ||
|
|
e8ddee284c | ||
|
|
abd7cfdc97 | ||
|
|
c904bd3a62 | ||
|
|
d48bda88e6 | ||
|
|
4ca24f114b | ||
|
|
7667c630a4 | ||
|
|
97458b2885 | ||
|
|
803bff4043 | ||
|
|
17aa8da9f0 | ||
|
|
7d5ee81628 | ||
|
|
b88be137ca | ||
|
|
195eb71200 | ||
|
|
f36e384ed7 | ||
|
|
3a3bd582b1 | ||
|
|
a342a5f8e0 | ||
|
|
42d139ee82 | ||
|
|
f1c6fd08c4 | ||
|
|
8ad2b3e7a1 | ||
|
|
a84695bb86 | ||
|
|
c2ec3b0bf4 | ||
|
|
bda9a833ba | ||
|
|
ac12f923ea | ||
|
|
b6be0e1b99 | ||
|
|
01809b08c9 | ||
|
|
42f5291f69 | ||
|
|
1d271ee771 | ||
|
|
1d19ea4a33 | ||
|
|
0d9b6ebc36 | ||
|
|
d9a48092e6 | ||
|
|
02ea713d6a | ||
|
|
94f15e3551 | ||
|
|
2d90b831f0 | ||
|
|
35110b6327 | ||
|
|
f52c670c05 | ||
|
|
f3adc8d738 | ||
|
|
40f6280c48 | ||
|
|
1c6d2857cb | ||
|
|
09967598e1 | ||
|
|
d3feb93619 | ||
|
|
0bba5cdc30 | ||
|
|
a3b1eec548 | ||
|
|
f174c4fccb | ||
|
|
32eead1542 | ||
|
|
1701e100cf | ||
|
|
397fef519c | ||
|
|
53bd0146bb | ||
|
|
a037758245 | ||
|
|
ffce1fc177 | ||
|
|
368f88740a | ||
|
|
ab369ab91d | ||
|
|
ddddf29f82 | ||
|
|
fdc36fb140 | ||
|
|
9ce5e25507 | ||
|
|
0bc4de2f34 | ||
|
|
e3dc242a3c | ||
|
|
bff2ed3837 | ||
|
|
9c31e26cf1 | ||
|
|
7a31c039fb | ||
|
|
7cca2b7fb0 | ||
|
|
10e5cf01cc | ||
|
|
384c19e54e | ||
|
|
7d5e7bf6c8 | ||
|
|
b6459e6172 | ||
|
|
b4f65840d1 | ||
|
|
b266ade4fe | ||
|
|
0f0fba0e9e | ||
|
|
54f25609c9 | ||
|
|
c48e90a556 | ||
|
|
e0409386c2 | ||
|
|
2aa69257a4 | ||
|
|
60d4b4c4f6 | ||
|
|
4a6a06fdc0 | ||
|
|
c631da7b0d | ||
|
|
9d425b4727 | ||
|
|
07d62bc111 | ||
|
|
91d0f87181 | ||
|
|
1c32564536 | ||
|
|
da07108be9 | ||
|
|
d7f4526a00 | ||
|
|
63dd6ad01a | ||
|
|
7b173a75e4 | ||
|
|
cb5a047e5d | ||
|
|
ed5abe5981 | ||
|
|
940534e303 | ||
|
|
1609473e5d | ||
|
|
1f951e2bd3 | ||
|
|
ed8e4962b9 | ||
|
|
10f9f9cc80 | ||
|
|
56c8e00b84 | ||
|
|
063577c19e | ||
|
|
57f20c0c22 | ||
|
|
e682b93883 | ||
|
|
a32b097e3c | ||
|
|
2ebf76cd50 | ||
|
|
65e5894363 | ||
|
|
dbef80f7bd | ||
|
|
06b0c89aee | ||
|
|
113bfe8fa2 | ||
|
|
df4e193990 | ||
|
|
28207c3313 | ||
|
|
e685c580f2 | ||
|
|
e6139c9f49 | ||
|
|
fac654ec5d | ||
|
|
1352e334b1 | ||
|
|
69ab6639b2 | ||
|
|
d52ee7ae27 | ||
|
|
ebcfc7f2b2 | ||
|
|
b347e1d861 | ||
|
|
8cb4a29a51 | ||
|
|
9fb08fb502 | ||
|
|
6710a77c26 | ||
|
|
e442fe753e | ||
|
|
a4685e6df3 | ||
|
|
a4f6c24273 | ||
|
|
53853814ff | ||
|
|
fb31f629c6 | ||
|
|
50612565e9 | ||
|
|
a92256e1cb | ||
|
|
d6c23486d5 | ||
|
|
d2bafdb2bf | ||
|
|
f2f2b534e6 | ||
|
|
2d9ae8ff2c | ||
|
|
4e4d406d23 | ||
|
|
a9bda2b12e | ||
|
|
5fb7ea8dbd | ||
|
|
d35678b891 | ||
|
|
405e3fc214 | ||
|
|
fbba78411d | ||
|
|
75cd816e02 | ||
|
|
c8a886e399 | ||
|
|
19b2568133 | ||
|
|
ccc8a05eb0 | ||
|
|
26125bcf0b | ||
|
|
263efbfe39 | ||
|
|
9a5ce2354d | ||
|
|
f25f5aeaaa | ||
|
|
af14020e42 | ||
|
|
4a49643bcd | ||
|
|
29596d12e3 | ||
|
|
1a28fb2a0c | ||
|
|
d985db60cc | ||
|
|
a76ad1478f | ||
|
|
044067f055 | ||
|
|
810d9e21bc | ||
|
|
7256579c16 | ||
|
|
ecf30b2c71 | ||
|
|
95f4f14dca | ||
|
|
391854058e | ||
|
|
1bcee2f11c | ||
|
|
572a04b40a | ||
|
|
d9ee8b2c32 | ||
|
|
614366e499 | ||
|
|
89e3f3210f | ||
|
|
dc55c710da | ||
|
|
47817b8ae1 | ||
|
|
3e66549ea4 | ||
|
|
8b7d0f33c3 | ||
|
|
a20fd4d463 | ||
|
|
bfd506f184 | ||
|
|
c20aa6062c | ||
|
|
b2a51db14e | ||
|
|
33ff7bf968 | ||
|
|
57a8b3f857 | ||
|
|
6e5a06421f | ||
|
|
5f0004b416 | ||
|
|
e79f450af9 | ||
|
|
c4f5d17db6 | ||
|
|
d1a018f2e8 | ||
|
|
6118570118 | ||
|
|
a9cceea850 | ||
|
|
81736a0129 | ||
|
|
dea4879938 | ||
|
|
2e2f984c45 | ||
|
|
bb639b08f7 | ||
|
|
5167f70015 | ||
|
|
cca5349110 | ||
|
|
5abe7d2dfb | ||
|
|
181d9a0777 | ||
|
|
5219c4a09a | ||
|
|
4da65183e0 | ||
|
|
b51ca4c8d3 | ||
|
|
198d2ab607 | ||
|
|
f43428aacf | ||
|
|
2d4f84563b | ||
|
|
418d102663 | ||
|
|
3b6a0d8e5c | ||
|
|
29c9972b86 | ||
|
|
7033966bb8 | ||
|
|
e90e4e4a59 | ||
|
|
954176cfc3 | ||
|
|
a8a6d807ff | ||
|
|
fe5f109af5 | ||
|
|
f1da003020 | ||
|
|
ea5a7180c7 | ||
|
|
9d0e2cbd89 | ||
|
|
032b6f193d | ||
|
|
e49c59959b | ||
|
|
b03cd330e5 | ||
|
|
542fa4a08c | ||
|
|
515f1e76b0 | ||
|
|
d95f7efea7 | ||
|
|
e97dd48b4c | ||
|
|
5915f31950 | ||
|
|
8caa4d9e37 | ||
|
|
d5525a38f1 | ||
|
|
e9a5af6109 | ||
|
|
fd6b32758e | ||
|
|
4387fb715b | ||
|
|
d7aaca6947 | ||
|
|
fa5115b3ed | ||
|
|
ec5e1067bc | ||
|
|
ee46faff1a | ||
|
|
fa629841bd | ||
|
|
155b57c2de | ||
|
|
6ea32a8ba3 | ||
|
|
8d72cea2d1 | ||
|
|
3ee4dd0d52 | ||
|
|
0f7832dc30 | ||
|
|
107083e3e4 | ||
|
|
d7a9d22a15 | ||
|
|
ecfbb10326 | ||
|
|
6c92a240cc | ||
|
|
0bad26e116 | ||
|
|
cd57483ed9 | ||
|
|
0908da9529 | ||
|
|
6e101e4582 | ||
|
|
f60309efa1 | ||
|
|
47f4007951 | ||
|
|
74f58818d6 | ||
|
|
17977effe7 | ||
|
|
477ed97c2f | ||
|
|
242ef70a77 | ||
|
|
755b751614 | ||
|
|
ad3a327366 | ||
|
|
a54bb07753 | ||
|
|
323ab3dba4 | ||
|
|
6947194824 | ||
|
|
879350b658 | ||
|
|
046e5e239f | ||
|
|
c5828fecc1 | ||
|
|
d12b360e92 | ||
|
|
5564b47dbc | ||
|
|
28ad60f892 | ||
|
|
171b6a222d | ||
|
|
f05181322c | ||
|
|
33d23a4a61 | ||
|
|
3e6088c614 | ||
|
|
8292553a20 | ||
|
|
6375401e0a | ||
|
|
b6b62506c5 | ||
|
|
f66aa336ac | ||
|
|
779cab047a | ||
|
|
cd575e80dd | ||
|
|
060cc15f81 | ||
|
|
6ed5784491 | ||
|
|
eab9040ee7 | ||
|
|
099b30afbf | ||
|
|
5cbf603203 | ||
|
|
c327b00efa | ||
|
|
7634d4ce69 | ||
|
|
98c6548d64 | ||
|
|
d169ee658e | ||
|
|
f718e2b0db | ||
|
|
dc59817a9d | ||
|
|
66fcea0ad8 | ||
|
|
a572609dbd | ||
|
|
94e458018b | ||
|
|
e5e0a6b31f | ||
|
|
5c63f7dd58 | ||
|
|
b0b5db770d | ||
|
|
878614f97a | ||
|
|
49e77e0f71 | ||
|
|
2115eb26a7 | ||
|
|
4f4c9bf5d6 | ||
|
|
90ab050493 | ||
|
|
28e0911f29 | ||
|
|
fd23844c8d | ||
|
|
5dc457b16c | ||
|
|
aadfb97d5a | ||
|
|
83abceb8be | ||
|
|
727a2fe4ea | ||
|
|
cb6c21ce90 | ||
|
|
a2e1019978 | ||
|
|
1171e1dd9c | ||
|
|
fff7be2c0f | ||
|
|
a1ef698cf2 | ||
|
|
43a794a905 | ||
|
|
4d50fe0928 | ||
|
|
e98938d03d | ||
|
|
c3c1572683 | ||
|
|
708f738952 | ||
|
|
5f1da17406 | ||
|
|
0499deea69 | ||
|
|
0fb0241901 | ||
|
|
24b55bbc9b | ||
|
|
3a7db8ec60 | ||
|
|
bc3e1e99fe | ||
|
|
efdd95fe7f | ||
|
|
65ecc5ae15 | ||
|
|
83a78a949d | ||
|
|
a7bf4366ce | ||
|
|
066ab8c1fc | ||
|
|
bedc393425 | ||
|
|
c1cc7bfc94 | ||
|
|
caae956f6e | ||
|
|
30a3339653 | ||
|
|
ef73607288 | ||
|
|
e7c3ecd192 | ||
|
|
a7d184ba54 | ||
|
|
546867c102 | ||
|
|
42fbc28b11 | ||
|
|
82631c3413 | ||
|
|
b153c651b4 | ||
|
|
8821986d87 | ||
|
|
35fc7328de | ||
|
|
7a611c6d47 | ||
|
|
f252f3efc5 | ||
|
|
da823125b9 | ||
|
|
7de5717418 | ||
|
|
a6f232f2b0 | ||
|
|
cbcd195461 | ||
|
|
837efcf5e7 | ||
|
|
8b0bcdb2a5 | ||
|
|
ca14ab3d55 | ||
|
|
cfdf1def2a | ||
|
|
37d350c3f5 | ||
|
|
b10c519cc1 | ||
|
|
78aeb50ce5 | ||
|
|
a12a614e7e | ||
|
|
f746418fda | ||
|
|
1bdab6e633 | ||
|
|
1bf2a9d47b | ||
|
|
8b4b135036 | ||
|
|
be10bf2ceb | ||
|
|
d4bd4ca000 | ||
|
|
2f3f95d3a9 | ||
|
|
d958f1099b | ||
|
|
7b0f3d9e26 | ||
|
|
92d581a342 | ||
|
|
8e11b2d6f0 | ||
|
|
79bd2ddd9c | ||
|
|
949ca844c5 | ||
|
|
f31af3c7c0 | ||
|
|
a0245f3e93 | ||
|
|
99811c90b6 | ||
|
|
c85f1a208d | ||
|
|
774923be1c | ||
|
|
d78b64d5b3 | ||
|
|
0938db8f7b | ||
|
|
d2c971eda9 | ||
|
|
57584ea429 | ||
|
|
49d84a364d | ||
|
|
89b5507354 | ||
|
|
2a25ddff36 | ||
|
|
b0b96daec0 | ||
|
|
8764cdf16a | ||
|
|
a45dd09fc0 | ||
|
|
320c32fd0f | ||
|
|
4afeefb5ce | ||
|
|
b2ad4e8c2a | ||
|
|
2bdf63d069 | ||
|
|
b897fd8315 | ||
|
|
82b35e2762 | ||
|
|
56f32104d5 | ||
|
|
2556d05602 | ||
|
|
7b06cb6682 | ||
|
|
cbd401c3e8 | ||
|
|
9277806664 | ||
|
|
828028259c | ||
|
|
d10525a375 | ||
|
|
d903758940 | ||
|
|
cf11ba1147 | ||
|
|
446b5550a2 | ||
|
|
4c2bdc9dc0 | ||
|
|
051759580d | ||
|
|
fb3f63bf59 | ||
|
|
f6b643e84e | ||
|
|
16d750d1f6 | ||
|
|
dfd626548f | ||
|
|
92d7c32f61 | ||
|
|
0ee48f6a58 | ||
|
|
664c762b35 | ||
|
|
9cb9608209 | ||
|
|
b20062efa6 | ||
|
|
8d4744d115 | ||
|
|
14f16a7ef0 | ||
|
|
df6c07aaad | ||
|
|
c95e9b9ba5 | ||
|
|
472a824a1e | ||
|
|
16df1c1ad4 | ||
|
|
e1fe637dcd | ||
|
|
2dce86d38e | ||
|
|
bcd02edd80 | ||
|
|
a73ea134cd | ||
|
|
e7a5aa7b9c | ||
|
|
aa33cacb62 | ||
|
|
0c74c79b18 | ||
|
|
0c973cc9fa | ||
|
|
62c921815f | ||
|
|
211cda540d | ||
|
|
6078d02c3a | ||
|
|
fa89b8f66d | ||
|
|
e399de8ad4 | ||
|
|
32a9487ff9 | ||
|
|
e891380ed5 | ||
|
|
2c73b457ef | ||
|
|
2f5f1a4d64 | ||
|
|
5c080ca4e8 | ||
|
|
4a85726e55 | ||
|
|
cb2eee1d2e | ||
|
|
8e80500ee6 | ||
|
|
03db9833e8 | ||
|
|
33153b8f3a | ||
|
|
3b2398ed01 | ||
|
|
a0a376e95e | ||
|
|
7b9df1d401 | ||
|
|
1244b0e36a | ||
|
|
ab58c95d27 | ||
|
|
a153368814 | ||
|
|
41fd729209 | ||
|
|
58aa0f3e1a | ||
|
|
02b390d7b8 | ||
|
|
41c2f74772 | ||
|
|
6c641b1834 | ||
|
|
700c05a55b | ||
|
|
188782c461 | ||
|
|
bdfdd23b36 | ||
|
|
9f0c3b496b | ||
|
|
1ae715da21 | ||
|
|
d5feb5135d | ||
|
|
fc533107ed | ||
|
|
1ee76cb506 | ||
|
|
4bb90dffc1 | ||
|
|
f4cd4184f8 | ||
|
|
c39c925d8d | ||
|
|
b1fc29be11 | ||
|
|
2a1f6e3df2 | ||
|
|
6f3493bb3c | ||
|
|
61257094b7 | ||
|
|
8aabc6bc3d | ||
|
|
f68148b7e0 | ||
|
|
4c526c7d3d | ||
|
|
4a24a8de43 | ||
|
|
b8ad22f525 | ||
|
|
d9ecca8591 | ||
|
|
83d07b9551 | ||
|
|
ee03391293 | ||
|
|
30503d6533 | ||
|
|
bbb83bea38 | ||
|
|
0f9ddbf3b2 | ||
|
|
8c4b8e623f | ||
|
|
b1c97dfcfd | ||
|
|
1a49f0d164 | ||
|
|
a2371d56fd | ||
|
|
c93db2cd21 | ||
|
|
15d422db80 | ||
|
|
14d1912115 | ||
|
|
b6477cd38b | ||
|
|
c42cbda904 | ||
|
|
39d56fd08f | ||
|
|
403f4c1a6b | ||
|
|
15ab331b6b | ||
|
|
495da14e38 | ||
|
|
9ca53fdc5d | ||
|
|
8e3a026276 | ||
|
|
b5ddd08630 | ||
|
|
a037590ce3 | ||
|
|
a18e8e1ede | ||
|
|
595cb13d8f | ||
|
|
9e44b07275 | ||
|
|
99e681c09f | ||
|
|
4f5e9d77b2 | ||
|
|
98ccdf65fb | ||
|
|
4c0c153b8f | ||
|
|
c533c62c64 | ||
|
|
384db9d10d | ||
|
|
5d8b0acc16 | ||
|
|
3d23f4ec77 | ||
|
|
215bd07f0b | ||
|
|
6c79e0c077 | ||
|
|
b2ea61ea3e | ||
|
|
47d2467e24 | ||
|
|
8e1716065e | ||
|
|
eaefb36212 | ||
|
|
a2f6f48daf | ||
|
|
608e679d33 | ||
|
|
155844f142 | ||
|
|
cee9a20e85 | ||
|
|
70ca4a7fea | ||
|
|
7445f1881e | ||
|
|
e58dc726c5 | ||
|
|
6bf6462a37 | ||
|
|
dd8a3d845e | ||
|
|
66fc1dcf33 | ||
|
|
816f4907e3 | ||
|
|
d7e24b2494 | ||
|
|
d4a957ca16 | ||
|
|
e08e6c182c | ||
|
|
1ca0b85196 | ||
|
|
df57e7ab93 | ||
|
|
fa02f3a108 | ||
|
|
360397b2ed | ||
|
|
fa944fc526 | ||
|
|
df6e75e1d6 | ||
|
|
c49935d91c | ||
|
|
85082ea509 | ||
|
|
47731c75fc | ||
|
|
b5481edfd7 | ||
|
|
1325a81e9a | ||
|
|
18b22f5f8a | ||
|
|
d609d2d2ad | ||
|
|
503c368f9e | ||
|
|
2848d1caaf | ||
|
|
a6d13f290b | ||
|
|
b6cad08273 | ||
|
|
7f423016f0 | ||
|
|
a41603ed85 | ||
|
|
f93431b43e | ||
|
|
f5a03102d8 | ||
|
|
e0e30ead58 | ||
|
|
0f208fb36b | ||
|
|
94fdcabac9 | ||
|
|
4f07abe655 | ||
|
|
bc01b6b4ad | ||
|
|
8783ccfd72 | ||
|
|
92615247ac | ||
|
|
78ed01f3ef | ||
|
|
232862ae08 | ||
|
|
285e04c77e | ||
|
|
70f8840fbd | ||
|
|
8d0d2015d7 | ||
|
|
cf11a89457 | ||
|
|
732dfa63c7 | ||
|
|
b1ff5367e7 | ||
|
|
96fdb88690 | ||
|
|
3e992604c7 | ||
|
|
c866c48252 | ||
|
|
7b4d0168c0 |
11
.gitignore
vendored
11
.gitignore
vendored
@@ -14,19 +14,21 @@
|
||||
*.rej
|
||||
# OSX .DS_Store files
|
||||
.DS_Store
|
||||
# version scripts (repo master only)
|
||||
# version scripts (repo master only)
|
||||
.version*
|
||||
Thumbs.db
|
||||
|
||||
|
||||
## Ignore RedMatrix site specific files and folders
|
||||
## Ignore site specific files and folders
|
||||
.htconfig.php
|
||||
favicon.*
|
||||
addon/
|
||||
widget/
|
||||
custom/
|
||||
/store/
|
||||
# site apps
|
||||
apps/
|
||||
!doc/context/*/apps
|
||||
# default startpage
|
||||
home.html
|
||||
# page header plugin
|
||||
@@ -44,7 +46,8 @@ doc/html/
|
||||
.zotshrc
|
||||
# external repositories for themes/addons
|
||||
extend/
|
||||
|
||||
# files generated by phpunit
|
||||
tests/results/
|
||||
|
||||
## exclude IDE files
|
||||
# config files and folders from Eclipse
|
||||
@@ -63,6 +66,8 @@ nbproject/
|
||||
## composer
|
||||
# locally installed composer binary
|
||||
composer.phar
|
||||
# allow composer.lock, as it is required to have a common state
|
||||
!composer.lock
|
||||
# vendor/ is managed by composer, no need to include in our repository
|
||||
# requires new deployment and needs discussion first
|
||||
#vendor/
|
||||
|
||||
@@ -2,10 +2,19 @@
|
||||
|
||||
Run hubzilla-setup.sh for an unattended installation of hubzilla.
|
||||
|
||||
The script is known to work with Debian 8.3 stable (Jessie)
|
||||
The script is known to work without adjustments with
|
||||
|
||||
+ Home-PC (Debian-8.3.0-amd64)
|
||||
+ DigitalOcean droplet (Debian 8.3 x64 / 512 MB Memory / 20 GB Disk / NYC3)
|
||||
+ Hardware
|
||||
- Mini-PC with Debian-9.2-amd64, or
|
||||
- Rapberry 3 with Raspbian, Debian-9.3
|
||||
+ DynDNS
|
||||
- selfHOST.de
|
||||
- freedns.afraid.org
|
||||
|
||||
## Disclaimers
|
||||
|
||||
- This script does work with Debian 9 only.
|
||||
- This script has to be used on a fresh debian install only (it does not take account for a possibly already installed and configured webserver or sql implementation).
|
||||
|
||||
# Step-by-Step Overwiew
|
||||
|
||||
@@ -14,13 +23,13 @@ The script is known to work with Debian 8.3 stable (Jessie)
|
||||
Hardware
|
||||
|
||||
+ Internet connection and router at home
|
||||
+ Mini-pc connected to your router
|
||||
+ Mini-pc connected to your router (a Raspberry 3 will do for very small Hubs)
|
||||
+ USB drive for backups
|
||||
|
||||
Software
|
||||
|
||||
+ Fresh installation of Debian on your mini-pc
|
||||
+ Router with open ports 80 and 443 for your Debian
|
||||
+ Fresh installation of Debian 9 (Stretch)
|
||||
+ Router with open ports 80 and 443 for your Hub
|
||||
|
||||
## The basic steps (quick overview)
|
||||
|
||||
@@ -30,9 +39,12 @@ Software
|
||||
- mkdir -p /var/www
|
||||
- cd /var/www
|
||||
- git clone https://github.com/redmatrix/hubzilla.git html
|
||||
- cp .homeinstall/hubzilla-config.txt.template .homeinstall/hubzilla-config.txt
|
||||
- nano .homeinstall/hubzilla-config.txt
|
||||
- Enter your values there: db pass, domain, values for dyn DNS
|
||||
- cd /html/.homeinstall
|
||||
- cp hubzilla-config.txt.template hubzilla-config.txt
|
||||
- nano hubzilla-config.txt
|
||||
- Read the comments carefully
|
||||
- Enter your values: db pass, domain, values for dyn DNS
|
||||
- Make sure your your external drive (for backups) is mounted
|
||||
- hubzilla-setup.sh as root
|
||||
- ... wait, wait, wait until the script is finised
|
||||
- reboot
|
||||
@@ -46,23 +58,44 @@ Software
|
||||
|
||||
### Recommended: USB Drive for Backups
|
||||
|
||||
The installation will create a daily backup.
|
||||
The installation will create a daily backup written to an external drive.
|
||||
|
||||
If the backup process does not find an external device than the backup goes to
|
||||
the internal disk.
|
||||
The USB drive must be compatible with the filesystems
|
||||
|
||||
The USB drive must be compatible with an encrpyted filesystem LUKS + ext4.
|
||||
- ext4 (if you do not want to encrypt the USB)
|
||||
- LUKS + ext4 (if you want to encrypt the USB)
|
||||
|
||||
The backup includes
|
||||
|
||||
- Hubzilla DB
|
||||
- Hubzilla installation /var/www/html
|
||||
- Certificates for letsencrypt
|
||||
|
||||
## Preparations Software
|
||||
|
||||
### Install Debian Linux on the Mini-PC
|
||||
|
||||
Download the stable Debian at https://www.debian.org/
|
||||
Download the stable Debian at https://www.debian.org/
|
||||
(Debian 8 is no longer supported.)
|
||||
|
||||
Create bootable USB drive with Debian on it. You could use the programm
|
||||
unetbootin, https://en.wikipedia.org/wiki/UNetbootin
|
||||
Create bootable USB drive with Debian on it.You could use
|
||||
|
||||
Switch of your mini pc, plug in your USB drive and start the mini pc from the
|
||||
- unetbootin, https://en.wikipedia.org/wiki/UNetbootin
|
||||
- or simply the linux command "dd"
|
||||
|
||||
Example for command dd...
|
||||
|
||||
su -
|
||||
dd if=2017-11-29-raspbian-stretch.img of=/dev/mmcblk0
|
||||
|
||||
Do not forget to unmount the SD card before and check if unmounted like in this example...
|
||||
|
||||
su -
|
||||
umount /dev/mmcblk0*
|
||||
df -h
|
||||
|
||||
|
||||
Switch off your mini pc, plug in your USB drive and start the mini pc from the
|
||||
stick. Install Debian. Follow the instructions of the installation.
|
||||
|
||||
### Configure your Router
|
||||
@@ -79,28 +112,20 @@ You can use subdomains as well
|
||||
|
||||
my.cooldomain.org
|
||||
|
||||
There are two way to get a domain
|
||||
There are two ways to get a domain...
|
||||
|
||||
- buy a domain (recommended) or
|
||||
- register a free subdomain
|
||||
### Method 1: Buy a Domain
|
||||
|
||||
### Method 1: Get yourself an own Domain (recommended)
|
||||
...for example buy at selfHOST.de
|
||||
|
||||
...for example at selfHOST.de
|
||||
The cost are around 10,- € once and 1,50 € per month (2017).
|
||||
|
||||
### Method 2 Register a (free) Subdomain
|
||||
The cost are around 10,- € once and 1,50 € per month (2017).
|
||||
|
||||
Register a free subdomain for example at
|
||||
...for example register at freedns.afraid.org
|
||||
|
||||
- freeDNS
|
||||
- selfHOST
|
||||
Follow the instructions in .homeinstall/hubzilla-config.txt.
|
||||
|
||||
WATCH THIS: A free subdomain is not the prefered way to get a domain name. Why?
|
||||
|
||||
Let's encrpyt issues a limited number of certificates each
|
||||
day. Possibly other users of this domain will try to issue a certificate
|
||||
at the same day as you do. So make sure you choose a domain with as less subdomains as
|
||||
possible.
|
||||
|
||||
## Install Hubzilla on your Debian
|
||||
|
||||
@@ -135,10 +160,12 @@ Copy the template file
|
||||
|
||||
cp hubzilla-config.txt.template hubzilla-config.txt
|
||||
|
||||
Change the file "hubzilla-config.txt". Read the instructions there and enter your values.
|
||||
Modify the file "hubzilla-config.txt". Read the instructions there carefully and enter your values.
|
||||
|
||||
nano hubzilla-config.txt
|
||||
|
||||
Make sure your external drive (for backups) is plugged in and can be mounted as configured in "hubzilla-config.txt". Otherwise the daily backups will not work.
|
||||
|
||||
Run the script
|
||||
|
||||
./hubzilla-setup.sh
|
||||
@@ -146,7 +173,7 @@ Run the script
|
||||
Wait... The script should not finish with an error message.
|
||||
|
||||
In a webbrowser open your domain.
|
||||
Expected: A test page of hubzilla is shown. All checks there shoulg be
|
||||
Expected: A test page of hubzilla is shown. All checks there should be
|
||||
successfull. Go on...
|
||||
Expected: A page for the Hubzilla server configuration shows up.
|
||||
|
||||
@@ -162,3 +189,28 @@ Leave db type "MySQL" untouched.
|
||||
|
||||
Follow the instructions in the next pages.
|
||||
|
||||
After the daily script was executed at 05:30 (am)
|
||||
|
||||
- look at var/www/html/hubzilla-daily.log
|
||||
- check your backup on the external drive
|
||||
- optionally view the daily log under yourdomain.org/admin/logs/
|
||||
- set the logfile to var/www/html/hubzilla-daily.log
|
||||
|
||||
## Note for the Rasperry
|
||||
|
||||
The script was tested with an Raspberry 3 under Raspian (Debian 9.3, 2017-11-29-raspbian-stretch.img).
|
||||
|
||||
It is recommended to deinstall these programms to avoid endless updates. Use...
|
||||
|
||||
sudo apt-get purge wolfram-engine sonic-pi
|
||||
sudo apt-get autoremove
|
||||
|
||||
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!
|
||||
|
||||
|
||||
|
||||
@@ -70,15 +70,17 @@ selfhost_pass=
|
||||
# freedns_key=U1Z6aGt2R0NzMFNPNWRjbWxxZGpsd093OjE1Mzg5NDE5
|
||||
#
|
||||
#
|
||||
#freedns_key=
|
||||
freedns_key=
|
||||
|
||||
|
||||
###############################################
|
||||
### OPTIONAL - Backup to external device ######
|
||||
#
|
||||
# The script can use an external device for the daily backup.
|
||||
# The file system of the device (USB stick for example) must be compatible
|
||||
# with encrypted LUKS + ext4
|
||||
# The file system of the device (USB stick for example) must be compatible with
|
||||
#
|
||||
# - encrypted LUKS + ext4, or
|
||||
# - ext4
|
||||
#
|
||||
# You should test to mount the device befor you run the script
|
||||
# (hubzilla-setup.sh).
|
||||
@@ -113,27 +115,21 @@ selfhost_pass=
|
||||
# lsof /media/hubzilla_backup
|
||||
#
|
||||
# If you leave the following parameters
|
||||
#
|
||||
# - "backup_device_name" and
|
||||
# - "backup_device_pass"
|
||||
#
|
||||
# empty the script will create daily backups on the internal disk (which could
|
||||
# save you as well).
|
||||
#
|
||||
# Example: backup_device_name=/dev/sdc1
|
||||
#
|
||||
# Leave "backup_device_pass=" empty if the external device is not encrypted.
|
||||
#
|
||||
backup_device_name=
|
||||
backup_device_pass=
|
||||
|
||||
|
||||
###############################################
|
||||
### OPTIONAL - Owncloud - deprecated ##########
|
||||
#
|
||||
# To install owncloud: owncloud=y
|
||||
# Leave empty if you don't want to install owncloud
|
||||
#
|
||||
#owncloud=
|
||||
|
||||
|
||||
|
||||
###############################################
|
||||
### OPTIONAL - do not mess with things below ##
|
||||
# (...if you are not certain)
|
||||
@@ -160,18 +156,3 @@ mysqlpass=$db_pass
|
||||
# Example: phpmyadminpass="aber hallo has blanks in it"
|
||||
phpmyadminpass=$db_pass
|
||||
|
||||
# TODO Prepare hubzilla for programmers
|
||||
# - install eclipse and plugins
|
||||
# - install xdebug to debug the php with eclipse
|
||||
# - weaken permissions on /var/www/html
|
||||
# - manual steps after this script
|
||||
# * in eclipse: install plugins for php git hub
|
||||
# * in eclipse: configure firefox (chrome,...) as browser to run with the php debuger
|
||||
# * in eclipse: switch php debugger from zend to xdebug
|
||||
# * in eclipse: add local hubzilla github repository
|
||||
#
|
||||
# Which user will use eclipse?
|
||||
# Leave this empty if you do not want to prepare hubzilla for debugging
|
||||
#
|
||||
#developer_name=
|
||||
|
||||
|
||||
@@ -114,7 +114,11 @@ function check_sanity {
|
||||
fi
|
||||
if [ ! -f /etc/debian_version ]
|
||||
then
|
||||
die "Ubuntu is not supported"
|
||||
die "Debian is supported only"
|
||||
fi
|
||||
if ! grep -q 'Linux 9' /etc/issue
|
||||
then
|
||||
die "Linux 9 (stretch) is supported only"x
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -253,11 +257,11 @@ function install_sendmail {
|
||||
}
|
||||
|
||||
function install_php {
|
||||
# openssl and mbstring are included in libapache2-mod-php5
|
||||
# to_to: php5-suhosin
|
||||
# openssl and mbstring are included in libapache2-mod-php
|
||||
print_info "installing php..."
|
||||
nocheck_install "libapache2-mod-php5 php5 php-pear php5-xcache php5-curl php5-mcrypt php5-gd"
|
||||
php5enmod mcrypt
|
||||
nocheck_install "libapache2-mod-php php php-pear php-curl php-mcrypt php-gd"
|
||||
sed -i "s/^upload_max_filesize =.*/upload_max_filesize = 100M/g" /etc/php/7.0/apache2/php.ini
|
||||
sed -i "s/^post_max_size =.*/post_max_size = 100M/g" /etc/php/7.0/apache2/php.ini
|
||||
}
|
||||
|
||||
function install_mysql {
|
||||
@@ -277,18 +281,17 @@ function install_mysql {
|
||||
# want to be prompted for it then this can be arranged by preseeding the
|
||||
# DebConf database with the required information.
|
||||
#
|
||||
# echo mysql-server-5.5 mysql-server/root_password password xyzzy | debconf-set-selections
|
||||
# echo mysql-server-5.5 mysql-server/root_password_again password xyzzy | debconf-set-selections
|
||||
# echo mysql-server mysql-server/root_password password xyzzy | debconf-set-selections
|
||||
# echo mysql-server mysql-server/root_password_again password xyzzy | debconf-set-selections
|
||||
#
|
||||
print_info "installing mysql..."
|
||||
if [ -z "$mysqlpass" ]
|
||||
then
|
||||
die "mysqlpass not set in $configfile"
|
||||
fi
|
||||
echo mysql-server-5.5 mysql-server/root_password password $mysqlpass | debconf-set-selections
|
||||
echo mysql-server-5.5 mysql-server/root_password_again password $mysqlpass | debconf-set-selections
|
||||
nocheck_install "php5-mysql mysql-server mysql-client"
|
||||
php5enmod mcrypt
|
||||
echo mysql-server mysql-server/root_password password $mysqlpass | debconf-set-selections
|
||||
echo mysql-server mysql-server/root_password_again password $mysqlpass | debconf-set-selections
|
||||
nocheck_install "php-mysql mysql-server mysql-client"
|
||||
}
|
||||
|
||||
function install_phpmyadmin {
|
||||
@@ -327,6 +330,7 @@ function install_phpmyadmin {
|
||||
echo "Include /etc/phpmyadmin/apache.conf" >> /etc/apache2/apache2.conf
|
||||
fi
|
||||
service apache2 restart
|
||||
/etc/init.d/mysql start
|
||||
}
|
||||
|
||||
function create_hubzilla_db {
|
||||
@@ -455,11 +459,6 @@ function configure_cron_selfhost {
|
||||
fi
|
||||
}
|
||||
|
||||
function install_git {
|
||||
print_info "installing git..."
|
||||
nocheck_install "git"
|
||||
}
|
||||
|
||||
function install_letsencrypt {
|
||||
print_info "installing let's encrypt ..."
|
||||
# check if user gave domain
|
||||
@@ -511,6 +510,8 @@ END
|
||||
then
|
||||
die "Failed to load $url_http"
|
||||
fi
|
||||
# accept terms of service of letsencrypt
|
||||
./dehydrated --register --accept-terms
|
||||
# run script dehydrated
|
||||
#
|
||||
./dehydrated --cron --config $le_dir/config.sh
|
||||
@@ -564,17 +565,13 @@ function check_https {
|
||||
}
|
||||
|
||||
function install_hubzilla {
|
||||
print_info "installing hubzilla..."
|
||||
# rm -R /var/www/html/ # for "stand alone" usage
|
||||
cd /var/www/
|
||||
# git clone https://github.com/redmatrix/hubzilla html # for "stand alone" usage
|
||||
cd html/
|
||||
git clone https://github.com/redmatrix/hubzilla-addons addon
|
||||
print_info "installing hubzilla addons..."
|
||||
cd /var/www/html/
|
||||
util/add_addon_repo https://github.com/redmatrix/hubzilla-addons.git hzaddons
|
||||
mkdir -p "store/[data]/smarty3"
|
||||
chmod -R 777 store
|
||||
touch .htconfig.php
|
||||
chmod ou+w .htconfig.php
|
||||
install_hubzilla_plugins
|
||||
cd /var/www/
|
||||
chown -R www-data:www-data html
|
||||
chown root:www-data /var/www/html/
|
||||
@@ -589,73 +586,6 @@ function install_hubzilla {
|
||||
print_info "installed hubzilla"
|
||||
}
|
||||
|
||||
function install_hubzilla_plugins {
|
||||
print_info "installing hubzilla plugins..."
|
||||
cd /var/www/html
|
||||
plugin_install=.homeinstall/plugin_install.txt
|
||||
theme_install=.homeinstall/theme_install.txt
|
||||
# overwrite script to update the plugin and themes
|
||||
rm -f $plugins_update
|
||||
echo "cd /var/www/html" >> $plugins_update
|
||||
###################
|
||||
# write plugin file
|
||||
if [ ! -f "$plugin_install" ]
|
||||
then
|
||||
echo "# To install a plugin" >> $plugin_install
|
||||
echo "# 1. add the plugin in a new line and run" >> $plugin_install
|
||||
echo "# 2. run" >> $plugin_install
|
||||
echo "# cd /var/www/html/.homeinstall" >> $plugin_install
|
||||
echo "# ./hubzilla-setup.sh" >> $plugin_install
|
||||
echo "https://gitlab.com/zot/ownmapp.git ownMapp" >> $plugin_install
|
||||
echo "https://gitlab.com/zot/hubzilla-chess.git chess" >> $plugin_install
|
||||
fi
|
||||
# install plugins
|
||||
while read -r line; do
|
||||
[[ "$line" =~ ^#.*$ ]] && continue
|
||||
p_url=$(echo $line | awk -F' ' '{print $1}')
|
||||
p_name=$(echo $line | awk -F' ' '{print $2}')
|
||||
# basic check of format
|
||||
if [ ${#p_url} -ge 1 ] && [ ${#p_name} -ge 1 ]
|
||||
then
|
||||
# install addon
|
||||
util/add_addon_repo $line
|
||||
util/update_addon_repo $p_name # not sure if this line is neccessary
|
||||
echo "util/update_addon_repo $p_name" >> $plugins_update
|
||||
else
|
||||
print_info "skipping installation of a plugin from file $plugin_install - something wrong with format in line: $line"
|
||||
fi
|
||||
done < "$plugin_install"
|
||||
###################
|
||||
# write theme file
|
||||
if [ ! -f "$theme_install" ]
|
||||
then
|
||||
echo "# To install a theme" >> $theme_install
|
||||
echo "# 1. add the theme in a new line and run" >> $theme_install
|
||||
echo "# 2. run" >> $theme_install
|
||||
echo "# cd /var/www/html/.homeinstall" >> $theme_install
|
||||
echo "# ./hubzilla-setup.sh" >> $theme_install
|
||||
echo "https://github.com/DeadSuperHero/hubzilla-themes.git DeadSuperHeroThemes" >> $theme_install
|
||||
|
||||
fi
|
||||
# install plugins
|
||||
while read -r line; do
|
||||
[[ "$line" =~ ^#.*$ ]] && continue
|
||||
p_url=$(echo $line | awk -F' ' '{print $1}')
|
||||
p_name=$(echo $line | awk -F' ' '{print $2}')
|
||||
# basic check of format
|
||||
if [ ${#p_url} -ge 1 ] && [ ${#p_name} -ge 1 ]
|
||||
then
|
||||
# install addon
|
||||
util/add_theme_repo $line
|
||||
util/update_theme_repo $p_name # not sure if this line is neccessary
|
||||
echo "util/update_theme_repo $p_name" >> $plugins_update
|
||||
else
|
||||
print_info "skipping installation of a theme from file $theme_install - something wrong with format in line: $line"
|
||||
fi
|
||||
done < "$theme_install"
|
||||
print_info "installed hubzilla plugins and themes"
|
||||
}
|
||||
|
||||
function rewrite_to_https {
|
||||
print_info "configuring apache to redirect http to httpS ..."
|
||||
htaccessfile=/var/www/html/.htaccess
|
||||
@@ -675,25 +605,19 @@ function rewrite_to_https {
|
||||
function install_rsnapshot {
|
||||
print_info "installing rsnapshot..."
|
||||
nocheck_install "rsnapshot"
|
||||
# internal disk
|
||||
cp -f /etc/rsnapshot.conf $snapshotconfig
|
||||
sed -i "/hourly/s/retain/#retain/" $snapshotconfig
|
||||
sed -i "/monthly/s/#retain/retain/" $snapshotconfig
|
||||
# internal disk
|
||||
cp -f /etc/rsnapshot.conf $snapshotconfig
|
||||
sed -i "s/^cmd_cp/#cmd_cp/" $snapshotconfig
|
||||
sed -i "s/^backup/#backup/" $snapshotconfig
|
||||
if [ -z "`grep 'letsencrypt' $snapshotconfig`" ]
|
||||
then
|
||||
echo "backup /var/lib/mysql/ localhost/" >> $snapshotconfig
|
||||
echo "backup /var/www/html/ localhost/" >> $snapshotconfig
|
||||
echo "backup /var/www/letsencrypt/ localhost/" >> $snapshotconfig
|
||||
fi
|
||||
echo "backup /var/lib/mysql/ localhost/" >> $snapshotconfig
|
||||
echo "backup /var/www/html/ localhost/" >> $snapshotconfig
|
||||
echo "backup /var/www/letsencrypt/ localhost/" >> $snapshotconfig
|
||||
# external disk
|
||||
if [ -n "$backup_device_name" ] && [ -n "$backup_device_pass" ]
|
||||
if [ -n "$backup_device_name" ]
|
||||
then
|
||||
cp -f /etc/rsnapshot.conf $snapshotconfig_external_device
|
||||
sed -i "s#snapshot_root.*#snapshot_root $backup_mount_point#" $snapshotconfig_external_device
|
||||
sed -i "/hourly/s/retain/#retain/" $snapshotconfig_external_device
|
||||
sed -i "/monthly/s/#retain/retain/" $snapshotconfig_external_device
|
||||
sed -i "/alpha/s/6/30/" $snapshotconfig_external_device
|
||||
sed -i "s/^cmd_cp/#cmd_cp/" $snapshotconfig_external_device
|
||||
sed -i "s/^backup/#backup/" $snapshotconfig_external_device
|
||||
if [ -z "`grep 'letsencrypt' $snapshotconfig_external_device`" ]
|
||||
@@ -767,9 +691,7 @@ echo " if mount $backup_device_name $backup_mount_point" >> /var/www/$hub
|
||||
echo " then" >> /var/www/$hubzilladaily
|
||||
echo " device_mounted=1" >> /var/www/$hubzilladaily
|
||||
echo " echo \"device $backup_device_name is now mounted. Starting backup...\"" >> /var/www/$hubzilladaily
|
||||
echo " rsnapshot -c $snapshotconfig_external_device daily" >> /var/www/$hubzilladaily
|
||||
echo " rsnapshot -c $snapshotconfig_external_device weekly" >> /var/www/$hubzilladaily
|
||||
echo " rsnapshot -c $snapshotconfig_external_device monthly" >> /var/www/$hubzilladaily
|
||||
echo " rsnapshot -c $snapshotconfig_external_device alpha" >> /var/www/$hubzilladaily
|
||||
echo " echo \"\$(date) - disk sizes...\"" >> /var/www/$hubzilladaily
|
||||
echo " df -h" >> /var/www/$hubzilladaily
|
||||
echo " echo \"\$(date) - db size...\"" >> /var/www/$hubzilladaily
|
||||
@@ -788,28 +710,22 @@ echo " fi" >> /var/www/$hubzilladaily
|
||||
echo "fi" >> /var/www/$hubzilladaily
|
||||
echo "if [ \$device_mounted == 0 ]" >> /var/www/$hubzilladaily
|
||||
echo "then" >> /var/www/$hubzilladaily
|
||||
echo " echo \"device could not be mounted $backup_device_name. Using internal disk for backup...\"" >> /var/www/$hubzilladaily
|
||||
echo " rsnapshot -c $snapshotconfig daily" >> /var/www/$hubzilladaily
|
||||
echo " rsnapshot -c $snapshotconfig weekly" >> /var/www/$hubzilladaily
|
||||
echo " rsnapshot -c $snapshotconfig monthly" >> /var/www/$hubzilladaily
|
||||
echo " echo \"device could not be mounted $backup_device_name. No backup written.\"" >> /var/www/$hubzilladaily
|
||||
echo "fi" >> /var/www/$hubzilladaily
|
||||
echo "#" >> /var/www/$hubzilladaily
|
||||
echo "echo \"\$(date) - db size...\"" >> /var/www/$hubzilladaily
|
||||
echo "du -h /var/cache/rsnapshot/ | grep mysql/hubzilla" >> /var/www/$hubzilladaily
|
||||
echo "du -h /var/lib/mysql/ | grep mysql/hubzilla" >> /var/www/$hubzilladaily
|
||||
echo "#" >> /var/www/$hubzilladaily
|
||||
echo "# update" >> /var/www/$hubzilladaily
|
||||
echo "echo \"\$(date) - updating dehydrated...\"" >> /var/www/$hubzilladaily
|
||||
echo "git -C /var/www/letsencrypt/ pull" >> /var/www/$hubzilladaily
|
||||
echo "echo \"\$(date) - updating hubhilla core...\"" >> /var/www/$hubzilladaily
|
||||
echo "git -C /var/www/html/ pull" >> /var/www/$hubzilladaily
|
||||
echo "echo \"\$(date) - updating hubhilla addons...\"" >> /var/www/$hubzilladaily
|
||||
echo "git -C /var/www/html/addon/ pull" >> /var/www/$hubzilladaily
|
||||
echo "bash /var/www/html/$plugins_update" >> /var/www/$hubzilladaily
|
||||
echo "(cd /var/www/html/ ; util/udall)" >> /var/www/$hubzilladaily
|
||||
echo "chown -R www-data:www-data /var/www/html/ # make all accessable for the webserver" >> /var/www/$hubzilladaily
|
||||
echo "chown root:www-data /var/www/html/.htaccess" >> /var/www/$hubzilladaily
|
||||
echo "chmod 0644 /var/www/html/.htaccess # www-data can read but not write it" >> /var/www/$hubzilladaily
|
||||
echo "echo \"\$(date) - updating linux...\"" >> /var/www/$hubzilladaily
|
||||
echo "apt-get -q -y update && apt-get -q -y dist-upgrade # update linux and upgrade" >> /var/www/$hubzilladaily
|
||||
echo "apt-get -q -y update && apt-get -q -y dist-upgrade && apt-get -q -y autoremove # update linux and upgrade" >> /var/www/$hubzilladaily
|
||||
echo "echo \"\$(date) - Backup hubzilla and update linux finished. Rebooting...\"" >> /var/www/$hubzilladaily
|
||||
echo "#" >> /var/www/$hubzilladaily
|
||||
echo "reboot" >> /var/www/$hubzilladaily
|
||||
@@ -894,7 +810,6 @@ install_run_selfhost
|
||||
ping_domain
|
||||
configure_cron_freedns
|
||||
configure_cron_selfhost
|
||||
install_git
|
||||
install_letsencrypt
|
||||
configure_apache_for_https
|
||||
check_https
|
||||
|
||||
186
.travis.yml
186
.travis.yml
@@ -1,44 +1,178 @@
|
||||
#
|
||||
# Travis-CI configuration file for Hubzilla
|
||||
#
|
||||
## configure things
|
||||
#
|
||||
|
||||
# see http://about.travis-ci.org/docs/user/languages/php/ for more hints
|
||||
language: php
|
||||
|
||||
# list any PHP version you want to test against
|
||||
# use newer 'trusty' based distro, old one is 'precise'
|
||||
dist: trusty
|
||||
# use docker based containers
|
||||
sudo: false
|
||||
|
||||
# Git branches whitelist to build on Travis CI
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- dev
|
||||
# whitelist our tags for release deployments e.g. 2.2
|
||||
- /^\d+\.\d+(\.\d+)?(-\S*)?$/
|
||||
|
||||
# Install additional software
|
||||
addons:
|
||||
# Install dependencies for generating API documentation with doxygen
|
||||
apt:
|
||||
packages:
|
||||
- doxygen
|
||||
- doxygen-latex
|
||||
- graphviz
|
||||
- ttf-liberation
|
||||
|
||||
# enable and start databases on a per job basis
|
||||
#services:
|
||||
# - mariadb
|
||||
# - postgresql
|
||||
|
||||
# any PHP version we want to test against, current stable phpunit requires PHP >= 7.0
|
||||
php:
|
||||
# using major version aliases
|
||||
- '7.0'
|
||||
- '7.1'
|
||||
- '7.2'
|
||||
# HHVM does not fulfil PHPUnit platform requirements as being compatible with PHP7 yet
|
||||
#- 'hhvm'
|
||||
|
||||
# aliased to a recent 5.6.x version
|
||||
- 5.6
|
||||
# aliased to a recent 7.x version
|
||||
- 7.0
|
||||
# aliased to a recent hhvm version
|
||||
- hhvm
|
||||
# list of environments to test
|
||||
env:
|
||||
global:
|
||||
# used for doxygen deployment script
|
||||
- DOXYFILE: $TRAVIS_BUILD_DIR/util/Doxyfile
|
||||
# Uncomment if a newer/specific version of Doxygen should be used
|
||||
#- DOXY_VER: 1.8.12
|
||||
# Code Coverage is slow, no need to have it in every build
|
||||
- PHPUCOV: "--no-coverage"
|
||||
# use matrix only for PHP and MySQL, all other combinations added through includes
|
||||
matrix:
|
||||
# trusty default MySQL 5.6
|
||||
- DB=mysql MYSQL_VERSION=5.6
|
||||
|
||||
# optionally specify a list of environments, for example to test different RDBMS
|
||||
#env:
|
||||
# - DB=mysql
|
||||
# - DB=pgsql
|
||||
|
||||
# optionally set up exclutions and allowed failures in the matrix
|
||||
# Matrix configuration details
|
||||
matrix:
|
||||
fast_finish: true
|
||||
# Additional check combinations
|
||||
include:
|
||||
# PHP7.1, mariadb 10.1
|
||||
- php: '7.1'
|
||||
env: DB=mariadb MARIADB_VERSION=10.1 CODECOV=1
|
||||
# use mariadb instead of MySQL
|
||||
addons:
|
||||
mariadb: '10.1'
|
||||
# PHP7.1, PostgreSQL 9.6
|
||||
- php: '7.1'
|
||||
env: DB=pgsql POSTGRESQL_VERSION=9.6 PHPUNITFILE=phpunit-pgsql.xml
|
||||
# Use newer postgres than 9.2 default
|
||||
addons:
|
||||
postgresql: '9.6'
|
||||
services:
|
||||
- postgresql
|
||||
# PHP7.1, old precise distribution with MySQL 5.5
|
||||
- php: '7.1'
|
||||
env: DB=mysql MYSQL_VERSION=5.5
|
||||
dist: precise
|
||||
services:
|
||||
- mysql
|
||||
# MySQL 5.7 with Docker container
|
||||
- php: '7.1'
|
||||
env: DB=mysql MYSQL_VERSION=5.7
|
||||
sudo: required
|
||||
services:
|
||||
- docker
|
||||
# Excludes from default matrix combinations
|
||||
# exclude:
|
||||
# - php: hhvm
|
||||
# env: DB=pgsql # PDO driver for pgsql is unsupported by HHVM (3rd party install for support)
|
||||
allow_failures:
|
||||
- php: hhvm
|
||||
|
||||
# cache composer downloads between runs
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/.composer/cache
|
||||
#- $HOME/doxygen/doxygen-$DOXY_VER/bin
|
||||
|
||||
|
||||
|
||||
#
|
||||
## execute things
|
||||
#
|
||||
|
||||
before_install:
|
||||
- travis_retry composer self-update
|
||||
# Start MySQL 5.7 Docker container, needs some time to come up
|
||||
- if [[ "$MYSQL_VERSION" == "5.7" ]]; then sudo service mysql stop; docker run -d -p 3306:3306 -e MYSQL_ALLOW_EMPTY_PASSWORD=yes mysql:5.7 && sleep 25 && docker ps; fi
|
||||
|
||||
# Install composer dev libs
|
||||
install:
|
||||
- travis_retry composer install --optimize-autoloader --no-progress
|
||||
|
||||
# execute any number of scripts before the test run, custom env's are available as variables
|
||||
#before_script:
|
||||
# - if [[ "$DB" == "pgsql" ]]; then psql -c "DROP DATABASE IF EXISTS hello_world_test;" -U postgres; fi
|
||||
# - if [[ "$DB" == "pgsql" ]]; then psql -c "create database hello_world_test;" -U postgres; fi
|
||||
# - if [[ "$DB" == "mysql" ]]; then mysql -e "create database IF NOT EXISTS hello_world_test;" -uroot; fi
|
||||
|
||||
install:
|
||||
- composer require phpunit/phpunit
|
||||
before_script:
|
||||
# Use code coverage config for phpunit
|
||||
- if [[ ! -z $CODECOV ]]; then export PHPUCOV=""; fi
|
||||
# Some preparation tasks of environment
|
||||
- ./tests/travis/prepare.sh
|
||||
# DB specific prepare scripts
|
||||
- if [[ "$DB" == "mysql" ]]; then ./tests/travis/prepare_mysql.sh; fi
|
||||
- if [[ "$DB" == "mariadb" ]]; then ./tests/travis/prepare_mysql.sh; fi
|
||||
- if [[ "$DB" == "pgsql" ]]; then ./tests/travis/prepare_pgsql.sh; fi
|
||||
|
||||
# omitting "script:" will default to phpunit
|
||||
# use the $DB env variable to determine the phpunit.xml to use
|
||||
script: vendor/bin/phpunit tests/unit/
|
||||
script:
|
||||
- ./vendor/bin/phpunit $PHPUCOV -c tests/$PHPUNITFILE
|
||||
|
||||
after_success:
|
||||
- cat tests/results/testdox.txt
|
||||
# Generate API documentation and prepare for deployment
|
||||
- ./tests/travis/gen_apidocs.sh
|
||||
after_failure:
|
||||
- cat tests/results/testdox.txt
|
||||
|
||||
# Deploying release and API documentation to GitHub
|
||||
before_deploy:
|
||||
- if [[ "$CODECOV" == "1" ]]; then zip -9 -r -q tests/hubzilla-testresults.zip tests/results; fi
|
||||
deploy:
|
||||
- provider: pages
|
||||
skip_cleanup: true
|
||||
local_dir: $TRAVIS_BUILD_DIR/doc/html
|
||||
github_token: $GH_TOKEN
|
||||
on:
|
||||
repo: redmatrix/hubzilla
|
||||
branch: master
|
||||
condition: '(-n "$GH_TOKEN") && ("$TRAVIS_JOB_NUMBER" == "${TRAVIS_BUILD_NUMBER}.1")'
|
||||
# add API documentation to release, could also be used to provide full packages if we want to drop vendor from our repo
|
||||
- provider: releases
|
||||
skip_cleanup: true
|
||||
api_key: $GH_TOKEN
|
||||
file: 'doc/hubzilla-api-documentation.zip'
|
||||
on:
|
||||
repo: redmatrix/hubzilla
|
||||
tags: true
|
||||
condition: '(-n "$GH_TOKEN") && ("$TRAVIS_JOB_NUMBER" == "${TRAVIS_BUILD_NUMBER}.1")'
|
||||
# add code coverage and test results to release
|
||||
- provider: releases
|
||||
skip_cleanup: true
|
||||
api_key: $GH_TOKEN
|
||||
file: 'tests/hubzilla-testresults.zip'
|
||||
on:
|
||||
repo: redmatrix/hubzilla
|
||||
tags: true
|
||||
condition: '(-n "$GH_TOKEN") && ("$CODECOV" == "1")'
|
||||
#after_deploy:
|
||||
|
||||
#after_script:
|
||||
|
||||
|
||||
|
||||
# configure notifications (email, IRC, campfire etc)
|
||||
notifications:
|
||||
#notifications:
|
||||
# irc: "irc.freenode.org#yourfavouriteroomfortravis"
|
||||
# a plugin/script to post to a hubzilla channel would be neat here
|
||||
|
||||
485
CHANGELOG
485
CHANGELOG
@@ -1,5 +1,488 @@
|
||||
Hubzilla 3.0 (2018-01-09)
|
||||
- Updated homeinstall script
|
||||
- Sort cloud directory by 1. is_dir and 2. name
|
||||
- Document that imagick calls/execs ffmpeg for mp4 video thumbnails
|
||||
- Use pipe_stream() instead of file_{get, put}_contents() in attach_store()
|
||||
- Make homeinstall script ready for Debian 9
|
||||
- Add url and headings to bbco_autocomplete()
|
||||
- Remove additional linebreaks after headings
|
||||
- html2bbcode: use headings bbcode for headings
|
||||
- Don't zidify all permalinks, only zot permalinks
|
||||
- Make remote homelink link to the home host and not to the home channel
|
||||
- Auto promote beginner (techlevel 0) accounts to level 1 after they show signs of active participation.
|
||||
- Go back to including the photo thumbnail data in the export file.
|
||||
- Improvements to file import/export
|
||||
- Default value for xlink_rating_text
|
||||
- Implement IMoveTarget and recursive file/directory move/rename - github issue #680
|
||||
- Synchronise an attach_move operation to clones
|
||||
- Provide a themed page with an error notification on errors instead of an obtuse XML error structure in mod cloud
|
||||
- Disallow backslashes in wiki and wiki-page names
|
||||
- We only require one update module. The rest are superfluous.
|
||||
- Render installable elements as buttons instead of links
|
||||
- Implement chunked uploads for photos page
|
||||
- Remove warning for large files on cloud upload
|
||||
- Add a filter for notification to show new posts only
|
||||
- Implement chunked uploads for cloud
|
||||
- Use httpsig auth for getfile
|
||||
- Load the profile images in the custom acl selector only if we actually need them
|
||||
- Rework liveUpdate() and notificationsUpdate() (aka ping) to first do the liveUpdate and when this is done only do the ping once.
|
||||
- Don't include invisible "update activities" in category widget
|
||||
- Default profile assign
|
||||
- Provide system config option for minimum registration age.
|
||||
- Remove deprecated $a argument from advanced_profile()
|
||||
- Change to bbcode calling parameters
|
||||
- Extra checking of server headers in upload functions
|
||||
- Provide a handler for chunked uploads in mod file_upload
|
||||
- Optional divider between item header and body
|
||||
- Allow toggle to SMBC scaling mode.
|
||||
- Add thumbnail hook
|
||||
- Implement SVG thumbnails and expose security setting
|
||||
- Implement video thumbnail generator
|
||||
- Implement pdf thumbnails
|
||||
- Implement thumbnail generator for epubs
|
||||
- Make browser history buttons work with ajax calls in mod display and hq
|
||||
- Implement tile view for mod cloud (read only)
|
||||
- Add mp3 audio thumbnail generator
|
||||
- Set display_path for photo_upload from the DAV File interface
|
||||
- Provide a generalised interface for thumbnail generators to support various content types
|
||||
- Add ID3Parser library.
|
||||
- Text thumbnails in cloud tile mode
|
||||
- Revisit media breakpoints - do not switch to mobile view to early.
|
||||
- Add French to help pages language dropdown selector
|
||||
- Inroduce the HQ module - an alternative landing page for hubzilla
|
||||
- Strip author name from notify messages in notifications - github issue #911
|
||||
- Remove column item.diaspora_meta
|
||||
- Provide ability to pin apps to navbar from mod apps
|
||||
- Add private forums to forum widget
|
||||
- Move notifications style to widgets.css
|
||||
- Sort out a few more large image upload issues
|
||||
- Move notifications full-screen handling to notifications widget
|
||||
- Move mailhost settings from plugin to core
|
||||
- Sort combined private mail conversations by latest updated conversation instead of created parent
|
||||
- Filter atokens on acl search
|
||||
- Allow a site to block (public) the directory separately from other resources.
|
||||
- Improve removed_channel final cleanup - github issue #386
|
||||
- Cleanup of upload_to_comments(
|
||||
- Dedicate the first click to slideup the cover again but make sure the nav buttons remain functional
|
||||
- Set os_syspath in DAV file put operation so that photos will scale correctly.
|
||||
- Unit tests for Zotlabs\Access classes
|
||||
- Bring back tabindex to submit comments
|
||||
- attach.php minor cleanup and doc
|
||||
- Allow cloud filenames to include ampersands without messing up auth tokens (zid, owt, and zat, and the constant placeholder 'f=')
|
||||
- Provide short localised summary for likes that will end up in displayed notifications
|
||||
- Improving Doxygen documentation.
|
||||
- Update item_normal() to not include ACTIVITY_OBJ_FILE obj_type
|
||||
- Sort out issues with pubstream item interactions
|
||||
- Don't perform zot_refresh on dead sites unless $force is set
|
||||
- Do not send message_list responses to dead sites (this delivery method bypassed the notifier)
|
||||
- Support for netselect query
|
||||
- Add another delivery control parameter (queue threshold)
|
||||
- Add some documentation about shareable widgets
|
||||
- Allow plugin class widgets
|
||||
- Some more work on unit tests
|
||||
- Encrypt the owa token
|
||||
- Bring back the markdown post feature
|
||||
- We call Theme:url() statically, make it also static.
|
||||
- Table structure for pseudo or proxy channels (pchan)
|
||||
|
||||
Bugfixes
|
||||
- Fix sync non-default profile photo changes to clones - github issue #113
|
||||
- Fix prev/next buttons on connedit can show deleted connections - github issue #673
|
||||
- Fix affinity widget settings
|
||||
- Fix dupe bug in content hooks - github issue #943
|
||||
- Fix directory keywords returned from dir_tagadelic() in standalone mode
|
||||
- Fix argument warning when arguments are correct in util/dcp
|
||||
- Fix issue with long filenames in mod cloud
|
||||
- Fix misc. issues with new 'insert photo from photo album' github issue #475
|
||||
- Fix regression in channel sources delivery
|
||||
- Fix loading of theme-specific widgets
|
||||
- Fix unable to add wiki pages with spaces
|
||||
- Fix mod display and others that require a non-zero profile_uid for updates
|
||||
- Fix various PHP 7.2 issues
|
||||
- Fix typo in HTTPSig
|
||||
- Fix pagetitle lost importing a pdl element from conversation
|
||||
- Fix js warning - getelementbyid (id doesn't exist)
|
||||
- Fix some pubstream on/off weirdness
|
||||
- Fix default addressbook has no name - github issue #921
|
||||
- Fix double html ids in caldav widget if more than one sharee
|
||||
- Fix regression in cdav calendar widget
|
||||
- Fix sync packet not generated when deleting a file using the web browser interface
|
||||
- Fix album cover thumb generator
|
||||
- Fix like-button for images - github issue #826
|
||||
- Fix typo - github issue #910
|
||||
- Fix issue with group_rmv()
|
||||
- Fix php warnings on photo delete
|
||||
- Fix some conflicts between private tags and forum tags
|
||||
- Fix some schema issues
|
||||
- Fix wiki pages not updating after creating new page
|
||||
- Fix a PHP warning in Permissions::FilledPerms()
|
||||
- Fix unicode characters in urls tripping up url regexes - github issue #901
|
||||
- Fix second half of github issue #893
|
||||
- Fix common connections on suggestion page showing wildly different results than remote profile, and is consistently off by one
|
||||
- Fix cloud redirects with owt tokens
|
||||
- Fix issues with diaspora xchans
|
||||
- Fix memory overflow trying to delete a connection with a very high noise to signal ratio
|
||||
- Fix sql error in page module
|
||||
- Fix unstar
|
||||
|
||||
Plugins/Addon
|
||||
Diaspora: fix 'view full size' photo link - core github issue #947
|
||||
Diaspora: implement recent changes in diaspora account_migration spec
|
||||
GNU-Social: fix uploading a photo to a post results in double post - github issue 75
|
||||
GNU-Social: fix gnusoc plugin not respecting delayed delivery - github issue 74
|
||||
Pubcrawl: fix PHP warning
|
||||
Diaspora: remove garbage from magic envelope
|
||||
Diaspora: fix permalinks for zot reshares
|
||||
New addon: hzfiles - sync files across hubzilla servers
|
||||
Fix various PHP 7.2 issues
|
||||
Remove Firefox social plugin - it was deprecated and removed in firefox version 57
|
||||
Diaspora: unset id and parent for local comments
|
||||
Pubsubhubbub: set interactive flag to avoid delivery killing if block_public is enabled
|
||||
Mailhost addon moved to core
|
||||
Remove js_upload addon
|
||||
|
||||
|
||||
Hubzilla 2.8.1 (2017-11-11)
|
||||
- Rename channel app events to calendar and add nav_set_selected() to /cal
|
||||
- Load notifications links to /display via ajax if we are already in /display
|
||||
- Add location info to the navbar for remote visitors
|
||||
- Bring back tabindex to submit comments
|
||||
- Add spanish translations for context help
|
||||
- Added mode to portfolio widget
|
||||
|
||||
Bugfixes
|
||||
- Fix os_syspath in DAV file put operation so that photos will scale correctly
|
||||
- Fix unicode characters in urls tripping up url regexes - github issue #901
|
||||
- Fix wiki pages not updating after creating new page
|
||||
- Fix notifications covered by cover photo on medium size screens - github issue #906
|
||||
- Fix unable to change permissions on wiki with space in name
|
||||
- Fix only show nav app link if we have a selected app
|
||||
- Fix unable to mark all messages read
|
||||
- Fix imagedata not set correctly if large photo and imagick is not installed
|
||||
- Fix issues with diaspora xchans
|
||||
- Fix profile photo issue triggered by a previous bug
|
||||
|
||||
Plugins/Addon
|
||||
N-S-F-W: improve the undocumented n-s-f-w author::word feature
|
||||
Diaspora: update the import_diaspora tool for the version 2.0 account export files
|
||||
Diaspora: fix comments are partly containing "diaspora_handle" instead of "author" - github issue #69
|
||||
Pubcrawl: provide feature setting for downgrade_media option
|
||||
Pubcrawl: fix issue where replies to replies did not find its parent
|
||||
Diaspora: fix friendica likes on comments
|
||||
Diaspora: fix private mail
|
||||
Diaspora: fix third party deletes/retractions not propagating
|
||||
Diaspora: likes not working - github issue #895 in core
|
||||
Diaspora: fix comments from unknown persons not accepted if allow public comments is enabled - github issue #68
|
||||
XMPP: fix php warning
|
||||
|
||||
Hubzilla 2.8 (2017-10-25)
|
||||
- Redirect to be moderated items to /moderate
|
||||
- Update notifications if notifications area remains open
|
||||
- Create an actual logout module instead of relying on internal variables
|
||||
- Add local_channel as a comanche condition variable
|
||||
- Implement possibility to pin app-tray apps in the navbar via app category navbar_default
|
||||
- Introduce custom navbars
|
||||
- Re-implement single delivery
|
||||
- Pdledit usability improvements
|
||||
- Implement next generation notifications in right aside
|
||||
- Implement single post view for /pubstream
|
||||
- Make anonymous comments work in mod display
|
||||
- Introduce notifications for unseen public stream posts (off by default)
|
||||
- Preperatory work on Zot VI
|
||||
- Add app for site admin
|
||||
- Introduce experimental alternate channel_menu navigation (off by default)
|
||||
- Introduce notifications for shared files
|
||||
- Bring back notifications for account approvals
|
||||
- Urlencode hashes from mod_acl
|
||||
- Don't use chanlink_url() for feed mentions
|
||||
- Design common friends widget to fit better in the app and move it to left aside
|
||||
- Allow navbar to be used when cover photo is displayed in mod channel
|
||||
- Implement admin setting to use imagick converter for large photos
|
||||
- Process activity deletes from OStatus which for whatever reason do not use the industry standard tombstone mechanism
|
||||
- Implement new css based spinner
|
||||
- Move the link header initialisation from Router to Webserver
|
||||
⁻ Extend activity_match() to work with arrays
|
||||
- Updated the trusted CA cert database
|
||||
- Ostatus - support likes of comments
|
||||
- Provide ability to mention a forum by using !forumname as well as the traditional red style (@forumname+)
|
||||
- Encrypt delivery reports (not backward compatible)
|
||||
- Provide a space between link header params (draft-cavage-http-signatures-08)
|
||||
- Turn common_friends into a widget
|
||||
- Update to jquery-3.2.1
|
||||
- Wiki pages sorted by name
|
||||
- Create new hooks for permissions_accept and permissions_reject
|
||||
- Provide rel=alternate link if no reshare content in post
|
||||
- Add remote login button to login page
|
||||
- DB update to add index to item.resource_id
|
||||
- Implement wiki editing (name and acl)
|
||||
- Provide a hook for importing a channel photo at channel creation time
|
||||
- Implement wiki mimetype lock
|
||||
- Bring back wiki downloads
|
||||
- Add text/plain mimetype to wiki
|
||||
- Implement per page mimetype selection for wikis
|
||||
- Added english context help for apps and appman
|
||||
- Implement owa (open web auth)
|
||||
- Ignore diaspora_meta column on item import
|
||||
- Check code permissions on cloud files
|
||||
- Remove period from characters allowed in username
|
||||
- Make comment highlighting more reliable
|
||||
- Sign zot-info packets with httpsignatures
|
||||
- Implement server to server magic auth
|
||||
- Provide support for json-ld signatures
|
||||
- Rewrite comment form open/close handling to be more reliable
|
||||
- Radically reduce code duplication in updateConvItems()
|
||||
- Remove discover tab in favour of the public stream app
|
||||
- Apply autotime to all autotime classed elements when static loading a page
|
||||
- Implement cards feature
|
||||
- Extended support for help page translations including table of contents files at the top level
|
||||
- Introduce util/dmkdir - a mkdir tool for DAV
|
||||
- Various doco improvements
|
||||
- Introduce util/dcp (DAV-copy) - copy file or directory from local system to Hubzilla
|
||||
- Provide support for HTTPsig
|
||||
- Implement mechanism for selective network following in protocol connectors (diaspora, ostatus, activitypub, zot, rss)
|
||||
|
||||
Bugfixes
|
||||
- Fix w2w posts not removed in contact_remove() - github issue #837
|
||||
- Fix guests not having a unique (non-existent) url
|
||||
- Fix mod register re-using the password
|
||||
- Fix write_storage permission not checked in /display
|
||||
- Fix discovery of moderated items in enotify
|
||||
- Fix profile thing image not deleted when thing deleted - github issue #868
|
||||
- Fix deletions to comments not synced on wall posts
|
||||
- Fix community tags not preserved on post edit - github issue #865
|
||||
- Fix profile photo propagation issue if the local xchan_photo_[l|m|s] fields were changed from the /photo/profile/l/n form to photo/[hash] form by a clone operation
|
||||
- Fix lockstate and current permissions not handed over to editor in mod card_edit
|
||||
- Fix profile edit dropdown for multiple profiles
|
||||
- Fix affinity slider spinner
|
||||
- Fix mod pubsites broken
|
||||
- Fix directory server admin selection includes known dead sites
|
||||
- Fix sticky-kit issue where the bottom of left aside was not visible when section content was short
|
||||
- Fix possibility to set bogus my_address
|
||||
- Fix deleting of wiki pages
|
||||
- Fix selected theme not appearing selected after change - github issue #855
|
||||
- Fix an issue where some encoded mids were not found in /display
|
||||
- Fix issue with mentions and xchans with @ or /
|
||||
- Fix webfinger returns invalid XML - github issue #851
|
||||
- Fix last remaining task in tasklist was not removed from view when completed
|
||||
|
||||
Plugins/Addon
|
||||
Hubwall: Remove errant $1 string in sender name
|
||||
Map federation protocols for zotinfo
|
||||
Gnusoc: force ostatus profile photos to get refreshed monthly
|
||||
Gnusoc: fix ostatus mention notifications
|
||||
Gnusoc: unsubscribe to gnusoc feeds if connector is disabled
|
||||
Phpmailer: not using load/unload
|
||||
Gnusoc: don't provide some information if gnusoc is disabled by the channel
|
||||
Diaspora: add a predelivery interval
|
||||
Diaspora: support for likes on comments
|
||||
Introduce the pubcrawl plugin - an unapologetically non-compliant ActivityPub Protocol implemention
|
||||
Introduce gravatar plugin
|
||||
Pubsubhubbub: produce much more compact PuSH feeds
|
||||
Diaspora: support text comments on reshare posts
|
||||
Diaspora: changes to delivery scenarios for the special handling of profile messages
|
||||
Diaspora: put diaspora seed_location in json webfinger
|
||||
Gnusoc: fix mis-attributed comments from mastodon
|
||||
Gnusoc: allow discovery by url (not just reddress) and permit upgrade from 'unknown' network to gnusoc
|
||||
Implement mechanism for selective network following in protocol connectors
|
||||
|
||||
|
||||
Hubzilla 2.6.3 (2017-09-18)
|
||||
- Fix anonymous comments/likes on photos - this is not yet implemented
|
||||
- Fix favicon not displayed on certain pages
|
||||
- Fix hubzilla logo icon for favicon and email notifications
|
||||
- Fix an issue with displaying selected theme in settings/display
|
||||
- [SECURITY] Restrict the input characters we accept in token verification strings to hex digits
|
||||
- Remove hubzilla.nl from fallback directory servers
|
||||
|
||||
Hubzilla 2.6.2 (2017-08-31)
|
||||
- Fix webfinger returns invalid XML (github issue #851)
|
||||
|
||||
|
||||
Hubzilla 2.6.1 (2017-08-18)
|
||||
- Fix a regression with dav clients
|
||||
- Raise install requirements
|
||||
|
||||
Plugins/Addon
|
||||
- Diaspora: fix PHP warning
|
||||
- GNU-Social: fix PHP warning
|
||||
|
||||
|
||||
Hubzilla 2.6 (2017-08-16)
|
||||
- Upgrade to bootstrap-4 beta
|
||||
- Consolidate disable_discover_tab config
|
||||
- Fix some bbcode to markdown conversion issues
|
||||
- Improved finding of recursive attachment permissions
|
||||
- Smaller line-height for notification badges
|
||||
- Bluegrid schema removed - will be added again if someone is willing to maintain it
|
||||
- Improved file_activity()
|
||||
- DB - add index for item.obj_type
|
||||
- Add options flag to bb_to_markdown() so we can distinguish between diaspora use and other use and therefore filter and adjust content selectively
|
||||
- Close the apps-menu if the notifications-menu is open and vice versa
|
||||
- Remove redundant call to jquery ready function in photo albums view
|
||||
- Remove borders from navbar toggler in mobile view
|
||||
- Improve the formatting of shares when converting from bbcode to markdown
|
||||
- Suppress fopen errors from dav
|
||||
- Make local channel (not our own) nav menus appear similar to what we are used from remote channels
|
||||
- Indicate the selected channel in the dropdown menu if the feature is enabled
|
||||
- Provide a mechanism to mark apps active in the app tray
|
||||
- Allow wildcard tag and category searches
|
||||
- Improved installer
|
||||
- Update some addon docs and ensure we only generate statistics once a day
|
||||
- Turn url requests where argv[0] is something.xyz into module='something' and $_REQUEST['module_format'] = 'xyz'; But leave modules beginning with . (like .well_known) alone (convert the initial . to _ and then strip it)
|
||||
- Turn platform name and std_version into config variables
|
||||
- Implement chunked uploads on the wall
|
||||
- Prevent expiration of conversations you are involved with
|
||||
- Update htmlpurifier to version 4.9.3
|
||||
- Update sabre/http to version 4.2.3
|
||||
- Add optimize-autoloader to composer config
|
||||
- Missing abook_{my,their}_perms in pg schema and missing keys in mysql schema
|
||||
- Provide a gender icon on the profile sidebar within reason
|
||||
- Provide more comprehensible information on the admin summary page
|
||||
- Upgrade blueimp from 9.8 to 9.18
|
||||
- Chanview - if already connected, bypass the chanview intermediary page and go straight to the remote profile.
|
||||
- Allow poke by xchan_hash
|
||||
- guess_image_type() - ignore scheme when checking for urls
|
||||
- Remove unused page_widgets.php include and provide a general function for loading sql from file
|
||||
- Migrate cdav from addons to core
|
||||
- Address several mail issues
|
||||
- Add files and photos to featured apps by default
|
||||
- import_author_zot() fixes
|
||||
- Remove deprecated app parameter from conversation()
|
||||
- Implement anonymous comments (like wordpress)
|
||||
- Add rel=noopener to all external target _blank links
|
||||
- Add 'can_comment_on_post' hook so we can better deal with the complications of Diaspora policy
|
||||
- Added Portfolio widget (requires foundation)
|
||||
- Convert schema_mysql engine to InnoDB and charset utf8mb4
|
||||
- Put unreachable federated connections in the archived tab of the connections list page
|
||||
- Indicate on connections page if a federated connection from another network is unavailable from the current location
|
||||
- Make authenticated oembeds optional, default to false.
|
||||
- Remove text_highlight css load from core
|
||||
- Numerous ostatus feed improvements (mastodon, gnu-social)
|
||||
- Provide hook when deleting a connection - we need this to clean up dangling PuSH subscriptions
|
||||
- Move code syntax highlighting to plugin
|
||||
- Oembed: ensure that width and height are returned as type int and not float
|
||||
- Rewrite wiki pages widget - no need for ajax on pageload, show the pages to not authenticated people.
|
||||
- Convert randprof to use chanlink_hash() instead of chanlink_url() and filter sys channels by xchan.xchan_system instead of xchan_addr != sys@%
|
||||
- Update Sabre libraries
|
||||
- Only provide "connected apps" on the settings menu if techlevel > 0.
|
||||
- Provide ability to search webpage
|
||||
- Move disapora xrd stuff to plugin
|
||||
- Deprecate server_role
|
||||
- Introduce automatic language selection for help, webpages, and wiki content
|
||||
- Provide ability to order apps in app-tray
|
||||
- Replace Markdownify library with html-to-markdown library
|
||||
|
||||
Bugfixes
|
||||
- Fix channel manager and nav channel select visible if in a delegate session
|
||||
- Fix wrong wiki pages in the sidebar github issue #841
|
||||
- Fix a bug where if multiple channels uploaded the same file to the same folder, the uploaded file would end up with an incremental number added to the filename for each upload even if the file did not exist yet in the channels folder
|
||||
- Fix privacy groups not syncing across clones properly (github issue #832)
|
||||
- Fix an issue where the ability to use a portion of the message-id to display a message wasn't honoured in all cases
|
||||
- Fix minor issues in the bs-default schema
|
||||
- Fix backward compatibility for album links generated in earlier times before the ambiguity of photo album names was solved (github issue #827)
|
||||
- Fix photo item comments not ported to bs4
|
||||
- Fix incorrect album link
|
||||
- Fix incorrect follow url in webfinger
|
||||
- Fix regression - allow position attributes in oembedable zcards
|
||||
- Fix affinitiy slider settings were being updated on any submit of of settings/featured
|
||||
- Fix minor weirdness in zot finger results after deleting a clone from a channel that was on a site which was previously migrated from http to https and still had the old hubloc
|
||||
- Fix cloud headers already sent issue
|
||||
- Partial fix for failure to sync photos - appears to be memory exhaustion and dependent on filesize although an unrelated issue was found with directory creation during file sync (we didn't check ownership when looking for duplicates)
|
||||
- Fix github issue #810
|
||||
- Don't allow negative age in directory listings
|
||||
- Fix allow setting a default schema for the hub (github issue #797) and allow selecting of focus (hubzilla default) schema if a default is set
|
||||
- Fix update_r1189() for mysql and postgres
|
||||
|
||||
Plugins/Addon
|
||||
Diaspora: Rewrite the addon to implemented Diaspora Version 2 federation protocol
|
||||
GNU-Social: GNU-Social and Mastodon compatibility was greatly increased and a "fetch conversations" feature added to try and locate missing contextual references and maintain conversations in posts from those networks
|
||||
Rename statistics_json to statistics and implement nodeinfo v2
|
||||
New authchoose addon to restrict what sites you authenticate to by default
|
||||
Cdav addon moved to core
|
||||
head_add_css() needs a preceding '/' to find files in the addons dir
|
||||
New addon code syntax highlighting (moved from core to addon)
|
||||
Pubsubhubbub: specify a minimum number of records - otherwise it defaults to zero
|
||||
|
||||
|
||||
Hubzilla 2.4 (2017-05-31)
|
||||
- Silence php warning during install
|
||||
- Implemented switch statement logic in Comanche layout parser
|
||||
- Don't allow html in plugin comment blocks
|
||||
- Handle Mastodon urls in markdown/bbcode conversion
|
||||
- Get rid of edit activities
|
||||
- Collapse sysapps if viewing a remote channel
|
||||
- Various Doxygen fixes
|
||||
- Update SimplePie library to version 1.5
|
||||
- Add check for PHP zip extension during install
|
||||
- Add unit tests for AccessList class
|
||||
- Authenticate onepoll so we can receive private posts/comments in zotfeed
|
||||
- Various postgres fixes
|
||||
- Some work on preparing clientside e2ee
|
||||
- Allow to set a default channel for the rare case where a default channel is not selected but channels actually exist
|
||||
- Support reverse magic-auth in oembed requests
|
||||
- Improved handling of Mastodon feeds
|
||||
- When template "none" is used in a webpage layout, then the contents of the page should be the sole output, with no other code before or after the page element content
|
||||
- If there is no site record, site_dead won't be 0, in a left join it will in fact be null. As long as it isn't 1, we should attempt delivery
|
||||
- Order wiki pages by creation date
|
||||
- Backend infrastructure for channel protection password; which will be used to optionally encrypt export files and resolve channel/identity ownership/hijacking disputes
|
||||
- Don't allow any null fields in notify creation
|
||||
- Webfinger cleanup
|
||||
- Envelope privacy
|
||||
- We do not parse the body in discover_by_url(), so no need to preserve iframes in SimplePie
|
||||
- Correct the mastodon "boost" (aka 'share') author attribution by checking for share activities and pulling the original author info from the activity:object
|
||||
- Only log zot_refresh content if json decode was successful
|
||||
- Revisit the import_author_zot algorithm yet again. There was one bug that we weren't returning necessary information in the first SQL query - and performance/loading problem if one tries to refresh a dead site
|
||||
- Import_author_xchan - since we rarely refresh zot-info for non-connections, force a cache reload once a week to catch things like profile photo updates and location changes
|
||||
- Create site_store_lowlevel() to initialise data structures for the site table
|
||||
- Change hook for perm_is_allowed while retaining backwards compatibility
|
||||
- import_author_zot() - check for both hubloc and xchan entries. This should catch and repair entries which were subject to transient storage failures
|
||||
- Import authors from any unrecognised network as network 'unknown'
|
||||
- Crypto update - default is now aes-256-ctr
|
||||
- Get rid of get_app()
|
||||
- Add 'author_is_pmable()' function with plugin hooks to control whether or not to display a 'send mail' link in the thread author menu
|
||||
- Provide platform specific install script
|
||||
- Allow for project specific DB updates
|
||||
- Get rid of davguest
|
||||
- Move db_upgrade to zlib
|
||||
- Add CSRF protection for import and import_items
|
||||
- Add some documentation for import functions
|
||||
- Do not allow creating two wikis with the same name
|
||||
- Update textcomplete library to version 1.8.0
|
||||
- Create channel_store_lowlevel()
|
||||
- Allow setting the system email name/address/reply
|
||||
- Use the same host macro for sender address as for reply_to address
|
||||
- Use the relevant attach directory/path for photo albums instead of an album basename which may not be unique. Created an 'ellipsify()' function to shorten long names and keep the beginning and end intact
|
||||
- Simplify the message signing spaghetti
|
||||
- Class MarkdownSoap to safely store markdown by purifying and preserving (escaped) what may be unsafe code in codeblocks. The stored item needs to be unescaped just prior to calling the markdown-to-html processor
|
||||
- Remove the unimplemented upload limit site settings from UI
|
||||
- Cleanup code_allowed
|
||||
- Move widgets to standalone classes
|
||||
- Upgrade redbasic to bootstrap 4
|
||||
- Updated HTML Purifier from 4.6.0 to 4.9.2 with better PHP7 compatibility
|
||||
- Remove redundant and non-functional/broken check for successfully cloned channel record which was left over from an earlier method of creating the table; which was deprecated a few months back
|
||||
- Update bshaffer/oauth2-server-php library
|
||||
- Add unit test for purify_html()
|
||||
|
||||
Bugfixes
|
||||
- Fix website export tool creating invalid zip file - issue #790
|
||||
- Fix files not synced correctly - issue #769
|
||||
- Fix empty ACL should not result in no ACL when uploading a file
|
||||
- Fix cover photo was unintentionally disabled when block_public in effect
|
||||
- Fix markdown autolinks - issue 752
|
||||
- Fix connectDefaultShare generated js function, though it isn't obvious if we still use it
|
||||
- Fix a couple more instances where we were still calling mail() directly for site critical messages
|
||||
- Fix when clicking a notification to view a private mail message, actually view that message instead of the most recent
|
||||
- Fix group by item query
|
||||
|
||||
Plugins/Addon
|
||||
- smileybutton: do not load emojis
|
||||
- pubsubhubbub: fixes associated with recent compatibility feed mods
|
||||
- gnusoc: mastodon follow_activity compatibility issues
|
||||
- gnusoc: add profile photo to feed meta
|
||||
- gnusoc: add salmon link information to the public feed when GNU-Social is enabled
|
||||
- chess: fix bugs when deleting games
|
||||
|
||||
Hubzilla 2.2 (2017-03-08)
|
||||
- Don't collapse long nsfw content if nsfw plugin is already collapsing it
|
||||
- Provide version compatibility check for themes (minversion, maxversion)
|
||||
- Use chanlink_hash() instead of chanlink_url() where appropriate
|
||||
- Use head_add_link() for feed discovery
|
||||
|
||||
37
DEVELOPERS
Normal file
37
DEVELOPERS
Normal file
@@ -0,0 +1,37 @@
|
||||
Developer Certificate of Origin
|
||||
Version 1.1
|
||||
|
||||
Copyright (C) 2004, 2006 The Linux Foundation and its contributors.
|
||||
1 Letterman Drive
|
||||
Suite D4700
|
||||
San Francisco, CA, 94129
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim copies of this
|
||||
license document, but changing it is not allowed.
|
||||
|
||||
|
||||
Developer's Certificate of Origin 1.1
|
||||
|
||||
By making a contribution to this project, I certify that:
|
||||
|
||||
(a) The contribution was created in whole or in part by me and I
|
||||
have the right to submit it under the open source license
|
||||
indicated in the file; or
|
||||
|
||||
(b) The contribution is based upon previous work that, to the best
|
||||
of my knowledge, is covered under an appropriate open source
|
||||
license and I have the right under that license to submit that
|
||||
work with modifications, whether created in whole or in part
|
||||
by me, under the same open source license (unless I am
|
||||
permitted to submit under a different license), as indicated
|
||||
in the file; or
|
||||
|
||||
(c) The contribution was provided directly to me by some other
|
||||
person who certified (a), (b) or (c) and I have not modified
|
||||
it.
|
||||
|
||||
(d) I understand and agree that this project and the contribution
|
||||
are public and that a record of the contribution (including all
|
||||
personal information I submit with it, including my sign-off) is
|
||||
maintained indefinitely and may be redistributed consistent with
|
||||
this project or the open source license(s) involved.
|
||||
@@ -2,21 +2,55 @@
|
||||
|
||||
namespace Zotlabs\Access;
|
||||
|
||||
|
||||
/**
|
||||
* @brief AccessList class.
|
||||
*
|
||||
* A class to hold an AccessList object with allowed and denied contacts and
|
||||
* groups.
|
||||
*/
|
||||
class AccessList {
|
||||
|
||||
/**
|
||||
* @brief Allow contacts
|
||||
* @var string
|
||||
*/
|
||||
private $allow_cid;
|
||||
/**
|
||||
* @brief Allow groups
|
||||
* @var string
|
||||
*/
|
||||
private $allow_gid;
|
||||
/**
|
||||
* @brief Deny contacts
|
||||
* @var string
|
||||
*/
|
||||
private $deny_cid;
|
||||
/**
|
||||
* @brief Deny groups
|
||||
* @var string
|
||||
*/
|
||||
private $deny_gid;
|
||||
/**
|
||||
* @brief Indicates if we are using the default constructor values or
|
||||
* values that have been set explicitly.
|
||||
* @var boolean
|
||||
*/
|
||||
private $explicit;
|
||||
|
||||
/* indicates if we are using the default constructor values or values that have been set explicitly. */
|
||||
|
||||
private $explicit;
|
||||
|
||||
/**
|
||||
* @brief Constructor for AccessList class.
|
||||
*
|
||||
* @note The array to pass to the constructor is different from the array
|
||||
* that you provide to the set() or set_from_array() functions.
|
||||
*
|
||||
* @param array $channel A channel array, where these entries are evaluated:
|
||||
* * \e string \b channel_allow_cid => string of allowed cids
|
||||
* * \e string \b channel_allow_gid => string of allowed gids
|
||||
* * \e string \b channel_deny_cid => string of denied cids
|
||||
* * \e string \b channel_deny_gid => string of denied gids
|
||||
*/
|
||||
function __construct($channel) {
|
||||
|
||||
if($channel) {
|
||||
if($channel) {
|
||||
$this->allow_cid = $channel['channel_allow_cid'];
|
||||
$this->allow_gid = $channel['channel_allow_gid'];
|
||||
$this->deny_cid = $channel['channel_deny_cid'];
|
||||
@@ -32,61 +66,95 @@ class AccessList {
|
||||
$this->explicit = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get if we are using the default constructor values
|
||||
* or values that have been set explicitly.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
function get_explicit() {
|
||||
return $this->explicit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set AccessList from strings such as those in already
|
||||
* existing stored data items
|
||||
* @brief Set access list from strings such as those in already
|
||||
* existing stored data items.
|
||||
*
|
||||
* @note The array to pass to this set function is different from the array
|
||||
* that you provide to the constructor or set_from_array().
|
||||
*
|
||||
* @param array $arr
|
||||
* * \e string \b allow_cid => string of allowed cids
|
||||
* * \e string \b allow_gid => string of allowed gids
|
||||
* * \e string \b deny_cid => string of denied cids
|
||||
* * \e string \b deny_gid => string of denied gids
|
||||
* @param boolean $explicit (optional) default true
|
||||
*/
|
||||
|
||||
function set($arr,$explicit = true) {
|
||||
function set($arr, $explicit = true) {
|
||||
$this->allow_cid = $arr['allow_cid'];
|
||||
$this->allow_gid = $arr['allow_gid'];
|
||||
$this->deny_cid = $arr['deny_cid'];
|
||||
$this->deny_gid = $arr['deny_gid'];
|
||||
|
||||
$this->explicit = $explicit;
|
||||
$this->explicit = $explicit;
|
||||
}
|
||||
|
||||
/**
|
||||
* return an array consisting of the current
|
||||
* access list components where the elements
|
||||
* are directly storable.
|
||||
* @brief Return an array consisting of the current access list components
|
||||
* where the elements are directly storable.
|
||||
*
|
||||
* @return Associative array with:
|
||||
* * \e string \b allow_cid => string of allowed cids
|
||||
* * \e string \b allow_gid => string of allowed gids
|
||||
* * \e string \b deny_cid => string of denied cids
|
||||
* * \e string \b deny_gid => string of denied gids
|
||||
*/
|
||||
|
||||
function get() {
|
||||
return array(
|
||||
return [
|
||||
'allow_cid' => $this->allow_cid,
|
||||
'allow_gid' => $this->allow_gid,
|
||||
'deny_cid' => $this->deny_cid,
|
||||
'deny_gid' => $this->deny_gid,
|
||||
);
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Set AccessList from arrays, such as those provided by
|
||||
* acl_selector(). For convenience, a string (or non-array) input is
|
||||
* assumed to be a comma-separated list and auto-converted into an array.
|
||||
*/
|
||||
|
||||
function set_from_array($arr,$explicit = true) {
|
||||
$this->allow_cid = perms2str((is_array($arr['contact_allow']))
|
||||
? $arr['contact_allow'] : explode(',',$arr['contact_allow']));
|
||||
* @brief Set access list components from arrays, such as those provided by
|
||||
* acl_selector().
|
||||
*
|
||||
* For convenience, a string (or non-array) input is assumed to be a
|
||||
* comma-separated list and auto-converted into an array.
|
||||
*
|
||||
* @note The array to pass to this set function is different from the array
|
||||
* that you provide to the constructor or set().
|
||||
*
|
||||
* @param array $arr An associative array with:
|
||||
* * \e array|string \b contact_allow => array with cids or comma-seperated string
|
||||
* * \e array|string \b group_allow => array with gids or comma-seperated string
|
||||
* * \e array|string \b contact_deny => array with cids or comma-seperated string
|
||||
* * \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) {
|
||||
$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']))
|
||||
? $arr['group_allow'] : explode(',',$arr['group_allow']));
|
||||
? $arr['group_allow'] : explode(',', $arr['group_allow']));
|
||||
$this->deny_cid = perms2str((is_array($arr['contact_deny']))
|
||||
? $arr['contact_deny'] : explode(',',$arr['contact_deny']));
|
||||
? $arr['contact_deny'] : explode(',', $arr['contact_deny']));
|
||||
$this->deny_gid = perms2str((is_array($arr['group_deny']))
|
||||
? $arr['group_deny'] : explode(',',$arr['group_deny']));
|
||||
? $arr['group_deny'] : explode(',', $arr['group_deny']));
|
||||
|
||||
$this->explicit = $explicit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns true if any access lists component is set.
|
||||
*
|
||||
* @return boolean Return true if any of allow_* deny_* values is set.
|
||||
*/
|
||||
function is_private() {
|
||||
return (($this->allow_cid || $this->allow_gid || $this->deny_cid || $this->deny_gid) ? true : false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ class PermissionLimits {
|
||||
$perms = Permissions::Perms();
|
||||
$limits = array();
|
||||
foreach($perms as $k => $v) {
|
||||
if(strstr($k,'view'))
|
||||
if(strstr($k,'view') || $k === 'post_comments')
|
||||
$limits[$k] = PERMS_PUBLIC;
|
||||
else
|
||||
$limits[$k] = PERMS_SPECIFIC;
|
||||
|
||||
@@ -1,12 +1,21 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Zotlabs\Access;
|
||||
|
||||
use Zotlabs\Lib as Zlib;
|
||||
|
||||
/**
|
||||
* @brief PermissionRoles class.
|
||||
*
|
||||
* @see Permissions
|
||||
*/
|
||||
class PermissionRoles {
|
||||
|
||||
/**
|
||||
* @brief PermissionRoles version.
|
||||
*
|
||||
* This must match the version in Permissions.php before permission updates can run.
|
||||
*
|
||||
* @return number
|
||||
*/
|
||||
static public function version() {
|
||||
return 2;
|
||||
}
|
||||
@@ -23,12 +32,13 @@ class PermissionRoles {
|
||||
$ret['default_collection'] = false;
|
||||
$ret['directory_publish'] = true;
|
||||
$ret['online'] = true;
|
||||
$ret['perms_connect'] = [
|
||||
$ret['perms_connect'] = [
|
||||
'view_stream', 'view_profile', 'view_contacts', 'view_storage',
|
||||
'view_pages', 'view_wiki', 'send_stream', 'post_wall', 'post_comments',
|
||||
'post_mail', 'chat', 'post_like', 'republish' ];
|
||||
|
||||
'view_pages', 'view_wiki', 'send_stream', 'post_wall', 'post_comments',
|
||||
'post_mail', 'chat', 'post_like', 'republish'
|
||||
];
|
||||
$ret['limits'] = PermissionLimits::Std_Limits();
|
||||
|
||||
break;
|
||||
|
||||
case 'social_restricted':
|
||||
@@ -36,11 +46,11 @@ class PermissionRoles {
|
||||
$ret['default_collection'] = true;
|
||||
$ret['directory_publish'] = true;
|
||||
$ret['online'] = true;
|
||||
$ret['perms_connect'] = [
|
||||
$ret['perms_connect'] = [
|
||||
'view_stream', 'view_profile', 'view_contacts', 'view_storage',
|
||||
'view_pages', 'view_wiki', 'send_stream', 'post_wall', 'post_comments',
|
||||
'post_mail', 'chat', 'post_like' ];
|
||||
|
||||
'view_pages', 'view_wiki', 'send_stream', 'post_wall', 'post_comments',
|
||||
'post_mail', 'chat', 'post_like'
|
||||
];
|
||||
$ret['limits'] = PermissionLimits::Std_Limits();
|
||||
|
||||
break;
|
||||
@@ -50,10 +60,11 @@ class PermissionRoles {
|
||||
$ret['default_collection'] = true;
|
||||
$ret['directory_publish'] = false;
|
||||
$ret['online'] = false;
|
||||
$ret['perms_connect'] = [
|
||||
$ret['perms_connect'] = [
|
||||
'view_stream', 'view_profile', 'view_contacts', 'view_storage',
|
||||
'view_pages', 'view_wiki', 'send_stream', 'post_wall', 'post_comments',
|
||||
'post_mail', 'post_like' ];
|
||||
'view_pages', 'view_wiki', 'send_stream', 'post_wall', 'post_comments',
|
||||
'post_mail', 'post_like'
|
||||
];
|
||||
$ret['limits'] = PermissionLimits::Std_Limits();
|
||||
$ret['limits']['view_contacts'] = PERMS_SPECIFIC;
|
||||
$ret['limits']['view_storage'] = PERMS_SPECIFIC;
|
||||
@@ -65,12 +76,13 @@ class PermissionRoles {
|
||||
$ret['default_collection'] = false;
|
||||
$ret['directory_publish'] = true;
|
||||
$ret['online'] = false;
|
||||
$ret['perms_connect'] = [
|
||||
$ret['perms_connect'] = [
|
||||
'view_stream', 'view_profile', 'view_contacts', 'view_storage',
|
||||
'view_pages', 'view_wiki', 'post_wall', 'post_comments', 'tag_deliver',
|
||||
'post_mail', 'post_like' , 'republish', 'chat' ];
|
||||
|
||||
'post_mail', 'post_like' , 'republish', 'chat'
|
||||
];
|
||||
$ret['limits'] = PermissionLimits::Std_Limits();
|
||||
|
||||
break;
|
||||
|
||||
case 'forum_restricted':
|
||||
@@ -78,11 +90,10 @@ class PermissionRoles {
|
||||
$ret['default_collection'] = true;
|
||||
$ret['directory_publish'] = true;
|
||||
$ret['online'] = false;
|
||||
$ret['perms_connect'] = [
|
||||
$ret['perms_connect'] = [
|
||||
'view_stream', 'view_profile', 'view_contacts', 'view_storage',
|
||||
'view_pages', 'view_wiki', 'post_wall', 'post_comments', 'tag_deliver',
|
||||
'post_mail', 'post_like' , 'chat' ];
|
||||
|
||||
$ret['limits'] = PermissionLimits::Std_Limits();
|
||||
|
||||
break;
|
||||
@@ -92,12 +103,11 @@ class PermissionRoles {
|
||||
$ret['default_collection'] = true;
|
||||
$ret['directory_publish'] = false;
|
||||
$ret['online'] = false;
|
||||
|
||||
$ret['perms_connect'] = [
|
||||
$ret['perms_connect'] = [
|
||||
'view_stream', 'view_profile', 'view_contacts', 'view_storage',
|
||||
'view_pages', 'view_wiki', 'post_wall', 'post_comments',
|
||||
'post_mail', 'post_like' , 'chat' ];
|
||||
|
||||
'post_mail', 'post_like' , 'chat'
|
||||
];
|
||||
$ret['limits'] = PermissionLimits::Std_Limits();
|
||||
$ret['limits']['view_profile'] = PERMS_SPECIFIC;
|
||||
$ret['limits']['view_contacts'] = PERMS_SPECIFIC;
|
||||
@@ -112,12 +122,11 @@ class PermissionRoles {
|
||||
$ret['default_collection'] = false;
|
||||
$ret['directory_publish'] = true;
|
||||
$ret['online'] = false;
|
||||
|
||||
$ret['perms_connect'] = [
|
||||
$ret['perms_connect'] = [
|
||||
'view_stream', 'view_profile', 'view_contacts', 'view_storage',
|
||||
'view_pages', 'view_wiki', 'send_stream', 'post_wall', 'post_comments',
|
||||
'post_mail', 'post_like' , 'republish' ];
|
||||
|
||||
'view_pages', 'view_wiki', 'send_stream', 'post_wall', 'post_comments',
|
||||
'post_mail', 'post_like' , 'republish'
|
||||
];
|
||||
$ret['limits'] = PermissionLimits::Std_Limits();
|
||||
|
||||
break;
|
||||
@@ -127,11 +136,11 @@ class PermissionRoles {
|
||||
$ret['default_collection'] = true;
|
||||
$ret['directory_publish'] = false;
|
||||
$ret['online'] = false;
|
||||
$ret['perms_connect'] = [
|
||||
$ret['perms_connect'] = [
|
||||
'view_stream', 'view_profile', 'view_contacts', 'view_storage',
|
||||
'view_pages', 'view_wiki', 'send_stream', 'post_wall', 'post_comments',
|
||||
'post_mail', 'post_like' , 'republish' ];
|
||||
|
||||
'view_pages', 'view_wiki', 'send_stream', 'post_wall', 'post_comments',
|
||||
'post_mail', 'post_like' , 'republish'
|
||||
];
|
||||
$ret['limits'] = PermissionLimits::Std_Limits();
|
||||
|
||||
break;
|
||||
@@ -141,11 +150,10 @@ class PermissionRoles {
|
||||
$ret['default_collection'] = false;
|
||||
$ret['directory_publish'] = true;
|
||||
$ret['online'] = false;
|
||||
|
||||
$ret['perms_connect'] = [
|
||||
$ret['perms_connect'] = [
|
||||
'view_stream', 'view_profile', 'view_contacts', 'view_storage',
|
||||
'view_pages', 'view_wiki', 'post_like' , 'republish' ];
|
||||
|
||||
'view_pages', 'view_wiki', 'post_like' , 'republish'
|
||||
];
|
||||
$ret['limits'] = PermissionLimits::Std_Limits();
|
||||
|
||||
break;
|
||||
@@ -155,13 +163,13 @@ class PermissionRoles {
|
||||
$ret['default_collection'] = false;
|
||||
$ret['directory_publish'] = true;
|
||||
$ret['online'] = false;
|
||||
|
||||
$ret['perms_connect'] = [
|
||||
$ret['perms_connect'] = [
|
||||
'view_stream', 'view_profile', 'view_contacts', 'view_storage',
|
||||
'view_pages', 'view_wiki', 'write_storage', 'write_pages', 'post_wall', 'post_comments', 'tag_deliver',
|
||||
'post_mail', 'post_like' , 'republish', 'chat', 'write_wiki' ];
|
||||
|
||||
'post_mail', 'post_like' , 'republish', 'chat', 'write_wiki'
|
||||
];
|
||||
$ret['limits'] = PermissionLimits::Std_Limits();
|
||||
|
||||
break;
|
||||
|
||||
case 'custom':
|
||||
@@ -170,11 +178,15 @@ class PermissionRoles {
|
||||
}
|
||||
|
||||
$x = get_config('system','role_perms');
|
||||
// let system settings over-ride any or all
|
||||
// let system settings over-ride any or all
|
||||
if($x && is_array($x) && array_key_exists($role,$x))
|
||||
$ret = array_merge($ret,$x[$role]);
|
||||
|
||||
call_hooks('get_role_perms',$ret);
|
||||
/**
|
||||
* @hooks get_role_perms
|
||||
* * \e array
|
||||
*/
|
||||
call_hooks('get_role_perms', $ret);
|
||||
|
||||
return $ret;
|
||||
}
|
||||
@@ -187,10 +199,10 @@ class PermissionRoles {
|
||||
// \Zotlabs\Access\PermissionLimits::Set($uid,$perm,1);
|
||||
|
||||
if($perm === 'view_wiki')
|
||||
\Zotlabs\Access\PermissionLimits::Set($uid,$perm,PERMS_PUBLIC);
|
||||
\Zotlabs\Access\PermissionLimits::Set($uid, $perm, PERMS_PUBLIC);
|
||||
|
||||
if($perm === 'write_wiki')
|
||||
\Zotlabs\Access\PermissionLimits::Set($uid,$perm,PERMS_SPECIFIC);
|
||||
\Zotlabs\Access\PermissionLimits::Set($uid, $perm, PERMS_SPECIFIC);
|
||||
|
||||
|
||||
// set autoperms here if applicable
|
||||
@@ -213,8 +225,6 @@ class PermissionRoles {
|
||||
if($c) {
|
||||
set_abconfig($uid,$c['channel_hash'],'autoperms',$perm,$value);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// now set something for all existing connections.
|
||||
@@ -242,38 +252,44 @@ class PermissionRoles {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Array with translated role names and grouping.
|
||||
*
|
||||
* Return an associative array with grouped role names that can be used
|
||||
* to create select groups like in \e field_select_grouped.tpl.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
static public function roles() {
|
||||
$roles = [
|
||||
$roles = [
|
||||
t('Social Networking') => [
|
||||
'social' => t('Social - Mostly Public'),
|
||||
'social_restricted' => t('Social - Restricted'),
|
||||
'social' => t('Social - Mostly Public'),
|
||||
'social_restricted' => t('Social - Restricted'),
|
||||
'social_private' => t('Social - Private')
|
||||
],
|
||||
|
||||
t('Community Forum') => [
|
||||
'forum' => t('Forum - Mostly Public'),
|
||||
'forum_restricted' => t('Forum - Restricted'),
|
||||
'forum' => t('Forum - Mostly Public'),
|
||||
'forum_restricted' => t('Forum - Restricted'),
|
||||
'forum_private' => t('Forum - Private')
|
||||
],
|
||||
|
||||
t('Feed Republish') => [
|
||||
'feed' => t('Feed - Mostly Public'),
|
||||
'feed' => t('Feed - Mostly Public'),
|
||||
'feed_restricted' => t('Feed - Restricted')
|
||||
],
|
||||
|
||||
t('Special Purpose') => [
|
||||
'soapbox' => t('Special - Celebrity/Soapbox'),
|
||||
'soapbox' => t('Special - Celebrity/Soapbox'),
|
||||
'repository' => t('Special - Group Repository')
|
||||
],
|
||||
|
||||
t('Other') => [
|
||||
'custom' => t('Custom/Expert Mode')
|
||||
]
|
||||
|
||||
];
|
||||
|
||||
return $roles;
|
||||
return $roles;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,45 +1,55 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Zotlabs\Access;
|
||||
|
||||
use Zotlabs\Lib as Zlib;
|
||||
|
||||
/**
|
||||
* @brief Extensible permissions.
|
||||
*
|
||||
* To add new permissions, add to the list of $perms below, with a simple description.
|
||||
*
|
||||
* Also visit PermissionRoles.php and add to the $ret['perms_connect'] property for any role
|
||||
* if this permission should be granted to new connections.
|
||||
*
|
||||
* Next look at PermissionRoles::new_custom_perms() and provide a handler for updating custom
|
||||
* permission roles. You will want to set a default PermissionLimit for each channel and also
|
||||
* provide a sane default for any existing connections. You may or may not wish to provide a
|
||||
* default auto permission. If in doubt, leave this alone as custom permissions by definition
|
||||
* are the responsibility of the channel owner to manage. You just don't want to create any
|
||||
* suprises or break things so you have an opportunity to provide sane settings.
|
||||
*
|
||||
* Update the version here and in PermissionRoles.
|
||||
*
|
||||
*
|
||||
* Permissions with 'view' in the name are considered read permissions. Anything
|
||||
* else requires authentication. Read permission limits are PERMS_PUBLIC and anything else
|
||||
* is given PERMS_SPECIFIC.
|
||||
*
|
||||
* PermissionLimits::Std_limits() retrieves the standard limits. A permission role
|
||||
* MAY alter an individual setting after retrieving the Std_limits if you require
|
||||
* something different for a specific permission within the given role.
|
||||
*
|
||||
*/
|
||||
class Permissions {
|
||||
|
||||
/**
|
||||
* Extensible permissions.
|
||||
* To add new permissions, add to the list of $perms below, with a simple description.
|
||||
* @brief Permissions version.
|
||||
*
|
||||
* Also visit PermissionRoles.php and add to the $ret['perms_connect'] property for any role
|
||||
* if this permission should be granted to new connections.
|
||||
*
|
||||
* Next look at PermissionRoles::new_custom_perms() and provide a handler for updating custom
|
||||
* permission roles. You will want to set a default PermissionLimit for each channel and also
|
||||
* provide a sane default for any existing connections. You may or may not wish to provide a
|
||||
* default auto permission. If in doubt, leave this alone as custom permissions by definition
|
||||
* are the responsibility of the channel owner to manage. You just don't want to create any
|
||||
* suprises or break things so you have an opportunity to provide sane settings.
|
||||
*
|
||||
* Update the version here and in PermissionRoles
|
||||
*
|
||||
*
|
||||
* Permissions with 'view' in the name are considered read permissions. Anything
|
||||
* else requires authentication. Read permission limits are PERMS_PUBLIC and anything else
|
||||
* is given PERMS_SPECIFIC.
|
||||
*
|
||||
* PermissionLimits::Std_limits() retrieves the standard limits. A permission role
|
||||
* MAY alter an individual setting after retrieving the Std_limits if you require
|
||||
* something different for a specific permission within the given role.
|
||||
* This must match the version in PermissionRoles.php before permission updates can run.
|
||||
*
|
||||
* @return number
|
||||
*/
|
||||
|
||||
static public function version() {
|
||||
// This must match the version in PermissionRoles.php before permission updates can run.
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Return an array with Permissions.
|
||||
*
|
||||
* @param string $filter (optional) only passed to hook permissions_list
|
||||
* @return array Associative array with permissions and short description.
|
||||
*/
|
||||
static public function Perms($filter = '') {
|
||||
|
||||
$perms = [
|
||||
@@ -63,18 +73,30 @@ class Permissions {
|
||||
'delegate' => t('Can administer my channel')
|
||||
];
|
||||
|
||||
$x = array('permissions' => $perms, 'filter' => $filter);
|
||||
call_hooks('permissions_list',$x);
|
||||
return($x['permissions']);
|
||||
$x = [
|
||||
'permissions' => $perms,
|
||||
'filter' => $filter
|
||||
];
|
||||
/**
|
||||
* @hooks permissions_list
|
||||
* * \e array \b permissions
|
||||
* * \e string \b filter
|
||||
*/
|
||||
call_hooks('permissions_list', $x);
|
||||
|
||||
return($x['permissions']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Perms from the above list that are blocked from anonymous observers.
|
||||
*
|
||||
* e.g. you must be authenticated.
|
||||
*
|
||||
* @return array Associative array with permissions and short description.
|
||||
*/
|
||||
static public function BlockedAnonPerms() {
|
||||
|
||||
// Perms from the above list that are blocked from anonymous observers.
|
||||
// e.g. you must be authenticated.
|
||||
|
||||
$res = array();
|
||||
$res = [];
|
||||
$perms = PermissionLimits::Std_limits();
|
||||
foreach($perms as $perm => $limit) {
|
||||
if($limit != PERMS_PUBLIC) {
|
||||
@@ -82,34 +104,55 @@ class Permissions {
|
||||
}
|
||||
}
|
||||
|
||||
$x = array('permissions' => $res);
|
||||
call_hooks('write_perms',$x);
|
||||
return($x['permissions']);
|
||||
$x = ['permissions' => $res];
|
||||
/**
|
||||
* @hooks write_perms
|
||||
* * \e array \b permissions
|
||||
*/
|
||||
call_hooks('write_perms', $x);
|
||||
|
||||
return($x['permissions']);
|
||||
}
|
||||
|
||||
// converts [ 0 => 'view_stream', ... ]
|
||||
// to [ 'view_stream' => 1 ]
|
||||
// for any permissions in $arr;
|
||||
// Undeclared permissions are set to 0
|
||||
|
||||
/**
|
||||
* @brief Converts indexed perms array to associative perms array.
|
||||
*
|
||||
* Converts [ 0 => 'view_stream', ... ]
|
||||
* to [ 'view_stream' => 1 ] for any permissions in $arr;
|
||||
* Undeclared permissions which exist in Perms() are added and set to 0.
|
||||
*
|
||||
* @param array $arr
|
||||
* @return array
|
||||
*/
|
||||
static public function FilledPerms($arr) {
|
||||
if(is_null($arr)) {
|
||||
btlogger('FilledPerms: null');
|
||||
$arr = [];
|
||||
}
|
||||
|
||||
$everything = self::Perms();
|
||||
$ret = [];
|
||||
foreach($everything as $k => $v) {
|
||||
if(in_array($k,$arr))
|
||||
if(in_array($k, $arr))
|
||||
$ret[$k] = 1;
|
||||
else
|
||||
$ret[$k] = 0;
|
||||
}
|
||||
return $ret;
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convert perms array to indexed array.
|
||||
*
|
||||
* Converts [ 'view_stream' => 1 ] for any permissions in $arr
|
||||
* to [ 0 => ['name' => 'view_stream', 'value' => 1], ... ]
|
||||
*
|
||||
* @param array $arr associative perms array 'view_stream' => 1
|
||||
* @return array Indexed array with elements that look like
|
||||
* * \e string \b name the perm name (e.g. view_stream)
|
||||
* * \e int \b value the value of the perm (e.g. 1)
|
||||
*/
|
||||
static public function OPerms($arr) {
|
||||
$ret = [];
|
||||
if($arr) {
|
||||
@@ -120,7 +163,12 @@ class Permissions {
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @param int $channel_id
|
||||
* @return boolean|array
|
||||
*/
|
||||
static public function FilledAutoperms($channel_id) {
|
||||
if(! intval(get_pconfig($channel_id,'system','autoperms')))
|
||||
return false;
|
||||
@@ -137,16 +185,33 @@ class Permissions {
|
||||
return $arr;
|
||||
}
|
||||
|
||||
static public function PermsCompare($p1,$p2) {
|
||||
/**
|
||||
* @brief Compares that all Permissions from $p1 exist also in $p2.
|
||||
*
|
||||
* @param array $p1 The perms that have to exist in $p2
|
||||
* @param array $p2 The perms to compare against
|
||||
* @return boolean true if all perms from $p1 exist also in $p2
|
||||
*/
|
||||
static public function PermsCompare($p1, $p2) {
|
||||
foreach($p1 as $k => $v) {
|
||||
if(! array_key_exists($k,$p2))
|
||||
if(! array_key_exists($k, $p2))
|
||||
return false;
|
||||
|
||||
if($p1[$k] != $p2[$k])
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @param int $channel_id A channel id
|
||||
* @return array Associative array with
|
||||
* * \e array \b perms Permission array
|
||||
* * \e int \b automatic 0 or 1
|
||||
*/
|
||||
static public function connect_perms($channel_id) {
|
||||
|
||||
$my_perms = [];
|
||||
@@ -155,7 +220,7 @@ class Permissions {
|
||||
|
||||
// If a default permcat exists, use that
|
||||
|
||||
$pc = ((feature_enabled($channel_id,'permcats')) ? get_pconfig($channel_id,'system','default_permcat') : 'default');
|
||||
$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);
|
||||
@@ -167,7 +232,7 @@ class Permissions {
|
||||
}
|
||||
|
||||
// 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
|
||||
// and if there was no permcat or a default permcat, set the perms
|
||||
// from the role
|
||||
|
||||
$role = get_pconfig($channel_id,'system','permissions_role');
|
||||
@@ -195,7 +260,7 @@ class Permissions {
|
||||
}
|
||||
|
||||
// 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
|
||||
// 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) {
|
||||
|
||||
@@ -78,7 +78,7 @@ class Cron {
|
||||
// channels and sites that quietly vanished and prevent the directory from accumulating stale
|
||||
// or dead entries.
|
||||
|
||||
$r = q("select channel_id from channel where channel_dirdate < %s - INTERVAL %s",
|
||||
$r = q("select channel_id from channel where channel_dirdate < %s - INTERVAL %s and channel_removed = 0",
|
||||
db_utcnow(),
|
||||
db_quoteinterval('30 DAY')
|
||||
);
|
||||
@@ -121,6 +121,9 @@ class Cron {
|
||||
}
|
||||
}
|
||||
|
||||
require_once('include/attach.php');
|
||||
attach_upgrade();
|
||||
|
||||
$abandon_days = intval(get_config('system','account_abandon_days'));
|
||||
if($abandon_days < 1)
|
||||
$abandon_days = 0;
|
||||
@@ -171,7 +174,8 @@ class Cron {
|
||||
|
||||
// pull in some public posts
|
||||
|
||||
if(! get_config('system','disable_discover_tab'))
|
||||
$disable_discover_tab = get_config('system','disable_discover_tab') || get_config('system','disable_discover_tab') === false;
|
||||
if(! $disable_discover_tab)
|
||||
Master::Summon(array('Externals'));
|
||||
|
||||
$generation = 0;
|
||||
|
||||
@@ -38,12 +38,20 @@ class Cron_daily {
|
||||
db_utcnow(), db_quoteinterval('30 DAY')
|
||||
);
|
||||
|
||||
// expire any unread notifications over a year old
|
||||
|
||||
q("delete from notify where seen = 0 and created < %s - INTERVAL %s",
|
||||
db_utcnow(), db_quoteinterval('1 YEAR')
|
||||
);
|
||||
|
||||
|
||||
//update statistics in config
|
||||
require_once('include/statistics_fns.php');
|
||||
update_channels_total_stat();
|
||||
update_channels_active_halfyear_stat();
|
||||
update_channels_active_monthly_stat();
|
||||
update_local_posts_stat();
|
||||
update_local_comments_stat();
|
||||
|
||||
|
||||
// expire old delivery reports
|
||||
@@ -80,7 +88,7 @@ class Cron_daily {
|
||||
|
||||
call_hooks('cron_daily',datetime_convert());
|
||||
|
||||
set_config('system','last_expire_day',$d2);
|
||||
set_config('system','last_expire_day',intval(datetime_convert('UTC','UTC','now','d')));
|
||||
|
||||
/**
|
||||
* End Cron Daily
|
||||
|
||||
@@ -21,6 +21,21 @@ class Cron_weekly {
|
||||
|
||||
mark_orphan_hubsxchans();
|
||||
|
||||
// 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.
|
||||
|
||||
$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')
|
||||
);
|
||||
if($r) {
|
||||
foreach($r as $rv) {
|
||||
channel_remove_final($rv['channel_id']);
|
||||
}
|
||||
}
|
||||
|
||||
// get rid of really old poco records
|
||||
|
||||
|
||||
@@ -53,6 +53,9 @@ class Deliver {
|
||||
remove_queue_item($r[0]['outq_hash']);
|
||||
|
||||
if($dresult && is_array($dresult)) {
|
||||
|
||||
// delivery reports for local deliveries do not require encryption
|
||||
|
||||
foreach($dresult as $xx) {
|
||||
if(is_array($xx) && array_key_exists('message_id',$xx)) {
|
||||
if(delivery_report_is_storable($xx)) {
|
||||
|
||||
@@ -17,7 +17,7 @@ class Gprobe {
|
||||
if(! strpos($url,'@'))
|
||||
return;
|
||||
|
||||
$r = q("select * from xchan where xchan_addr = '%s' limit 1",
|
||||
$r = q("select * from hubloc where hubloc_addr = '%s' limit 1",
|
||||
dbesc($url)
|
||||
);
|
||||
|
||||
|
||||
@@ -21,12 +21,18 @@ class Importdoc {
|
||||
$files = glob("$d/$f");
|
||||
if($files) {
|
||||
foreach($files as $fi) {
|
||||
if($fi === 'doc/html')
|
||||
if($fi === 'doc/html') {
|
||||
continue;
|
||||
if(is_dir($fi))
|
||||
}
|
||||
if(is_dir($fi)) {
|
||||
self::update_docs_dir("$fi/*");
|
||||
else
|
||||
store_doc_file($fi);
|
||||
}
|
||||
else {
|
||||
// don't update media content
|
||||
if(strpos(z_mime_content_type($fi),'text') === 0) {
|
||||
store_doc_file($fi);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
47
Zotlabs/Daemon/Importfile.php
Normal file
47
Zotlabs/Daemon/Importfile.php
Normal file
@@ -0,0 +1,47 @@
|
||||
<?php /** @file */
|
||||
|
||||
namespace Zotlabs\Daemon;
|
||||
|
||||
class Importfile {
|
||||
|
||||
static public function run($argc,$argv){
|
||||
|
||||
logger('Importfile: ' . print_r($argv,true));
|
||||
|
||||
if($argc < 3)
|
||||
return;
|
||||
|
||||
$channel = channelx_by_n($argv[1]);
|
||||
if(! $channel)
|
||||
return;
|
||||
|
||||
$srcfile = $argv[2];
|
||||
$folder = (($argc > 3) ? $argv[3] : '');
|
||||
$dstname = (($argc > 4) ? $argv[4] : '');
|
||||
|
||||
$hash = random_string();
|
||||
|
||||
$arr = [
|
||||
'src' => $srcfile,
|
||||
'filename' => (($dstname) ? $dstname : basename($srcfile)),
|
||||
'hash' => $hash,
|
||||
'allow_cid' => $channel['channel_allow_cid'],
|
||||
'allow_gid' => $channel['channel_allow_gid'],
|
||||
'deny_cid' => $channel['channel_deny_cid'],
|
||||
'deny_gid' => $channel['channel_deny_gid'],
|
||||
'preserve_original' => true,
|
||||
'replace' => true
|
||||
];
|
||||
|
||||
if($folder)
|
||||
$arr['folder'] = $folder;
|
||||
|
||||
attach_store($channel,$channel['channel_hash'],'import',$arr);
|
||||
|
||||
$sync = attach_export_data($channel,$hash);
|
||||
if($sync)
|
||||
build_sync_packet($channel['channel_id'],array('file' => array($sync)));
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,11 @@ namespace Zotlabs\Daemon;
|
||||
require_once('include/queue_fn.php');
|
||||
require_once('include/html2plain.php');
|
||||
require_once('include/conversation.php');
|
||||
require_once('include/zot.php');
|
||||
require_once('include/items.php');
|
||||
require_once('include/bbcode.php');
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* This file was at one time responsible for doing all deliveries, but this caused
|
||||
@@ -54,6 +59,8 @@ require_once('include/conversation.php');
|
||||
*
|
||||
* ZOT
|
||||
* permission_create abook_id
|
||||
* permission_accept abook_id
|
||||
* permission_reject abook_id
|
||||
* permission_update abook_id
|
||||
* refresh_all channel_id
|
||||
* purge_all channel_id
|
||||
@@ -64,17 +71,11 @@ require_once('include/conversation.php');
|
||||
* location channel_id
|
||||
* request channel_id xchan_hash message_id
|
||||
* rating xlink_id
|
||||
* keychange channel_id
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
require_once('include/zot.php');
|
||||
require_once('include/queue_fn.php');
|
||||
require_once('include/datetime.php');
|
||||
require_once('include/items.php');
|
||||
require_once('include/bbcode.php');
|
||||
require_once('include/channel.php');
|
||||
|
||||
|
||||
class Notifier {
|
||||
|
||||
@@ -98,16 +99,6 @@ class Notifier {
|
||||
|
||||
$deliveries = array();
|
||||
|
||||
$dead_hubs = array();
|
||||
|
||||
$dh = q("select site_url from site where site_dead = 1");
|
||||
if($dh) {
|
||||
foreach($dh as $dead) {
|
||||
$dead_hubs[] = $dead['site_url'];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$request = false;
|
||||
$mail = false;
|
||||
$top_level = false;
|
||||
@@ -158,7 +149,21 @@ class Notifier {
|
||||
$packet_type = 'request';
|
||||
$normal_mode = false;
|
||||
}
|
||||
elseif($cmd == 'permission_update' || $cmd == 'permission_create') {
|
||||
elseif($cmd === 'keychange') {
|
||||
$channel = channelx_by_n($item_id);
|
||||
$r = q("select abook_xchan from abook where abook_channel = %d",
|
||||
intval($item_id)
|
||||
);
|
||||
if($r) {
|
||||
foreach($r as $rr) {
|
||||
$recipients[] = $rr['abook_xchan'];
|
||||
}
|
||||
}
|
||||
$private = false;
|
||||
$packet_type = 'keychange';
|
||||
$normal_mode = false;
|
||||
}
|
||||
elseif(in_array($cmd, [ 'permission_update', 'permission_reject', 'permission_accept', 'permission_create' ])) {
|
||||
// Get the (single) recipient
|
||||
$r = q("select * from abook left join xchan on abook_xchan = xchan_hash where abook_id = %d and abook_self = 0",
|
||||
intval($item_id)
|
||||
@@ -170,8 +175,12 @@ class Notifier {
|
||||
if($channel) {
|
||||
$perm_update = array('sender' => $channel, 'recipient' => $r[0], 'success' => false, 'deliveries' => '');
|
||||
|
||||
if($cmd == 'permission_create')
|
||||
if($cmd === 'permission_create')
|
||||
call_hooks('permissions_create',$perm_update);
|
||||
elseif($cmd === 'permission_accept')
|
||||
call_hooks('permissions_accept',$perm_update);
|
||||
elseif($cmd === 'permission_reject')
|
||||
call_hooks('permissions_reject',$perm_update);
|
||||
else
|
||||
call_hooks('permissions_update',$perm_update);
|
||||
|
||||
@@ -275,14 +284,15 @@ class Notifier {
|
||||
$deleted_item = true;
|
||||
}
|
||||
|
||||
if(intval($target_item['item_type']) != ITEM_TYPE_POST) {
|
||||
if(! in_array(intval($target_item['item_type']), [ ITEM_TYPE_POST ] )) {
|
||||
logger('notifier: target item not forwardable: type ' . $target_item['item_type'], LOGGER_DEBUG);
|
||||
return;
|
||||
}
|
||||
|
||||
// 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']) ||
|
||||
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;
|
||||
@@ -403,7 +413,6 @@ class Notifier {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$walltowall = (($top_level_post && $channel['xchan_hash'] === $target_item['author_xchan']) ? true : false);
|
||||
@@ -417,14 +426,16 @@ class Notifier {
|
||||
logger('notifier: encoded item: ' . print_r($x,true), LOGGER_DATA, LOG_DEBUG);
|
||||
|
||||
stringify_array_elms($recipients);
|
||||
if(! $recipients)
|
||||
if(! $recipients) {
|
||||
logger('no recipients');
|
||||
return;
|
||||
}
|
||||
|
||||
// logger('notifier: recipients: ' . print_r($recipients,true), LOGGER_NORMAL, LOG_DEBUG);
|
||||
// logger('notifier: recipients: ' . print_r($recipients,true), LOGGER_NORMAL, LOG_DEBUG);
|
||||
|
||||
$env_recips = (($private) ? array() : null);
|
||||
|
||||
$details = q("select xchan_hash, xchan_instance_url, xchan_network, xchan_addr, xchan_guid, xchan_guid_sig from xchan where xchan_hash in (" . implode(',',$recipients) . ")");
|
||||
$details = q("select xchan_hash, xchan_instance_url, xchan_network, xchan_addr, xchan_guid, xchan_guid_sig from xchan where xchan_hash in (" . protect_sprintf(implode(',',$recipients)) . ")");
|
||||
|
||||
|
||||
$recip_list = array();
|
||||
@@ -433,40 +444,40 @@ class Notifier {
|
||||
foreach($details as $d) {
|
||||
|
||||
$recip_list[] = $d['xchan_addr'] . ' (' . $d['xchan_hash'] . ')';
|
||||
if($private)
|
||||
$env_recips[] = array('guid' => $d['xchan_guid'],'guid_sig' => $d['xchan_guid_sig'],'hash' => $d['xchan_hash']);
|
||||
|
||||
if($d['xchan_network'] === 'mail' && $normal_mode) {
|
||||
$delivery_options = get_xconfig($d['xchan_hash'],'system','delivery_mode');
|
||||
if(! $delivery_options)
|
||||
format_and_send_email($channel,$d,$target_item);
|
||||
if($private) {
|
||||
$env_recips[] = [
|
||||
'guid' => $d['xchan_guid'],
|
||||
'guid_sig' => $d['xchan_guid_sig'],
|
||||
'hash' => $d['xchan_hash']
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$narr = array(
|
||||
'channel' => $channel,
|
||||
'upstream' => $upstream,
|
||||
'env_recips' => $env_recips,
|
||||
'packet_recips' => $packet_recips,
|
||||
'recipients' => $recipients,
|
||||
'item' => $item,
|
||||
'target_item' => $target_item,
|
||||
$narr = [
|
||||
'channel' => $channel,
|
||||
'upstream' => $upstream,
|
||||
'env_recips' => $env_recips,
|
||||
'packet_recips' => $packet_recips,
|
||||
'recipients' => $recipients,
|
||||
'item' => $item,
|
||||
'target_item' => $target_item,
|
||||
'parent_item' => $parent_item,
|
||||
'top_level_post' => $top_level_post,
|
||||
'private' => $private,
|
||||
'private' => $private,
|
||||
'relay_to_owner' => $relay_to_owner,
|
||||
'uplink' => $uplink,
|
||||
'cmd' => $cmd,
|
||||
'mail' => $mail,
|
||||
'single' => (($cmd === 'single_mail' || $cmd === 'single_activity') ? true : false),
|
||||
'location' => $location,
|
||||
'request' => $request,
|
||||
'normal_mode' => $normal_mode,
|
||||
'packet_type' => $packet_type,
|
||||
'walltowall' => $walltowall,
|
||||
'queued' => array()
|
||||
);
|
||||
'uplink' => $uplink,
|
||||
'cmd' => $cmd,
|
||||
'mail' => $mail,
|
||||
'single' => (($cmd === 'single_mail' || $cmd === 'single_activity') ? true : false),
|
||||
'location' => $location,
|
||||
'request' => $request,
|
||||
'normal_mode' => $normal_mode,
|
||||
'packet_type' => $packet_type,
|
||||
'walltowall' => $walltowall,
|
||||
'queued' => []
|
||||
];
|
||||
|
||||
call_hooks('notifier_process', $narr);
|
||||
if($narr['queued']) {
|
||||
@@ -489,10 +500,10 @@ class Notifier {
|
||||
|
||||
|
||||
// Now we have collected recipients (except for external mentions, FIXME)
|
||||
// Let's reduce this to a set of hubs.
|
||||
// Let's reduce this to a set of hubs; checking that the site is not dead.
|
||||
|
||||
$r = q("select hubloc.*, site.site_crypto from hubloc left join site on site_url = hubloc_url where hubloc_hash in (" . implode(',',$recipients) . ")
|
||||
and hubloc_error = 0 and hubloc_deleted = 0"
|
||||
$r = q("select hubloc.*, site.site_crypto, site.site_flags from hubloc left join site on site_url = hubloc_url where hubloc_hash in (" . protect_sprintf(implode(',',$recipients)) . ")
|
||||
and hubloc_error = 0 and hubloc_deleted = 0 and ( site_dead = 0 OR site_dead is null ) "
|
||||
);
|
||||
|
||||
|
||||
@@ -503,73 +514,78 @@ class Notifier {
|
||||
|
||||
$hubs = $r;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Reduce the hubs to those that are unique. For zot hubs, we need to verify uniqueness by the sitekey, since it may have been
|
||||
* a re-install which has not yet been detected and pruned.
|
||||
* Reduce the hubs to those that are unique. For zot hubs, we need to verify uniqueness by the sitekey,
|
||||
* since it may have been a re-install which has not yet been detected and pruned.
|
||||
* For other networks which don't have or require sitekeys, we'll have to use the URL
|
||||
*/
|
||||
|
||||
|
||||
$hublist = array(); // this provides an easily printable list for the logs
|
||||
$dhubs = array(); // delivery hubs where we store our resulting unique array
|
||||
$keys = array(); // array of keys to check uniquness for zot hubs
|
||||
$urls = array(); // array of urls to check uniqueness of hubs from other networks
|
||||
|
||||
$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
|
||||
|
||||
foreach($hubs as $hub) {
|
||||
if(in_array($hub['hubloc_url'],$dead_hubs)) {
|
||||
logger('skipping dead hub: ' . $hub['hubloc_url'], LOGGER_DEBUG, LOG_INFO);
|
||||
continue;
|
||||
|
||||
if($env_recips) {
|
||||
foreach($env_recips as $er) {
|
||||
if($hub['hubloc_hash'] === $er['hash']) {
|
||||
if(! array_key_exists($hub['hubloc_host'] . $hub['hubloc_sitekey'], $hub_env)) {
|
||||
$hub_env[$hub['hubloc_host'] . $hub['hubloc_sitekey']] = [];
|
||||
}
|
||||
$hub_env[$hub['hubloc_host'] . $hub['hubloc_sitekey']][] = $er;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if($hub['hubloc_network'] == 'zot') {
|
||||
if(! in_array($hub['hubloc_sitekey'],$keys)) {
|
||||
$hublist[] = $hub['hubloc_host'];
|
||||
$dhubs[] = $hub;
|
||||
$keys[] = $hub['hubloc_sitekey'];
|
||||
$hublist[] = $hub['hubloc_host'] . ' ' . $hub['hubloc_network'];
|
||||
$dhubs[] = $hub;
|
||||
$keys[] = $hub['hubloc_sitekey'];
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(! in_array($hub['hubloc_url'],$urls)) {
|
||||
$hublist[] = $hub['hubloc_host'];
|
||||
$dhubs[] = $hub;
|
||||
$urls[] = $hub['hubloc_url'];
|
||||
$hublist[] = $hub['hubloc_host'] . ' ' . $hub['hubloc_network'];
|
||||
$dhubs[] = $hub;
|
||||
$urls[] = $hub['hubloc_url'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logger('notifier: will notify/deliver to these hubs: ' . print_r($hublist,true), LOGGER_DEBUG, LOG_DEBUG);
|
||||
|
||||
|
||||
foreach($dhubs as $hub) {
|
||||
|
||||
if($hub['hubloc_network'] !== 'zot') {
|
||||
|
||||
$narr = array(
|
||||
'channel' => $channel,
|
||||
'upstream' => $upstream,
|
||||
'env_recips' => $env_recips,
|
||||
'packet_recips' => $packet_recips,
|
||||
'recipients' => $recipients,
|
||||
'item' => $item,
|
||||
'target_item' => $target_item,
|
||||
'hub' => $hub,
|
||||
$narr = [
|
||||
'channel' => $channel,
|
||||
'upstream' => $upstream,
|
||||
'env_recips' => $env_recips,
|
||||
'packet_recips' => $packet_recips,
|
||||
'recipients' => $recipients,
|
||||
'item' => $item,
|
||||
'target_item' => $target_item,
|
||||
'parent_item' => $parent_item,
|
||||
'hub' => $hub,
|
||||
'top_level_post' => $top_level_post,
|
||||
'private' => $private,
|
||||
'private' => $private,
|
||||
'relay_to_owner' => $relay_to_owner,
|
||||
'uplink' => $uplink,
|
||||
'cmd' => $cmd,
|
||||
'mail' => $mail,
|
||||
'single' => (($cmd === 'single_mail' || $cmd === 'single_activity') ? true : false),
|
||||
'location' => $location,
|
||||
'request' => $request,
|
||||
'normal_mode' => $normal_mode,
|
||||
'packet_type' => $packet_type,
|
||||
'walltowall' => $walltowall,
|
||||
'queued' => array()
|
||||
);
|
||||
'uplink' => $uplink,
|
||||
'cmd' => $cmd,
|
||||
'mail' => $mail,
|
||||
'single' => (($cmd === 'single_mail' || $cmd === 'single_activity') ? true : false),
|
||||
'location' => $location,
|
||||
'request' => $request,
|
||||
'normal_mode' => $normal_mode,
|
||||
'packet_type' => $packet_type,
|
||||
'walltowall' => $walltowall,
|
||||
'queued' => []
|
||||
];
|
||||
|
||||
|
||||
call_hooks('notifier_hub',$narr);
|
||||
@@ -582,13 +598,13 @@ class Notifier {
|
||||
}
|
||||
|
||||
// singleton deliveries by definition 'not got zot'.
|
||||
// Single deliveries are other federated networks (plugins) and we're essentially
|
||||
// Single deliveries are other federated networks (plugins) and we're essentially
|
||||
// delivering only to those that have this site url in their abook_instance
|
||||
// and only from within a sync operation. This means if you post from a clone,
|
||||
// and a connection is connected to one of your other clones; assuming that hub
|
||||
// is running it will receive a sync packet. On receipt of this sync packet it
|
||||
// will invoke a delivery to those connections which are connected to just that
|
||||
// hub instance.
|
||||
// hub instance.
|
||||
|
||||
if($cmd === 'single_mail' || $cmd === 'single_activity') {
|
||||
continue;
|
||||
@@ -596,14 +612,20 @@ class Notifier {
|
||||
|
||||
// default: zot protocol
|
||||
|
||||
$hash = random_string();
|
||||
$hash = random_string();
|
||||
$packet = null;
|
||||
$pmsg = '';
|
||||
|
||||
if($packet_type === 'refresh' || $packet_type === 'purge') {
|
||||
$packet = zot_build_packet($channel,$packet_type,(($packet_recips) ? $packet_recips : null));
|
||||
}
|
||||
if($packet_type === 'keychange') {
|
||||
$packet = zot_build_packet($channel,$packet_type,(($packet_recips) ? $packet_recips : null));
|
||||
$pmsg = get_pconfig($channel['channel_id'],'system','keychange');
|
||||
}
|
||||
elseif($packet_type === 'request') {
|
||||
$packet = zot_build_packet($channel,$packet_type,$env_recips,$hub['hubloc_sitekey'],$hub['site_crypto'],
|
||||
$env = (($hub_env && $hub_env[$hub['hubloc_host'] . $hub['hubloc_sitekey']]) ? $hub_env[$hub['hubloc_host'] . $hub['hubloc_sitekey']] : '');
|
||||
$packet = zot_build_packet($channel,$packet_type,$env,$hub['hubloc_sitekey'],$hub['site_crypto'],
|
||||
$hash, array('message_id' => $request_message_id)
|
||||
);
|
||||
}
|
||||
@@ -614,19 +636,23 @@ class Notifier {
|
||||
'account_id' => $channel['channel_account_id'],
|
||||
'channel_id' => $channel['channel_id'],
|
||||
'posturl' => $hub['hubloc_callback'],
|
||||
'notify' => $packet
|
||||
'notify' => $packet,
|
||||
'msg' => (($pmsg) ? json_encode($pmsg) : '')
|
||||
));
|
||||
}
|
||||
else {
|
||||
$packet = zot_build_packet($channel,'notify',$env_recips,(($private) ? $hub['hubloc_sitekey'] : null), $hub['site_crypto'],$hash);
|
||||
queue_insert(array(
|
||||
'hash' => $hash,
|
||||
'account_id' => $target_item['aid'],
|
||||
'channel_id' => $target_item['uid'],
|
||||
'posturl' => $hub['hubloc_callback'],
|
||||
'notify' => $packet,
|
||||
'msg' => json_encode($encoded_item)
|
||||
));
|
||||
$env = (($hub_env && $hub_env[$hub['hubloc_host'] . $hub['hubloc_sitekey']]) ? $hub_env[$hub['hubloc_host'] . $hub['hubloc_sitekey']] : '');
|
||||
$packet = zot_build_packet($channel,'notify',$env,(($private) ? $hub['hubloc_sitekey'] : null), $hub['site_crypto'],$hash);
|
||||
queue_insert(
|
||||
[
|
||||
'hash' => $hash,
|
||||
'account_id' => $target_item['aid'],
|
||||
'channel_id' => $target_item['uid'],
|
||||
'posturl' => $hub['hubloc_callback'],
|
||||
'notify' => $packet,
|
||||
'msg' => json_encode($encoded_item)
|
||||
]
|
||||
);
|
||||
|
||||
// only create delivery reports for normal undeleted items
|
||||
if(is_array($target_item) && array_key_exists('postopts',$target_item) && (! $target_item['item_deleted']) && (! get_config('system','disable_dreport'))) {
|
||||
@@ -647,9 +673,9 @@ class Notifier {
|
||||
|
||||
if($normal_mode) {
|
||||
$x = q("select * from hook where hook = 'notifier_normal'");
|
||||
if($x)
|
||||
Master::Summon(array('Deliver_hooks',$target_item['id']));
|
||||
|
||||
if($x) {
|
||||
Master::Summon( [ 'Deliver_hooks', $target_item['id'] ] );
|
||||
}
|
||||
}
|
||||
|
||||
if($deliveries)
|
||||
|
||||
@@ -118,13 +118,29 @@ class Onepoll {
|
||||
|
||||
if($fetch_feed) {
|
||||
|
||||
$feedurl = str_replace('/poco/','/zotfeed/',$contact['xchan_connurl']);
|
||||
$feedurl .= '?f=&mindate=' . urlencode($last_update);
|
||||
if(strpos($contact['xchan_connurl'],z_root()) === 0) {
|
||||
// local channel - save a network fetch
|
||||
$c = channelx_by_hash($contact['xchan_hash']);
|
||||
if($c) {
|
||||
$x = [
|
||||
'success' => true,
|
||||
'body' => json_encode( [
|
||||
'success' => true,
|
||||
'messages' => zot_feed($c['channel_id'], $importer['xchan_hash'], [ 'mindate' => $last_update ])
|
||||
])
|
||||
];
|
||||
}
|
||||
}
|
||||
else {
|
||||
// remote fetch
|
||||
|
||||
$x = z_fetch_url($feedurl);
|
||||
$feedurl = str_replace('/poco/','/zotfeed/',$contact['xchan_connurl']);
|
||||
$feedurl .= '?f=&mindate=' . urlencode($last_update) . '&zid=' . $importer['channel_address'] . '@' . \App::get_hostname();
|
||||
$recurse = 0;
|
||||
$x = z_fetch_url($feedurl, false, $recurse, [ 'session' => true ]);
|
||||
}
|
||||
|
||||
logger('feed_update: ' . print_r($x,true), LOGGER_DATA);
|
||||
|
||||
}
|
||||
|
||||
if(($x) && ($x['success'])) {
|
||||
|
||||
@@ -12,6 +12,7 @@ class Queue {
|
||||
require_once('include/items.php');
|
||||
require_once('include/bbcode.php');
|
||||
|
||||
|
||||
if(argc() > 1)
|
||||
$queue_id = argv(1);
|
||||
else
|
||||
|
||||
@@ -88,6 +88,14 @@ class Ratenotif {
|
||||
'msg' => json_encode($encoded_item)
|
||||
));
|
||||
|
||||
|
||||
$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',300))) {
|
||||
logger('immediate delivery deferred.', LOGGER_DEBUG, LOG_INFO);
|
||||
update_queue_item($hash);
|
||||
continue;
|
||||
}
|
||||
|
||||
$deliver[] = $hash;
|
||||
|
||||
if(count($deliver) >= $deliveries_per_process) {
|
||||
|
||||
78
Zotlabs/Daemon/Thumbnail.php
Normal file
78
Zotlabs/Daemon/Thumbnail.php
Normal file
@@ -0,0 +1,78 @@
|
||||
<?php /** @file */
|
||||
|
||||
namespace Zotlabs\Daemon;
|
||||
|
||||
|
||||
class Thumbnail {
|
||||
|
||||
static public function run($argc,$argv) {
|
||||
|
||||
if(! $argc == 2)
|
||||
return;
|
||||
|
||||
$c = q("select * from attach where hash = '%s' ",
|
||||
dbesc($argv[1])
|
||||
);
|
||||
|
||||
if(! $c)
|
||||
return;
|
||||
|
||||
$attach = $c[0];
|
||||
|
||||
$preview_style = intval(get_config('system','thumbnail_security',0));
|
||||
$preview_width = intval(get_config('system','thumbnail_width',300));
|
||||
$preview_height = intval(get_config('system','thumbnail_height',300));
|
||||
|
||||
$p = [
|
||||
'attach' => $attach,
|
||||
'preview_style' => $preview_style,
|
||||
'preview_width' => $preview_width,
|
||||
'preview_height' => $preview_height,
|
||||
'thumbnail' => null
|
||||
];
|
||||
|
||||
/**
|
||||
* @hooks thumbnail
|
||||
* * \e array \b attach
|
||||
* * \e int \b preview_style
|
||||
* * \e int \b preview_width
|
||||
* * \e int \b preview_height
|
||||
* * \e string \b thumbnail
|
||||
*/
|
||||
|
||||
call_hooks('thumbnail',$p);
|
||||
if($p['thumbnail']) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
$default_controller = null;
|
||||
|
||||
$files = glob('Zotlabs/Thumbs/*.php');
|
||||
if($files) {
|
||||
foreach($files as $f) {
|
||||
$clsname = '\\Zotlabs\\Thumbs\\' . ucfirst(basename($f,'.php'));
|
||||
if(class_exists($clsname)) {
|
||||
$x = new $clsname();
|
||||
if(method_exists($x,'Match')) {
|
||||
$matched = $x->Match($attach['filetype']);
|
||||
if($matched) {
|
||||
$x->Thumb($attach,$preview_style,$preview_width,$preview_height);
|
||||
}
|
||||
}
|
||||
if(method_exists($x,'MatchDefault')) {
|
||||
$default_matched = $x->MatchDefault(substr($attach['filetype'],0,strpos($attach['filetype'],'/')));
|
||||
if($default_matched) {
|
||||
$default_controller = $x;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(($default_controller)
|
||||
&& ((! file_exists(dbunescbin($attach['content']) . '.thumb'))
|
||||
|| (filectime(dbunescbin($attach['content']) . 'thumb') < (time() - 60)))) {
|
||||
$default_controller->Thumb($attach,$preview_style,$preview_width,$preview_height);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,12 @@
|
||||
|
||||
namespace Zotlabs\Extend;
|
||||
|
||||
use App;
|
||||
|
||||
/**
|
||||
* @brief Hook class.
|
||||
*
|
||||
*/
|
||||
class Hook {
|
||||
|
||||
static public function register($hook,$file,$function,$version = 1,$priority = 0) {
|
||||
@@ -40,6 +45,15 @@ class Hook {
|
||||
return $r;
|
||||
}
|
||||
|
||||
static public function register_array($file,$arr) {
|
||||
if($arr) {
|
||||
foreach($arr as $k => $v) {
|
||||
self::register($k,$file,$v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static public function unregister($hook,$file,$function,$version = 1,$priority = 0) {
|
||||
if(is_array($function)) {
|
||||
$function = serialize($function);
|
||||
@@ -55,11 +69,14 @@ class Hook {
|
||||
return $r;
|
||||
}
|
||||
|
||||
// unregister all hooks with this file component.
|
||||
// Useful for addon upgrades where you want to clean out old interfaces.
|
||||
|
||||
/**
|
||||
* @brief Unregister all hooks with this file component.
|
||||
*
|
||||
* Useful for addon upgrades where you want to clean out old interfaces.
|
||||
*
|
||||
* @param string $file
|
||||
*/
|
||||
static public function unregister_by_file($file) {
|
||||
|
||||
$r = q("DELETE FROM hook WHERE file = '%s' ",
|
||||
dbesc($file)
|
||||
);
|
||||
@@ -67,7 +84,6 @@ class Hook {
|
||||
return $r;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Inserts a hook into a page request.
|
||||
*
|
||||
@@ -89,7 +105,6 @@ class Hook {
|
||||
* @param int $priority
|
||||
* currently not implemented in this function, would require the hook array to be resorted
|
||||
*/
|
||||
|
||||
static public function insert($hook, $fn, $version = 0, $priority = 0) {
|
||||
if(is_array($fn)) {
|
||||
$fn = serialize($fn);
|
||||
|
||||
273
Zotlabs/Lib/ActivityStreams.php
Normal file
273
Zotlabs/Lib/ActivityStreams.php
Normal file
@@ -0,0 +1,273 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
/**
|
||||
* @brief ActivityStreams class.
|
||||
*
|
||||
* Parses an ActivityStream JSON string.
|
||||
*/
|
||||
class ActivityStreams {
|
||||
|
||||
public $data;
|
||||
public $valid = false;
|
||||
public $id = '';
|
||||
public $type = '';
|
||||
public $actor = null;
|
||||
public $obj = null;
|
||||
public $tgt = null;
|
||||
public $origin = null;
|
||||
public $owner = null;
|
||||
public $signer = null;
|
||||
public $ldsig = null;
|
||||
public $sigok = false;
|
||||
public $recips = null;
|
||||
public $raw_recips = null;
|
||||
|
||||
/**
|
||||
* @brief Constructor for ActivityStreams.
|
||||
*
|
||||
* Takes a JSON string as parameter, decodes it and sets up this object.
|
||||
*
|
||||
* @param string $string
|
||||
*/
|
||||
function __construct($string) {
|
||||
|
||||
$this->data = json_decode($string, true);
|
||||
if($this->data) {
|
||||
$this->valid = true;
|
||||
}
|
||||
|
||||
if($this->is_valid()) {
|
||||
$this->id = $this->get_property_obj('id');
|
||||
$this->type = $this->get_primary_type();
|
||||
$this->actor = $this->get_compound_property('actor');
|
||||
$this->obj = $this->get_compound_property('object');
|
||||
$this->tgt = $this->get_compound_property('target');
|
||||
$this->origin = $this->get_compound_property('origin');
|
||||
$this->recips = $this->collect_recips();
|
||||
|
||||
$this->ldsig = $this->get_compound_property('signature');
|
||||
if($this->ldsig) {
|
||||
$this->signer = $this->get_compound_property('creator',$this->ldsig);
|
||||
if($this->signer && $this->signer['publicKey'] && $this->signer['publicKey']['publicKeyPem']) {
|
||||
$this->sigok = \Zotlabs\Lib\LDSignatures::verify($this->data,$this->signer['publicKey']['publicKeyPem']);
|
||||
}
|
||||
}
|
||||
|
||||
if(($this->type === 'Note') && (! $this->obj)) {
|
||||
$this->obj = $this->data;
|
||||
$this->type = 'Create';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return if instantiated ActivityStream is valid.
|
||||
*
|
||||
* @return boolean Return true if the JSON string could be decoded.
|
||||
*/
|
||||
function is_valid() {
|
||||
return $this->valid;
|
||||
}
|
||||
|
||||
function set_recips($arr) {
|
||||
$this->saved_recips = $arr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Collects all recipients.
|
||||
*
|
||||
* @param string $base
|
||||
* @param string $namespace (optional) default empty
|
||||
* @return array
|
||||
*/
|
||||
function collect_recips($base = '', $namespace = '') {
|
||||
$x = [];
|
||||
$fields = [ 'to', 'cc', 'bto', 'bcc', 'audience'];
|
||||
foreach($fields as $f) {
|
||||
$y = $this->get_compound_property($f, $base, $namespace);
|
||||
if($y) {
|
||||
$x = array_merge($x, $y);
|
||||
if(! is_array($this->raw_recips))
|
||||
$this->raw_recips = [];
|
||||
|
||||
$this->raw_recips[$f] = $x;
|
||||
}
|
||||
}
|
||||
// not yet ready for prime time
|
||||
// $x = $this->expand($x,$base,$namespace);
|
||||
return $x;
|
||||
}
|
||||
|
||||
function expand($arr,$base = '',$namespace = '') {
|
||||
$ret = [];
|
||||
|
||||
// right now use a hardwired recursion depth of 5
|
||||
|
||||
for($z = 0; $z < 5; $z ++) {
|
||||
if(is_array($arr) && $arr) {
|
||||
foreach($arr as $a) {
|
||||
if(is_array($a)) {
|
||||
$ret[] = $a;
|
||||
}
|
||||
else {
|
||||
$x = $this->get_compound_property($a,$base,$namespace);
|
||||
if($x) {
|
||||
$ret = array_merge($ret,$x);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// @fixme de-duplicate
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @param array $base
|
||||
* @param string $namespace if not set return empty string
|
||||
* @return string|NULL
|
||||
*/
|
||||
function get_namespace($base, $namespace) {
|
||||
|
||||
if(! $namespace)
|
||||
return '';
|
||||
|
||||
$key = null;
|
||||
|
||||
foreach( [ $this->data, $base ] as $b ) {
|
||||
if(! $b)
|
||||
continue;
|
||||
|
||||
if(array_key_exists('@context', $b)) {
|
||||
if(is_array($b['@context'])) {
|
||||
foreach($b['@context'] as $ns) {
|
||||
if(is_array($ns)) {
|
||||
foreach($ns as $k => $v) {
|
||||
if($namespace === $v)
|
||||
$key = $k;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if($namespace === $ns) {
|
||||
$key = '';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if($namespace === $b['@context']) {
|
||||
$key = '';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $key;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @param string $property
|
||||
* @param array $base (optional)
|
||||
* @param string $namespace (optional) default empty
|
||||
* @return NULL|mixed
|
||||
*/
|
||||
function get_property_obj($property, $base = '', $namespace = '') {
|
||||
$prefix = $this->get_namespace($base, $namespace);
|
||||
if($prefix === null)
|
||||
return null;
|
||||
|
||||
$base = (($base) ? $base : $this->data);
|
||||
$propname = (($prefix) ? $prefix . ':' : '') . $property;
|
||||
|
||||
return ((array_key_exists($propname, $base)) ? $base[$propname] : null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Fetches a property from an URL.
|
||||
*
|
||||
* @param string $url
|
||||
* @return NULL|mixed
|
||||
*/
|
||||
function fetch_property($url) {
|
||||
$redirects = 0;
|
||||
if(! check_siteallowed($url)) {
|
||||
logger('blacklisted: ' . $url);
|
||||
return null;
|
||||
}
|
||||
|
||||
$x = z_fetch_url($url, true, $redirects,
|
||||
['headers' => [ 'Accept: application/ld+json; profile="https://www.w3.org/ns/activitystreams", application/activity+json' ]]);
|
||||
if($x['success'])
|
||||
return json_decode($x['body'], true);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @param string $property
|
||||
* @param array $base
|
||||
* @param string $namespace (optional) default empty
|
||||
* @return NULL|mixed
|
||||
*/
|
||||
function get_compound_property($property, $base = '', $namespace = '') {
|
||||
$x = $this->get_property_obj($property, $base, $namespace);
|
||||
if($this->is_url($x)) {
|
||||
$x = $this->fetch_property($x);
|
||||
}
|
||||
|
||||
return $x;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if string starts with http.
|
||||
*
|
||||
* @param string $url
|
||||
* @return boolean
|
||||
*/
|
||||
function is_url($url) {
|
||||
if(($url) && (! is_array($url)) && (strpos($url, 'http') === 0)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the type property.
|
||||
*
|
||||
* @param array $base
|
||||
* @param string $namespace (optional) default empty
|
||||
* @return NULL|mixed
|
||||
*/
|
||||
function get_primary_type($base = '', $namespace = '') {
|
||||
if(! $base)
|
||||
$base = $this->data;
|
||||
|
||||
$x = $this->get_property_obj('type', $base, $namespace);
|
||||
if(is_array($x)) {
|
||||
foreach($x as $y) {
|
||||
if(strpos($y, ':') === false) {
|
||||
return $y;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $x;
|
||||
}
|
||||
|
||||
function debug() {
|
||||
$x = var_export($this, true);
|
||||
return $x;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -34,7 +34,7 @@ class Apps {
|
||||
if($files) {
|
||||
foreach($files as $f) {
|
||||
$path = explode('/',$f);
|
||||
$plugin = $path[1];
|
||||
$plugin = trim($path[1]);
|
||||
if(plugin_is_installed($plugin)) {
|
||||
$x = self::parse_app_description($f,$translate);
|
||||
if($x) {
|
||||
@@ -169,6 +169,14 @@ class Apps {
|
||||
$requires = explode(',',$ret['requires']);
|
||||
foreach($requires as $require) {
|
||||
$require = trim(strtolower($require));
|
||||
$config = false;
|
||||
|
||||
if(substr($require, 0, 7) == 'config:') {
|
||||
$config = true;
|
||||
$require = ltrim($require, 'config:');
|
||||
$require = explode('=', $require);
|
||||
}
|
||||
|
||||
switch($require) {
|
||||
case 'nologin':
|
||||
if(local_channel())
|
||||
@@ -191,10 +199,13 @@ class Apps {
|
||||
unset($ret);
|
||||
break;
|
||||
default:
|
||||
if(! (local_channel() && feature_enabled(local_channel(),$require)))
|
||||
if($config)
|
||||
$unset = ((get_config('system', $require[0]) == $require[1]) ? false : true);
|
||||
else
|
||||
$unset = ((local_channel() && feature_enabled(local_channel(),$require)) ? false : true);
|
||||
if($unset)
|
||||
unset($ret);
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -209,7 +220,9 @@ class Apps {
|
||||
|
||||
static public function translate_system_apps(&$arr) {
|
||||
$apps = array(
|
||||
'Site Admin' => t('Site Admin'),
|
||||
'Apps' => t('Apps'),
|
||||
'Cards' => t('Cards'),
|
||||
'Admin' => t('Site Admin'),
|
||||
'Report Bug' => t('Report Bug'),
|
||||
'View Bookmarks' => t('View Bookmarks'),
|
||||
'My Chatrooms' => t('My Chatrooms'),
|
||||
@@ -219,7 +232,7 @@ class Apps {
|
||||
'Suggest Channels' => t('Suggest Channels'),
|
||||
'Login' => t('Login'),
|
||||
'Channel Manager' => t('Channel Manager'),
|
||||
'Grid' => t('Grid'),
|
||||
'Grid' => t('Activity'),
|
||||
'Settings' => t('Settings'),
|
||||
'Files' => t('Files'),
|
||||
'Webpages' => t('Webpages'),
|
||||
@@ -245,9 +258,19 @@ class Apps {
|
||||
'Profile Photo' => t('Profile Photo')
|
||||
);
|
||||
|
||||
if(array_key_exists($arr['name'],$apps)) {
|
||||
$arr['name'] = $apps[$arr['name']];
|
||||
if(array_key_exists('name',$arr)) {
|
||||
if(array_key_exists($arr['name'],$apps)) {
|
||||
$arr['name'] = $apps[$arr['name']];
|
||||
}
|
||||
}
|
||||
else {
|
||||
for($x = 0; $x < count($arr); $x++) {
|
||||
if(array_key_exists($arr[$x]['name'],$apps)) {
|
||||
$arr[$x]['name'] = $apps[$arr[$x]['name']];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -275,7 +298,7 @@ class Apps {
|
||||
|
||||
self::translate_system_apps($papp);
|
||||
|
||||
if(($papp['plugin']) && (! plugin_is_installed($papp['plugin'])))
|
||||
if(trim($papp['plugin']) && (! plugin_is_installed(trim($papp['plugin']))))
|
||||
return '';
|
||||
|
||||
$papp['papp'] = self::papp_encode($papp);
|
||||
@@ -294,8 +317,17 @@ class Apps {
|
||||
|
||||
if($k === 'requires') {
|
||||
$requires = explode(',',$v);
|
||||
|
||||
foreach($requires as $require) {
|
||||
$require = trim(strtolower($require));
|
||||
$config = false;
|
||||
|
||||
if(substr($require, 0, 7) == 'config:') {
|
||||
$config = true;
|
||||
$require = ltrim($require, 'config:');
|
||||
$require = explode('=', $require);
|
||||
}
|
||||
|
||||
switch($require) {
|
||||
case 'nologin':
|
||||
if(local_channel())
|
||||
@@ -319,10 +351,13 @@ class Apps {
|
||||
return '';
|
||||
break;
|
||||
default:
|
||||
if(! (local_channel() && feature_enabled(local_channel(),$require)))
|
||||
if($config)
|
||||
$unset = ((get_config('system', $require[0]) === $require[1]) ? false : true);
|
||||
else
|
||||
$unset = ((local_channel() && feature_enabled(local_channel(),$require)) ? false : true);
|
||||
if($unset)
|
||||
return '';
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -348,6 +383,13 @@ class Apps {
|
||||
$install_action = (($installed) ? t('Update') : t('Install'));
|
||||
$icon = ((strpos($papp['photo'],'icon:') === 0) ? substr($papp['photo'],5) : '');
|
||||
|
||||
if($mode === 'navbar') {
|
||||
return replace_macros(get_markup_template('app_nav.tpl'),array(
|
||||
'$app' => $papp,
|
||||
'$icon' => $icon,
|
||||
));
|
||||
}
|
||||
|
||||
return replace_macros(get_markup_template('app.tpl'),array(
|
||||
'$app' => $papp,
|
||||
'$icon' => $icon,
|
||||
@@ -359,10 +401,15 @@ class Apps {
|
||||
'$undelete' => ((local_channel() && $installed && $mode == 'edit') ? t('Undelete') : ''),
|
||||
'$deleted' => $papp['deleted'],
|
||||
'$feature' => (($papp['embed']) ? false : true),
|
||||
'$pin' => (($papp['embed']) ? false : true),
|
||||
'$featured' => ((strpos($papp['categories'], 'nav_featured_app') === false) ? false : true),
|
||||
'$pinned' => ((strpos($papp['categories'], 'nav_pinned_app') === false) ? false : true),
|
||||
'$navapps' => (($mode == 'nav') ? true : false),
|
||||
'$order' => (($mode == 'nav-order') ? true : false),
|
||||
'$add' => t('Add to app-tray'),
|
||||
'$remove' => t('Remove from app-tray')
|
||||
'$remove' => t('Remove from app-tray'),
|
||||
'$add_nav' => t('Pin to navbar'),
|
||||
'$remove_nav' => t('Unpin from navbar')
|
||||
));
|
||||
}
|
||||
|
||||
@@ -455,25 +502,27 @@ class Apps {
|
||||
}
|
||||
}
|
||||
|
||||
static public function app_feature($uid,$app) {
|
||||
static public function app_feature($uid,$app,$term) {
|
||||
$r = q("select id from app where app_id = '%s' and app_channel = %d limit 1",
|
||||
dbesc($app['guid']),
|
||||
intval($uid)
|
||||
);
|
||||
|
||||
$x = q("select * from term where otype = %d and oid = %d and term = 'nav_featured_app' limit 1",
|
||||
$x = q("select * from term where otype = %d and oid = %d and term = '%s' limit 1",
|
||||
intval(TERM_OBJ_APP),
|
||||
intval($r[0]['id'])
|
||||
intval($r[0]['id']),
|
||||
dbesc($term)
|
||||
);
|
||||
|
||||
if($x) {
|
||||
q("delete from term where otype = %d and oid = %d and term = 'nav_featured_app'",
|
||||
q("delete from term where otype = %d and oid = %d and term = '%s'",
|
||||
intval(TERM_OBJ_APP),
|
||||
intval($x[0]['oid'])
|
||||
intval($x[0]['oid']),
|
||||
dbesc($term)
|
||||
);
|
||||
}
|
||||
else {
|
||||
store_item_tag($uid,$r[0]['id'],TERM_OBJ_APP,TERM_CATEGORY,'nav_featured_app',escape_tags(z_root() . '/apps/?f=&cat=nav_featured_app'));
|
||||
store_item_tag($uid, $r[0]['id'], TERM_OBJ_APP, TERM_CATEGORY, $term, escape_tags(z_root() . '/apps/?f=&cat=' . $term));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -488,16 +537,27 @@ class Apps {
|
||||
}
|
||||
|
||||
|
||||
static public function app_list($uid, $deleted = false, $cat = '') {
|
||||
static public function app_list($uid, $deleted = false, $cats = []) {
|
||||
if($deleted)
|
||||
$sql_extra = "";
|
||||
else
|
||||
$sql_extra = " and app_deleted = 0 ";
|
||||
|
||||
if($cat) {
|
||||
$r = q("select oid from term where otype = %d and term = '%s'",
|
||||
intval(TERM_OBJ_APP),
|
||||
dbesc($cat)
|
||||
if($cats) {
|
||||
|
||||
$cat_sql_extra = " and ( ";
|
||||
|
||||
foreach($cats as $cat) {
|
||||
if(strpos($cat_sql_extra, 'term'))
|
||||
$cat_sql_extra .= "or ";
|
||||
|
||||
$cat_sql_extra .= "term = '" . dbesc($cat) . "' ";
|
||||
}
|
||||
|
||||
$cat_sql_extra .= ") ";
|
||||
|
||||
$r = q("select oid from term where otype = %d $cat_sql_extra",
|
||||
intval(TERM_OBJ_APP)
|
||||
);
|
||||
if(! $r)
|
||||
return $r;
|
||||
@@ -529,6 +589,129 @@ class Apps {
|
||||
return($r);
|
||||
}
|
||||
|
||||
static public function app_order($uid,$apps) {
|
||||
|
||||
if(! $apps)
|
||||
return $apps;
|
||||
|
||||
$x = (($uid) ? get_pconfig($uid,'system','app_order') : get_config('system','app_order'));
|
||||
if(($x) && (! is_array($x))) {
|
||||
$y = explode(',',$x);
|
||||
$y = array_map('trim',$y);
|
||||
$x = $y;
|
||||
}
|
||||
|
||||
if(! (is_array($x) && ($x)))
|
||||
return $apps;
|
||||
|
||||
$ret = [];
|
||||
foreach($x as $xx) {
|
||||
$y = self::find_app_in_array($xx,$apps);
|
||||
if($y) {
|
||||
$ret[] = $y;
|
||||
}
|
||||
}
|
||||
foreach($apps as $ap) {
|
||||
if(! self::find_app_in_array($ap['name'],$ret)) {
|
||||
$ret[] = $ap;
|
||||
}
|
||||
}
|
||||
return $ret;
|
||||
|
||||
}
|
||||
|
||||
static function find_app_in_array($name,$arr) {
|
||||
if(! $arr)
|
||||
return false;
|
||||
foreach($arr as $x) {
|
||||
if($x['name'] === $name) {
|
||||
return $x;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static function moveup($uid,$guid) {
|
||||
$syslist = array();
|
||||
$list = self::app_list($uid, false, ['nav_featured_app', 'nav_pinned_app']);
|
||||
if($list) {
|
||||
foreach($list as $li) {
|
||||
$syslist[] = self::app_encode($li);
|
||||
}
|
||||
}
|
||||
self::translate_system_apps($syslist);
|
||||
|
||||
usort($syslist,'self::app_name_compare');
|
||||
|
||||
$syslist = self::app_order($uid,$syslist);
|
||||
|
||||
if(! $syslist)
|
||||
return;
|
||||
|
||||
$newlist = [];
|
||||
|
||||
foreach($syslist as $k => $li) {
|
||||
if($li['guid'] === $guid) {
|
||||
$position = $k;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(! $position)
|
||||
return;
|
||||
$dest_position = $position - 1;
|
||||
$saved = $syslist[$dest_position];
|
||||
$syslist[$dest_position] = $syslist[$position];
|
||||
$syslist[$position] = $saved;
|
||||
|
||||
$narr = [];
|
||||
foreach($syslist as $x) {
|
||||
$narr[] = $x['name'];
|
||||
}
|
||||
|
||||
set_pconfig($uid,'system','app_order',implode(',',$narr));
|
||||
|
||||
}
|
||||
|
||||
static function movedown($uid,$guid) {
|
||||
$syslist = array();
|
||||
$list = self::app_list($uid, false, ['nav_featured_app', 'nav_pinned_app']);
|
||||
if($list) {
|
||||
foreach($list as $li) {
|
||||
$syslist[] = self::app_encode($li);
|
||||
}
|
||||
}
|
||||
self::translate_system_apps($syslist);
|
||||
|
||||
usort($syslist,'self::app_name_compare');
|
||||
|
||||
$syslist = self::app_order($uid,$syslist);
|
||||
|
||||
if(! $syslist)
|
||||
return;
|
||||
|
||||
$newlist = [];
|
||||
|
||||
foreach($syslist as $k => $li) {
|
||||
if($li['guid'] === $guid) {
|
||||
$position = $k;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if($position >= count($syslist) - 1)
|
||||
return;
|
||||
$dest_position = $position + 1;
|
||||
$saved = $syslist[$dest_position];
|
||||
$syslist[$dest_position] = $syslist[$position];
|
||||
$syslist[$position] = $saved;
|
||||
|
||||
$narr = [];
|
||||
foreach($syslist as $x) {
|
||||
$narr[] = $x['name'];
|
||||
}
|
||||
|
||||
set_pconfig($uid,'system','app_order',implode(',',$narr));
|
||||
|
||||
}
|
||||
|
||||
static public function app_decode($s) {
|
||||
$x = base64_decode(str_replace(array('<br />',"\r","\n",' '),array('','','',''),$s));
|
||||
@@ -565,7 +748,7 @@ class Apps {
|
||||
$darray['app_addr'] = ((x($arr,'addr')) ? escape_tags($arr['addr']) : '');
|
||||
$darray['app_price'] = ((x($arr,'price')) ? escape_tags($arr['price']) : '');
|
||||
$darray['app_page'] = ((x($arr,'page')) ? escape_tags($arr['page']) : '');
|
||||
$darray['app_plugin'] = ((x($arr,'plugin')) ? escape_tags($arr['plugin']) : '');
|
||||
$darray['app_plugin'] = ((x($arr,'plugin')) ? escape_tags(trim($arr['plugin'])) : '');
|
||||
$darray['app_requires'] = ((x($arr,'requires')) ? escape_tags($arr['requires']) : '');
|
||||
$darray['app_system'] = ((x($arr,'system')) ? intval($arr['system']) : 0);
|
||||
$darray['app_deleted'] = ((x($arr,'deleted')) ? intval($arr['deleted']) : 0);
|
||||
@@ -643,7 +826,7 @@ class Apps {
|
||||
$darray['app_addr'] = ((x($arr,'addr')) ? escape_tags($arr['addr']) : '');
|
||||
$darray['app_price'] = ((x($arr,'price')) ? escape_tags($arr['price']) : '');
|
||||
$darray['app_page'] = ((x($arr,'page')) ? escape_tags($arr['page']) : '');
|
||||
$darray['app_plugin'] = ((x($arr,'plugin')) ? escape_tags($arr['plugin']) : '');
|
||||
$darray['app_plugin'] = ((x($arr,'plugin')) ? escape_tags(trim($arr['plugin'])) : '');
|
||||
$darray['app_requires'] = ((x($arr,'requires')) ? escape_tags($arr['requires']) : '');
|
||||
$darray['app_system'] = ((x($arr,'system')) ? intval($arr['system']) : 0);
|
||||
$darray['app_deleted'] = ((x($arr,'deleted')) ? intval($arr['deleted']) : 0);
|
||||
@@ -753,7 +936,7 @@ class Apps {
|
||||
$ret['system'] = $app['app_system'];
|
||||
|
||||
if($app['app_plugin'])
|
||||
$ret['plugin'] = $app['app_plugin'];
|
||||
$ret['plugin'] = trim($app['app_plugin']);
|
||||
|
||||
if($app['app_deleted'])
|
||||
$ret['deleted'] = $app['app_deleted'];
|
||||
|
||||
@@ -9,10 +9,10 @@ namespace Zotlabs\Lib;
|
||||
class Cache {
|
||||
public static function get($key) {
|
||||
|
||||
$key = substr($key,0,254);
|
||||
$hash = hash('whirlpool',$key);
|
||||
|
||||
$r = q("SELECT v FROM cache WHERE k = '%s' limit 1",
|
||||
dbesc($key)
|
||||
dbesc($hash)
|
||||
);
|
||||
|
||||
if ($r)
|
||||
@@ -22,20 +22,20 @@ class Cache {
|
||||
|
||||
public static function set($key,$value) {
|
||||
|
||||
$key = substr($key,0,254);
|
||||
$hash = hash('whirlpool',$key);
|
||||
|
||||
$r = q("SELECT * FROM cache WHERE k = '%s' limit 1",
|
||||
dbesc($key)
|
||||
dbesc($hash)
|
||||
);
|
||||
if($r) {
|
||||
q("UPDATE cache SET v = '%s', updated = '%s' WHERE k = '%s'",
|
||||
dbesc($value),
|
||||
dbesc(datetime_convert()),
|
||||
dbesc($key));
|
||||
dbesc($hash));
|
||||
}
|
||||
else {
|
||||
q("INSERT INTO cache ( k, v, updated) VALUES ('%s','%s','%s')",
|
||||
dbesc($key),
|
||||
dbesc($hash),
|
||||
dbesc($value),
|
||||
dbesc(datetime_convert()));
|
||||
}
|
||||
|
||||
@@ -2,22 +2,18 @@
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
/**
|
||||
* @brief Chat related functions.
|
||||
* @brief A class with chatroom related static methods.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
class Chatroom {
|
||||
/**
|
||||
* @brief Creates a chatroom.
|
||||
*
|
||||
* @param array $channel
|
||||
* @param array $arr
|
||||
* @return An associative array containing:
|
||||
* - success: A boolean
|
||||
* - message: (optional) A string
|
||||
* @return array An associative array containing:
|
||||
* * \e boolean \b success - A boolean success status
|
||||
* * \e string \b message - (optional) A string
|
||||
*/
|
||||
|
||||
static public function create($channel, $arr) {
|
||||
|
||||
$ret = array('success' => false);
|
||||
@@ -150,8 +146,8 @@ class Chatroom {
|
||||
}
|
||||
|
||||
if(intval($x[0]['cr_expire'])) {
|
||||
$r = q("delete from chat where created < %s - INTERVAL %s and chat_room = %d",
|
||||
db_utcnow(),
|
||||
$r = q("delete from chat where created < %s - INTERVAL %s and chat_room = %d",
|
||||
db_utcnow(),
|
||||
db_quoteinterval( intval($x[0]['cr_expire']) . ' MINUTE' ),
|
||||
intval($x[0]['cr_id'])
|
||||
);
|
||||
@@ -225,10 +221,16 @@ class Chatroom {
|
||||
}
|
||||
|
||||
/**
|
||||
* create a chat message via API.
|
||||
* @brief Create a chat message via API.
|
||||
*
|
||||
* It is the caller's responsibility to enter the room.
|
||||
*/
|
||||
|
||||
*
|
||||
* @param int $uid
|
||||
* @param int $room_id
|
||||
* @param string $xchan
|
||||
* @param string $text
|
||||
* @return array
|
||||
*/
|
||||
static public function message($uid, $room_id, $xchan, $text) {
|
||||
|
||||
$ret = array('success' => false);
|
||||
@@ -245,12 +247,18 @@ class Chatroom {
|
||||
if(! $r)
|
||||
return $ret;
|
||||
|
||||
$arr = array(
|
||||
$arr = [
|
||||
'chat_room' => $room_id,
|
||||
'chat_xchan' => $xchan,
|
||||
'chat_text' => $text
|
||||
);
|
||||
|
||||
];
|
||||
/**
|
||||
* @hooks chat_message
|
||||
* Called to create a chat message.
|
||||
* * \e int \b chat_room
|
||||
* * \e string \b chat_xchan
|
||||
* * \e string \b chat_text
|
||||
*/
|
||||
call_hooks('chat_message', $arr);
|
||||
|
||||
$x = q("insert into chat ( chat_room, chat_xchan, created, chat_text )
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<?php /** @file */
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
@@ -14,7 +14,6 @@ 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();
|
||||
@@ -30,7 +29,7 @@ class Config {
|
||||
}
|
||||
\App::$config[$family]['config_loaded'] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -47,13 +46,12 @@ class Config {
|
||||
* @return mixed
|
||||
* Return the set value, or false if the database update failed
|
||||
*/
|
||||
|
||||
static public function Set($family,$key,$value) {
|
||||
static public function Set($family, $key, $value) {
|
||||
// manage array value
|
||||
$dbvalue = ((is_array($value)) ? serialize($value) : $value);
|
||||
$dbvalue = ((is_bool($dbvalue)) ? intval($dbvalue) : $dbvalue);
|
||||
|
||||
if(get_config($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),
|
||||
@@ -76,8 +74,8 @@ class Config {
|
||||
\App::$config[$family][$key] = $value;
|
||||
$ret = $value;
|
||||
}
|
||||
return $ret;
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -88,25 +86,25 @@ class Config {
|
||||
* $key from a cached storage in App::$config[$family]. If a key is found in the
|
||||
* DB but does not exist in local config cache, pull it into the cache so we
|
||||
* do not have to hit the DB again for this item.
|
||||
*
|
||||
*
|
||||
* Returns false if not set.
|
||||
*
|
||||
* @param string $family
|
||||
* The category of the configuration value
|
||||
* @param string $key
|
||||
* The configuration key to query
|
||||
* @param string $default (optional) default false
|
||||
* @return mixed Return value or false on error or if not set
|
||||
*/
|
||||
|
||||
static public function Get($family,$key,$default = false) {
|
||||
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);
|
||||
|
||||
if(array_key_exists('config_loaded', \App::$config[$family])) {
|
||||
if(! array_key_exists($key, \App::$config[$family])) {
|
||||
return $default;
|
||||
return $default;
|
||||
}
|
||||
return ((! is_array(\App::$config[$family][$key])) && (preg_match('|^a:[0-9]+:{.*}$|s', \App::$config[$family][$key]))
|
||||
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]
|
||||
);
|
||||
@@ -127,17 +125,18 @@ class Config {
|
||||
* The configuration key to delete
|
||||
* @return mixed
|
||||
*/
|
||||
|
||||
static public function Delete($family,$key) {
|
||||
static public 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]);
|
||||
$ret = q("DELETE FROM config WHERE cat = '%s' AND k = '%s'",
|
||||
|
||||
$ret = q("DELETE FROM config WHERE cat = '%s' AND k = '%s'",
|
||||
dbesc($family),
|
||||
dbesc($key)
|
||||
);
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
@@ -154,12 +153,12 @@ class Config {
|
||||
* The configuration key to query
|
||||
* @return mixed
|
||||
*/
|
||||
|
||||
static private function get_from_storage($family,$key) {
|
||||
$ret = q("SELECT * FROM config WHERE cat = '%s' AND k = '%s' LIMIT 1",
|
||||
dbesc($family),
|
||||
dbesc($key)
|
||||
);
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
121
Zotlabs/Lib/DB_Upgrade.php
Normal file
121
Zotlabs/Lib/DB_Upgrade.php
Normal file
@@ -0,0 +1,121 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
|
||||
class DB_Upgrade {
|
||||
|
||||
public $config_name = '';
|
||||
public $func_prefix = '';
|
||||
|
||||
function __construct($db_revision) {
|
||||
|
||||
$platform_name = System::get_platform_name();
|
||||
|
||||
$update_file = 'install/' . $platform_name . '/update.php';
|
||||
if(! file_exists($update_file)) {
|
||||
$update_file = 'install/update.php';
|
||||
$this->config_name = 'db_version';
|
||||
$this->func_prefix = 'update_r';
|
||||
}
|
||||
else {
|
||||
$this->config_name = $platform_name . '_db_version';
|
||||
$this->func_prefix = $platform_name . '_update_';
|
||||
}
|
||||
|
||||
$build = get_config('system', $this->config_name, 0);
|
||||
if(! intval($build))
|
||||
$build = set_config('system', $this->config_name, $db_revision);
|
||||
|
||||
if($build == $db_revision) {
|
||||
// Nothing to be done.
|
||||
return;
|
||||
}
|
||||
else {
|
||||
$stored = intval($build);
|
||||
if(! $stored) {
|
||||
logger('Critical: check_config unable to determine database schema version');
|
||||
return;
|
||||
}
|
||||
|
||||
$current = intval($db_revision);
|
||||
|
||||
if(($stored < $current) && file_exists($update_file)) {
|
||||
|
||||
Config::Load('database');
|
||||
|
||||
// We're reporting a different version than what is currently installed.
|
||||
// Run any existing update scripts to bring the database up to current.
|
||||
|
||||
require_once($update_file);
|
||||
|
||||
// make sure that boot.php and update.php are the same release, we might be
|
||||
// updating from git right this very second and the correct version of the update.php
|
||||
// file may not be here yet. This can happen on a very busy site.
|
||||
|
||||
if($db_revision == UPDATE_VERSION) {
|
||||
for($x = $stored; $x < $current; $x ++) {
|
||||
$func = $this->func_prefix . $x;
|
||||
if(function_exists($func)) {
|
||||
// There could be a lot of processes running or about to run.
|
||||
// We want exactly one process to run the update command.
|
||||
// So store the fact that we're taking responsibility
|
||||
// after first checking to see if somebody else already has.
|
||||
|
||||
// If the update fails or times-out completely you may need to
|
||||
// delete the config entry to try again.
|
||||
|
||||
if(get_config('database', $func))
|
||||
break;
|
||||
set_config('database',$func, '1');
|
||||
// call the specific update
|
||||
|
||||
$retval = $func();
|
||||
if($retval) {
|
||||
|
||||
// Prevent sending hundreds of thousands of emails by creating
|
||||
// a lockfile.
|
||||
|
||||
$lockfile = 'store/[data]/mailsent';
|
||||
|
||||
if ((file_exists($lockfile)) && (filemtime($lockfile) > (time() - 86400)))
|
||||
return;
|
||||
@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'])
|
||||
);
|
||||
push_lang(($r) ? $r[0]['account_language'] : 'en');
|
||||
|
||||
z_mail(
|
||||
[
|
||||
'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'),
|
||||
[
|
||||
'$sitename' => \App::$config['system']['sitename'],
|
||||
'$siteurl' => z_root(),
|
||||
'$update' => $x,
|
||||
'$error' => sprintf( t('Update %s failed. See error logs.'), $x)
|
||||
]
|
||||
)
|
||||
]
|
||||
);
|
||||
|
||||
//try the logger
|
||||
logger('CRITICAL: Update Failed: ' . $x);
|
||||
pop_lang();
|
||||
}
|
||||
else {
|
||||
set_config('database',$func, 'success');
|
||||
}
|
||||
}
|
||||
}
|
||||
set_config('system', $this->config_name, $db_revision);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -67,7 +67,7 @@ class Enotify {
|
||||
$sender_name = $product;
|
||||
$hostname = \App::get_hostname();
|
||||
if(strpos($hostname,':'))
|
||||
$hostname = substr($hostname,0,strpos($hostname,':'));
|
||||
$hostname = substr($hostname,0,strpos($hostname,':'));
|
||||
|
||||
// Do not translate 'noreply' as it must be a legal 7-bit email address
|
||||
|
||||
@@ -77,7 +77,7 @@ class Enotify {
|
||||
|
||||
$sender_email = get_config('system','from_email');
|
||||
if(! $sender_email)
|
||||
$sender_email = 'Administrator' . '@' . \App::get_hostname();
|
||||
$sender_email = 'Administrator' . '@' . $hostname;
|
||||
|
||||
$sender_name = get_config('system','from_email_name');
|
||||
if(! $sender_name)
|
||||
@@ -130,7 +130,9 @@ class Enotify {
|
||||
if ($params['type'] == NOTIFY_COMMENT) {
|
||||
// logger("notification: params = " . print_r($params, true), LOGGER_DEBUG);
|
||||
|
||||
$itemlink = $params['link'];
|
||||
$moderated = (($params['item']['item_blocked'] == ITEM_MODERATED) ? true : false);
|
||||
|
||||
$itemlink = $params['link'];
|
||||
|
||||
// ignore like/unlike activity on posts - they probably require a separate notification preference
|
||||
|
||||
@@ -170,7 +172,6 @@ class Enotify {
|
||||
|
||||
xchan_query($p);
|
||||
|
||||
|
||||
$item_post_type = item_post_type($p[0]);
|
||||
// $private = $p[0]['item_private'];
|
||||
$parent_id = $p[0]['id'];
|
||||
@@ -208,13 +209,21 @@ class Enotify {
|
||||
// Before this we have the name of the replier on the subject rendering
|
||||
// differents subjects for messages on the same thread.
|
||||
|
||||
$subject = sprintf( t('[$Projectname:Notify] Comment to conversation #%1$d by %2$s'), $parent_id, $sender['xchan_name']);
|
||||
if($moderated)
|
||||
$subject = sprintf( t('[$Projectname:Notify] Moderated Comment to conversation #%1$d by %2$s'), $parent_id, $sender['xchan_name']);
|
||||
else
|
||||
$subject = sprintf( t('[$Projectname:Notify] Comment to conversation #%1$d by %2$s'), $parent_id, $sender['xchan_name']);
|
||||
$preamble = sprintf( t('%1$s, %2$s commented on an item/conversation you have been following.'), $recip['channel_name'], $sender['xchan_name']);
|
||||
$epreamble = $dest_str;
|
||||
|
||||
$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>');
|
||||
if($moderated) {
|
||||
$tsitelink .= "\n\n" . sprintf( t('Please visit %s to approve or reject this comment.'), z_root() . '/moderate' );
|
||||
$hsitelink .= "<br><br>" . sprintf( t('Please visit %s to approve or reject this comment.'), '<a href="' . z_root() . '/moderate">' . z_root() . '/moderate</a>' );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ($params['type'] == NOTIFY_LIKE) {
|
||||
@@ -495,13 +504,14 @@ class Enotify {
|
||||
}
|
||||
}
|
||||
|
||||
$r = q("insert into notify (hash,xname,url,photo,created,aid,uid,link,parent,seen,ntype,verb,otype)
|
||||
values('%s','%s','%s','%s','%s',%d,%d,'%s','%s',%d,%d,'%s','%s')",
|
||||
$r = q("insert into notify (hash,xname,url,photo,created,msg,aid,uid,link,parent,seen,ntype,verb,otype)
|
||||
values('%s','%s','%s','%s','%s','%s',%d,%d,'%s','%s',%d,%d,'%s','%s')",
|
||||
dbesc($datarray['hash']),
|
||||
dbesc($datarray['xname']),
|
||||
dbesc($datarray['url']),
|
||||
dbesc($datarray['photo']),
|
||||
dbesc($datarray['created']),
|
||||
dbesc(''), // will fill this in below after the record is created
|
||||
intval($datarray['aid']),
|
||||
intval($datarray['uid']),
|
||||
dbesc($datarray['link']),
|
||||
@@ -768,10 +778,14 @@ class Enotify {
|
||||
|
||||
// Call localize_item to get a one line status for activities.
|
||||
// This should set $item['localized'] to indicate we have a brief summary.
|
||||
// and perhaps $item['shortlocalized'] for an even briefer summary
|
||||
|
||||
localize_item($item);
|
||||
|
||||
if($item['localize']) {
|
||||
if($item['shortlocalize']) {
|
||||
$itemem_text = $item['shortlocalize'];
|
||||
}
|
||||
elseif($item['localize']) {
|
||||
$itemem_text = $item['localize'];
|
||||
}
|
||||
else {
|
||||
@@ -788,7 +802,10 @@ class Enotify {
|
||||
'url' => $item['author']['xchan_url'],
|
||||
'photo' => $item['author']['xchan_photo_s'],
|
||||
'when' => relative_date($item['created']),
|
||||
'class' => (intval($item['item_unseen']) ? 'notify-unseen' : 'notify-seen'),
|
||||
'class' => (intval($item['item_unseen']) ? 'notify-unseen' : 'notify-seen'),
|
||||
'b64mid' => ((in_array($item['verb'], [ACTIVITY_LIKE, ACTIVITY_DISLIKE])) ? 'b64.' . base64url_encode($item['thr_parent']) : 'b64.' . base64url_encode($item['mid'])),
|
||||
'notify_id' => 'undefined',
|
||||
'thread_top' => (($item['item_thread_top']) ? true : false),
|
||||
'message' => strip_tags(bbcode($itemem_text))
|
||||
);
|
||||
|
||||
|
||||
38
Zotlabs/Lib/JSalmon.php
Normal file
38
Zotlabs/Lib/JSalmon.php
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
|
||||
class JSalmon {
|
||||
|
||||
static function sign($data,$key_id,$key) {
|
||||
|
||||
$arr = $data;
|
||||
$data = json_encode($data,JSON_UNESCAPED_SLASHES);
|
||||
$data = base64url_encode($data, false); // do not strip padding
|
||||
$data_type = 'application/x-zot+json';
|
||||
$encoding = 'base64url';
|
||||
$algorithm = 'RSA-SHA256';
|
||||
|
||||
$data = preg_replace('/\s+/','',$data);
|
||||
|
||||
// precomputed base64url encoding of data_type, encoding, algorithm concatenated with periods
|
||||
|
||||
$precomputed = '.' . base64url_encode($data_type,false) . '.YmFzZTY0dXJs.UlNBLVNIQTI1Ng==';
|
||||
|
||||
$signature = base64url_encode(rsa_sign($data . $precomputed, $key), false);
|
||||
|
||||
return ([
|
||||
'signed' => true,
|
||||
'data' => $data,
|
||||
'data_type' => $data_type,
|
||||
'encoding' => $encoding,
|
||||
'alg' => $algorithm,
|
||||
'sigs' => [
|
||||
'value' => $signature,
|
||||
'key_id' => base64url_encode($key_id)
|
||||
]
|
||||
]);
|
||||
|
||||
}
|
||||
}
|
||||
135
Zotlabs/Lib/LDSignatures.php
Normal file
135
Zotlabs/Lib/LDSignatures.php
Normal file
@@ -0,0 +1,135 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
require_once('library/jsonld/jsonld.php');
|
||||
|
||||
class LDSignatures {
|
||||
|
||||
|
||||
static function verify($data,$pubkey) {
|
||||
|
||||
$ohash = self::hash(self::signable_options($data['signature']));
|
||||
$dhash = self::hash(self::signable_data($data));
|
||||
|
||||
$x = rsa_verify($ohash . $dhash,base64_decode($data['signature']['signatureValue']), $pubkey);
|
||||
logger('LD-verify: ' . intval($x));
|
||||
|
||||
return $x;
|
||||
}
|
||||
|
||||
static function dopplesign(&$data,$channel) {
|
||||
// remove for the time being - performance issues
|
||||
// $data['magicEnv'] = self::salmon_sign($data,$channel);
|
||||
return self::sign($data,$channel);
|
||||
}
|
||||
|
||||
static function sign($data,$channel) {
|
||||
|
||||
$options = [
|
||||
'type' => 'RsaSignature2017',
|
||||
'nonce' => random_string(64),
|
||||
'creator' => z_root() . '/channel/' . $channel['channel_address'] . '/public_key_pem',
|
||||
'created' => datetime_convert('UTC','UTC', 'now', 'Y-m-d\Th:i:s\Z')
|
||||
];
|
||||
|
||||
$ohash = self::hash(self::signable_options($options));
|
||||
$dhash = self::hash(self::signable_data($data));
|
||||
$options['signatureValue'] = base64_encode(rsa_sign($ohash . $dhash,$channel['channel_prvkey']));
|
||||
|
||||
$signed = array_merge([
|
||||
'@context' => [
|
||||
ACTIVITYSTREAMS_JSONLD_REV,
|
||||
'https://w3id.org/security/v1' ],
|
||||
],$options);
|
||||
|
||||
return $signed;
|
||||
}
|
||||
|
||||
|
||||
static function signable_data($data) {
|
||||
|
||||
$newdata = [];
|
||||
if($data) {
|
||||
foreach($data as $k => $v) {
|
||||
if(! in_array($k,[ 'signature' ])) {
|
||||
$newdata[$k] = $v;
|
||||
}
|
||||
}
|
||||
}
|
||||
return json_encode($newdata,JSON_UNESCAPED_SLASHES);
|
||||
}
|
||||
|
||||
|
||||
static function signable_options($options) {
|
||||
|
||||
$newopts = [ '@context' => 'https://w3id.org/identity/v1' ];
|
||||
if($options) {
|
||||
foreach($options as $k => $v) {
|
||||
if(! in_array($k,[ 'type','id','signatureValue' ])) {
|
||||
$newopts[$k] = $v;
|
||||
}
|
||||
}
|
||||
}
|
||||
return json_encode($newopts,JSON_UNESCAPED_SLASHES);
|
||||
}
|
||||
|
||||
static function hash($obj) {
|
||||
|
||||
return hash('sha256',self::normalise($obj));
|
||||
}
|
||||
|
||||
static function normalise($data) {
|
||||
if(is_string($data)) {
|
||||
$data = json_decode($data);
|
||||
}
|
||||
|
||||
if(! is_object($data))
|
||||
return '';
|
||||
|
||||
jsonld_set_document_loader('jsonld_document_loader');
|
||||
|
||||
try {
|
||||
$d = jsonld_normalize($data,[ 'algorithm' => 'URDNA2015', 'format' => 'application/nquads' ]);
|
||||
}
|
||||
catch (\Exception $e) {
|
||||
logger('normalise error:' . print_r($e,true));
|
||||
logger('normalise error: ' . print_r($data,true));
|
||||
}
|
||||
|
||||
return $d;
|
||||
}
|
||||
|
||||
static function salmon_sign($data,$channel) {
|
||||
|
||||
$arr = $data;
|
||||
$data = json_encode($data,JSON_UNESCAPED_SLASHES);
|
||||
$data = base64url_encode($data, false); // do not strip padding
|
||||
$data_type = 'application/activity+json';
|
||||
$encoding = 'base64url';
|
||||
$algorithm = 'RSA-SHA256';
|
||||
$keyhash = base64url_encode(z_root() . '/channel/' . $channel['channel_address']);
|
||||
|
||||
$data = str_replace(array(" ","\t","\r","\n"),array("","","",""),$data);
|
||||
|
||||
// precomputed base64url encoding of data_type, encoding, algorithm concatenated with periods
|
||||
|
||||
$precomputed = '.' . base64url_encode($data_type,false) . '.YmFzZTY0dXJs.UlNBLVNIQTI1Ng==';
|
||||
|
||||
$signature = base64url_encode(rsa_sign($data . $precomputed,$channel['channel_prvkey']));
|
||||
|
||||
return ([
|
||||
'id' => $arr['id'],
|
||||
'meData' => $data,
|
||||
'meDataType' => $data_type,
|
||||
'meEncoding' => $encoding,
|
||||
'meAlgorithm' => $algorithm,
|
||||
'meCreator' => z_root() . '/channel/' . $channel['channel_address'] . '/public_key_pem',
|
||||
'meSignatureValue' => $signature
|
||||
]);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
103
Zotlabs/Lib/MarkdownSoap.php
Normal file
103
Zotlabs/Lib/MarkdownSoap.php
Normal file
@@ -0,0 +1,103 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
/**
|
||||
* MarkdownSoap
|
||||
* Purify Markdown for storage
|
||||
* $x = new MarkdownSoap($string_to_be_cleansed);
|
||||
* $text = $x->clean();
|
||||
*
|
||||
* What this does:
|
||||
* 1. extracts code blocks and privately escapes them from processing
|
||||
* 2. Run html purifier on the content
|
||||
* 3. put back the code blocks
|
||||
* 4. run htmlspecialchars on the entire content for safe storage
|
||||
*
|
||||
* At render time:
|
||||
* $markdown = \Zotlabs\Lib\MarkdownSoap::unescape($text);
|
||||
* $html = \Michelf\MarkdownExtra::DefaultTransform($markdown);
|
||||
*/
|
||||
|
||||
|
||||
|
||||
class MarkdownSoap {
|
||||
|
||||
private $token;
|
||||
|
||||
private $str;
|
||||
|
||||
function __construct($s) {
|
||||
$this->str = $s;
|
||||
$this->token = random_string(20);
|
||||
}
|
||||
|
||||
|
||||
function clean() {
|
||||
|
||||
$x = $this->extract_code($this->str);
|
||||
|
||||
$x = $this->purify($x);
|
||||
|
||||
$x = $this->putback_code($x);
|
||||
|
||||
$x = $this->escape($x);
|
||||
|
||||
return $x;
|
||||
}
|
||||
|
||||
function extract_code($s) {
|
||||
|
||||
$text = preg_replace_callback('{
|
||||
(?:\n\n|\A\n?)
|
||||
( # $1 = the code block -- one or more lines, starting with a space/tab
|
||||
(?>
|
||||
[ ]{'.'4'.'} # Lines must start with a tab or a tab-width of spaces
|
||||
.*\n+
|
||||
)+
|
||||
)
|
||||
((?=^[ ]{0,'.'4'.'}\S)|\Z) # Lookahead for non-space at line-start, or end of doc
|
||||
}xm',
|
||||
[ $this , 'encode_code' ], $s);
|
||||
|
||||
return $text;
|
||||
}
|
||||
|
||||
function encode_code($matches) {
|
||||
return $this->token . ';' . base64_encode($matches[0]) . ';' ;
|
||||
}
|
||||
|
||||
function decode_code($matches) {
|
||||
return base64_decode($matches[1]);
|
||||
}
|
||||
|
||||
function putback_code($s) {
|
||||
$text = preg_replace_callback('{' . $this->token . '\;(.*?)\;}xm',[ $this, 'decode_code' ], $s);
|
||||
return $text;
|
||||
}
|
||||
|
||||
function purify($s) {
|
||||
$s = $this->protect_autolinks($s);
|
||||
$s = purify_html($s);
|
||||
$s = $this->unprotect_autolinks($s);
|
||||
return $s;
|
||||
}
|
||||
|
||||
function protect_autolinks($s) {
|
||||
$s = preg_replace('/\<(https?\:\/\/)(.*?)\>/','[$1$2]($1$2)',$s);
|
||||
return $s;
|
||||
}
|
||||
|
||||
function unprotect_autolinks($s) {
|
||||
return $s;
|
||||
|
||||
}
|
||||
|
||||
function escape($s) {
|
||||
return htmlspecialchars($s,ENT_QUOTES,'UTF-8',false);
|
||||
}
|
||||
|
||||
static public function unescape($s) {
|
||||
return htmlspecialchars_decode($s,ENT_QUOTES);
|
||||
}
|
||||
}
|
||||
@@ -18,11 +18,18 @@ class NativeWiki {
|
||||
|
||||
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['mimeType'] = get_iconfig($w, 'wiki', 'mimeType');
|
||||
$w['lock'] = (($w['item_private'] || $w['allow_cid'] || $w['allow_gid'] || $w['deny_cid'] || $w['deny_gid']) ? true : false);
|
||||
$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
|
||||
@@ -84,7 +91,9 @@ class NativeWiki {
|
||||
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'];
|
||||
@@ -98,16 +107,77 @@ class NativeWiki {
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
static public 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 = %d )) ",
|
||||
$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),
|
||||
intval($resource_id)
|
||||
dbesc($resource_id)
|
||||
);
|
||||
if($r) {
|
||||
$q = q("select * from item where resource_type = 'nwikipage' and resource_id = '%s'",
|
||||
dbesc($r[0]['resource_type'])
|
||||
);
|
||||
if($q) {
|
||||
$r = array_merge($r,$q);
|
||||
}
|
||||
xchan_query($r);
|
||||
$sync_item = fetch_post_tags($r);
|
||||
build_sync_packet($uid,array('wiki' => array(encode_item($sync_item[0],true))));
|
||||
@@ -150,13 +220,15 @@ class NativeWiki {
|
||||
// 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,
|
||||
'wiki' => $w,
|
||||
'rawName' => $rawName,
|
||||
'htmlName' => escape_tags($rawName),
|
||||
'urlName' => urlencode(urlencode($rawName)),
|
||||
'mimeType' => $mimeType
|
||||
'urlName' => urlencode(urlencode($rawName)),
|
||||
'mimeType' => $mimeType,
|
||||
'typelock' => $typelock
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,19 +21,30 @@ class NativeWikiPage {
|
||||
$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 group by mid",
|
||||
$sql_extra order by title asc",
|
||||
dbesc($resource_id),
|
||||
intval($channel_id)
|
||||
);
|
||||
if($r) {
|
||||
$items = fetch_post_tags($r,true);
|
||||
$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' => urlencode(urlencode($title)),
|
||||
'url' => str_replace('%2F','/',urlencode(str_replace('%2F','/',urlencode($title)))),
|
||||
'link_id' => 'id_' . substr($resource_id, 0, 10) . '_' . $page_item['id']
|
||||
];
|
||||
}
|
||||
@@ -44,7 +55,12 @@ class NativeWikiPage {
|
||||
}
|
||||
|
||||
|
||||
static public function create_page($channel_id, $observer_hash, $name, $resource_id) {
|
||||
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);
|
||||
|
||||
@@ -52,11 +68,16 @@ class NativeWikiPage {
|
||||
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'];
|
||||
@@ -122,8 +143,14 @@ class NativeWikiPage {
|
||||
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),
|
||||
@@ -156,10 +183,11 @@ class NativeWikiPage {
|
||||
$content = $item['body'];
|
||||
|
||||
return [
|
||||
'content' => json_encode($content),
|
||||
'mimeType' => $w['mimeType'],
|
||||
'message' => '',
|
||||
'success' => true
|
||||
'content' => $content,
|
||||
'mimeType' => $w['mimeType'],
|
||||
'pageMimeType' => $item['mimetype'],
|
||||
'message' => '',
|
||||
'success' => true
|
||||
];
|
||||
}
|
||||
|
||||
@@ -307,56 +335,32 @@ class NativeWikiPage {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static public function prepare_content($s) {
|
||||
|
||||
$text = preg_replace_callback('{
|
||||
(?:\n\n|\A\n?)
|
||||
( # $1 = the code block -- one or more lines, starting with a space/tab
|
||||
(?>
|
||||
[ ]{'.'4'.'} # Lines must start with a tab or a tab-width of spaces
|
||||
.*\n+
|
||||
)+
|
||||
)
|
||||
((?=^[ ]{0,'.'4'.'}\S)|\Z) # Lookahead for non-space at line-start, or end of doc
|
||||
}xm',
|
||||
'self::nwiki_prepare_content_callback', $s);
|
||||
|
||||
return $text;
|
||||
}
|
||||
|
||||
static public function nwiki_prepare_content_callback($matches) {
|
||||
$codeblock = $matches[1];
|
||||
|
||||
$codeblock = htmlspecialchars($codeblock, ENT_NOQUOTES, UTF8, false);
|
||||
return "\n\n" . $codeblock ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static public function save_page($arr) {
|
||||
|
||||
$pageUrlName = ((array_key_exists('pageUrlName',$arr)) ? $arr['pageUrlName'] : '');
|
||||
$content = ((array_key_exists('content',$arr)) ? purify_html(Zlib\NativeWikiPage::prepare_content($arr['content'])) : '');
|
||||
$resource_id = ((array_key_exists('resource_id',$arr)) ? $arr['resource_id'] : '');
|
||||
$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);
|
||||
$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']);
|
||||
@@ -367,6 +371,7 @@ class NativeWikiPage {
|
||||
$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 ++) {
|
||||
@@ -534,6 +539,29 @@ class NativeWikiPage {
|
||||
}
|
||||
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')
|
||||
));
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Replace the instances of the string [toc] with a list element that will be populated by
|
||||
@@ -590,10 +618,13 @@ class NativeWikiPage {
|
||||
}
|
||||
|
||||
static public function get_file_ext($arr) {
|
||||
if($arr['mimeType'] == 'text/bbcode')
|
||||
if($arr['mimetype'] === 'text/bbcode')
|
||||
return '.bb';
|
||||
else
|
||||
elseif($arr['mimetype'] === 'text/markdown')
|
||||
return '.md';
|
||||
elseif($arr['mimetype'] === 'text/plain')
|
||||
return '.txt';
|
||||
|
||||
}
|
||||
|
||||
// This function is derived from
|
||||
|
||||
@@ -1,8 +1,21 @@
|
||||
<?php /** @file */
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Class for handling channel specific configurations.
|
||||
*
|
||||
* <b>PConfig</b> is used for channel specific configurations and takes a
|
||||
* <i>channel_id</i> as identifier. It stores for example which features are
|
||||
* enabled per channel. The storage is of size MEDIUMTEXT.
|
||||
*
|
||||
* @code{.php}$var = Zotlabs\Lib\PConfig::Get('uid', 'category', 'key');
|
||||
* // with default value for non existent key
|
||||
* $var = Zotlabs\Lib\PConfig::Get('uid', 'category', 'unsetkey', 'defaultvalue');@endcode
|
||||
*
|
||||
* The old (deprecated?) way to access a PConfig value is:
|
||||
* @code{.php}$var = get_pconfig(local_channel(), 'category', 'key');@endcode
|
||||
*/
|
||||
class PConfig {
|
||||
|
||||
/**
|
||||
@@ -13,18 +26,18 @@ class PConfig {
|
||||
*
|
||||
* @param string $uid
|
||||
* The channel_id
|
||||
* @return void|false Nothing or false if $uid is false
|
||||
* @return void|false Nothing or false if $uid is null or false
|
||||
*/
|
||||
|
||||
static public function Load($uid) {
|
||||
if(is_null($uid) || $uid === false)
|
||||
return false;
|
||||
|
||||
if(! array_key_exists($uid, \App::$config))
|
||||
\App::$config[$uid] = array();
|
||||
|
||||
if(! is_array(\App::$config)) {
|
||||
btlogger('App::$config not an array: ' . $uid);
|
||||
btlogger('App::$config not an array');
|
||||
}
|
||||
|
||||
if(! array_key_exists($uid, \App::$config)) {
|
||||
\App::$config[$uid] = array();
|
||||
}
|
||||
|
||||
if(! is_array(\App::$config[$uid])) {
|
||||
@@ -63,11 +76,11 @@ class PConfig {
|
||||
* The category of the configuration value
|
||||
* @param string $key
|
||||
* The configuration key to query
|
||||
* @param boolean $instore (deprecated, without function)
|
||||
* @param mixed $default (optional, default false)
|
||||
* Default value to return if key does not exist
|
||||
* @return mixed Stored value or false if it does not exist
|
||||
*/
|
||||
|
||||
static public function Get($uid,$family,$key,$default = false) {
|
||||
static public function Get($uid, $family, $key, $default = false) {
|
||||
|
||||
if(is_null($uid) || $uid === false)
|
||||
return $default;
|
||||
@@ -78,11 +91,10 @@ class PConfig {
|
||||
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]))
|
||||
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]
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -101,12 +113,11 @@ class PConfig {
|
||||
* The value to store
|
||||
* @return mixed Stored $value or false
|
||||
*/
|
||||
|
||||
static public function Set($uid, $family, $key, $value) {
|
||||
|
||||
// this catches subtle errors where this function has been called
|
||||
// this catches subtle errors where this function has been called
|
||||
// with local_channel() when not logged in (which returns false)
|
||||
// and throws an error in array_key_exists below.
|
||||
// and throws an error in array_key_exists below.
|
||||
// we provide a function backtrace in the logs so that we can find
|
||||
// and fix the calling function.
|
||||
|
||||
@@ -119,7 +130,7 @@ class PConfig {
|
||||
$dbvalue = ((is_array($value)) ? serialize($value) : $value);
|
||||
$dbvalue = ((is_bool($dbvalue)) ? intval($dbvalue) : $dbvalue);
|
||||
|
||||
if(get_pconfig($uid, $family, $key) === false) {
|
||||
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]))
|
||||
@@ -131,7 +142,6 @@ class PConfig {
|
||||
dbesc($key),
|
||||
dbesc($dbvalue)
|
||||
);
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -141,7 +151,6 @@ class PConfig {
|
||||
dbesc($family),
|
||||
dbesc($key)
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
// keep a separate copy for all variables which were
|
||||
@@ -177,7 +186,6 @@ class PConfig {
|
||||
* The configuration key to delete
|
||||
* @return mixed
|
||||
*/
|
||||
|
||||
static public function Delete($uid, $family, $key) {
|
||||
|
||||
if(is_null($uid) || $uid === false)
|
||||
@@ -185,12 +193,12 @@ class PConfig {
|
||||
|
||||
$ret = false;
|
||||
|
||||
if(array_key_exists($uid,\App::$config)
|
||||
&& is_array(\App::$config['uid'])
|
||||
&& array_key_exists($family,\App::$config['uid'])
|
||||
if(array_key_exists($uid,\App::$config)
|
||||
&& is_array(\App::$config['uid'])
|
||||
&& array_key_exists($family,\App::$config['uid'])
|
||||
&& array_key_exists($key, \App::$config[$uid][$family]))
|
||||
unset(\App::$config[$uid][$family][$key]);
|
||||
|
||||
|
||||
$ret = q("DELETE FROM pconfig WHERE uid = %d AND cat = '%s' AND k = '%s'",
|
||||
intval($uid),
|
||||
dbesc($family),
|
||||
@@ -201,4 +209,3 @@ class PConfig {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
28
Zotlabs/Lib/SConfig.php
Normal file
28
Zotlabs/Lib/SConfig.php
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
/**
|
||||
* @brief Account configuration storage is built on top of the under-utilised xconfig.
|
||||
*
|
||||
* @see XConfig
|
||||
*/
|
||||
class SConfig {
|
||||
|
||||
static public function Load($server_id) {
|
||||
return XConfig::Load('s_' . $server_id);
|
||||
}
|
||||
|
||||
static public function Get($server_id,$family,$key,$default = false) {
|
||||
return XConfig::Get('s_' . $server_id,$family,$key, $default);
|
||||
}
|
||||
|
||||
static public function Set($server_id,$family,$key,$value) {
|
||||
return XConfig::Set('s_' . $server_id,$family,$key,$value);
|
||||
}
|
||||
|
||||
static public function Delete($server_id,$family,$key) {
|
||||
return XConfig::Delete('s_' . $server_id,$family,$key);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -19,6 +19,9 @@ class System {
|
||||
static public function get_project_version() {
|
||||
if(is_array(\App::$config) && is_array(\App::$config['system']) && \App::$config['system']['hide_version'])
|
||||
return '';
|
||||
if(is_array(\App::$config) && is_array(\App::$config['system']) && array_key_exists('std_version',\App::$config['system']))
|
||||
return \App::$config['system']['std_version'];
|
||||
|
||||
return self::get_std_version();
|
||||
}
|
||||
|
||||
@@ -54,12 +57,15 @@ class System {
|
||||
return 'https://github.com/redmatrix/hubzilla';
|
||||
}
|
||||
|
||||
|
||||
|
||||
static public function get_server_role() {
|
||||
if(is_array(\App::$config) && is_array(\App::$config['system']) && \App::$config['system']['server_role'])
|
||||
return \App::$config['system']['server_role'];
|
||||
return 'standard';
|
||||
return 'pro';
|
||||
}
|
||||
|
||||
|
||||
static public function get_zot_revision() {
|
||||
$x = [ 'revision' => ZOT_REVISION ];
|
||||
call_hooks('zot_revision',$x);
|
||||
return $x['revision'];
|
||||
}
|
||||
|
||||
static public function get_std_version() {
|
||||
@@ -72,11 +78,8 @@ class System {
|
||||
|
||||
if(get_directory_realm() != DIRECTORY_REALM)
|
||||
return true;
|
||||
|
||||
foreach(['hubzilla','zap'] as $t) {
|
||||
if(stristr($p,$t))
|
||||
return true;
|
||||
}
|
||||
if(in_array(strtolower($p),['hubzilla','zap','red']))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,12 +7,12 @@ class Techlevels {
|
||||
|
||||
static public function levels() {
|
||||
$techlevels = [
|
||||
'0' => t('Beginner/Basic'),
|
||||
'1' => t('Novice - not skilled but willing to learn'),
|
||||
'2' => t('Intermediate - somewhat comfortable'),
|
||||
'3' => t('Advanced - very comfortable'),
|
||||
'4' => t('Expert - I can write computer code'),
|
||||
'5' => t('Wizard - I probably know more than you do')
|
||||
'0' => t('0. Beginner/Basic'),
|
||||
'1' => t('1. Novice - not skilled but willing to learn'),
|
||||
'2' => t('2. Intermediate - somewhat comfortable'),
|
||||
'3' => t('3. Advanced - very comfortable'),
|
||||
'4' => t('4. Expert - I can write computer code'),
|
||||
'5' => t('5. Wizard - I probably know more than you do')
|
||||
];
|
||||
return $techlevels;
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ class ThreadItem {
|
||||
private $visiting = false;
|
||||
private $channel = null;
|
||||
private $display_mode = 'normal';
|
||||
private $reload = '';
|
||||
|
||||
|
||||
public function __construct($data) {
|
||||
@@ -37,7 +38,7 @@ class ThreadItem {
|
||||
$this->toplevel = ($this->get_id() == $this->get_data_value('parent'));
|
||||
|
||||
// Prepare the children
|
||||
if(count($data['children'])) {
|
||||
if($data['children']) {
|
||||
foreach($data['children'] as $item) {
|
||||
|
||||
/*
|
||||
@@ -82,7 +83,8 @@ class ThreadItem {
|
||||
$dropping = false;
|
||||
$star = false;
|
||||
$isstarred = "unstarred fa-star-o";
|
||||
$indent = '';
|
||||
$is_comment = false;
|
||||
$is_item = false;
|
||||
$osparkle = '';
|
||||
$total_children = $this->count_descendants();
|
||||
$unseen_comments = (($item['real_uid']) ? 0 : $this->count_unseen_descendants());
|
||||
@@ -100,10 +102,23 @@ class ThreadItem {
|
||||
if($item['author']['xchan_network'] === 'rss')
|
||||
$shareable = true;
|
||||
|
||||
|
||||
$mode = $conv->get_mode();
|
||||
|
||||
switch($item['item_type']) {
|
||||
case ITEM_TYPE_CARD:
|
||||
$edlink = 'card_edit';
|
||||
break;
|
||||
case ITEM_TYPE_ARTICLE:
|
||||
$edlink = 'article_edit';
|
||||
break;
|
||||
default:
|
||||
$edlink = 'editpost';
|
||||
break;
|
||||
}
|
||||
|
||||
if(local_channel() && $observer['xchan_hash'] === $item['author_xchan'])
|
||||
$edpost = array(z_root()."/editpost/".$item['id'], t("Edit"));
|
||||
$edpost = array(z_root() . '/' . $edlink . '/' . $item['id'], t('Edit'));
|
||||
else
|
||||
$edpost = false;
|
||||
|
||||
@@ -152,7 +167,7 @@ class ThreadItem {
|
||||
$response_verbs[] = 'attendyes';
|
||||
$response_verbs[] = 'attendno';
|
||||
$response_verbs[] = 'attendmaybe';
|
||||
if($this->is_commentable()) {
|
||||
if($this->is_commentable() && $observer) {
|
||||
$isevent = true;
|
||||
$attend = array( t('I will attend'), t('I will not attend'), t('I might attend'));
|
||||
}
|
||||
@@ -163,7 +178,7 @@ class ThreadItem {
|
||||
$response_verbs[] = 'agree';
|
||||
$response_verbs[] = 'disagree';
|
||||
$response_verbs[] = 'abstain';
|
||||
if($this->is_commentable()) {
|
||||
if($this->is_commentable() && $observer) {
|
||||
$conlabels = array( t('I agree'), t('I disagree'), t('I abstain'));
|
||||
$canvote = true;
|
||||
}
|
||||
@@ -181,9 +196,9 @@ class ThreadItem {
|
||||
|
||||
$like_count = ((x($conv_responses['like'],$item['mid'])) ? $conv_responses['like'][$item['mid']] : '');
|
||||
$like_list = ((x($conv_responses['like'],$item['mid'])) ? $conv_responses['like'][$item['mid'] . '-l'] : '');
|
||||
if (count($like_list) > MAX_LIKERS) {
|
||||
if (($like_list) && (count($like_list) > MAX_LIKERS)) {
|
||||
$like_list_part = array_slice($like_list, 0, MAX_LIKERS);
|
||||
array_push($like_list_part, '<a href="#" data-toggle="modal" data-target="#likeModal-' . $this->get_id() . '"><b>' . t('View all') . '</b></a>');
|
||||
array_push($like_list_part, '<a class="dropdown-item" href="#" data-toggle="modal" data-target="#likeModal-' . $this->get_id() . '"><b>' . t('View all') . '</b></a>');
|
||||
} else {
|
||||
$like_list_part = '';
|
||||
}
|
||||
@@ -193,9 +208,9 @@ class ThreadItem {
|
||||
$dislike_count = ((x($conv_responses['dislike'],$item['mid'])) ? $conv_responses['dislike'][$item['mid']] : '');
|
||||
$dislike_list = ((x($conv_responses['dislike'],$item['mid'])) ? $conv_responses['dislike'][$item['mid'] . '-l'] : '');
|
||||
$dislike_button_label = tt('Dislike','Dislikes',$dislike_count,'noun');
|
||||
if (count($dislike_list) > MAX_LIKERS) {
|
||||
if (($dislike_list) && (count($dislike_list) > MAX_LIKERS)) {
|
||||
$dislike_list_part = array_slice($dislike_list, 0, MAX_LIKERS);
|
||||
array_push($dislike_list_part, '<a href="#" data-toggle="modal" data-target="#dislikeModal-' . $this->get_id() . '"><b>' . t('View all') . '</b></a>');
|
||||
array_push($dislike_list_part, '<a class="dropdown-item" href="#" data-toggle="modal" data-target="#dislikeModal-' . $this->get_id() . '"><b>' . t('View all') . '</b></a>');
|
||||
} else {
|
||||
$dislike_list_part = '';
|
||||
}
|
||||
@@ -232,7 +247,7 @@ class ThreadItem {
|
||||
}
|
||||
}
|
||||
else {
|
||||
$indent = 'comment';
|
||||
$is_comment = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -250,8 +265,6 @@ class ThreadItem {
|
||||
);
|
||||
}
|
||||
|
||||
$server_role = get_config('system','server_role');
|
||||
|
||||
$has_bookmarks = false;
|
||||
if(is_array($item['term'])) {
|
||||
foreach($item['term'] as $t) {
|
||||
@@ -264,7 +277,7 @@ class ThreadItem {
|
||||
if(($item['obj_type'] === ACTIVITY_OBJ_EVENT) && $conv->get_profile_owner() == local_channel())
|
||||
$has_event = true;
|
||||
|
||||
if($this->is_commentable()) {
|
||||
if($this->is_commentable() && $observer) {
|
||||
$like = array( t("I like this \x28toggle\x29"), t("like"));
|
||||
$dislike = array( t("I don't like this \x28toggle\x29"), t("dislike"));
|
||||
}
|
||||
@@ -276,13 +289,13 @@ class ThreadItem {
|
||||
|
||||
$keep_reports = intval(get_config('system','expire_delivery_reports'));
|
||||
if($keep_reports === 0)
|
||||
$keep_reports = 30;
|
||||
$keep_reports = 10;
|
||||
|
||||
if((! get_config('system','disable_dreport')) && strcmp(datetime_convert('UTC','UTC',$item['created']),datetime_convert('UTC','UTC',"now - $keep_reports days")) > 0)
|
||||
$dreport = t('Delivery Report');
|
||||
|
||||
if(strcmp(datetime_convert('UTC','UTC',$item['created']),datetime_convert('UTC','UTC','now - 12 hours')) > 0)
|
||||
$indent .= ' shiny';
|
||||
$is_new = true;
|
||||
|
||||
|
||||
localize_item($item);
|
||||
@@ -300,7 +313,7 @@ class ThreadItem {
|
||||
$comment_count_txt = sprintf( tt('%d comment','%d comments',$total_children),$total_children );
|
||||
$list_unseen_txt = (($unseen_comments) ? sprintf('%d unseen',$unseen_comments) : '');
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -310,7 +323,8 @@ class ThreadItem {
|
||||
|
||||
$tmp_item = array(
|
||||
'template' => $this->get_template(),
|
||||
'mode' => $mode,
|
||||
'mode' => $mode,
|
||||
'item_type' => intval($item['item_type']),
|
||||
'type' => implode("",array_slice(explode("/",$item['verb']),-1)),
|
||||
'body' => $body['html'],
|
||||
'tags' => $body['tags'],
|
||||
@@ -337,7 +351,6 @@ class ThreadItem {
|
||||
'profile_url' => $profile_link,
|
||||
'thread_action_menu' => thread_action_menu($item,$conv->get_mode()),
|
||||
'thread_author_menu' => thread_author_menu($item,$conv->get_mode()),
|
||||
'item_photo_menu' => item_photo_menu($item),
|
||||
'dreport' => $dreport,
|
||||
'name' => $profile_name,
|
||||
'thumb' => $profile_avatar,
|
||||
@@ -357,11 +370,13 @@ class ThreadItem {
|
||||
'unverified' => $unverified,
|
||||
'forged' => $forged,
|
||||
'location' => $location,
|
||||
'divider' => get_pconfig($conv->get_profile_owner(),'system','item_divider'),
|
||||
'attend_label' => t('Attend'),
|
||||
'attend_title' => t('Attendance Options'),
|
||||
'vote_label' => t('Vote'),
|
||||
'vote_title' => t('Voting Options'),
|
||||
'indent' => $indent,
|
||||
'is_comment' => $is_comment,
|
||||
'is_new' => $is_new,
|
||||
'owner_url' => $this->get_owner_url(),
|
||||
'owner_photo' => $this->get_owner_photo(),
|
||||
'owner_name' => $this->get_owner_name(),
|
||||
@@ -370,7 +385,7 @@ class ThreadItem {
|
||||
'has_tags' => $has_tags,
|
||||
'reactions' => $this->reactions,
|
||||
// Item toolbar buttons
|
||||
'emojis' => (($this->is_toplevel() && $this->is_commentable() && feature_enabled($conv->get_profile_owner(),'emojis')) ? '1' : ''),
|
||||
'emojis' => (($this->is_toplevel() && $this->is_commentable() && $observer && feature_enabled($conv->get_profile_owner(),'emojis')) ? '1' : ''),
|
||||
'like' => $like,
|
||||
'dislike' => ((feature_enabled($conv->get_profile_owner(),'dislike')) ? $dislike : ''),
|
||||
'share' => $share,
|
||||
@@ -407,9 +422,10 @@ class ThreadItem {
|
||||
'showlike' => $showlike,
|
||||
'showdislike' => $showdislike,
|
||||
'comment' => $this->get_comment_box($indent),
|
||||
'previewing' => ($conv->is_preview() ? ' preview ' : ''),
|
||||
'previewing' => ($conv->is_preview() ? true : false ),
|
||||
'preview_lbl' => t('This is an unsaved preview'),
|
||||
'wait' => t('Please wait'),
|
||||
'submid' => str_replace(['+','='], ['',''], base64_encode(substr($item['mid'],0,32))),
|
||||
'submid' => str_replace(['+','='], ['',''], base64_encode($item['mid'])),
|
||||
'thread_level' => $thread_level
|
||||
);
|
||||
|
||||
@@ -480,6 +496,14 @@ class ThreadItem {
|
||||
return $this->threaded;
|
||||
}
|
||||
|
||||
public function set_reload($val) {
|
||||
$this->reload = $val;
|
||||
}
|
||||
|
||||
public function get_reload() {
|
||||
return $this->reload;
|
||||
}
|
||||
|
||||
public function set_commentable($val) {
|
||||
$this->commentable = $val;
|
||||
foreach($this->get_children() as $child)
|
||||
@@ -713,11 +737,10 @@ class ThreadItem {
|
||||
call_hooks('comment_buttons',$arr);
|
||||
$comment_buttons = $arr['comment_buttons'];
|
||||
|
||||
|
||||
$comment_box = replace_macros($template,array(
|
||||
'$return_path' => '',
|
||||
'$threaded' => $this->is_threaded(),
|
||||
'$jsreload' => '', //(($conv->get_mode() === 'display') ? $_SESSION['return_url'] : ''),
|
||||
'$jsreload' => $conv->reload,
|
||||
'$type' => (($conv->get_mode() === 'channel') ? 'wall-comment' : 'net-comment'),
|
||||
'$id' => $this->get_id(),
|
||||
'$parent' => $this->get_id(),
|
||||
@@ -735,15 +758,21 @@ class ThreadItem {
|
||||
'$edquote' => t('Quote'),
|
||||
'$edcode' => t('Code'),
|
||||
'$edimg' => t('Image'),
|
||||
'$edatt' => t('Attach File'),
|
||||
'$edurl' => t('Insert Link'),
|
||||
'$edvideo' => t('Video'),
|
||||
'$preview' => t('Preview'), // ((feature_enabled($conv->get_profile_owner(),'preview')) ? t('Preview') : ''),
|
||||
'$indent' => $indent,
|
||||
'$can_upload' => (perm_is_allowed($conv->get_profile_owner(),get_observer_hash(),'write_storage') && $conv->is_uploadable()),
|
||||
'$feature_encrypt' => ((feature_enabled($conv->get_profile_owner(),'content_encrypt')) ? true : false),
|
||||
'$encrypt' => t('Encrypt text'),
|
||||
'$cipher' => $conv->get_cipher(),
|
||||
'$sourceapp' => \App::$sourcename
|
||||
|
||||
'$sourceapp' => \App::$sourcename,
|
||||
'$observer' => get_observer_hash(),
|
||||
'$anoncomments' => ((($conv->get_mode() === 'channel' || $conv->get_mode() === 'display') && perm_is_allowed($conv->get_profile_owner(),'','post_comments')) ? true : false),
|
||||
'$anonname' => [ 'anonname', t('Your full name (required)') ],
|
||||
'$anonmail' => [ 'anonmail', t('Your email address (required)') ],
|
||||
'$anonurl' => [ 'anonurl', t('Your website URL (optional)') ]
|
||||
));
|
||||
|
||||
return $comment_box;
|
||||
|
||||
@@ -18,18 +18,21 @@ class ThreadStream {
|
||||
private $observer = null;
|
||||
private $writable = false;
|
||||
private $commentable = false;
|
||||
private $uploadable = false;
|
||||
private $profile_owner = 0;
|
||||
private $preview = false;
|
||||
private $prepared_item = '';
|
||||
public $reload = '';
|
||||
private $cipher = 'aes256';
|
||||
|
||||
// $prepared_item is for use by alternate conversation structures such as photos
|
||||
// wherein we've already prepared a top level item which doesn't look anything like
|
||||
// a normal "post" item
|
||||
|
||||
public function __construct($mode, $preview, $prepared_item = '') {
|
||||
public function __construct($mode, $preview, $uploadable, $prepared_item = '') {
|
||||
$this->set_mode($mode);
|
||||
$this->preview = $preview;
|
||||
$this->uploadable = $uploadable;
|
||||
$this->prepared_item = $prepared_item;
|
||||
$c = ((local_channel()) ? get_pconfig(local_channel(),'system','default_cipher') : '');
|
||||
if($c)
|
||||
@@ -51,15 +54,34 @@ class ThreadStream {
|
||||
$this->profile_owner = local_channel();
|
||||
$this->writable = true;
|
||||
break;
|
||||
case 'pubstream':
|
||||
$this->profile_owner = local_channel();
|
||||
$this->writable = ((local_channel()) ? true : false);
|
||||
break;
|
||||
case 'hq':
|
||||
$this->profile_owner = local_channel();
|
||||
$this->writable = true;
|
||||
break;
|
||||
case 'channel':
|
||||
$this->profile_owner = \App::$profile['profile_uid'];
|
||||
$this->writable = perm_is_allowed($this->profile_owner,$ob_hash,'post_comments');
|
||||
break;
|
||||
case 'cards':
|
||||
$this->profile_owner = \App::$profile['profile_uid'];
|
||||
$this->writable = perm_is_allowed($this->profile_owner,$ob_hash,'post_comments');
|
||||
$this->reload = $_SESSION['return_url'];
|
||||
break;
|
||||
case 'articles':
|
||||
$this->profile_owner = \App::$profile['profile_uid'];
|
||||
$this->writable = perm_is_allowed($this->profile_owner,$ob_hash,'post_comments');
|
||||
$this->reload = $_SESSION['return_url'];
|
||||
break;
|
||||
case 'display':
|
||||
// in this mode we set profile_owner after initialisation (from conversation()) and then
|
||||
// pull some trickery which allows us to re-invoke this function afterward
|
||||
// it's an ugly hack so @FIXME
|
||||
$this->writable = perm_is_allowed($this->profile_owner,$ob_hash,'post_comments');
|
||||
$this->uploadable = perm_is_allowed($this->profile_owner,$ob_hash,'write_storage');
|
||||
break;
|
||||
case 'page':
|
||||
$this->profile_owner = \App::$profile['uid'];
|
||||
@@ -91,6 +113,11 @@ class ThreadStream {
|
||||
return $this->commentable;
|
||||
}
|
||||
|
||||
public function is_uploadable() {
|
||||
return $this->uploadable;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check if page is a preview
|
||||
*/
|
||||
@@ -158,13 +185,17 @@ class ThreadStream {
|
||||
if(intval($item->get_data_value('item_nocomment'))) {
|
||||
$item->set_commentable(false);
|
||||
}
|
||||
elseif(($this->observer) && (! $item->is_commentable())) {
|
||||
elseif(! $item->is_commentable()) {
|
||||
if((array_key_exists('owner',$item->data)) && intval($item->data['owner']['abook_self']))
|
||||
$item->set_commentable(perm_is_allowed($this->profile_owner,$ob_hash,'post_comments'));
|
||||
else
|
||||
$item->set_commentable(can_comment_on_post($ob_hash,$item->data));
|
||||
}
|
||||
}
|
||||
if($this->mode === 'pubstream' && (! local_channel())) {
|
||||
$item->set_commentable(false);
|
||||
}
|
||||
|
||||
require_once('include/channel.php');
|
||||
|
||||
$item->set_conversation($this);
|
||||
|
||||
@@ -2,7 +2,26 @@
|
||||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Class for handling observer's config.
|
||||
*
|
||||
* <b>XConfig</b> is comparable to <i>PConfig</i>, except that it uses <i>xchan</i>
|
||||
* (an observer hash) as an identifier.
|
||||
*
|
||||
* <b>XConfig</b> is used for observer specific configurations and takes a
|
||||
* <i>xchan</i> as identifier.
|
||||
* The storage is of size MEDIUMTEXT.
|
||||
*
|
||||
* @code{.php}$var = Zotlabs\Lib\XConfig::Get('xchan', 'category', 'key');
|
||||
* // with default value for non existent key
|
||||
* $var = Zotlabs\Lib\XConfig::Get('xchan', 'category', 'unsetkey', 'defaultvalue');@endcode
|
||||
*
|
||||
* The old (deprecated?) way to access a XConfig value is:
|
||||
* @code{.php}$observer = App::get_observer_hash();
|
||||
* if ($observer) {
|
||||
* $var = get_xconfig($observer, 'category', 'key');
|
||||
* }@endcode
|
||||
*/
|
||||
class XConfig {
|
||||
|
||||
/**
|
||||
@@ -15,7 +34,6 @@ class XConfig {
|
||||
* The observer's hash
|
||||
* @return void|false Returns false if xchan is not set
|
||||
*/
|
||||
|
||||
static public function Load($xchan) {
|
||||
|
||||
if(! $xchan)
|
||||
@@ -56,9 +74,9 @@ class XConfig {
|
||||
* The category of the configuration value
|
||||
* @param string $key
|
||||
* The configuration key to query
|
||||
* @param boolean $default (optional) default false
|
||||
* @return mixed Stored $value or false if it does not exist
|
||||
*/
|
||||
|
||||
static public function Get($xchan, $family, $key, $default = false) {
|
||||
|
||||
if(! $xchan)
|
||||
@@ -70,7 +88,7 @@ class XConfig {
|
||||
if((! array_key_exists($family, \App::$config[$xchan])) || (! array_key_exists($key, \App::$config[$xchan][$family])))
|
||||
return $default;
|
||||
|
||||
return ((! is_array(\App::$config[$xchan][$family][$key])) && (preg_match('|^a:[0-9]+:{.*}$|s', \App::$config[$xchan][$family][$key]))
|
||||
return ((! is_array(\App::$config[$xchan][$family][$key])) && (preg_match('|^a:[0-9]+:{.*}$|s', \App::$config[$xchan][$family][$key]))
|
||||
? unserialize(\App::$config[$xchan][$family][$key])
|
||||
: \App::$config[$xchan][$family][$key]
|
||||
);
|
||||
@@ -82,7 +100,6 @@ class XConfig {
|
||||
* Stores a config value ($value) in the category ($family) under the key ($key)
|
||||
* for the observer's $xchan hash.
|
||||
*
|
||||
*
|
||||
* @param string $xchan
|
||||
* The observer's hash
|
||||
* @param string $family
|
||||
@@ -93,7 +110,6 @@ class XConfig {
|
||||
* The value to store
|
||||
* @return mixed Stored $value or false
|
||||
*/
|
||||
|
||||
static public function Set($xchan, $family, $key, $value) {
|
||||
|
||||
// manage array value
|
||||
@@ -106,7 +122,7 @@ class XConfig {
|
||||
if(! array_key_exists($family, \App::$config[$xchan]))
|
||||
\App::$config[$xchan][$family] = array();
|
||||
|
||||
$ret = q("INSERT INTO xconfig ( xchan, cat, k, v ) VALUES ( '%s', '%s', '%s', '%s' ) ",
|
||||
$ret = q("INSERT INTO xconfig ( xchan, cat, k, v ) VALUES ( '%s', '%s', '%s', '%s' )",
|
||||
dbesc($xchan),
|
||||
dbesc($family),
|
||||
dbesc($key),
|
||||
@@ -126,6 +142,7 @@ class XConfig {
|
||||
|
||||
if($ret)
|
||||
return $value;
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
@@ -143,11 +160,11 @@ class XConfig {
|
||||
* The configuration key to delete
|
||||
* @return mixed
|
||||
*/
|
||||
|
||||
static public function Delete($xchan, $family, $key) {
|
||||
|
||||
if(x(\App::$config[$xchan][$family], $key))
|
||||
unset(\App::$config[$xchan][$family][$key]);
|
||||
|
||||
$ret = q("DELETE FROM xconfig WHERE xchan = '%s' AND cat = '%s' AND k = '%s'",
|
||||
dbesc($xchan),
|
||||
dbesc($family),
|
||||
|
||||
@@ -21,7 +21,7 @@ class Acl extends \Zotlabs\Web\Controller {
|
||||
|
||||
function init() {
|
||||
|
||||
// logger('mod_acl: ' . print_r($_REQUEST,true));
|
||||
logger('mod_acl: ' . print_r($_REQUEST,true));
|
||||
|
||||
$start = (x($_REQUEST,'start') ? $_REQUEST['start'] : 0);
|
||||
$count = (x($_REQUEST,'count') ? $_REQUEST['count'] : 500);
|
||||
@@ -33,6 +33,7 @@ class Acl extends \Zotlabs\Web\Controller {
|
||||
// $type =
|
||||
// '' => standard ACL request
|
||||
// 'g' => Groups only ACL request
|
||||
// 'f' => forums only ACL request
|
||||
// 'c' => Connections only ACL request or editor (textarea) mention request
|
||||
// $_REQUEST['search'] contains ACL search text.
|
||||
|
||||
@@ -56,12 +57,12 @@ class Acl extends \Zotlabs\Web\Controller {
|
||||
$search = $_REQUEST['query'];
|
||||
}
|
||||
|
||||
if( (! local_channel()) && (! ($type == 'x' || $type == 'c')))
|
||||
if( (! local_channel()) && (! in_array($type, [ 'x', 'c', 'f' ])))
|
||||
killme();
|
||||
|
||||
$permitted = [];
|
||||
|
||||
if(in_array($type, [ 'm', 'a', 'c' ])) {
|
||||
if(in_array($type, [ 'm', 'a', 'c', 'f' ])) {
|
||||
|
||||
// These queries require permission checking. We'll create a simple array of xchan_hash for those with
|
||||
// the requisite permissions which we can check against.
|
||||
@@ -154,7 +155,7 @@ class Acl extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
}
|
||||
|
||||
if($type == '' || $type == 'c') {
|
||||
if($type == '' || $type == 'c' || $type === 'f') {
|
||||
|
||||
$extra_channels_sql = '';
|
||||
|
||||
@@ -175,11 +176,18 @@ class Acl extends \Zotlabs\Web\Controller {
|
||||
$extra_channels_sql = " OR (abook_channel IN ($extra_channels_sql)) and abook_hidden = 0 ";
|
||||
|
||||
|
||||
// Add atokens belonging to the local channel @TODO restrict by search
|
||||
// Add atokens belonging to the local channel
|
||||
|
||||
if($search) {
|
||||
$sql_extra_atoken = "AND ( atoken_name LIKE " . protect_sprintf( "'%" . dbesc($search) . "%'" ) . ") ";
|
||||
}
|
||||
else {
|
||||
$sql_extra_atoken = '';
|
||||
}
|
||||
|
||||
$r2 = null;
|
||||
|
||||
$r1 = q("select * from atoken where atoken_uid = %d",
|
||||
$r1 = q("select * from atoken where atoken_uid = %d $sql_extra_atoken",
|
||||
intval(local_channel())
|
||||
);
|
||||
|
||||
@@ -307,7 +315,7 @@ class Acl extends \Zotlabs\Web\Controller {
|
||||
$contacts[] = array(
|
||||
"photo" => $g['photo'],
|
||||
"name" => $g['name'],
|
||||
"nick" => $g['address'],
|
||||
"nick" => $g['address']
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -324,18 +332,24 @@ class Acl extends \Zotlabs\Web\Controller {
|
||||
$r = array();
|
||||
|
||||
if($r) {
|
||||
foreach($r as $g){
|
||||
foreach($r as $g) {
|
||||
|
||||
// remove RSS feeds from ACLs - they are inaccessible
|
||||
if(strpos($g['hash'],'/') && $type != 'a')
|
||||
if(($g['network'] === 'rss') && ($type != 'a'))
|
||||
continue;
|
||||
|
||||
if(in_array($g['hash'],$permitted) && $type == 'c' && (! $noforums)) {
|
||||
|
||||
$g['hash'] = urlencode($g['hash']);
|
||||
|
||||
if(! $g['nick']) {
|
||||
$t = explode(' ',strtolower($g['name']));
|
||||
$g['nick'] = $t[0] . '@';
|
||||
}
|
||||
|
||||
if(in_array($g['hash'],$permitted) && in_array($type, [ 'c', 'f' ]) && (! $noforums)) {
|
||||
$contacts[] = array(
|
||||
"type" => "c",
|
||||
"photo" => "images/twopeople.png",
|
||||
"name" => $g['name'] . '+',
|
||||
"id" => $g['id'] . '+',
|
||||
"name" => $g['name'] . (($type === 'f') ? '' : '+'),
|
||||
"id" => urlencode($g['id']) . (($type === 'f') ? '' : '+'),
|
||||
"xid" => $g['hash'],
|
||||
"link" => $g['nick'],
|
||||
"nick" => substr($g['nick'],0,strpos($g['nick'],'@')),
|
||||
@@ -344,18 +358,20 @@ class Acl extends \Zotlabs\Web\Controller {
|
||||
"label" => t('network')
|
||||
);
|
||||
}
|
||||
$contacts[] = array(
|
||||
"type" => "c",
|
||||
"photo" => $g['micro'],
|
||||
"name" => $g['name'],
|
||||
"id" => $g['id'],
|
||||
"xid" => $g['hash'],
|
||||
"link" => $g['nick'],
|
||||
"nick" => (($g['nick']) ? substr($g['nick'],0,strpos($g['nick'],'@')) : t('RSS')),
|
||||
"self" => (intval($g['abook_self']) ? 'abook-self' : ''),
|
||||
"taggable" => '',
|
||||
"label" => '',
|
||||
);
|
||||
if($type !== 'f') {
|
||||
$contacts[] = array(
|
||||
"type" => "c",
|
||||
"photo" => $g['micro'],
|
||||
"name" => $g['name'],
|
||||
"id" => urlencode($g['id']),
|
||||
"xid" => $g['hash'],
|
||||
"link" => $g['nick'],
|
||||
"nick" => (($g['nick']) ? substr($g['nick'],0,strpos($g['nick'],'@')) : $g['nick']),
|
||||
"self" => (intval($g['abook_self']) ? 'abook-self' : ''),
|
||||
"taggable" => '',
|
||||
"label" => '',
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -412,10 +428,12 @@ class Acl extends \Zotlabs\Web\Controller {
|
||||
$directory = find_upstream_directory($dirmode);
|
||||
$url = $directory['url'] . '/dirsearch';
|
||||
}
|
||||
|
||||
$token = get_config('system','realm_token');
|
||||
|
||||
$count = (x($_REQUEST,'count') ? $_REQUEST['count'] : 100);
|
||||
if($url) {
|
||||
$query = $url . '?f=' ;
|
||||
$query = $url . '?f=' . (($token) ? '&t=' . urlencode($token) : '');
|
||||
$query .= '&name=' . urlencode($search) . "&limit=$count" . (($address) ? '&address=' . urlencode($search) : '');
|
||||
|
||||
$x = z_fetch_url($query);
|
||||
|
||||
@@ -52,6 +52,8 @@ class Admin extends \Zotlabs\Web\Controller {
|
||||
* Page content
|
||||
*/
|
||||
|
||||
nav_set_selected('Admin');
|
||||
|
||||
$o = '';
|
||||
|
||||
if(argc() > 1) {
|
||||
@@ -91,10 +93,10 @@ class Admin extends \Zotlabs\Web\Controller {
|
||||
intval(ACCOUNT_BLOCKED)
|
||||
);
|
||||
if ($r) {
|
||||
$accounts['total'] = array('label' => t('# Accounts'), 'val' => $r[0]['total']);
|
||||
$accounts['blocked'] = array('label' => t('# blocked accounts'), 'val' => $r[0]['blocked']);
|
||||
$accounts['expired'] = array('label' => t('# expired accounts'), 'val' => $r[0]['expired']);
|
||||
$accounts['expiring'] = array('label' => t('# expiring accounts'), 'val' => $r[0]['expiring']);
|
||||
$accounts['total'] = array('label' => t('Accounts'), 'val' => $r[0]['total']);
|
||||
$accounts['blocked'] = array('label' => t('Blocked accounts'), 'val' => $r[0]['blocked']);
|
||||
$accounts['expired'] = array('label' => t('Expired accounts'), 'val' => $r[0]['expired']);
|
||||
$accounts['expiring'] = array('label' => t('Expiring accounts'), 'val' => $r[0]['expiring']);
|
||||
}
|
||||
|
||||
// pending registrations
|
||||
@@ -105,9 +107,9 @@ class Admin extends \Zotlabs\Web\Controller {
|
||||
$channels = array();
|
||||
$r = q("SELECT COUNT(*) AS total, COUNT(CASE WHEN channel_primary = 1 THEN 1 ELSE NULL END) AS main, COUNT(CASE WHEN channel_primary = 0 THEN 1 ELSE NULL END) AS clones FROM channel WHERE channel_removed = 0");
|
||||
if ($r) {
|
||||
$channels['total'] = array('label' => t('# Channels'), 'val' => $r[0]['total']);
|
||||
$channels['main'] = array('label' => t('# primary'), 'val' => $r[0]['main']);
|
||||
$channels['clones'] = array('label' => t('# clones'), 'val' => $r[0]['clones']);
|
||||
$channels['total'] = array('label' => t('Channels'), 'val' => $r[0]['total']);
|
||||
$channels['main'] = array('label' => t('Primary'), 'val' => $r[0]['main']);
|
||||
$channels['clones'] = array('label' => t('Clones'), 'val' => $r[0]['clones']);
|
||||
}
|
||||
|
||||
// We can do better, but this is a quick queue status
|
||||
@@ -118,14 +120,11 @@ class Admin extends \Zotlabs\Web\Controller {
|
||||
// If no plugins active return 0, otherwise list of plugin names
|
||||
$plugins = (count(\App::$plugins) == 0) ? count(\App::$plugins) : \App::$plugins;
|
||||
|
||||
if(is_array($plugins))
|
||||
sort($plugins);
|
||||
|
||||
// Could be extended to provide also other alerts to the admin
|
||||
$alertmsg = '';
|
||||
// annoy admin about upcoming unsupported PHP version
|
||||
if (version_compare(PHP_VERSION, '5.4', '<')) {
|
||||
$alertmsg = 'Your PHP version ' . PHP_VERSION . ' will not be supported with the next major release of $Projectname. You are strongly urged to upgrade to a current version.'
|
||||
. '<br>PHP 5.3 has reached its <a href="http://php.net/eol.php" class="alert-link">End of Life (EOL)</a> in August 2014.'
|
||||
. ' A list about current PHP versions can be found <a href="http://php.net/supported-versions.php" class="alert-link">here</a>.';
|
||||
}
|
||||
|
||||
$vmaster = get_repository_version('master');
|
||||
$vdev = get_repository_version('dev');
|
||||
|
||||
@@ -3,10 +3,14 @@
|
||||
namespace Zotlabs\Module\Admin;
|
||||
|
||||
use \Zotlabs\Storage\GitRepo as GitRepo;
|
||||
use \Michelf\MarkdownExtra;
|
||||
|
||||
class Plugins {
|
||||
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
*/
|
||||
function post() {
|
||||
|
||||
if(argc() > 2 && is_file("addon/" . argv(2) . "/" . argv(2) . ".php")) {
|
||||
@@ -15,16 +19,15 @@ class Plugins {
|
||||
$func = argv(2) . '_plugin_admin_post';
|
||||
$func($a);
|
||||
}
|
||||
|
||||
goaway(z_root() . '/admin/plugins/' . argv(2) );
|
||||
|
||||
goaway(z_root() . '/admin/plugins/' . argv(2) );
|
||||
}
|
||||
elseif(argc() > 2) {
|
||||
switch(argv(2)) {
|
||||
case 'updaterepo':
|
||||
if (array_key_exists('repoName', $_REQUEST)) {
|
||||
$repoName = $_REQUEST['repoName'];
|
||||
}
|
||||
}
|
||||
else {
|
||||
json_return_and_die(array('message' => 'No repo name provided.', 'success' => false));
|
||||
}
|
||||
@@ -101,16 +104,15 @@ class Plugins {
|
||||
logger('Repo directory not writable to web server: ' . $repoDir);
|
||||
json_return_and_die(array('message' => 'Repo directory not writable to web server.', 'success' => false));
|
||||
}
|
||||
// TODO: remove directory and unlink /addon/files
|
||||
/// @TODO remove directory and unlink /addon/files
|
||||
if (rrmdir($repoDir)) {
|
||||
json_return_and_die(array('message' => 'Repo deleted.', 'success' => true));
|
||||
} else {
|
||||
json_return_and_die(array('message' => 'Error deleting addon repo.', 'success' => false));
|
||||
}
|
||||
case 'installrepo':
|
||||
require_once('library/markdown.php');
|
||||
if (array_key_exists('repoURL', $_REQUEST)) {
|
||||
require_once('library/PHPGit.autoload.php'); // Load PHPGit dependencies
|
||||
require_once('library/PHPGit.autoload.php'); // Load PHPGit dependencies
|
||||
$repoURL = $_REQUEST['repoURL'];
|
||||
$extendDir = 'store/[data]/git/sys/extend';
|
||||
$addonDir = $extendDir . '/addon';
|
||||
@@ -170,9 +172,8 @@ class Plugins {
|
||||
json_return_and_die(array('repo' => $repo, 'message' => '', 'success' => true));
|
||||
}
|
||||
case 'addrepo':
|
||||
require_once('library/markdown.php');
|
||||
if (array_key_exists('repoURL', $_REQUEST)) {
|
||||
require_once('library/PHPGit.autoload.php'); // Load PHPGit dependencies
|
||||
require_once('library/PHPGit.autoload.php'); // Load PHPGit dependencies
|
||||
$repoURL = $_REQUEST['repoURL'];
|
||||
$extendDir = 'store/[data]/git/sys/extend';
|
||||
$addonDir = $extendDir . '/addon';
|
||||
@@ -225,7 +226,7 @@ class Plugins {
|
||||
$repo['readme'] = $repo['manifest'] = null;
|
||||
foreach ($git->git->tree('master') as $object) {
|
||||
if ($object['type'] == 'blob' && (strtolower($object['file']) === 'readme.md' || strtolower($object['file']) === 'readme')) {
|
||||
$repo['readme'] = Markdown($git->git->cat->blob($object['hash']));
|
||||
$repo['readme'] = MarkdownExtra::defaultTransform($git->git->cat->blob($object['hash']));
|
||||
} else if ($object['type'] == 'blob' && strtolower($object['file']) === 'manifest.json') {
|
||||
$repo['manifest'] = $git->git->cat->blob($object['hash']);
|
||||
}
|
||||
@@ -241,7 +242,11 @@ class Plugins {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Plugins admin page.
|
||||
*
|
||||
* @return string with parsed HTML
|
||||
*/
|
||||
function get() {
|
||||
|
||||
/*
|
||||
@@ -254,13 +259,13 @@ class Plugins {
|
||||
notice( t("Item not found.") );
|
||||
return '';
|
||||
}
|
||||
|
||||
|
||||
$enabled = in_array($plugin,\App::$plugins);
|
||||
$info = get_plugin_info($plugin);
|
||||
$x = check_plugin_versions($info);
|
||||
|
||||
|
||||
// disable plugins which are installed but incompatible versions
|
||||
|
||||
|
||||
if($enabled && ! $x) {
|
||||
$enabled = false;
|
||||
$idz = array_search($plugin, \App::$plugins);
|
||||
@@ -271,7 +276,7 @@ class Plugins {
|
||||
}
|
||||
}
|
||||
$info['disabled'] = 1-intval($x);
|
||||
|
||||
|
||||
if (x($_GET,"a") && $_GET['a']=="t"){
|
||||
check_form_security_token_redirectOnErr('/admin/plugins', 'admin_plugins', 't');
|
||||
$pinstalled = false;
|
||||
@@ -297,9 +302,9 @@ class Plugins {
|
||||
}
|
||||
goaway(z_root() . '/admin/plugins' );
|
||||
}
|
||||
|
||||
// display plugin details
|
||||
require_once('library/markdown.php');
|
||||
|
||||
|
||||
if (in_array($plugin, \App::$plugins)){
|
||||
$status = 'on';
|
||||
$action = t('Disable');
|
||||
@@ -307,21 +312,21 @@ class Plugins {
|
||||
$status = 'off';
|
||||
$action = t('Enable');
|
||||
}
|
||||
|
||||
|
||||
$readme = null;
|
||||
if (is_file("addon/$plugin/README.md")){
|
||||
$readme = file_get_contents("addon/$plugin/README.md");
|
||||
$readme = Markdown($readme);
|
||||
$readme = MarkdownExtra::defaultTransform($readme);
|
||||
} else if (is_file("addon/$plugin/README")){
|
||||
$readme = "<pre>". file_get_contents("addon/$plugin/README") ."</pre>";
|
||||
}
|
||||
|
||||
|
||||
$admin_form = '';
|
||||
|
||||
|
||||
$r = q("select * from addon where plugin_admin = 1 and aname = '%s' limit 1",
|
||||
dbesc($plugin)
|
||||
);
|
||||
|
||||
|
||||
if($r) {
|
||||
@require_once("addon/$plugin/$plugin.php");
|
||||
if(function_exists($plugin.'_plugin_admin')) {
|
||||
@@ -329,8 +334,8 @@ class Plugins {
|
||||
$func($a, $admin_form);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
$t = get_markup_template('admin_plugins_details.tpl');
|
||||
return replace_macros($t, array(
|
||||
'$title' => t('Administration'),
|
||||
@@ -338,7 +343,7 @@ class Plugins {
|
||||
'$toggle' => t('Toggle'),
|
||||
'$settings' => t('Settings'),
|
||||
'$baseurl' => z_root(),
|
||||
|
||||
|
||||
'$plugin' => $plugin,
|
||||
'$status' => $status,
|
||||
'$action' => $action,
|
||||
@@ -351,17 +356,17 @@ class Plugins {
|
||||
'$str_serverroles' => t('Compatible Server Roles: '),
|
||||
'$str_requires' => t('Requires: '),
|
||||
'$disabled' => t('Disabled - version incompatibility'),
|
||||
|
||||
|
||||
'$admin_form' => $admin_form,
|
||||
'$function' => 'plugins',
|
||||
'$screenshot' => '',
|
||||
'$readme' => $readme,
|
||||
|
||||
|
||||
'$form_security_token' => get_form_security_token('admin_plugins'),
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* List plugins
|
||||
*/
|
||||
@@ -374,9 +379,9 @@ class Plugins {
|
||||
$info = get_plugin_info($id);
|
||||
$enabled = in_array($id,\App::$plugins);
|
||||
$x = check_plugin_versions($info);
|
||||
|
||||
|
||||
// disable plugins which are installed but incompatible versions
|
||||
|
||||
|
||||
if($enabled && ! $x) {
|
||||
$enabled = false;
|
||||
$idz = array_search($id, \App::$plugins);
|
||||
@@ -387,19 +392,19 @@ class Plugins {
|
||||
}
|
||||
}
|
||||
$info['disabled'] = 1-intval($x);
|
||||
|
||||
|
||||
$plugins[] = array( $id, (($enabled)?"on":"off") , $info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
usort($plugins,'self::plugin_sort');
|
||||
|
||||
$allowManageRepos = false;
|
||||
if(is_writable('extend/addon') && is_writable('store/[data]')) {
|
||||
$allowManageRepos = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$admin_plugins_add_repo_form= replace_macros(
|
||||
get_markup_template('admin_plugins_addrepo.tpl'), array(
|
||||
'$post' => 'admin/plugins/addrepo',
|
||||
@@ -418,14 +423,14 @@ class Plugins {
|
||||
'$cancel' => t('Cancel')
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
$reponames = $this->listAddonRepos();
|
||||
$addonrepos = [];
|
||||
foreach($reponames as $repo) {
|
||||
$addonrepos[] = array('name' => $repo, 'description' => '');
|
||||
// TODO: Parse repo info to provide more information about repos
|
||||
/// @TODO Parse repo info to provide more information about repos
|
||||
}
|
||||
|
||||
|
||||
$t = get_markup_template('admin_plugins.tpl');
|
||||
return replace_macros($t, array(
|
||||
'$title' => t('Administration'),
|
||||
@@ -471,5 +476,4 @@ class Plugins {
|
||||
return(strcmp(strtolower($a[2]['name']),strtolower($b[2]['name'])));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -17,7 +17,6 @@ class Site {
|
||||
check_form_security_token_redirectOnErr('/admin/site', 'admin_site');
|
||||
|
||||
$sitename = ((x($_POST,'sitename')) ? notags(trim($_POST['sitename'])) : '');
|
||||
$server_role = ((x($_POST,'server_role')) ? notags(trim($_POST['server_role'])) : 'standard');
|
||||
|
||||
$banner = ((x($_POST,'banner')) ? trim($_POST['banner']) : false);
|
||||
|
||||
@@ -48,6 +47,10 @@ class Site {
|
||||
$no_community_page = !((x($_POST,'no_community_page')) ? True : False);
|
||||
$default_expire_days = ((array_key_exists('default_expire_days',$_POST)) ? intval($_POST['default_expire_days']) : 0);
|
||||
|
||||
$reply_address = ((array_key_exists('reply_address',$_POST) && trim($_POST['reply_address'])) ? trim($_POST['reply_address']) : 'noreply@' . \App::get_hostname());
|
||||
$from_email = ((array_key_exists('from_email',$_POST) && trim($_POST['from_email'])) ? trim($_POST['from_email']) : 'Administrator@' . \App::get_hostname());
|
||||
$from_email_name = ((array_key_exists('from_email_name',$_POST) && trim($_POST['from_email_name'])) ? trim($_POST['from_email_name']) : \Zotlabs\Lib\System::get_site_name());
|
||||
|
||||
$verifyssl = ((x($_POST,'verifyssl')) ? True : False);
|
||||
$proxyuser = ((x($_POST,'proxyuser')) ? notags(trim($_POST['proxyuser'])) : '');
|
||||
$proxy = ((x($_POST,'proxy')) ? notags(trim($_POST['proxy'])) : '');
|
||||
@@ -58,13 +61,15 @@ class Site {
|
||||
$maxloadavg = ((x($_POST,'maxloadavg')) ? intval(trim($_POST['maxloadavg'])) : 50);
|
||||
$feed_contacts = ((x($_POST,'feed_contacts')) ? intval($_POST['feed_contacts']) : 0);
|
||||
$verify_email = ((x($_POST,'verify_email')) ? 1 : 0);
|
||||
$techlevel_lock = ((x($_POST,'techlock')) ? intval($_POST['techlock']) : 0);
|
||||
$techlevel_lock = ((x($_POST,'techlock')) ? intval($_POST['techlock']) : 0);
|
||||
$imagick_path = ((x($_POST,'imagick_path')) ? trim($_POST['imagick_path']) : '');
|
||||
$thumbnail_security = ((x($_POST,'thumbnail_security')) ? intval($_POST['thumbnail_security']) : 0);
|
||||
$force_queue = ((intval($_POST['force_queue']) > 0) ? intval($_POST['force_queue']) : 300);
|
||||
|
||||
$techlevel = null;
|
||||
if(array_key_exists('techlevel', $_POST))
|
||||
$techlevel = intval($_POST['techlevel']);
|
||||
|
||||
set_config('system', 'server_role', $server_role);
|
||||
set_config('system', 'feed_contacts', $feed_contacts);
|
||||
set_config('system', 'delivery_interval', $delivery_interval);
|
||||
set_config('system', 'delivery_batch_count', $delivery_batch_count);
|
||||
@@ -77,8 +82,16 @@ class Site {
|
||||
set_config('system', 'enable_context_help', $enable_context_help);
|
||||
set_config('system', 'verify_email', $verify_email);
|
||||
set_config('system', 'default_expire_days', $default_expire_days);
|
||||
set_config('system', 'reply_address', $reply_address);
|
||||
set_config('system', 'from_email', $from_email);
|
||||
set_config('system', 'from_email_name' , $from_email_name);
|
||||
set_config('system', 'imagick_convert_path' , $imagick_path);
|
||||
set_config('system', 'thumbnail_security' , $thumbnail_security);
|
||||
|
||||
set_config('system', 'techlevel_lock', $techlevel_lock);
|
||||
|
||||
|
||||
|
||||
if(! is_null($techlevel))
|
||||
set_config('system', 'techlevel', $techlevel);
|
||||
|
||||
@@ -117,6 +130,7 @@ class Site {
|
||||
set_config('system','allowed_sites', $allowed_sites);
|
||||
set_config('system','publish_all', $force_publish);
|
||||
set_config('system','disable_discover_tab', $disable_discover_tab);
|
||||
set_config('system','force_queue_threshold', $force_queue);
|
||||
if ($global_directory == '') {
|
||||
del_config('system', 'directory_submit_url');
|
||||
} else {
|
||||
@@ -197,7 +211,7 @@ class Site {
|
||||
// directory server should not be set or settable unless we are a directory client
|
||||
|
||||
if($dirmode == DIRECTORY_MODE_NORMAL) {
|
||||
$x = q("select site_url from site where site_flags in (%d,%d) and site_realm = '%s'",
|
||||
$x = q("select site_url from site where site_flags in (%d,%d) and site_realm = '%s' and site_dead = 0",
|
||||
intval(DIRECTORY_MODE_SECONDARY),
|
||||
intval(DIRECTORY_MODE_PRIMARY),
|
||||
dbesc($realm)
|
||||
@@ -237,18 +251,13 @@ class Site {
|
||||
);
|
||||
|
||||
$discover_tab = get_config('system','disable_discover_tab');
|
||||
|
||||
// $disable public streams by default
|
||||
if($discover_tab === false)
|
||||
$discover_tab = 1;
|
||||
// now invert the logic for the setting.
|
||||
$discover_tab = (1 - $discover_tab);
|
||||
|
||||
$server_roles = [
|
||||
'basic' => t('Basic/Minimal Social Networking'),
|
||||
'standard' => t('Standard Configuration (default)'),
|
||||
'pro' => t('Professional')
|
||||
];
|
||||
|
||||
$techlevels = [
|
||||
'0' => t('Beginner/Basic'),
|
||||
'1' => t('Novice - not skilled but willing to learn'),
|
||||
@@ -275,8 +284,6 @@ class Site {
|
||||
// name, label, value, help string, extra data...
|
||||
'$sitename' => array('sitename', t("Site name"), htmlspecialchars(get_config('system','sitename'), ENT_QUOTES, 'UTF-8'),''),
|
||||
|
||||
'$server_role' => array('server_role', t("Server Configuration/Role"), get_config('system','server_role'),'',$server_roles),
|
||||
|
||||
'$techlevel' => [ 'techlevel', t('Site default technical skill level'), get_config('system','techlevel'), t('Used to provide a member experience matched to technical comfort level'), $techlevels ],
|
||||
|
||||
'$techlock' => [ 'techlock', t('Lock the technical skill level setting'), get_config('system','techlevel_lock'), t('Members can set their own technical comfort level by default') ],
|
||||
@@ -304,6 +311,10 @@ class Site {
|
||||
'$login_on_homepage' => array('login_on_homepage', t("Login on Homepage"),((intval($homelogin) || $homelogin === false) ? 1 : '') , t("Present a login box to visitors on the home page if no other content has been configured.")),
|
||||
'$enable_context_help' => array('enable_context_help', t("Enable context help"),((intval($enable_context_help) === 1 || $enable_context_help === false) ? 1 : 0) , t("Display contextual help for the current page when the help button is pressed.")),
|
||||
|
||||
'$reply_address' => [ 'reply_address', t('Reply-to email address for system generated email.'), get_config('system','reply_address','noreply@' . \App::get_hostname()),'' ],
|
||||
'$from_email' => [ 'from_email', t('Sender (From) email address for system generated email.'), get_config('system','from_email','Administrator@' . \App::get_hostname()),'' ],
|
||||
'$from_email_name' => [ 'from_email_name', t('Name of email sender for system generated email.'), get_config('system','from_email_name',\Zotlabs\Lib\System::get_site_name()),'' ],
|
||||
|
||||
'$directory_server' => (($dir_choices) ? array('directory_server', t("Directory Server URL"), get_config('system','directory_server'), t("Default directory server"), $dir_choices) : null),
|
||||
|
||||
'$proxyuser' => array('proxyuser', t("Proxy user"), get_config('system','proxyuser'), ""),
|
||||
@@ -311,7 +322,10 @@ class Site {
|
||||
'$timeout' => array('timeout', t("Network timeout"), (x(get_config('system','curl_timeout'))?get_config('system','curl_timeout'):60), t("Value is in seconds. Set to 0 for unlimited (not recommended).")),
|
||||
'$delivery_interval' => array('delivery_interval', t("Delivery interval"), (x(get_config('system','delivery_interval'))?get_config('system','delivery_interval'):2), t("Delay background delivery processes by this many seconds to reduce system load. Recommend: 4-5 for shared hosts, 2-3 for virtual private servers. 0-1 for large dedicated servers.")),
|
||||
'$delivery_batch_count' => array('delivery_batch_count', t('Deliveries per process'),(x(get_config('system','delivery_batch_count'))?get_config('system','delivery_batch_count'):1), t("Number of deliveries to attempt in a single operating system process. Adjust if necessary to tune system performance. Recommend: 1-5.")),
|
||||
'$force_queue' => array('force_queue', t("Queue Threshold"), get_config('system','force_queue_threshold',300), t("Always defer immediate delivery if queue contains more than this number of entries.")),
|
||||
'$poll_interval' => array('poll_interval', t("Poll interval"), (x(get_config('system','poll_interval'))?get_config('system','poll_interval'):2), t("Delay background polling processes by this many seconds to reduce system load. If 0, use delivery interval.")),
|
||||
'$imagick_path' => array('imagick_path', t("Path to ImageMagick convert program"), get_config('system','imagick_convert_path'), t("If set, use this program to generate photo thumbnails for huge images ( > 4000 pixels in either dimension), otherwise memory exhaustion may occur. Example: /usr/bin/convert")),
|
||||
'$thumbnail_security' => array('thumbnail_security', t("Allow SVG thumbnails in file browser"), get_config('system','thumbnail_security',0), t("WARNING: SVG images may contain malicious code.")),
|
||||
'$maxloadavg' => array('maxloadavg', t("Maximum Load Average"), ((intval(get_config('system','maxloadavg')) > 0)?get_config('system','maxloadavg'):50), t("Maximum system load before delivery and poll processes are deferred - default 50.")),
|
||||
'$default_expire_days' => array('default_expire_days', t('Expiration period in days for imported (grid/network) content'), intval(get_config('system','default_expire_days')), t('0 for no expiration of imported content')),
|
||||
'$form_security_token' => get_form_security_token("admin_site"),
|
||||
|
||||
@@ -2,38 +2,41 @@
|
||||
|
||||
namespace Zotlabs\Module\Admin;
|
||||
|
||||
use \Michelf\MarkdownExtra;
|
||||
|
||||
/**
|
||||
* @brief Admin area theme settings.
|
||||
*/
|
||||
class Themes {
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
*/
|
||||
function post() {
|
||||
|
||||
$theme = argv(2);
|
||||
if (is_file("view/theme/$theme/php/config.php")){
|
||||
require_once("view/theme/$theme/php/config.php");
|
||||
// fixme add parent theme if derived
|
||||
if (function_exists("theme_admin_post")){
|
||||
/// @FIXME add parent theme if derived
|
||||
if (function_exists('theme_admin_post')){
|
||||
theme_admin_post($a);
|
||||
}
|
||||
}
|
||||
info(t('Theme settings updated.'));
|
||||
if(is_ajax())
|
||||
if(is_ajax())
|
||||
return;
|
||||
|
||||
|
||||
goaway(z_root() . '/admin/themes/' . $theme );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Themes admin page.
|
||||
*
|
||||
* @return string
|
||||
* @return string with parsed HTML
|
||||
*/
|
||||
|
||||
function get(){
|
||||
|
||||
$allowed_themes_str = get_config('system', 'allowed_themes');
|
||||
$allowed_themes_raw = explode(',', $allowed_themes_str);
|
||||
$allowed_themes = array();
|
||||
@@ -41,7 +44,7 @@ class Themes {
|
||||
foreach($allowed_themes_raw as $x)
|
||||
if(strlen(trim($x)))
|
||||
$allowed_themes[] = trim($x);
|
||||
|
||||
|
||||
$themes = array();
|
||||
$files = glob('view/theme/*');
|
||||
if($files) {
|
||||
@@ -53,56 +56,55 @@ class Themes {
|
||||
$themes[] = array('name' => $f, 'experimental' => $is_experimental, 'supported' => $is_supported, 'allowed' => $is_allowed);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(! count($themes)) {
|
||||
notice( t('No themes found.'));
|
||||
return '';
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Single theme
|
||||
*/
|
||||
|
||||
|
||||
if (\App::$argc == 3){
|
||||
$theme = \App::$argv[2];
|
||||
if(! is_dir("view/theme/$theme")){
|
||||
notice( t("Item not found.") );
|
||||
return '';
|
||||
}
|
||||
|
||||
|
||||
if (x($_GET,"a") && $_GET['a']=="t"){
|
||||
check_form_security_token_redirectOnErr('/admin/themes', 'admin_themes', 't');
|
||||
|
||||
|
||||
// Toggle theme status
|
||||
|
||||
|
||||
$this->toggle_theme($themes, $theme, $result);
|
||||
$s = $this->rebuild_theme_table($themes);
|
||||
if($result)
|
||||
info( sprintf('Theme %s enabled.', $theme));
|
||||
else
|
||||
info( sprintf('Theme %s disabled.', $theme));
|
||||
|
||||
|
||||
set_config('system', 'allowed_themes', $s);
|
||||
goaway(z_root() . '/admin/themes' );
|
||||
}
|
||||
|
||||
|
||||
// display theme details
|
||||
require_once('library/markdown.php');
|
||||
|
||||
|
||||
if ($this->theme_status($themes,$theme)) {
|
||||
$status="on"; $action= t("Disable");
|
||||
} else {
|
||||
$status="off"; $action= t("Enable");
|
||||
}
|
||||
|
||||
|
||||
$readme=Null;
|
||||
if (is_file("view/theme/$theme/README.md")){
|
||||
$readme = file_get_contents("view/theme/$theme/README.md");
|
||||
$readme = Markdown($readme);
|
||||
$readme = MarkdownExtra::defaultTransform($readme);
|
||||
} else if (is_file("view/theme/$theme/README")){
|
||||
$readme = "<pre>". file_get_contents("view/theme/$theme/README") ."</pre>";
|
||||
$readme = '<pre>'. file_get_contents("view/theme/$theme/README") .'</pre>';
|
||||
}
|
||||
|
||||
|
||||
$admin_form = '';
|
||||
if (is_file("view/theme/$theme/php/config.php")){
|
||||
require_once("view/theme/$theme/php/config.php");
|
||||
@@ -110,11 +112,11 @@ class Themes {
|
||||
$admin_form = theme_admin($a);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$screenshot = array( get_theme_screenshot($theme), t('Screenshot'));
|
||||
if(! stristr($screenshot[0],$theme))
|
||||
$screenshot = null;
|
||||
|
||||
|
||||
$t = get_markup_template('admin_plugins_details.tpl');
|
||||
return replace_macros($t, array(
|
||||
'$title' => t('Administration'),
|
||||
@@ -122,7 +124,7 @@ class Themes {
|
||||
'$toggle' => t('Toggle'),
|
||||
'$settings' => t('Settings'),
|
||||
'$baseurl' => z_root(),
|
||||
|
||||
|
||||
'$plugin' => $theme,
|
||||
'$status' => $status,
|
||||
'$action' => $action,
|
||||
@@ -133,22 +135,22 @@ class Themes {
|
||||
'$str_maintainer' => t('Maintainer: '),
|
||||
'$screenshot' => $screenshot,
|
||||
'$readme' => $readme,
|
||||
|
||||
|
||||
'$form_security_token' => get_form_security_token('admin_themes'),
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* List themes
|
||||
*/
|
||||
|
||||
|
||||
$xthemes = array();
|
||||
if($themes) {
|
||||
foreach($themes as $th) {
|
||||
$xthemes[] = array($th['name'],(($th['allowed']) ? "on" : "off"), get_theme_info($th['name']));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$t = get_markup_template('admin_plugins.tpl');
|
||||
return replace_macros($t, array(
|
||||
'$title' => t('Administration'),
|
||||
@@ -162,13 +164,14 @@ class Themes {
|
||||
'$form_security_token' => get_form_security_token('admin_themes'),
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param array $themes
|
||||
* @param string $th
|
||||
* @param int $result
|
||||
* @brief Toggle a theme.
|
||||
*
|
||||
* @param array &$themes
|
||||
* @param[in] string $th
|
||||
* @param[out] int &$result
|
||||
*/
|
||||
function toggle_theme(&$themes, $th, &$result) {
|
||||
for($x = 0; $x < count($themes); $x ++) {
|
||||
@@ -184,7 +187,7 @@ class Themes {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param array $themes
|
||||
* @param string $th
|
||||
@@ -203,8 +206,7 @@ class Themes {
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param array $themes
|
||||
* @return string
|
||||
@@ -222,12 +224,5 @@ class Themes {
|
||||
}
|
||||
return $o;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -64,7 +64,11 @@ class Appman extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
|
||||
if($_POST['feature']) {
|
||||
Zlib\Apps::app_feature(local_channel(),$papp);
|
||||
Zlib\Apps::app_feature(local_channel(), $papp, $_POST['feature']);
|
||||
}
|
||||
|
||||
if($_POST['pin']) {
|
||||
Zlib\Apps::app_feature(local_channel(), $papp, $_POST['pin']);
|
||||
}
|
||||
|
||||
if($_SESSION['return_url'])
|
||||
@@ -84,6 +88,20 @@ class Appman extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
|
||||
$channel = \App::get_channel();
|
||||
|
||||
if(argc() > 2) {
|
||||
if(argv(2) === 'moveup') {
|
||||
Zlib\Apps::moveup(local_channel(),argv(1));
|
||||
}
|
||||
if(argv(2) === 'movedown') {
|
||||
Zlib\Apps::movedown(local_channel(),argv(1));
|
||||
}
|
||||
goaway(z_root() . '/apporder');
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
$app = null;
|
||||
$embed = null;
|
||||
if($_REQUEST['appid']) {
|
||||
|
||||
51
Zotlabs/Module/Apporder.php
Normal file
51
Zotlabs/Module/Apporder.php
Normal file
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
use \Zotlabs\Lib as Zlib;
|
||||
|
||||
class Apporder extends \Zotlabs\Web\Controller {
|
||||
|
||||
function post() {
|
||||
|
||||
}
|
||||
|
||||
function get() {
|
||||
|
||||
if(! local_channel())
|
||||
return;
|
||||
|
||||
nav_set_selected('Order Apps');
|
||||
|
||||
$syslist = array();
|
||||
$list = Zlib\Apps::app_list(local_channel(), false, ['nav_featured_app', 'nav_pinned_app']);
|
||||
if($list) {
|
||||
foreach($list as $li) {
|
||||
$syslist[] = Zlib\Apps::app_encode($li);
|
||||
}
|
||||
}
|
||||
Zlib\Apps::translate_system_apps($syslist);
|
||||
|
||||
usort($syslist,'Zotlabs\\Lib\\Apps::app_name_compare');
|
||||
|
||||
$syslist = Zlib\Apps::app_order(local_channel(),$syslist);
|
||||
|
||||
foreach($syslist as $app) {
|
||||
if(strpos($app['categories'],'nav_pinned_app') !== false) {
|
||||
$navbar_apps[] = Zlib\Apps::app_render($app,'nav-order');
|
||||
}
|
||||
else {
|
||||
$nav_apps[] = Zlib\Apps::app_render($app,'nav-order');
|
||||
}
|
||||
}
|
||||
|
||||
return replace_macros(get_markup_template('apporder.tpl'),
|
||||
[
|
||||
'$header' => [t('Change Order of Pinned Navbar Apps'), t('Change Order of App Tray Apps')],
|
||||
'$desc' => [t('Use arrows to move the corresponding app left (top) or right (bottom) in the navbar'), t('Use arrows to move the corresponding app up or down in the app tray')],
|
||||
'$nav_apps' => $nav_apps,
|
||||
'$navbar_apps' => $navbar_apps
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,8 @@ use \Zotlabs\Lib as Zlib;
|
||||
class Apps extends \Zotlabs\Web\Controller {
|
||||
|
||||
function get() {
|
||||
|
||||
nav_set_selected('Apps');
|
||||
|
||||
if(argc() == 2 && argv(1) == 'edit')
|
||||
$mode = 'edit';
|
||||
@@ -20,7 +22,8 @@ class Apps extends \Zotlabs\Web\Controller {
|
||||
if(local_channel()) {
|
||||
Zlib\Apps::import_system_apps();
|
||||
$syslist = array();
|
||||
$list = Zlib\Apps::app_list(local_channel(), (($mode == 'edit') ? true : false), $_GET['cat']);
|
||||
$cat = ((array_key_exists('cat',$_GET) && $_GET['cat']) ? [ escape_tags($_GET['cat']) ] : '');
|
||||
$list = Zlib\Apps::app_list(local_channel(), (($mode == 'edit') ? true : false), $cat);
|
||||
if($list) {
|
||||
foreach($list as $x) {
|
||||
$syslist[] = Zlib\Apps::app_encode($x);
|
||||
@@ -41,7 +44,7 @@ class Apps extends \Zotlabs\Web\Controller {
|
||||
|
||||
return replace_macros(get_markup_template('myapps.tpl'), array(
|
||||
'$sitename' => get_config('system','sitename'),
|
||||
'$cat' => ((array_key_exists('cat',$_GET) && $_GET['cat']) ? escape_tags($_GET['cat']) : ''),
|
||||
'$cat' => $cat,
|
||||
'$title' => t('Apps'),
|
||||
'$apps' => $apps,
|
||||
'$authed' => ((local_channel()) ? true : false),
|
||||
|
||||
138
Zotlabs/Module/Article_edit.php
Normal file
138
Zotlabs/Module/Article_edit.php
Normal file
@@ -0,0 +1,138 @@
|
||||
<?php
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
require_once('include/channel.php');
|
||||
require_once('include/acl_selectors.php');
|
||||
require_once('include/conversation.php');
|
||||
|
||||
class Article_edit extends \Zotlabs\Web\Controller {
|
||||
|
||||
|
||||
function get() {
|
||||
|
||||
// Figure out which post we're editing
|
||||
$post_id = ((argc() > 1) ? intval(argv(1)) : 0);
|
||||
|
||||
if(! $post_id) {
|
||||
notice( t('Item not found') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
$itm = q("SELECT * FROM item WHERE id = %d and item_type = %d LIMIT 1",
|
||||
intval($post_id),
|
||||
intval(ITEM_TYPE_ARTICLE)
|
||||
);
|
||||
if($itm) {
|
||||
$item_id = q("select * from iconfig where cat = 'system' and k = 'ARTICLE' and iid = %d limit 1",
|
||||
intval($itm[0]['id'])
|
||||
);
|
||||
if($item_id)
|
||||
$card_title = $item_id[0]['v'];
|
||||
}
|
||||
else {
|
||||
notice( t('Item not found') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
$owner = $itm[0]['uid'];
|
||||
$uid = local_channel();
|
||||
|
||||
$observer = \App::get_observer();
|
||||
|
||||
$channel = channelx_by_n($owner);
|
||||
if(! $channel) {
|
||||
notice( t('Channel not found.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
$ob_hash = (($observer) ? $observer['xchan_hash'] : '');
|
||||
|
||||
if(! perm_is_allowed($owner,$ob_hash,'write_pages')) {
|
||||
notice( t('Permission denied.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
$is_owner = (($uid && $uid == $owner) ? true : false);
|
||||
|
||||
$o = '';
|
||||
|
||||
|
||||
|
||||
$category = '';
|
||||
$catsenabled = ((feature_enabled($owner,'categories')) ? 'categories' : '');
|
||||
|
||||
if ($catsenabled){
|
||||
$itm = fetch_post_tags($itm);
|
||||
|
||||
$cats = get_terms_oftype($itm[0]['term'], TERM_CATEGORY);
|
||||
|
||||
foreach ($cats as $cat) {
|
||||
if (strlen($category))
|
||||
$category .= ', ';
|
||||
$category .= $cat['term'];
|
||||
}
|
||||
}
|
||||
|
||||
if($itm[0]['attach']) {
|
||||
$j = json_decode($itm[0]['attach'],true);
|
||||
if($j) {
|
||||
foreach($j as $jj) {
|
||||
$itm[0]['body'] .= "\n" . '[attachment]' . basename($jj['href']) . ',' . $jj['revision'] . '[/attachment]' . "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$mimetype = $itm[0]['mimetype'];
|
||||
|
||||
$content = $itm[0]['body'];
|
||||
|
||||
|
||||
|
||||
$rp = 'articles/' . $channel['channel_address'];
|
||||
|
||||
$x = array(
|
||||
'nickname' => $channel['channel_address'],
|
||||
'bbco_autocomplete'=> 'bbcode',
|
||||
'return_path' => $rp,
|
||||
'webpage' => ITEM_TYPE_ARTICLE,
|
||||
'button' => t('Edit'),
|
||||
'writefiles' => perm_is_allowed($owner, get_observer_hash(), 'write_pages'),
|
||||
'weblink' => t('Insert web link'),
|
||||
'hide_voting' => false,
|
||||
'hide_future' => false,
|
||||
'hide_location' => false,
|
||||
'hide_expire' => false,
|
||||
'showacl' => true,
|
||||
'acl' => populate_acl($itm[0],false,\Zotlabs\Lib\PermissionDescription::fromGlobalPermission('view_pages')),
|
||||
'permissions' => $itm[0],
|
||||
'lockstate' => (($itm[0]['allow_cid'] || $itm[0]['allow_gid'] || $itm[0]['deny_cid'] || $itm[0]['deny_gid']) ? 'lock' : 'unlock'),
|
||||
'ptyp' => $itm[0]['type'],
|
||||
'mimeselect' => false,
|
||||
'mimetype' => $itm[0]['mimetype'],
|
||||
'body' => undo_post_tagging($content),
|
||||
'post_id' => $post_id,
|
||||
'visitor' => true,
|
||||
'title' => htmlspecialchars($itm[0]['title'],ENT_COMPAT,'UTF-8'),
|
||||
'placeholdertitle' => t('Title (optional)'),
|
||||
'pagetitle' => $card_title,
|
||||
'profile_uid' => (intval($channel['channel_id'])),
|
||||
'catsenabled' => $catsenabled,
|
||||
'category' => $category,
|
||||
'bbcode' => (($mimetype == 'text/bbcode') ? true : false)
|
||||
);
|
||||
|
||||
$editor = status_editor($a, $x);
|
||||
|
||||
$o .= replace_macros(get_markup_template('edpost_head.tpl'), array(
|
||||
'$title' => t('Edit Article'),
|
||||
'$delete' => ((($itm[0]['author_xchan'] === $ob_hash) || ($itm[0]['owner_xchan'] === $ob_hash)) ? t('Delete') : false),
|
||||
'$id' => $itm[0]['id'],
|
||||
'$editor' => $editor
|
||||
));
|
||||
|
||||
return $o;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
187
Zotlabs/Module/Articles.php
Normal file
187
Zotlabs/Module/Articles.php
Normal file
@@ -0,0 +1,187 @@
|
||||
<?php
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
require_once('include/channel.php');
|
||||
require_once('include/conversation.php');
|
||||
require_once('include/acl_selectors.php');
|
||||
|
||||
|
||||
class Articles extends \Zotlabs\Web\Controller {
|
||||
|
||||
function init() {
|
||||
|
||||
if(argc() > 1)
|
||||
$which = argv(1);
|
||||
else
|
||||
return;
|
||||
|
||||
profile_load($which);
|
||||
|
||||
}
|
||||
|
||||
function get($update = 0, $load = false) {
|
||||
|
||||
if(observer_prohibited(true)) {
|
||||
return login();
|
||||
}
|
||||
|
||||
if(! \App::$profile) {
|
||||
notice( t('Requested profile is not available.') . EOL );
|
||||
\App::$error = 404;
|
||||
return;
|
||||
}
|
||||
|
||||
if(! feature_enabled(\App::$profile_uid,'articles')) {
|
||||
return;
|
||||
}
|
||||
|
||||
nav_set_selected(t('Cards'));
|
||||
|
||||
head_add_link([
|
||||
'rel' => 'alternate',
|
||||
'type' => 'application/json+oembed',
|
||||
'href' => z_root() . '/oep?f=&url=' . urlencode(z_root() . '/' . \App::$query_string),
|
||||
'title' => 'oembed'
|
||||
]);
|
||||
|
||||
|
||||
$category = (($_REQUEST['cat']) ? escape_tags(trim($_REQUEST['cat'])) : '');
|
||||
|
||||
if($category) {
|
||||
$sql_extra2 .= protect_sprintf(term_item_parent_query(\App::$profile['profile_uid'],'item', $category, TERM_CATEGORY));
|
||||
}
|
||||
|
||||
|
||||
$which = argv(1);
|
||||
|
||||
$selected_card = ((argc() > 2) ? argv(2) : '');
|
||||
|
||||
$_SESSION['return_url'] = \App::$query_string;
|
||||
|
||||
$uid = local_channel();
|
||||
$owner = \App::$profile_uid;
|
||||
$observer = \App::get_observer();
|
||||
|
||||
$ob_hash = (($observer) ? $observer['xchan_hash'] : '');
|
||||
|
||||
if(! perm_is_allowed($owner,$ob_hash,'view_pages')) {
|
||||
notice( t('Permission denied.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
$is_owner = ($uid && $uid == $owner);
|
||||
|
||||
$channel = channelx_by_n($owner);
|
||||
|
||||
if($channel) {
|
||||
$channel_acl = array(
|
||||
'allow_cid' => $channel['channel_allow_cid'],
|
||||
'allow_gid' => $channel['channel_allow_gid'],
|
||||
'deny_cid' => $channel['channel_deny_cid'],
|
||||
'deny_gid' => $channel['channel_deny_gid']
|
||||
);
|
||||
}
|
||||
else {
|
||||
$channel_acl = [ 'allow_cid' => '', 'allow_gid' => '', 'deny_cid' => '', 'deny_gid' => '' ];
|
||||
}
|
||||
|
||||
|
||||
|
||||
if(perm_is_allowed($owner,$ob_hash,'write_pages')) {
|
||||
|
||||
$x = [
|
||||
'webpage' => ITEM_TYPE_ARTICLE,
|
||||
'is_owner' => true,
|
||||
'content_label' => t('Add Article'),
|
||||
'button' => t('Create'),
|
||||
'nickname' => $channel['channel_address'],
|
||||
'lockstate' => (($channel['channel_allow_cid'] || $channel['channel_allow_gid']
|
||||
|| $channel['channel_deny_cid'] || $channel['channel_deny_gid']) ? 'lock' : 'unlock'),
|
||||
'acl' => (($is_owner) ? populate_acl($channel_acl, false,
|
||||
\Zotlabs\Lib\PermissionDescription::fromGlobalPermission('view_pages')) : ''),
|
||||
'permissions' => $channel_acl,
|
||||
'showacl' => (($is_owner) ? true : false),
|
||||
'visitor' => true,
|
||||
'hide_location' => false,
|
||||
'hide_voting' => false,
|
||||
'profile_uid' => intval($owner),
|
||||
'mimetype' => 'text/bbcode',
|
||||
'mimeselect' => false,
|
||||
'layoutselect' => false,
|
||||
'expanded' => false,
|
||||
'novoting' => false,
|
||||
'catsenabled' => feature_enabled($owner,'categories'),
|
||||
'bbco_autocomplete' => 'bbcode',
|
||||
'bbcode' => true
|
||||
];
|
||||
|
||||
if($_REQUEST['title'])
|
||||
$x['title'] = $_REQUEST['title'];
|
||||
if($_REQUEST['body'])
|
||||
$x['body'] = $_REQUEST['body'];
|
||||
$editor = status_editor($a,$x);
|
||||
|
||||
}
|
||||
else {
|
||||
$editor = '';
|
||||
}
|
||||
|
||||
|
||||
$sql_extra = item_permissions_sql($owner);
|
||||
|
||||
if($selected_card) {
|
||||
$r = q("select * from iconfig where iconfig.cat = 'system' and iconfig.k = 'ARTICLE' and iconfig.v = '%s' limit 1",
|
||||
dbesc($selected_card)
|
||||
);
|
||||
if($r) {
|
||||
$sql_extra .= "and item.id = " . intval($r[0]['iid']) . " ";
|
||||
}
|
||||
}
|
||||
|
||||
$r = q("select * from item
|
||||
where item.uid = %d and item_type = %d
|
||||
$sql_extra order by item.created desc",
|
||||
intval($owner),
|
||||
intval(ITEM_TYPE_ARTICLE)
|
||||
);
|
||||
|
||||
$item_normal = " and item.item_hidden = 0 and item.item_type in (0,7) and item.item_deleted = 0
|
||||
and item.item_unpublished = 0 and item.item_delayed = 0 and item.item_pending_remove = 0
|
||||
and item.item_blocked = 0 ";
|
||||
|
||||
if($r) {
|
||||
|
||||
$parents_str = ids_to_querystr($r,'id');
|
||||
|
||||
$items = q("SELECT item.*, item.id AS item_id
|
||||
FROM item
|
||||
WHERE item.uid = %d $item_normal
|
||||
AND item.parent IN ( %s )
|
||||
$sql_extra $sql_extra2 ",
|
||||
intval(\App::$profile['profile_uid']),
|
||||
dbesc($parents_str)
|
||||
);
|
||||
if($items) {
|
||||
xchan_query($items);
|
||||
$items = fetch_post_tags($items, true);
|
||||
$items = conv_sort($items,'updated');
|
||||
}
|
||||
else
|
||||
$items = [];
|
||||
}
|
||||
|
||||
$mode = 'articles';
|
||||
|
||||
$content = conversation($items,$mode,false,'traditional');
|
||||
|
||||
$o = replace_macros(get_markup_template('cards.tpl'), [
|
||||
'$title' => t('Articles'),
|
||||
'$editor' => $editor,
|
||||
'$content' => $content,
|
||||
'$pager' => alt_pager($a,count($items))
|
||||
]);
|
||||
|
||||
return $o;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -31,7 +31,7 @@ class Attach extends \Zotlabs\Web\Controller {
|
||||
|
||||
$unsafe_types = array('text/html','text/css','application/javascript');
|
||||
|
||||
if(in_array($r['data']['filetype'],$unsafe_types)) {
|
||||
if(in_array($r['data']['filetype'],$unsafe_types) && (! channel_codeallowed($r['data']['uid']))) {
|
||||
header('Content-type: text/plain');
|
||||
}
|
||||
else {
|
||||
|
||||
71
Zotlabs/Module/Authorize.php
Normal file
71
Zotlabs/Module/Authorize.php
Normal file
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
|
||||
class Authorize extends \Zotlabs\Web\Controller {
|
||||
|
||||
|
||||
function get() {
|
||||
|
||||
|
||||
// workaround for HTTP-auth in CGI mode
|
||||
if (x($_SERVER, 'REDIRECT_REMOTE_USER')) {
|
||||
$userpass = base64_decode(substr($_SERVER["REDIRECT_REMOTE_USER"], 6)) ;
|
||||
if(strlen($userpass)) {
|
||||
list($name, $password) = explode(':', $userpass);
|
||||
$_SERVER['PHP_AUTH_USER'] = $name;
|
||||
$_SERVER['PHP_AUTH_PW'] = $password;
|
||||
}
|
||||
}
|
||||
|
||||
if (x($_SERVER, 'HTTP_AUTHORIZATION')) {
|
||||
$userpass = base64_decode(substr($_SERVER["HTTP_AUTHORIZATION"], 6)) ;
|
||||
if(strlen($userpass)) {
|
||||
list($name, $password) = explode(':', $userpass);
|
||||
$_SERVER['PHP_AUTH_USER'] = $name;
|
||||
$_SERVER['PHP_AUTH_PW'] = $password;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
require_once('include/oauth2.php');
|
||||
|
||||
$request = \OAuth2\Request::createFromGlobals();
|
||||
$response = new \OAuth2\Response();
|
||||
|
||||
// validate the authorize request
|
||||
if (! $oauth2_server->validateAuthorizeRequest($request, $response)) {
|
||||
$response->send();
|
||||
killme();
|
||||
}
|
||||
|
||||
// display an authorization form
|
||||
if (empty($_POST)) {
|
||||
|
||||
return '
|
||||
<form method="post">
|
||||
<label>Do You Authorize TestClient?</label><br />
|
||||
<input type="submit" name="authorized" value="yes">
|
||||
<input type="submit" name="authorized" value="no">
|
||||
</form>';
|
||||
}
|
||||
|
||||
// print the authorization code if the user has authorized your client
|
||||
$is_authorized = ($_POST['authorized'] === 'yes');
|
||||
$oauth2_server->handleAuthorizeRequest($request, $response, $is_authorized);
|
||||
if ($is_authorized) {
|
||||
// this is only here so that you get to see your code in the cURL request. Otherwise,
|
||||
// we'd redirect back to the client
|
||||
$code = substr($response->getHttpHeader('Location'), strpos($response->getHttpHeader('Location'), 'code=')+5, 40);
|
||||
echo("SUCCESS! Authorization Code: $code");
|
||||
|
||||
}
|
||||
|
||||
$response->send();
|
||||
killme();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3,8 +3,6 @@ namespace Zotlabs\Module;
|
||||
|
||||
require_once('include/items.php');
|
||||
require_once('include/conversation.php');
|
||||
require_once('include/page_widgets.php');
|
||||
|
||||
|
||||
class Block extends \Zotlabs\Web\Controller {
|
||||
|
||||
|
||||
@@ -7,6 +7,9 @@ class Bookmarks extends \Zotlabs\Web\Controller {
|
||||
function init() {
|
||||
if(! local_channel())
|
||||
return;
|
||||
|
||||
nav_set_selected('View Bookmarks');
|
||||
|
||||
$item_id = intval($_REQUEST['item']);
|
||||
$burl = trim($_REQUEST['burl']);
|
||||
|
||||
@@ -68,7 +71,8 @@ class Bookmarks extends \Zotlabs\Web\Controller {
|
||||
|
||||
$channel = \App::get_channel();
|
||||
|
||||
$o = profile_tabs($a,true,$channel['channel_address']);
|
||||
//$o = profile_tabs($a,true,$channel['channel_address']);
|
||||
$o = '';
|
||||
|
||||
$o .= '<div class="generic-content-wrapper-styled">';
|
||||
|
||||
|
||||
@@ -69,6 +69,8 @@ class Cal extends \Zotlabs\Web\Controller {
|
||||
notice( t('Permissions denied.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
nav_set_selected('Calendar');
|
||||
|
||||
$sql_extra = permissions_sql($channel['channel_id'],get_observer_hash(),'event');
|
||||
|
||||
@@ -86,7 +88,8 @@ class Cal extends \Zotlabs\Web\Controller {
|
||||
|
||||
$o = '';
|
||||
|
||||
$tabs = profile_tabs($a, True, $channel['channel_address']);
|
||||
//$tabs = profile_tabs($a, True, $channel['channel_address']);
|
||||
$tabs = '';
|
||||
|
||||
$mode = 'view';
|
||||
$y = 0;
|
||||
|
||||
138
Zotlabs/Module/Card_edit.php
Normal file
138
Zotlabs/Module/Card_edit.php
Normal file
@@ -0,0 +1,138 @@
|
||||
<?php
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
require_once('include/channel.php');
|
||||
require_once('include/acl_selectors.php');
|
||||
require_once('include/conversation.php');
|
||||
|
||||
class Card_edit extends \Zotlabs\Web\Controller {
|
||||
|
||||
|
||||
function get() {
|
||||
|
||||
// Figure out which post we're editing
|
||||
$post_id = ((argc() > 1) ? intval(argv(1)) : 0);
|
||||
|
||||
if(! $post_id) {
|
||||
notice( t('Item not found') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
$itm = q("SELECT * FROM item WHERE id = %d and item_type = %d LIMIT 1",
|
||||
intval($post_id),
|
||||
intval(ITEM_TYPE_CARD)
|
||||
);
|
||||
if($itm) {
|
||||
$item_id = q("select * from iconfig where cat = 'system' and k = 'CARD' and iid = %d limit 1",
|
||||
intval($itm[0]['id'])
|
||||
);
|
||||
if($item_id)
|
||||
$card_title = $item_id[0]['v'];
|
||||
}
|
||||
else {
|
||||
notice( t('Item not found') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
$owner = $itm[0]['uid'];
|
||||
$uid = local_channel();
|
||||
|
||||
$observer = \App::get_observer();
|
||||
|
||||
$channel = channelx_by_n($owner);
|
||||
if(! $channel) {
|
||||
notice( t('Channel not found.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
$ob_hash = (($observer) ? $observer['xchan_hash'] : '');
|
||||
|
||||
if(! perm_is_allowed($owner,$ob_hash,'write_pages')) {
|
||||
notice( t('Permission denied.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
$is_owner = (($uid && $uid == $owner) ? true : false);
|
||||
|
||||
$o = '';
|
||||
|
||||
|
||||
|
||||
$category = '';
|
||||
$catsenabled = ((feature_enabled($owner,'categories')) ? 'categories' : '');
|
||||
|
||||
if ($catsenabled){
|
||||
$itm = fetch_post_tags($itm);
|
||||
|
||||
$cats = get_terms_oftype($itm[0]['term'], TERM_CATEGORY);
|
||||
|
||||
foreach ($cats as $cat) {
|
||||
if (strlen($category))
|
||||
$category .= ', ';
|
||||
$category .= $cat['term'];
|
||||
}
|
||||
}
|
||||
|
||||
if($itm[0]['attach']) {
|
||||
$j = json_decode($itm[0]['attach'],true);
|
||||
if($j) {
|
||||
foreach($j as $jj) {
|
||||
$itm[0]['body'] .= "\n" . '[attachment]' . basename($jj['href']) . ',' . $jj['revision'] . '[/attachment]' . "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$mimetype = $itm[0]['mimetype'];
|
||||
|
||||
$content = $itm[0]['body'];
|
||||
|
||||
|
||||
|
||||
$rp = 'cards/' . $channel['channel_address'];
|
||||
|
||||
$x = array(
|
||||
'nickname' => $channel['channel_address'],
|
||||
'bbco_autocomplete'=> 'bbcode',
|
||||
'return_path' => $rp,
|
||||
'webpage' => ITEM_TYPE_CARD,
|
||||
'button' => t('Edit'),
|
||||
'writefiles' => perm_is_allowed($owner, get_observer_hash(), 'write_pages'),
|
||||
'weblink' => t('Insert web link'),
|
||||
'hide_voting' => false,
|
||||
'hide_future' => false,
|
||||
'hide_location' => false,
|
||||
'hide_expire' => false,
|
||||
'showacl' => true,
|
||||
'acl' => populate_acl($itm[0],false,\Zotlabs\Lib\PermissionDescription::fromGlobalPermission('view_pages')),
|
||||
'permissions' => $itm[0],
|
||||
'lockstate' => (($itm[0]['allow_cid'] || $itm[0]['allow_gid'] || $itm[0]['deny_cid'] || $itm[0]['deny_gid']) ? 'lock' : 'unlock'),
|
||||
'ptyp' => $itm[0]['type'],
|
||||
'mimeselect' => false,
|
||||
'mimetype' => $itm[0]['mimetype'],
|
||||
'body' => undo_post_tagging($content),
|
||||
'post_id' => $post_id,
|
||||
'visitor' => true,
|
||||
'title' => htmlspecialchars($itm[0]['title'],ENT_COMPAT,'UTF-8'),
|
||||
'placeholdertitle' => t('Title (optional)'),
|
||||
'pagetitle' => $card_title,
|
||||
'profile_uid' => (intval($channel['channel_id'])),
|
||||
'catsenabled' => $catsenabled,
|
||||
'category' => $category,
|
||||
'bbcode' => (($mimetype == 'text/bbcode') ? true : false)
|
||||
);
|
||||
|
||||
$editor = status_editor($a, $x);
|
||||
|
||||
$o .= replace_macros(get_markup_template('edpost_head.tpl'), array(
|
||||
'$title' => t('Edit Card'),
|
||||
'$delete' => ((($itm[0]['author_xchan'] === $ob_hash) || ($itm[0]['owner_xchan'] === $ob_hash)) ? t('Delete') : false),
|
||||
'$id' => $itm[0]['id'],
|
||||
'$editor' => $editor
|
||||
));
|
||||
|
||||
return $o;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
187
Zotlabs/Module/Cards.php
Normal file
187
Zotlabs/Module/Cards.php
Normal file
@@ -0,0 +1,187 @@
|
||||
<?php
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
require_once('include/channel.php');
|
||||
require_once('include/conversation.php');
|
||||
require_once('include/acl_selectors.php');
|
||||
|
||||
|
||||
class Cards extends \Zotlabs\Web\Controller {
|
||||
|
||||
function init() {
|
||||
|
||||
if(argc() > 1)
|
||||
$which = argv(1);
|
||||
else
|
||||
return;
|
||||
|
||||
profile_load($which);
|
||||
|
||||
}
|
||||
|
||||
function get($update = 0, $load = false) {
|
||||
|
||||
if(observer_prohibited(true)) {
|
||||
return login();
|
||||
}
|
||||
|
||||
if(! \App::$profile) {
|
||||
notice( t('Requested profile is not available.') . EOL );
|
||||
\App::$error = 404;
|
||||
return;
|
||||
}
|
||||
|
||||
if(! feature_enabled(\App::$profile_uid,'cards')) {
|
||||
return;
|
||||
}
|
||||
|
||||
nav_set_selected(t('Cards'));
|
||||
|
||||
head_add_link([
|
||||
'rel' => 'alternate',
|
||||
'type' => 'application/json+oembed',
|
||||
'href' => z_root() . '/oep?f=&url=' . urlencode(z_root() . '/' . \App::$query_string),
|
||||
'title' => 'oembed'
|
||||
]);
|
||||
|
||||
|
||||
$category = (($_REQUEST['cat']) ? escape_tags(trim($_REQUEST['cat'])) : '');
|
||||
|
||||
if($category) {
|
||||
$sql_extra2 .= protect_sprintf(term_item_parent_query(\App::$profile['profile_uid'],'item', $category, TERM_CATEGORY));
|
||||
}
|
||||
|
||||
|
||||
$which = argv(1);
|
||||
|
||||
$selected_card = ((argc() > 2) ? argv(2) : '');
|
||||
|
||||
$_SESSION['return_url'] = \App::$query_string;
|
||||
|
||||
$uid = local_channel();
|
||||
$owner = \App::$profile_uid;
|
||||
$observer = \App::get_observer();
|
||||
|
||||
$ob_hash = (($observer) ? $observer['xchan_hash'] : '');
|
||||
|
||||
if(! perm_is_allowed($owner,$ob_hash,'view_pages')) {
|
||||
notice( t('Permission denied.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
$is_owner = ($uid && $uid == $owner);
|
||||
|
||||
$channel = channelx_by_n($owner);
|
||||
|
||||
if($channel) {
|
||||
$channel_acl = array(
|
||||
'allow_cid' => $channel['channel_allow_cid'],
|
||||
'allow_gid' => $channel['channel_allow_gid'],
|
||||
'deny_cid' => $channel['channel_deny_cid'],
|
||||
'deny_gid' => $channel['channel_deny_gid']
|
||||
);
|
||||
}
|
||||
else {
|
||||
$channel_acl = [ 'allow_cid' => '', 'allow_gid' => '', 'deny_cid' => '', 'deny_gid' => '' ];
|
||||
}
|
||||
|
||||
|
||||
|
||||
if(perm_is_allowed($owner,$ob_hash,'write_pages')) {
|
||||
|
||||
$x = [
|
||||
'webpage' => ITEM_TYPE_CARD,
|
||||
'is_owner' => true,
|
||||
'content_label' => t('Add Card'),
|
||||
'button' => t('Create'),
|
||||
'nickname' => $channel['channel_address'],
|
||||
'lockstate' => (($channel['channel_allow_cid'] || $channel['channel_allow_gid']
|
||||
|| $channel['channel_deny_cid'] || $channel['channel_deny_gid']) ? 'lock' : 'unlock'),
|
||||
'acl' => (($is_owner) ? populate_acl($channel_acl, false,
|
||||
\Zotlabs\Lib\PermissionDescription::fromGlobalPermission('view_pages')) : ''),
|
||||
'permissions' => $channel_acl,
|
||||
'showacl' => (($is_owner) ? true : false),
|
||||
'visitor' => true,
|
||||
'hide_location' => false,
|
||||
'hide_voting' => false,
|
||||
'profile_uid' => intval($owner),
|
||||
'mimetype' => 'text/bbcode',
|
||||
'mimeselect' => false,
|
||||
'layoutselect' => false,
|
||||
'expanded' => false,
|
||||
'novoting' => false,
|
||||
'catsenabled' => feature_enabled($owner,'categories'),
|
||||
'bbco_autocomplete' => 'bbcode',
|
||||
'bbcode' => true
|
||||
];
|
||||
|
||||
if($_REQUEST['title'])
|
||||
$x['title'] = $_REQUEST['title'];
|
||||
if($_REQUEST['body'])
|
||||
$x['body'] = $_REQUEST['body'];
|
||||
$editor = status_editor($a,$x);
|
||||
|
||||
}
|
||||
else {
|
||||
$editor = '';
|
||||
}
|
||||
|
||||
|
||||
$sql_extra = item_permissions_sql($owner);
|
||||
|
||||
if($selected_card) {
|
||||
$r = q("select * from iconfig where iconfig.cat = 'system' and iconfig.k = 'CARD' and iconfig.v = '%s' limit 1",
|
||||
dbesc($selected_card)
|
||||
);
|
||||
if($r) {
|
||||
$sql_extra .= "and item.id = " . intval($r[0]['iid']) . " ";
|
||||
}
|
||||
}
|
||||
|
||||
$r = q("select * from item
|
||||
where item.uid = %d and item_type = %d
|
||||
$sql_extra order by item.created desc",
|
||||
intval($owner),
|
||||
intval(ITEM_TYPE_CARD)
|
||||
);
|
||||
|
||||
$item_normal = " and item.item_hidden = 0 and item.item_type in (0,6) and item.item_deleted = 0
|
||||
and item.item_unpublished = 0 and item.item_delayed = 0 and item.item_pending_remove = 0
|
||||
and item.item_blocked = 0 ";
|
||||
|
||||
if($r) {
|
||||
|
||||
$parents_str = ids_to_querystr($r,'id');
|
||||
|
||||
$items = q("SELECT item.*, item.id AS item_id
|
||||
FROM item
|
||||
WHERE item.uid = %d $item_normal
|
||||
AND item.parent IN ( %s )
|
||||
$sql_extra $sql_extra2 ",
|
||||
intval(\App::$profile['profile_uid']),
|
||||
dbesc($parents_str)
|
||||
);
|
||||
if($items) {
|
||||
xchan_query($items);
|
||||
$items = fetch_post_tags($items, true);
|
||||
$items = conv_sort($items,'updated');
|
||||
}
|
||||
else
|
||||
$items = [];
|
||||
}
|
||||
|
||||
$mode = 'cards';
|
||||
|
||||
$content = conversation($items,$mode,false,'traditional');
|
||||
|
||||
$o = replace_macros(get_markup_template('cards.tpl'), [
|
||||
'$title' => t('Cards'),
|
||||
'$editor' => $editor,
|
||||
'$content' => $content,
|
||||
'$pager' => alt_pager($a,count($items))
|
||||
]);
|
||||
|
||||
return $o;
|
||||
}
|
||||
|
||||
}
|
||||
1259
Zotlabs/Module/Cdav.php
Normal file
1259
Zotlabs/Module/Cdav.php
Normal file
File diff suppressed because it is too large
Load Diff
88
Zotlabs/Module/Changeaddr.php
Normal file
88
Zotlabs/Module/Changeaddr.php
Normal file
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
|
||||
class Changeaddr extends \Zotlabs\Web\Controller {
|
||||
|
||||
function post() {
|
||||
|
||||
if(! local_channel())
|
||||
return;
|
||||
|
||||
if($_SESSION['delegate'])
|
||||
return;
|
||||
|
||||
if((! x($_POST,'qxz_password')) || (! strlen(trim($_POST['qxz_password']))))
|
||||
return;
|
||||
|
||||
if((! x($_POST,'verify')) || (! strlen(trim($_POST['verify']))))
|
||||
return;
|
||||
|
||||
if($_POST['verify'] !== $_SESSION['remove_account_verify'])
|
||||
return;
|
||||
|
||||
|
||||
$account = \App::get_account();
|
||||
$channel = \App::get_channel();
|
||||
|
||||
$x = account_verify_password($account['account_email'],$_POST['qxz_password']);
|
||||
if(! ($x && $x['account']))
|
||||
return;
|
||||
|
||||
if($account['account_password_changed'] > NULL_DATE) {
|
||||
$d1 = datetime_convert('UTC','UTC','now - 48 hours');
|
||||
if($account['account_password_changed'] > d1) {
|
||||
notice( t('Channel name changes are not allowed within 48 hours of changing the account password.') . EOL);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$new_address = trim($_POST['newname']);
|
||||
|
||||
if($new_address === $channel['channel_address'])
|
||||
return;
|
||||
|
||||
if($new_address === 'sys') {
|
||||
notice( t('Reserved nickname. Please choose another.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
if(check_webbie(array($new_address)) !== $new_address) {
|
||||
notice( t('Nickname has unsupported characters or is already being used on this site.') . EOL);
|
||||
return $ret;
|
||||
}
|
||||
|
||||
channel_change_address($channel,$new_address);
|
||||
|
||||
goaway(z_root() . '/changeaddr');
|
||||
|
||||
}
|
||||
|
||||
|
||||
function get() {
|
||||
|
||||
if(! local_channel())
|
||||
goaway(z_root());
|
||||
|
||||
$channel = \App::get_channel();
|
||||
|
||||
$hash = random_string();
|
||||
|
||||
$_SESSION['remove_account_verify'] = $hash;
|
||||
|
||||
$tpl = get_markup_template('channel_rename.tpl');
|
||||
$o .= replace_macros($tpl, array(
|
||||
'$basedir' => z_root(),
|
||||
'$hash' => $hash,
|
||||
'$title' => t('Change channel nickname/address'),
|
||||
'$desc' => array(t('WARNING: '), t('Any/all connections on other networks will be lost!')),
|
||||
'$passwd' => t('Please enter your password for verification:'),
|
||||
'$newname' => array('newname', t('New channel address'),$channel['channel_address'], ''),
|
||||
'$submit' => t('Rename Channel')
|
||||
));
|
||||
|
||||
return $o;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -92,11 +92,6 @@ class Channel extends \Zotlabs\Web\Controller {
|
||||
// Ensure we've got a profile owner if updating.
|
||||
\App::$profile['profile_uid'] = \App::$profile_uid = $update;
|
||||
}
|
||||
else {
|
||||
if(\App::$profile['profile_uid'] == local_channel()) {
|
||||
nav_set_selected('home');
|
||||
}
|
||||
}
|
||||
|
||||
$is_owner = (((local_channel()) && (\App::$profile['profile_uid'] == local_channel())) ? true : false);
|
||||
|
||||
@@ -119,11 +114,13 @@ class Channel extends \Zotlabs\Web\Controller {
|
||||
|
||||
if(! $update) {
|
||||
|
||||
nav_set_selected('Channel Home');
|
||||
|
||||
$static = channel_manual_conv_update(\App::$profile['profile_uid']);
|
||||
|
||||
$o .= profile_tabs($a, $is_owner, \App::$profile['channel_address']);
|
||||
//$o .= profile_tabs($a, $is_owner, \App::$profile['channel_address']);
|
||||
|
||||
$o .= common_friends_visitor_widget(\App::$profile['profile_uid']);
|
||||
// $o .= common_friends_visitor_widget(\App::$profile['profile_uid']);
|
||||
|
||||
if($channel && $is_owner) {
|
||||
$channel_acl = array(
|
||||
@@ -169,6 +166,7 @@ class Channel extends \Zotlabs\Web\Controller {
|
||||
*/
|
||||
|
||||
$item_normal = item_normal();
|
||||
$item_normal_update = item_normal_update();
|
||||
$sql_extra = item_permissions_sql(\App::$profile['profile_uid']);
|
||||
|
||||
if(get_pconfig(\App::$profile['profile_uid'],'system','channel_list_mode') && (! $mid))
|
||||
@@ -180,7 +178,12 @@ class Channel extends \Zotlabs\Web\Controller {
|
||||
|
||||
$simple_update = (($update) ? " AND item_unseen = 1 " : '');
|
||||
|
||||
\App::$page['htmlhead'] .= "\r\n" . '<link rel="alternate" type="application/json+oembed" href="' . z_root() . '/oep?f=&url=' . urlencode(z_root() . '/' . \App::$query_string) . '" title="oembed" />' . "\r\n";
|
||||
head_add_link([
|
||||
'rel' => 'alternate',
|
||||
'type' => 'application/json+oembed',
|
||||
'href' => z_root() . '/oep?f=&url=' . urlencode(z_root() . '/' . \App::$query_string),
|
||||
'title' => 'oembed'
|
||||
]);
|
||||
|
||||
if($update && $_SESSION['loadtime'])
|
||||
$simple_update = " AND (( item_unseen = 1 AND item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' ) OR item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' ) ";
|
||||
@@ -188,12 +191,12 @@ class Channel extends \Zotlabs\Web\Controller {
|
||||
$simple_update = '';
|
||||
|
||||
if($static && $simple_update)
|
||||
$simple_update .= " and item_thread_top = 0 and author_xchan = '" . protect_sprintf(get_observer_hash()) . "' ";
|
||||
$simple_update .= " and author_xchan = '" . protect_sprintf(get_observer_hash()) . "' ";
|
||||
|
||||
if(($update) && (! $load)) {
|
||||
|
||||
if($mid) {
|
||||
$r = q("SELECT parent AS item_id from item where mid like '%s' and uid = %d $item_normal
|
||||
$r = q("SELECT parent AS item_id from item where mid like '%s' and uid = %d $item_normal_update
|
||||
AND item_wall = 1 $simple_update $sql_extra limit 1",
|
||||
dbesc($mid . '%'),
|
||||
intval(\App::$profile['profile_uid'])
|
||||
@@ -203,7 +206,7 @@ class Channel extends \Zotlabs\Web\Controller {
|
||||
else {
|
||||
$r = q("SELECT distinct parent AS item_id, created from item
|
||||
left join abook on ( item.owner_xchan = abook.abook_xchan $abook_uids )
|
||||
WHERE uid = %d $item_normal
|
||||
WHERE uid = %d $item_normal_update
|
||||
AND item_wall = 1 $simple_update
|
||||
AND (abook.abook_blocked = 0 or abook.abook_flags is null)
|
||||
$sql_extra
|
||||
@@ -217,10 +220,10 @@ class Channel extends \Zotlabs\Web\Controller {
|
||||
else {
|
||||
|
||||
if(x($category)) {
|
||||
$sql_extra .= protect_sprintf(term_query('item', $category, TERM_CATEGORY));
|
||||
$sql_extra2 .= protect_sprintf(term_item_parent_query(\App::$profile['profile_uid'],'item', $category, TERM_CATEGORY));
|
||||
}
|
||||
if(x($hashtags)) {
|
||||
$sql_extra .= protect_sprintf(term_query('item', $hashtags, TERM_HASHTAG, TERM_COMMUNITYTAG));
|
||||
$sql_extra2 .= protect_sprintf(term_item_parent_query(\App::$profile['profile_uid'],'item', $hashtags, TERM_HASHTAG, TERM_COMMUNITYTAG));
|
||||
}
|
||||
|
||||
if($datequery) {
|
||||
@@ -236,9 +239,9 @@ class Channel extends \Zotlabs\Web\Controller {
|
||||
|
||||
if($load || ($checkjs->disabled())) {
|
||||
if($mid) {
|
||||
$r = q("SELECT parent AS item_id from item where mid = '%s' and uid = %d $item_normal
|
||||
$r = q("SELECT distinct parent AS item_id from item where mid like '%s' and uid = %d $item_normal
|
||||
AND item_wall = 1 $sql_extra limit 1",
|
||||
dbesc($mid),
|
||||
dbesc($mid . '%'),
|
||||
intval(\App::$profile['profile_uid'])
|
||||
);
|
||||
if (! $r) {
|
||||
@@ -321,13 +324,15 @@ class Channel extends \Zotlabs\Web\Controller {
|
||||
'$static' => $static,
|
||||
'$page' => ((\App::$pager['page'] != 1) ? \App::$pager['page'] : 1),
|
||||
'$search' => '',
|
||||
'$xchan' => '',
|
||||
'$order' => '',
|
||||
'$list' => ((x($_REQUEST,'list')) ? intval($_REQUEST['list']) : 0),
|
||||
'$file' => '',
|
||||
'$cats' => (($category) ? $category : ''),
|
||||
'$tags' => (($hashtags) ? $hashtags : ''),
|
||||
'$cats' => (($category) ? urlencode($category) : ''),
|
||||
'$tags' => (($hashtags) ? urlencode($hashtags) : ''),
|
||||
'$mid' => $mid,
|
||||
'$verb' => '',
|
||||
'$net' => '',
|
||||
'$dend' => $datequery,
|
||||
'$dbegin' => $datequery2
|
||||
));
|
||||
@@ -357,17 +362,21 @@ class Channel extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
|
||||
if($is_owner && $update_unseen) {
|
||||
$r = q("UPDATE item SET item_unseen = 0 where item_unseen = 1 and item_wall = 1 AND uid = %d $update_unseen",
|
||||
intval(local_channel())
|
||||
);
|
||||
$x = [ 'channel_id' => local_channel(), 'update' => 'unset' ];
|
||||
call_hooks('update_unseen',$x);
|
||||
if($x['update'] === 'unset' || intval($x['update'])) {
|
||||
$r = q("UPDATE item SET item_unseen = 0 where item_unseen = 1 and item_wall = 1 AND uid = %d $update_unseen",
|
||||
intval(local_channel())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if($checkjs->disabled()) {
|
||||
$o .= conversation($a,$items,'channel',$update,'traditional');
|
||||
$o .= conversation($items,'channel',$update,'traditional');
|
||||
}
|
||||
else {
|
||||
$o .= conversation($a,$items,'channel',$update,$page_mode);
|
||||
$o .= conversation($items,'channel',$update,$page_mode);
|
||||
}
|
||||
|
||||
if((! $update) || ($checkjs->disabled())) {
|
||||
|
||||
@@ -102,27 +102,32 @@ class Chanview extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
|
||||
$is_zot = false;
|
||||
$connected = false;
|
||||
|
||||
if (\App::$poi) {
|
||||
$url = \App::$poi['xchan_url'];
|
||||
if(\App::$poi['xchan_network'] === 'zot') {
|
||||
$is_zot = true;
|
||||
}
|
||||
if(local_channel()) {
|
||||
$c = q("select abook_id from abook where abook_channel = %d and abook_xchan = '%s' limit 1",
|
||||
intval(local_channel()),
|
||||
dbesc(\App::$poi['xchan_hash'])
|
||||
);
|
||||
if($c)
|
||||
$connected = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// We will load the chanview template if it's a foreign network,
|
||||
// just so that we can provide a connect button along with a profile
|
||||
// photo. Chances are we can't load the remote profile into an iframe
|
||||
// because of cross-domain security headers. So provide a link to
|
||||
// the remote profile.
|
||||
|
||||
// If we are already connected, just go to the profile.
|
||||
// Zot channels will usually have a connect link.
|
||||
// If it isn't zot, 'pro' members won't be able to use the connect
|
||||
// button as it is a foreign network so just send them to the remote
|
||||
// profile.
|
||||
|
||||
|
||||
if($is_zot || \Zotlabs\Lib\System::get_server_role() === 'pro') {
|
||||
if($is_zot || $connected) {
|
||||
if($is_zot && $observer) {
|
||||
$url = zid($url);
|
||||
}
|
||||
|
||||
@@ -89,9 +89,11 @@ class Chat extends \Zotlabs\Web\Controller {
|
||||
|
||||
function get() {
|
||||
|
||||
if(local_channel())
|
||||
if(local_channel()) {
|
||||
$channel = \App::get_channel();
|
||||
|
||||
nav_set_selected('My Chatrooms');
|
||||
}
|
||||
|
||||
$ob = \App::get_observer();
|
||||
$observer = get_observer_hash();
|
||||
if(! $observer) {
|
||||
@@ -210,7 +212,8 @@ class Chat extends \Zotlabs\Web\Controller {
|
||||
|
||||
require_once('include/conversation.php');
|
||||
|
||||
$o = profile_tabs($a,((local_channel() && local_channel() == \App::$profile['profile_uid']) ? true : false),\App::$profile['channel_address']);
|
||||
//$o = profile_tabs($a,((local_channel() && local_channel() == \App::$profile['profile_uid']) ? true : false),\App::$profile['channel_address']);
|
||||
$o = '';
|
||||
|
||||
if(! feature_enabled(\App::$profile['profile_uid'],'ajaxchat')) {
|
||||
notice( t('Feature disabled.') . EOL);
|
||||
|
||||
@@ -57,14 +57,12 @@ class Cloud extends \Zotlabs\Web\Controller {
|
||||
$auth->observer = $ob_hash;
|
||||
}
|
||||
|
||||
// if we arrived at this path with any query parameters in the url, build a clean url without
|
||||
// them and redirect.
|
||||
|
||||
$_SERVER['QUERY_STRING'] = str_replace(array('?f=', '&f='), array('', ''), $_SERVER['QUERY_STRING']);
|
||||
$_SERVER['QUERY_STRING'] = strip_zids($_SERVER['QUERY_STRING']);
|
||||
$_SERVER['QUERY_STRING'] = preg_replace('/[\?&]davguest=(.*?)([\?&]|$)/ism', '', $_SERVER['QUERY_STRING']);
|
||||
|
||||
$_SERVER['REQUEST_URI'] = str_replace(array('?f=', '&f='), array('', ''), $_SERVER['REQUEST_URI']);
|
||||
$_SERVER['REQUEST_URI'] = strip_zids($_SERVER['REQUEST_URI']);
|
||||
$_SERVER['REQUEST_URI'] = preg_replace('/[\?&]davguest=(.*?)([\?&]|$)/ism', '', $_SERVER['REQUEST_URI']);
|
||||
$x = clean_query_string();
|
||||
if($x !== \App::$query_string)
|
||||
goaway(z_root() . '/' . $x);
|
||||
|
||||
$rootDirectory = new \Zotlabs\Storage\Directory('/', $auth);
|
||||
|
||||
@@ -85,16 +83,42 @@ class Cloud extends \Zotlabs\Web\Controller {
|
||||
$server->addPlugin($browser);
|
||||
|
||||
// Experimental QuotaPlugin
|
||||
// require_once('\Zotlabs\Storage/QuotaPlugin.php');
|
||||
// $server->addPlugin(new \Zotlabs\Storage\\QuotaPlugin($auth));
|
||||
// require_once('\Zotlabs\Storage/QuotaPlugin.php');
|
||||
// $server->addPlugin(new \Zotlabs\Storage\\QuotaPlugin($auth));
|
||||
|
||||
|
||||
// over-ride the default XML output on thrown exceptions
|
||||
|
||||
$server->on('exception', [ $this, 'DAVException' ]);
|
||||
|
||||
ob_start();
|
||||
// All we need to do now, is to fire up the server
|
||||
|
||||
$server->exec();
|
||||
|
||||
ob_end_flush();
|
||||
if($browser->build_page)
|
||||
construct_page();
|
||||
|
||||
killme();
|
||||
}
|
||||
|
||||
|
||||
function DAVException($err) {
|
||||
|
||||
if($err instanceof \Sabre\DAV\Exception\NotFound) {
|
||||
notice( t('Not found') . EOL);
|
||||
}
|
||||
elseif($err instanceof \Sabre\DAV\Exception\Forbidden) {
|
||||
notice( t('Permission denied') . EOL);
|
||||
}
|
||||
else {
|
||||
notice( t('Unknown error') . EOL);
|
||||
}
|
||||
|
||||
construct_page();
|
||||
|
||||
killme();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
21
Zotlabs/Module/Cloud_tiles.php
Normal file
21
Zotlabs/Module/Cloud_tiles.php
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
class Cloud_tiles extends \Zotlabs\Web\Controller {
|
||||
|
||||
function init() {
|
||||
|
||||
if(intval($_SESSION['cloud_tiles']))
|
||||
$_SESSION['cloud_tiles'] = 0;
|
||||
else
|
||||
$_SESSION['cloud_tiles'] = 1;
|
||||
|
||||
if(local_channel()) {
|
||||
set_pconfig(local_channel(),'system','cloud_tiles',$_SESSION['cloud_tiles']);
|
||||
}
|
||||
|
||||
goaway(z_root() . '/' . hex2bin(argv(1)));
|
||||
|
||||
}
|
||||
}
|
||||
@@ -25,7 +25,7 @@ class Common extends \Zotlabs\Web\Controller {
|
||||
|
||||
}
|
||||
|
||||
function get() {
|
||||
function get() {
|
||||
|
||||
$o = '';
|
||||
|
||||
@@ -34,38 +34,37 @@ class Common extends \Zotlabs\Web\Controller {
|
||||
|
||||
$observer_hash = get_observer_hash();
|
||||
|
||||
|
||||
if(! perm_is_allowed(\App::$profile['profile_uid'],$observer_hash,'view_contacts')) {
|
||||
notice( t('Permission denied.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
$o .= '<h2>' . t('Common connections') . '</h2>';
|
||||
|
||||
$t = count_common_friends(\App::$profile['profile_uid'],$observer_hash);
|
||||
|
||||
if(! $t) {
|
||||
notice( t('No connections in common.') . EOL);
|
||||
return $o;
|
||||
return;
|
||||
}
|
||||
|
||||
$r = common_friends(\App::$profile['profile_uid'],$observer_hash);
|
||||
|
||||
if($r) {
|
||||
|
||||
$tpl = get_markup_template('common_friends.tpl');
|
||||
|
||||
foreach($r as $rr) {
|
||||
$o .= replace_macros($tpl,array(
|
||||
'$url' => $rr['xchan_url'],
|
||||
'$name' => $rr['xchan_name'],
|
||||
'$photo' => $rr['xchan_photo_m'],
|
||||
'$tags' => ''
|
||||
));
|
||||
$items[] = [
|
||||
'url' => $rr['xchan_url'],
|
||||
'name' => $rr['xchan_name'],
|
||||
'photo' => $rr['xchan_photo_m'],
|
||||
'tags' => ''
|
||||
];
|
||||
}
|
||||
|
||||
$o .= cleardiv();
|
||||
}
|
||||
|
||||
$tpl = get_markup_template('common_friends.tpl');
|
||||
|
||||
$o = replace_macros($tpl, [
|
||||
'$title' => t('View Common Connections'),
|
||||
'$items' => $items
|
||||
]);
|
||||
|
||||
return $o;
|
||||
}
|
||||
|
||||
@@ -5,10 +5,6 @@ namespace Zotlabs\Module;
|
||||
require_once('include/socgraph.php');
|
||||
require_once('include/selectors.php');
|
||||
require_once('include/group.php');
|
||||
require_once('include/contact_widgets.php');
|
||||
require_once('include/zot.php');
|
||||
require_once('include/widgets.php');
|
||||
|
||||
|
||||
class Connections extends \Zotlabs\Web\Controller {
|
||||
|
||||
@@ -23,7 +19,7 @@ class Connections extends \Zotlabs\Web\Controller {
|
||||
|
||||
}
|
||||
|
||||
function get() {
|
||||
function get() {
|
||||
|
||||
$sort_type = 0;
|
||||
$o = '';
|
||||
@@ -33,6 +29,8 @@ class Connections extends \Zotlabs\Web\Controller {
|
||||
notice( t('Permission denied.') . EOL);
|
||||
return login();
|
||||
}
|
||||
|
||||
nav_set_selected('Connections');
|
||||
|
||||
$blocked = false;
|
||||
$hidden = false;
|
||||
@@ -67,15 +65,14 @@ class Connections extends \Zotlabs\Web\Controller {
|
||||
$hidden = true;
|
||||
break;
|
||||
case 'archived':
|
||||
$search_flags = " and abook_archived = 1 ";
|
||||
$head = t('Archived');
|
||||
$search_flags = " and ( abook_archived = 1 OR abook_not_here = 1) ";
|
||||
$head = t('Archived/Unreachable');
|
||||
$archived = true;
|
||||
break;
|
||||
case 'pending':
|
||||
$search_flags = " and abook_pending = 1 ";
|
||||
$head = t('New');
|
||||
$pending = true;
|
||||
nav_set_selected('intros');
|
||||
break;
|
||||
case 'ifpending':
|
||||
$r = q("SELECT COUNT(abook.abook_id) AS total FROM abook left join xchan on abook.abook_xchan = xchan.xchan_hash where abook_channel = %d and abook_pending = 1 and abook_self = 0 and abook_ignored = 0 and xchan_deleted = 0 and xchan_orphan = 0 ",
|
||||
@@ -85,7 +82,6 @@ class Connections extends \Zotlabs\Web\Controller {
|
||||
$search_flags = " and abook_pending = 1 ";
|
||||
$head = t('New');
|
||||
$pending = true;
|
||||
nav_set_selected('intros');
|
||||
\App::$argv[1] = 'pending';
|
||||
}
|
||||
else {
|
||||
@@ -95,7 +91,6 @@ class Connections extends \Zotlabs\Web\Controller {
|
||||
\App::$argc = 1;
|
||||
unset(\App::$argv[1]);
|
||||
}
|
||||
nav_set_selected('intros');
|
||||
break;
|
||||
// case 'unconnected':
|
||||
// $search_flags = " and abook_unconnected = 1 ";
|
||||
@@ -172,10 +167,10 @@ class Connections extends \Zotlabs\Web\Controller {
|
||||
),
|
||||
|
||||
'archived' => array(
|
||||
'label' => t('Archived'),
|
||||
'label' => t('Archived/Unreachable'),
|
||||
'url' => z_root() . '/connections/archived',
|
||||
'sel' => ($archived) ? 'active' : '',
|
||||
'title' => t('Only show archived connections'),
|
||||
'title' => t('Only show archived/unreachable connections'),
|
||||
),
|
||||
|
||||
'hidden' => array(
|
||||
@@ -247,7 +242,8 @@ class Connections extends \Zotlabs\Web\Controller {
|
||||
((intval($rr['abook_archived'])) ? t('Archived') : ''),
|
||||
((intval($rr['abook_hidden'])) ? t('Hidden') : ''),
|
||||
((intval($rr['abook_ignored'])) ? t('Ignored') : ''),
|
||||
((intval($rr['abook_blocked'])) ? t('Blocked') : '')
|
||||
((intval($rr['abook_blocked'])) ? t('Blocked') : ''),
|
||||
((intval($rr['abook_not_here'])) ? t('Not connected at this location') : '')
|
||||
);
|
||||
|
||||
foreach($status as $str) {
|
||||
@@ -261,11 +257,12 @@ class Connections extends \Zotlabs\Web\Controller {
|
||||
$contacts[] = array(
|
||||
'img_hover' => sprintf( t('%1$s [%2$s]'),$rr['xchan_name'],$rr['xchan_url']),
|
||||
'edit_hover' => t('Edit connection'),
|
||||
'edit' => t('Edit'),
|
||||
'delete_hover' => t('Delete connection'),
|
||||
'id' => $rr['abook_id'],
|
||||
'thumb' => $rr['xchan_photo_m'],
|
||||
'name' => $rr['xchan_name'],
|
||||
'classes' => (intval($rr['abook_archived']) ? 'archived' : ''),
|
||||
'classes' => ((intval($rr['abook_archived']) || intval($rr['abook_not_here'])) ? 'archived' : ''),
|
||||
'link' => z_root() . '/connedit/' . $rr['abook_id'],
|
||||
'deletelink' => z_root() . '/connedit/' . intval($rr['abook_id']) . '/drop',
|
||||
'delete' => t('Delete'),
|
||||
|
||||
@@ -11,9 +11,6 @@ namespace Zotlabs\Module;
|
||||
require_once('include/socgraph.php');
|
||||
require_once('include/selectors.php');
|
||||
require_once('include/group.php');
|
||||
require_once('include/contact_widgets.php');
|
||||
require_once('include/zot.php');
|
||||
require_once('include/widgets.php');
|
||||
require_once('include/photos.php');
|
||||
|
||||
|
||||
@@ -251,6 +248,10 @@ class Connedit extends \Zotlabs\Web\Controller {
|
||||
notice( t('Failed to update connection record.') . EOL);
|
||||
|
||||
if(! intval(\App::$poi['abook_self'])) {
|
||||
if($new_friend) {
|
||||
\Zotlabs\Daemon\Master::Summon( [ 'Notifier', 'permission_accept', $contact_id ] );
|
||||
}
|
||||
|
||||
\Zotlabs\Daemon\Master::Summon( [
|
||||
'Notifier',
|
||||
(($new_friend) ? 'permission_create' : 'permission_update'),
|
||||
@@ -391,30 +392,22 @@ class Connedit extends \Zotlabs\Web\Controller {
|
||||
|
||||
$section = ((array_key_exists('section',$_REQUEST)) ? $_REQUEST['section'] : '');
|
||||
$channel = \App::get_channel();
|
||||
$my_perms = get_channel_default_perms(local_channel());
|
||||
$role = get_pconfig(local_channel(),'system','permissions_role');
|
||||
if($role) {
|
||||
$x = \Zotlabs\Access\PermissionRoles::role_perms($role);
|
||||
if($x['perms_connect'])
|
||||
$my_perms = $x['perms_connect'];
|
||||
}
|
||||
|
||||
$yes_no = array(t('No'),t('Yes'));
|
||||
|
||||
if($my_perms) {
|
||||
$o .= "<script>function connectDefaultShare() {
|
||||
\$('.abook-edit-me').each(function() {
|
||||
if(! $(this).is(':disabled'))
|
||||
$(this).prop('checked', false);
|
||||
});\n\n";
|
||||
$perms = get_perms();
|
||||
foreach($perms as $p => $v) {
|
||||
if($my_perms & $v[1]) {
|
||||
$o .= "\$('#me_id_perms_" . $p . "').prop('checked', true); \n";
|
||||
}
|
||||
$connect_perms = \Zotlabs\Access\Permissions::connect_perms(local_channel());
|
||||
|
||||
$o .= "<script>function connectDefaultShare() {
|
||||
\$('.abook-edit-me').each(function() {
|
||||
if(! $(this).is(':disabled'))
|
||||
$(this).prop('checked', false);
|
||||
});\n\n";
|
||||
foreach($connect_perms['perms'] as $p => $v) {
|
||||
if($v) {
|
||||
$o .= "\$('#me_id_perms_" . $p . "').prop('checked', true); \n";
|
||||
}
|
||||
$o .= " }\n</script>\n";
|
||||
}
|
||||
$o .= " }\n</script>\n";
|
||||
|
||||
if(argc() == 3) {
|
||||
|
||||
@@ -441,6 +434,34 @@ class Connedit extends \Zotlabs\Web\Controller {
|
||||
goaway(z_root() . '/connedit/' . $contact_id);
|
||||
|
||||
}
|
||||
|
||||
if($cmd === 'fetchvc') {
|
||||
$url = str_replace('/channel/','/profile/',$orig_record[0]['xchan_url']) . '/vcard';
|
||||
$recurse = 0;
|
||||
$x = z_fetch_url(zid($url),false,$recurse,['session' => true]);
|
||||
if($x['success']) {
|
||||
$h = new \Zotlabs\Web\HTTPHeaders($x['header']);
|
||||
$fields = $h->fetch();
|
||||
if($fields) {
|
||||
foreach($fields as $y) {
|
||||
if(array_key_exists('content-type',$y)) {
|
||||
$type = explode(';',trim($y['content-type']));
|
||||
if($type && $type[0] === 'text/vcard' && $x['body']) {
|
||||
$vc = \Sabre\VObject\Reader::read($x['body']);
|
||||
$vcard = $vc->serialize();
|
||||
if($vcard) {
|
||||
set_abconfig(local_channel(),$orig_record[0]['abook_xchan'],'system','vcard',$vcard);
|
||||
$this->connedit_clone($a);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
goaway(z_root() . '/connedit/' . $contact_id);
|
||||
}
|
||||
|
||||
|
||||
if($cmd === 'resetphoto') {
|
||||
q("update xchan set xchan_photo_date = '2001-01-01 00:00:00' where xchan_hash = '%s'",
|
||||
dbesc($orig_record[0]['xchan_hash'])
|
||||
@@ -546,7 +567,7 @@ class Connedit extends \Zotlabs\Web\Controller {
|
||||
$contact_id = \App::$poi['abook_id'];
|
||||
$contact = \App::$poi;
|
||||
|
||||
$cn = q("SELECT abook_id, xchan_name from abook left join xchan on abook_xchan = xchan_hash where abook_channel = %d and abook_self = 0 order by xchan_name",
|
||||
$cn = q("SELECT abook_id, xchan_name from abook left join xchan on abook_xchan = xchan_hash where abook_channel = %d and abook_self = 0 and xchan_deleted = 0 order by xchan_name",
|
||||
intval(local_channel())
|
||||
);
|
||||
|
||||
@@ -582,6 +603,13 @@ class Connedit extends \Zotlabs\Web\Controller {
|
||||
'sel' => '',
|
||||
'title' => t('Fetch updated permissions'),
|
||||
),
|
||||
|
||||
'rephoto' => array(
|
||||
'label' => t('Refresh Photo'),
|
||||
'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/resetphoto',
|
||||
'sel' => '',
|
||||
'title' => t('Fetch updated photo'),
|
||||
),
|
||||
|
||||
'recent' => array(
|
||||
'label' => t('Recent Activity'),
|
||||
@@ -631,6 +659,17 @@ class Connedit extends \Zotlabs\Web\Controller {
|
||||
|
||||
);
|
||||
|
||||
|
||||
if($contact['xchan_network'] === 'zot') {
|
||||
$tools['fetchvc'] = [
|
||||
'label' => t('Fetch Vcard'),
|
||||
'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/fetchvc',
|
||||
'sel' => '',
|
||||
'title' => t('Fetch electronic calling card for this connection')
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
$sections = [];
|
||||
|
||||
$sections['perms'] = [
|
||||
@@ -806,7 +845,23 @@ class Connedit extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
}
|
||||
else
|
||||
$locstr = t('none');
|
||||
$locstr = $contact['xchan_url'];
|
||||
|
||||
$clone_warn = '';
|
||||
$clonable = (in_array($contact['xchan_network'],['zot','rss']) ? true : false);
|
||||
if(! $clonable) {
|
||||
$clone_warn = '<strong>';
|
||||
$clone_warn .= ((intval($contact['abook_not_here']))
|
||||
? t('This connection is unreachable from this location.')
|
||||
: t('This connection may be unreachable from other channel locations.')
|
||||
);
|
||||
$clone_warn .= '</strong><br>' . t('Location independence is not supported by their network.');
|
||||
}
|
||||
|
||||
|
||||
|
||||
if(intval($contact['abook_not_here']) && $unclonable)
|
||||
$not_here = t('This connection is unreachable from this location. Location independence is not supported by their network.');
|
||||
|
||||
$o .= replace_macros($tpl, [
|
||||
'$header' => (($self) ? t('Connection Default Permissions') : sprintf( t('Connection: %s'),$contact['xchan_name'])),
|
||||
@@ -815,12 +870,14 @@ class Connedit extends \Zotlabs\Web\Controller {
|
||||
'$permcat_new' => t('Add permission role'),
|
||||
'$permcat_enable' => feature_enabled(local_channel(),'permcats'),
|
||||
'$addr' => $contact['xchan_addr'],
|
||||
'$primeurl' => $contact['xchan_url'],
|
||||
'$section' => $section,
|
||||
'$sections' => $sections,
|
||||
'$vcard' => $vcard,
|
||||
'$addr_text' => t('This connection\'s primary address is'),
|
||||
'$loc_text' => t('Available locations:'),
|
||||
'$locstr' => $locstr,
|
||||
'$unclonable' => $clone_warn,
|
||||
'$notself' => (($self) ? '' : '1'),
|
||||
'$self' => (($self) ? '1' : ''),
|
||||
'$autolbl' => t('The permissions indicated on this page will be applied to all new connections.'),
|
||||
|
||||
@@ -23,19 +23,17 @@ require_once('include/channel.php');
|
||||
class Cover_photo extends \Zotlabs\Web\Controller {
|
||||
|
||||
function init() {
|
||||
|
||||
if(! local_channel()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$channel = \App::get_channel();
|
||||
profile_load($channel['channel_address']);
|
||||
|
||||
profile_load($channel['channel_address']);
|
||||
}
|
||||
|
||||
/* @brief Evaluate posted values
|
||||
/**
|
||||
* @brief Evaluate posted values
|
||||
*
|
||||
* @param $a Current application
|
||||
* @return void
|
||||
*
|
||||
*/
|
||||
@@ -130,8 +128,15 @@ class Cover_photo extends \Zotlabs\Web\Controller {
|
||||
|
||||
$aid = get_account_id();
|
||||
|
||||
$p = array('aid' => $aid, 'uid' => local_channel(), 'resource_id' => $base_image['resource_id'],
|
||||
'filename' => $base_image['filename'], 'album' => t('Cover Photos'));
|
||||
$p = [
|
||||
'aid' => $aid,
|
||||
'uid' => local_channel(),
|
||||
'resource_id' => $base_image['resource_id'],
|
||||
'filename' => $base_image['filename'],
|
||||
'album' => t('Cover Photos'),
|
||||
'os_path' => $base_image['os_path'],
|
||||
'display_path' => $base_image['display_path']
|
||||
];
|
||||
|
||||
$p['imgscale'] = 7;
|
||||
$p['photo_usage'] = PHOTO_COVER;
|
||||
@@ -195,11 +200,10 @@ class Cover_photo extends \Zotlabs\Web\Controller {
|
||||
$os_storage = false;
|
||||
|
||||
foreach($i as $ii) {
|
||||
$smallest = intval($ii['imgscale']);
|
||||
$smallest = intval($ii['imgscale']);
|
||||
$os_storage = intval($ii['os_storage']);
|
||||
$imagedata = $ii['content'];
|
||||
$filetype = $ii['mimetype'];
|
||||
|
||||
$imagedata = $ii['content'];
|
||||
$filetype = $ii['mimetype'];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -263,10 +267,10 @@ class Cover_photo extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
|
||||
|
||||
/* @brief Generate content of profile-photo view
|
||||
/**
|
||||
* @brief Generate content of profile-photo view
|
||||
*
|
||||
* @param $a Current application
|
||||
* @return void
|
||||
* @return string
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -350,15 +354,15 @@ class Cover_photo extends \Zotlabs\Web\Controller {
|
||||
$tpl = get_markup_template('cover_photo.tpl');
|
||||
|
||||
$o .= replace_macros($tpl,array(
|
||||
'$user' => \App::$channel['channel_address'],
|
||||
'$lbl_upfile' => t('Upload File:'),
|
||||
'$lbl_profiles' => t('Select a profile:'),
|
||||
'$title' => t('Upload Cover Photo'),
|
||||
'$submit' => t('Upload'),
|
||||
'$profiles' => $profiles,
|
||||
'$user' => \App::$channel['channel_address'],
|
||||
'$lbl_upfile' => t('Upload File:'),
|
||||
'$lbl_profiles' => t('Select a profile:'),
|
||||
'$title' => t('Upload Cover Photo'),
|
||||
'$submit' => t('Upload'),
|
||||
'$profiles' => $profiles,
|
||||
'$form_security_token' => get_form_security_token("cover_photo"),
|
||||
// FIXME - yuk
|
||||
'$select' => sprintf('%s %s', t('or'), ($newuser) ? '<a href="' . z_root() . '">' . t('skip this step') . '</a>' : '<a href="'. z_root() . '/photos/' . \App::$channel['channel_address'] . '">' . t('select a photo from your photo albums') . '</a>')
|
||||
/// @FIXME - yuk
|
||||
'$select' => sprintf('%s %s', t('or'), ($newuser) ? '<a href="' . z_root() . '">' . t('skip this step') . '</a>' : '<a href="'. z_root() . '/photos/' . \App::$channel['channel_address'] . '">' . t('select a photo from your photo albums') . '</a>')
|
||||
));
|
||||
|
||||
call_hooks('cover_photo_content_end', $o);
|
||||
@@ -370,14 +374,14 @@ class Cover_photo extends \Zotlabs\Web\Controller {
|
||||
$resolution = 3;
|
||||
$tpl = get_markup_template("cropcover.tpl");
|
||||
$o .= replace_macros($tpl,array(
|
||||
'$filename' => $filename,
|
||||
'$profile' => intval($_REQUEST['profile']),
|
||||
'$resource' => \App::$data['imagecrop'] . '-3',
|
||||
'$image_url' => z_root() . '/photo/' . $filename,
|
||||
'$title' => t('Crop Image'),
|
||||
'$desc' => t('Please adjust the image cropping for optimum viewing.'),
|
||||
'$filename' => $filename,
|
||||
'$profile' => intval($_REQUEST['profile']),
|
||||
'$resource' => \App::$data['imagecrop'] . '-3',
|
||||
'$image_url' => z_root() . '/photo/' . $filename,
|
||||
'$title' => t('Crop Image'),
|
||||
'$desc' => t('Please adjust the image cropping for optimum viewing.'),
|
||||
'$form_security_token' => get_form_security_token("cover_photo"),
|
||||
'$done' => t('Done Editing')
|
||||
'$done' => t('Done Editing')
|
||||
));
|
||||
return $o;
|
||||
}
|
||||
@@ -393,8 +397,6 @@ class Cover_photo extends \Zotlabs\Web\Controller {
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
function cover_photo_crop_ui_head(&$a, $ph, $hash, $smallest){
|
||||
|
||||
$max_length = get_config('system','max_image_length');
|
||||
|
||||
@@ -12,6 +12,9 @@ use \Sabre\DAV as SDAV;
|
||||
use \Zotlabs\Storage;
|
||||
|
||||
require_once('include/attach.php');
|
||||
require_once('include/auth.php');
|
||||
require_once('include/security.php');
|
||||
|
||||
|
||||
class Dav extends \Zotlabs\Web\Controller {
|
||||
|
||||
@@ -21,22 +24,65 @@ class Dav extends \Zotlabs\Web\Controller {
|
||||
*/
|
||||
function init() {
|
||||
|
||||
// workaround for HTTP-auth in CGI mode
|
||||
if (x($_SERVER, 'REDIRECT_REMOTE_USER')) {
|
||||
$userpass = base64_decode(substr($_SERVER["REDIRECT_REMOTE_USER"], 6)) ;
|
||||
if(strlen($userpass)) {
|
||||
list($name, $password) = explode(':', $userpass);
|
||||
$_SERVER['PHP_AUTH_USER'] = $name;
|
||||
$_SERVER['PHP_AUTH_PW'] = $password;
|
||||
}
|
||||
}
|
||||
foreach([ 'REDIRECT_REMOTE_USER', 'HTTP_AUTHORIZATION' ] as $head) {
|
||||
|
||||
if (x($_SERVER, 'HTTP_AUTHORIZATION')) {
|
||||
$userpass = base64_decode(substr($_SERVER["HTTP_AUTHORIZATION"], 6)) ;
|
||||
if(strlen($userpass)) {
|
||||
list($name, $password) = explode(':', $userpass);
|
||||
$_SERVER['PHP_AUTH_USER'] = $name;
|
||||
$_SERVER['PHP_AUTH_PW'] = $password;
|
||||
/* Basic authentication */
|
||||
|
||||
if(array_key_exists($head,$_SERVER) && substr(trim($_SERVER[$head]),0,5) === 'Basic') {
|
||||
$userpass = @base64_decode(substr(trim($_SERVER[$head]),6)) ;
|
||||
if(strlen($userpass)) {
|
||||
list($name, $password) = explode(':', $userpass);
|
||||
$_SERVER['PHP_AUTH_USER'] = $name;
|
||||
$_SERVER['PHP_AUTH_PW'] = $password;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* Signature authentication */
|
||||
|
||||
if(array_key_exists($head,$_SERVER) && substr(trim($_SERVER[$head]),0,9) === 'Signature') {
|
||||
if($head !== 'HTTP_AUTHORIZATION') {
|
||||
$_SERVER['HTTP_AUTHORIZATION'] = $_SERVER[$head];
|
||||
continue;
|
||||
}
|
||||
|
||||
$sigblock = \Zotlabs\Web\HTTPSig::parse_sigheader($_SERVER[$head]);
|
||||
if($sigblock) {
|
||||
$keyId = str_replace('acct:','',$sigblock['keyId']);
|
||||
if($keyId) {
|
||||
$r = q("select * from hubloc where hubloc_addr = '%s' limit 1",
|
||||
dbesc($keyId)
|
||||
);
|
||||
if($r) {
|
||||
$c = channelx_by_hash($r[0]['hubloc_hash']);
|
||||
if($c) {
|
||||
$a = q("select * from account where account_id = %d limit 1",
|
||||
intval($c['channel_account_id'])
|
||||
);
|
||||
if($a) {
|
||||
$record = [ 'channel' => $c, 'account' => $a[0] ];
|
||||
$channel_login = $c['channel_id'];
|
||||
}
|
||||
}
|
||||
}
|
||||
if(! $record)
|
||||
continue;
|
||||
|
||||
if($record) {
|
||||
$verified = \Zotlabs\Web\HTTPSig::verify('',$record['channel']['channel_pubkey']);
|
||||
if(! ($verified && $verified['header_signed'] && $verified['header_valid'])) {
|
||||
$record = null;
|
||||
}
|
||||
if($record['account']) {
|
||||
authenticate_success($record['account']);
|
||||
if($channel_login) {
|
||||
change_channel($channel_login);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
267
Zotlabs/Module/Defperms.php
Normal file
267
Zotlabs/Module/Defperms.php
Normal file
@@ -0,0 +1,267 @@
|
||||
<?php
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
|
||||
require_once('include/socgraph.php');
|
||||
require_once('include/selectors.php');
|
||||
require_once('include/group.php');
|
||||
require_once('include/photos.php');
|
||||
|
||||
|
||||
class Defperms extends \Zotlabs\Web\Controller {
|
||||
|
||||
/* @brief Initialize the connection-editor
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
function init() {
|
||||
|
||||
if(! local_channel())
|
||||
return;
|
||||
|
||||
$r = q("SELECT abook.*, xchan.*
|
||||
FROM abook left join xchan on abook_xchan = xchan_hash
|
||||
WHERE abook_self = 1 and abook_id = %d LIMIT 1",
|
||||
intval(local_channel())
|
||||
);
|
||||
if($r) {
|
||||
\App::$poi = $r[0];
|
||||
}
|
||||
|
||||
$channel = \App::get_channel();
|
||||
if($channel)
|
||||
head_set_icon($channel['xchan_photo_s']);
|
||||
}
|
||||
|
||||
|
||||
/* @brief Evaluate posted values and set changes
|
||||
*
|
||||
*/
|
||||
|
||||
function post() {
|
||||
|
||||
if(! local_channel())
|
||||
return;
|
||||
|
||||
$contact_id = intval(argv(1));
|
||||
if(! $contact_id)
|
||||
return;
|
||||
|
||||
$channel = \App::get_channel();
|
||||
|
||||
$orig_record = q("SELECT * FROM abook WHERE abook_id = %d AND abook_channel = %d LIMIT 1",
|
||||
intval($contact_id),
|
||||
intval(local_channel())
|
||||
);
|
||||
|
||||
if(! $orig_record) {
|
||||
notice( t('Could not access contact record.') . EOL);
|
||||
goaway(z_root() . '/connections');
|
||||
return; // NOTREACHED
|
||||
}
|
||||
|
||||
|
||||
if(intval($orig_record[0]['abook_self'])) {
|
||||
$autoperms = intval($_POST['autoperms']);
|
||||
$is_self = true;
|
||||
}
|
||||
else {
|
||||
$autoperms = null;
|
||||
$is_self = false;
|
||||
}
|
||||
|
||||
|
||||
$all_perms = \Zotlabs\Access\Permissions::Perms();
|
||||
|
||||
if($all_perms) {
|
||||
foreach($all_perms as $perm => $desc) {
|
||||
|
||||
$checkinherited = \Zotlabs\Access\PermissionLimits::Get(local_channel(),$perm);
|
||||
$inherited = (($checkinherited & PERMS_SPECIFIC) ? false : true);
|
||||
|
||||
if(array_key_exists('perms_' . $perm, $_POST)) {
|
||||
set_abconfig($channel['channel_id'],$orig_record[0]['abook_xchan'],'my_perms',$perm,
|
||||
intval($_POST['perms_' . $perm]));
|
||||
if($autoperms) {
|
||||
set_pconfig($channel['channel_id'],'autoperms',$perm,intval($_POST['perms_' . $perm]));
|
||||
}
|
||||
}
|
||||
else {
|
||||
set_abconfig($channel['channel_id'],$orig_record[0]['abook_xchan'],'my_perms',$perm,0);
|
||||
if($autoperms) {
|
||||
set_pconfig($channel['channel_id'],'autoperms',$perm,0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(! is_null($autoperms))
|
||||
set_pconfig($channel['channel_id'],'system','autoperms',$autoperms);
|
||||
|
||||
|
||||
notice( t('Settings updated.') . EOL);
|
||||
|
||||
|
||||
// Refresh the structure in memory with the new data
|
||||
|
||||
$r = q("SELECT abook.*, xchan.*
|
||||
FROM abook left join xchan on abook_xchan = xchan_hash
|
||||
WHERE abook_channel = %d and abook_id = %d LIMIT 1",
|
||||
intval(local_channel()),
|
||||
intval($contact_id)
|
||||
);
|
||||
if($r) {
|
||||
\App::$poi = $r[0];
|
||||
}
|
||||
|
||||
|
||||
$this->defperms_clone($a);
|
||||
|
||||
goaway(z_root() . '/defperms');
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
/* @brief Clone connection
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
function defperms_clone(&$a) {
|
||||
|
||||
if(! \App::$poi)
|
||||
return;
|
||||
|
||||
$channel = \App::get_channel();
|
||||
|
||||
$r = q("SELECT abook.*, xchan.*
|
||||
FROM abook left join xchan on abook_xchan = xchan_hash
|
||||
WHERE abook_channel = %d and abook_id = %d LIMIT 1",
|
||||
intval(local_channel()),
|
||||
intval(\App::$poi['abook_id'])
|
||||
);
|
||||
if($r) {
|
||||
\App::$poi = array_shift($r);
|
||||
}
|
||||
|
||||
$clone = \App::$poi;
|
||||
|
||||
unset($clone['abook_id']);
|
||||
unset($clone['abook_account']);
|
||||
unset($clone['abook_channel']);
|
||||
|
||||
$abconfig = load_abconfig($channel['channel_id'],$clone['abook_xchan']);
|
||||
if($abconfig)
|
||||
$clone['abconfig'] = $abconfig;
|
||||
|
||||
build_sync_packet(0 /* use the current local_channel */, array('abook' => array($clone)));
|
||||
}
|
||||
|
||||
/* @brief Generate content of connection default permissions page
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
function get() {
|
||||
|
||||
$sort_type = 0;
|
||||
$o = '';
|
||||
|
||||
if(! local_channel()) {
|
||||
notice( t('Permission denied.') . EOL);
|
||||
return login();
|
||||
}
|
||||
|
||||
$section = ((array_key_exists('section',$_REQUEST)) ? $_REQUEST['section'] : '');
|
||||
$channel = \App::get_channel();
|
||||
|
||||
$yes_no = array(t('No'),t('Yes'));
|
||||
|
||||
$connect_perms = \Zotlabs\Access\Permissions::connect_perms(local_channel());
|
||||
|
||||
$o .= "<script>function connectDefaultShare() {
|
||||
\$('.abook-edit-me').each(function() {
|
||||
if(! $(this).is(':disabled'))
|
||||
$(this).prop('checked', false);
|
||||
});\n\n";
|
||||
foreach($connect_perms['perms'] as $p => $v) {
|
||||
if($v) {
|
||||
$o .= "\$('#me_id_perms_" . $p . "').prop('checked', true); \n";
|
||||
}
|
||||
}
|
||||
$o .= " }\n</script>\n";
|
||||
|
||||
if(\App::$poi) {
|
||||
|
||||
$sections = [];
|
||||
|
||||
$self = false;
|
||||
|
||||
$tpl = get_markup_template('defperms.tpl');
|
||||
|
||||
|
||||
$perms = array();
|
||||
$channel = \App::get_channel();
|
||||
|
||||
$contact = \App::$poi;
|
||||
|
||||
$global_perms = \Zotlabs\Access\Permissions::Perms();
|
||||
|
||||
$existing = get_all_perms(local_channel(),$contact['abook_xchan']);
|
||||
$hidden_perms = [];
|
||||
|
||||
foreach($global_perms as $k => $v) {
|
||||
$thisperm = get_abconfig(local_channel(),$contact['abook_xchan'],'my_perms',$k);
|
||||
|
||||
$checkinherited = \Zotlabs\Access\PermissionLimits::Get(local_channel(),$k);
|
||||
|
||||
$inherited = (($checkinherited & PERMS_SPECIFIC) ? false : true);
|
||||
|
||||
$perms[] = [ 'perms_' . $k, $v, intval($thisperm), '', $yes_no, (($inherited) ? ' disabled="disabled" ' : '') ];
|
||||
if($inherited) {
|
||||
$hidden_perms[] = [ 'perms_' . $k, intval($thisperm) ];
|
||||
}
|
||||
}
|
||||
|
||||
$pcat = new \Zotlabs\Lib\Permcat(local_channel());
|
||||
$pcatlist = $pcat->listing();
|
||||
$permcats = [];
|
||||
if($pcatlist) {
|
||||
foreach($pcatlist as $pc) {
|
||||
$permcats[$pc['name']] = $pc['localname'];
|
||||
}
|
||||
}
|
||||
|
||||
$o .= replace_macros($tpl, [
|
||||
'$header' => t('Connection Default Permissions'),
|
||||
'$autoperms' => array('autoperms',t('Apply these permissions automatically'), ((get_pconfig(local_channel(),'system','autoperms')) ? 1 : 0), t('If enabled, connection requests will be approved without your interaction'), $yes_no),
|
||||
'$permcat' => [ 'permcat', t('Permission role'), '', '',$permcats ],
|
||||
'$permcat_new' => t('Add permission role'),
|
||||
'$permcat_enable' => feature_enabled(local_channel(),'permcats'),
|
||||
'$section' => $section,
|
||||
'$sections' => $sections,
|
||||
'$autolbl' => t('The permissions indicated on this page will be applied to all new connections.'),
|
||||
'$autoapprove' => t('Automatic approval settings'),
|
||||
'$unapproved' => $unapproved,
|
||||
'$inherited' => t('inherited'),
|
||||
'$submit' => t('Submit'),
|
||||
'$me' => t('My Settings'),
|
||||
'$perms' => $perms,
|
||||
'$hidden_perms' => $hidden_perms,
|
||||
'$permlbl' => t('Individual Permissions'),
|
||||
'$permnote_self' => t('Some individual permissions may have been preset or locked based on your channel type and privacy settings.'),
|
||||
'$contact_id' => $contact['abook_id'],
|
||||
'$name' => $contact['xchan_name'],
|
||||
]);
|
||||
|
||||
$arr = array('contact' => $contact,'output' => $o);
|
||||
|
||||
call_hooks('contact_edit', $arr);
|
||||
|
||||
return $arr['output'];
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,6 @@ namespace Zotlabs\Module;
|
||||
|
||||
require_once('include/socgraph.php');
|
||||
require_once('include/dir_fns.php');
|
||||
require_once('include/widgets.php');
|
||||
require_once('include/bbcode.php');
|
||||
|
||||
|
||||
@@ -65,6 +64,11 @@ class Directory extends \Zotlabs\Web\Controller {
|
||||
return;
|
||||
}
|
||||
|
||||
if(get_config('system','block_public_directory',false) && (! get_observer_hash())) {
|
||||
notice( t('Public access denied.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
$observer = get_observer_hash();
|
||||
|
||||
$globaldir = get_directory_setting($observer, 'globaldir');
|
||||
@@ -78,7 +82,7 @@ class Directory extends \Zotlabs\Web\Controller {
|
||||
$pubforums = get_directory_setting($observer, 'pubforums');
|
||||
|
||||
$o = '';
|
||||
nav_set_selected('directory');
|
||||
nav_set_selected('Directory');
|
||||
|
||||
if(x($_POST,'search'))
|
||||
$search = notags(trim($_POST['search']));
|
||||
@@ -103,7 +107,7 @@ class Directory extends \Zotlabs\Web\Controller {
|
||||
$common = array();
|
||||
$index = 0;
|
||||
foreach($r as $rr) {
|
||||
$common[$rr['xchan_addr']] = $rr['total'];
|
||||
$common[$rr['xchan_addr']] = ((intval($rr['total']) > 0) ? intval($rr['total']) - 1 : 0);
|
||||
$addresses[$rr['xchan_addr']] = $index++;
|
||||
}
|
||||
|
||||
@@ -234,7 +238,7 @@ class Directory extends \Zotlabs\Web\Controller {
|
||||
|
||||
$age = '';
|
||||
if(strlen($rr['birthday'])) {
|
||||
if(($years = age($rr['birthday'],'UTC','')) != 0)
|
||||
if(($years = age($rr['birthday'],'UTC','')) > 0)
|
||||
$age = $years;
|
||||
}
|
||||
|
||||
@@ -335,7 +339,7 @@ class Directory extends \Zotlabs\Web\Controller {
|
||||
'ignlink' => $suggest ? z_root() . '/directory?ignore=' . $rr['hash'] : '',
|
||||
'ignore_label' => t('Don\'t suggest'),
|
||||
'common_friends' => (($common[$rr['address']]) ? intval($common[$rr['address']]) : ''),
|
||||
'common_label' => t('Common connections:'),
|
||||
'common_label' => t('Common connections (estimated):'),
|
||||
'common_count' => intval($common[$rr['address']]),
|
||||
'safe' => $safe_mode
|
||||
);
|
||||
|
||||
@@ -12,25 +12,36 @@ class Display extends \Zotlabs\Web\Controller {
|
||||
|
||||
function get($update = 0, $load = false) {
|
||||
|
||||
$module_format = 'html';
|
||||
|
||||
|
||||
if(argc() > 1) {
|
||||
$module_format = substr(argv(1),strrpos(argv(1),'.') + 1);
|
||||
if(! in_array($module_format,['atom','zot','json']))
|
||||
$module_format = 'html';
|
||||
}
|
||||
|
||||
$checkjs = new \Zotlabs\Web\CheckJS(1);
|
||||
|
||||
if($load)
|
||||
$_SESSION['loadtime'] = datetime_convert();
|
||||
|
||||
|
||||
if(observer_prohibited()) {
|
||||
notice( t('Public access denied.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if(argc() > 1 && argv(1) !== 'load')
|
||||
if(argc() > 1) {
|
||||
$item_hash = argv(1);
|
||||
if($module_format !== 'html') {
|
||||
$item_hash = substr($item_hash,0,strrpos($item_hash,'.'));
|
||||
}
|
||||
}
|
||||
|
||||
if($_REQUEST['mid'])
|
||||
$item_hash = $_REQUEST['mid'];
|
||||
|
||||
if(! $item_hash) {
|
||||
if(! $item_hash) {
|
||||
\App::$error = 404;
|
||||
notice( t('Item not found.') . EOL);
|
||||
return;
|
||||
@@ -38,45 +49,41 @@ class Display extends \Zotlabs\Web\Controller {
|
||||
|
||||
$observer_is_owner = false;
|
||||
$updateable = false;
|
||||
|
||||
|
||||
|
||||
if(local_channel() && (! $update)) {
|
||||
|
||||
$channel = \App::get_channel();
|
||||
|
||||
|
||||
|
||||
$channel_acl = array(
|
||||
'allow_cid' => $channel['channel_allow_cid'],
|
||||
'allow_gid' => $channel['channel_allow_gid'],
|
||||
'deny_cid' => $channel['channel_deny_cid'],
|
||||
'deny_gid' => $channel['channel_deny_gid']
|
||||
'deny_cid' => $channel['channel_deny_cid'],
|
||||
'deny_gid' => $channel['channel_deny_gid']
|
||||
);
|
||||
|
||||
|
||||
|
||||
$x = array(
|
||||
'is_owner' => true,
|
||||
'allow_location' => ((intval(get_pconfig($channel['channel_id'],'system','use_browser_location'))) ? '1' : ''),
|
||||
'default_location' => $channel['channel_location'],
|
||||
'nickname' => $channel['channel_address'],
|
||||
'lockstate' => (($group || $cid || $channel['channel_allow_cid'] || $channel['channel_allow_gid'] || $channel['channel_deny_cid'] || $channel['channel_deny_gid']) ? 'lock' : 'unlock'),
|
||||
'is_owner' => true,
|
||||
'allow_location' => ((intval(get_pconfig($channel['channel_id'],'system','use_browser_location'))) ? '1' : ''),
|
||||
'default_location' => $channel['channel_location'],
|
||||
'nickname' => $channel['channel_address'],
|
||||
'lockstate' => (($group || $cid || $channel['channel_allow_cid'] || $channel['channel_allow_gid'] || $channel['channel_deny_cid'] || $channel['channel_deny_gid']) ? 'lock' : 'unlock'),
|
||||
|
||||
'acl' => populate_acl($channel_acl),
|
||||
'permissions' => $channel_acl,
|
||||
'bang' => '',
|
||||
'visitor' => true,
|
||||
'profile_uid' => local_channel(),
|
||||
'return_path' => 'channel/' . $channel['channel_address'],
|
||||
'expanded' => true,
|
||||
'acl' => populate_acl($channel_acl),
|
||||
'permissions' => $channel_acl,
|
||||
'bang' => '',
|
||||
'visitor' => true,
|
||||
'profile_uid' => local_channel(),
|
||||
'return_path' => 'channel/' . $channel['channel_address'],
|
||||
'expanded' => true,
|
||||
'editor_autocomplete' => true,
|
||||
'bbco_autocomplete' => 'bbcode',
|
||||
'bbcode' => true,
|
||||
'jotnets' => true
|
||||
'bbco_autocomplete' => 'bbcode',
|
||||
'bbcode' => true,
|
||||
'jotnets' => true
|
||||
);
|
||||
|
||||
$o = '<div id="jot-popup">';
|
||||
$o .= status_editor($a,$x);
|
||||
$o .= '</div>';
|
||||
|
||||
}
|
||||
|
||||
// This page can be viewed by anybody so the query could be complicated
|
||||
@@ -95,14 +102,18 @@ class Display extends \Zotlabs\Web\Controller {
|
||||
if($decoded)
|
||||
$item_hash = $decoded;
|
||||
|
||||
$r = q("select id, uid, mid, parent_mid, item_type, item_deleted from item where mid like '%s' limit 1",
|
||||
dbesc($item_hash . '%'),
|
||||
dbesc($decoded . '%')
|
||||
$r = q("select id, uid, mid, parent_mid, thr_parent, verb, item_type, item_deleted, item_blocked from item where mid like '%s' limit 1",
|
||||
dbesc($item_hash . '%')
|
||||
);
|
||||
|
||||
if($r) {
|
||||
$target_item = $r[0];
|
||||
}
|
||||
|
||||
//if the item is to be moderated redirect to /moderate
|
||||
if($target_item['item_blocked'] == ITEM_MODERATED) {
|
||||
goaway(z_root() . '/moderate/' . $target_item['id']);
|
||||
}
|
||||
|
||||
$r = null;
|
||||
|
||||
@@ -138,59 +149,74 @@ class Display extends \Zotlabs\Web\Controller {
|
||||
$simple_update .= " and item_thread_top = 0 and author_xchan = '" . protect_sprintf(get_observer_hash()) . "' ";
|
||||
|
||||
if((! $update) && (! $load)) {
|
||||
|
||||
|
||||
$static = ((local_channel()) ? channel_manual_conv_update(local_channel()) : 0);
|
||||
|
||||
$static = ((local_channel()) ? channel_manual_conv_update(local_channel()) : 1);
|
||||
|
||||
// if the target item is not a post (eg a like) we want to address its thread parent
|
||||
|
||||
$mid = ((($target_item['verb'] == ACTIVITY_LIKE) || ($target_item['verb'] == ACTIVITY_DISLIKE)) ? $target_item['thr_parent'] : $target_item['mid']);
|
||||
|
||||
// if we got a decoded hash we must encode it again before handing to javascript
|
||||
if($decoded)
|
||||
$mid = 'b64.' . base64url_encode($mid);
|
||||
|
||||
$o .= '<div id="live-display"></div>' . "\r\n";
|
||||
$o .= "<script> var profile_uid = " . ((intval(local_channel())) ? local_channel() : (-1))
|
||||
. "; var netargs = '?f='; var profile_page = " . \App::$pager['page'] . "; </script>\r\n";
|
||||
|
||||
\App::$page['htmlhead'] .= replace_macros(get_markup_template("build_query.tpl"),array(
|
||||
'$baseurl' => z_root(),
|
||||
'$pgtype' => 'display',
|
||||
'$uid' => '0',
|
||||
'$gid' => '0',
|
||||
'$cid' => '0',
|
||||
'$cmin' => '0',
|
||||
'$cmax' => '99',
|
||||
'$star' => '0',
|
||||
'$liked' => '0',
|
||||
'$conv' => '0',
|
||||
'$spam' => '0',
|
||||
'$fh' => '0',
|
||||
'$pgtype' => 'display',
|
||||
'$uid' => '0',
|
||||
'$gid' => '0',
|
||||
'$cid' => '0',
|
||||
'$cmin' => '0',
|
||||
'$cmax' => '99',
|
||||
'$star' => '0',
|
||||
'$liked' => '0',
|
||||
'$conv' => '0',
|
||||
'$spam' => '0',
|
||||
'$fh' => '0',
|
||||
'$nouveau' => '0',
|
||||
'$wall' => '0',
|
||||
'$static' => $static,
|
||||
'$page' => ((\App::$pager['page'] != 1) ? \App::$pager['page'] : 1),
|
||||
'$list' => ((x($_REQUEST,'list')) ? intval($_REQUEST['list']) : 0),
|
||||
'$search' => '',
|
||||
'$order' => '',
|
||||
'$file' => '',
|
||||
'$cats' => '',
|
||||
'$tags' => '',
|
||||
'$dend' => '',
|
||||
'$dbegin' => '',
|
||||
'$verb' => '',
|
||||
'$mid' => $item_hash
|
||||
'$wall' => '0',
|
||||
'$static' => $static,
|
||||
'$page' => ((\App::$pager['page'] != 1) ? \App::$pager['page'] : 1),
|
||||
'$list' => ((x($_REQUEST,'list')) ? intval($_REQUEST['list']) : 0),
|
||||
'$search' => '',
|
||||
'$xchan' => '',
|
||||
'$order' => '',
|
||||
'$file' => '',
|
||||
'$cats' => '',
|
||||
'$tags' => '',
|
||||
'$dend' => '',
|
||||
'$dbegin' => '',
|
||||
'$verb' => '',
|
||||
'$net' => '',
|
||||
'$mid' => $mid
|
||||
));
|
||||
|
||||
|
||||
|
||||
head_add_link([
|
||||
'rel' => 'alternate',
|
||||
'type' => 'application/json+oembed',
|
||||
'href' => z_root() . '/oep?f=&url=' . urlencode(z_root() . '/' . \App::$query_string),
|
||||
'title' => 'oembed'
|
||||
]);
|
||||
|
||||
}
|
||||
|
||||
|
||||
$observer_hash = get_observer_hash();
|
||||
$item_normal = item_normal();
|
||||
|
||||
$item_normal_update = item_normal_update();
|
||||
|
||||
$sql_extra = public_permissions_sql($observer_hash);
|
||||
|
||||
if(($update && $load) || ($checkjs->disabled())) {
|
||||
|
||||
|
||||
if(($update && $load) || ($checkjs->disabled()) || ($module_format !== 'html')) {
|
||||
|
||||
$pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(\App::$pager['itemspage']),intval(\App::$pager['start']));
|
||||
|
||||
if($load || ($checkjs->disabled())) {
|
||||
|
||||
if($load || ($checkjs->disabled()) || ($module_format !== 'html')) {
|
||||
$r = null;
|
||||
|
||||
|
||||
require_once('include/channel.php');
|
||||
$sys = get_sys_channel();
|
||||
$sysid = $sys['channel_id'];
|
||||
@@ -206,25 +232,22 @@ class Display extends \Zotlabs\Web\Controller {
|
||||
);
|
||||
if($r) {
|
||||
$updateable = true;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if($r === null) {
|
||||
|
||||
|
||||
// in case somebody turned off public access to sys channel content using permissions
|
||||
// make that content unsearchable by ensuring the owner_xchan can't match
|
||||
|
||||
// make that content unsearchable by ensuring the owner uid can't match
|
||||
|
||||
if(! perm_is_allowed($sysid,$observer_hash,'view_stream'))
|
||||
$sysid = 0;
|
||||
|
||||
|
||||
|
||||
$r = q("SELECT item.id as item_id from item
|
||||
WHERE mid = '%s'
|
||||
AND (((( item.allow_cid = '' AND item.allow_gid = '' AND item.deny_cid = ''
|
||||
AND item.deny_gid = '' AND item_private = 0 )
|
||||
and owner_xchan in ( " . stream_perms_xchans(($observer_hash) ? (PERMS_NETWORK|PERMS_PUBLIC) : PERMS_PUBLIC) . " ))
|
||||
and uid in ( " . stream_perms_api_uids(($observer_hash) ? (PERMS_NETWORK|PERMS_PUBLIC) : PERMS_PUBLIC) . " ))
|
||||
OR uid = %d )
|
||||
$sql_extra )
|
||||
$item_normal
|
||||
@@ -232,14 +255,13 @@ class Display extends \Zotlabs\Web\Controller {
|
||||
dbesc($target_item['parent_mid']),
|
||||
intval($sysid)
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
elseif($update && !$load) {
|
||||
$r = null;
|
||||
|
||||
|
||||
require_once('include/channel.php');
|
||||
$sys = get_sys_channel();
|
||||
$sysid = $sys['channel_id'];
|
||||
@@ -248,7 +270,7 @@ class Display extends \Zotlabs\Web\Controller {
|
||||
$r = q("SELECT item.parent AS item_id from item
|
||||
WHERE uid = %d
|
||||
and parent_mid = '%s'
|
||||
$item_normal
|
||||
$item_normal_update
|
||||
$simple_update
|
||||
limit 1",
|
||||
intval(local_channel()),
|
||||
@@ -264,15 +286,14 @@ class Display extends \Zotlabs\Web\Controller {
|
||||
// make that content unsearchable by ensuring the owner_xchan can't match
|
||||
if(! perm_is_allowed($sysid,$observer_hash,'view_stream'))
|
||||
$sysid = 0;
|
||||
|
||||
$r = q("SELECT item.parent AS item_id from item
|
||||
WHERE parent_mid = '%s'
|
||||
AND (((( item.allow_cid = '' AND item.allow_gid = '' AND item.deny_cid = ''
|
||||
AND item.deny_gid = '' AND item_private = 0 )
|
||||
and owner_xchan in ( " . stream_perms_xchans(($observer_hash) ? (PERMS_NETWORK|PERMS_PUBLIC) : PERMS_PUBLIC) . " ))
|
||||
and uid in ( " . stream_perms_api_uids(($observer_hash) ? (PERMS_NETWORK|PERMS_PUBLIC) : PERMS_PUBLIC) . " ))
|
||||
OR uid = %d )
|
||||
$sql_extra )
|
||||
$item_normal
|
||||
$item_normal_update
|
||||
$simple_update
|
||||
limit 1",
|
||||
dbesc($target_item['parent_mid']),
|
||||
@@ -287,32 +308,77 @@ class Display extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
|
||||
if($r) {
|
||||
|
||||
$parents_str = ids_to_querystr($r,'item_id');
|
||||
if($parents_str) {
|
||||
|
||||
$items = q("SELECT item.*, item.id AS item_id
|
||||
FROM item
|
||||
WHERE parent in ( %s ) $item_normal ",
|
||||
dbesc($parents_str)
|
||||
);
|
||||
|
||||
xchan_query($items);
|
||||
$items = fetch_post_tags($items,true);
|
||||
$items = conv_sort($items,'created');
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
$items = array();
|
||||
}
|
||||
|
||||
|
||||
if ($checkjs->disabled()) {
|
||||
$o .= conversation($a, $items, 'display', $update, 'traditional');
|
||||
if ($items[0]['title'])
|
||||
\App::$page['title'] = $items[0]['title'] . " - " . \App::$page['title'];
|
||||
}
|
||||
else {
|
||||
$o .= conversation($a, $items, 'display', $update, 'client');
|
||||
|
||||
switch($module_format) {
|
||||
|
||||
case 'html':
|
||||
|
||||
if ($checkjs->disabled()) {
|
||||
$o .= conversation($items, 'display', $update, 'traditional');
|
||||
if ($items[0]['title'])
|
||||
\App::$page['title'] = $items[0]['title'] . " - " . \App::$page['title'];
|
||||
}
|
||||
else {
|
||||
$o .= conversation($items, 'display', $update, 'client');
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'atom':
|
||||
|
||||
$atom = replace_macros(get_markup_template('atom_feed.tpl'), array(
|
||||
'$version' => xmlify(\Zotlabs\Lib\System::get_project_version()),
|
||||
'$red' => xmlify(\Zotlabs\Lib\System::get_platform_name()),
|
||||
'$feed_id' => xmlify(\App::$cmd),
|
||||
'$feed_title' => xmlify(t('Article')),
|
||||
'$feed_updated' => xmlify(datetime_convert('UTC', 'UTC', 'now', ATOM_TIME)),
|
||||
'$author' => '',
|
||||
'$owner' => '',
|
||||
'$profile_page' => xmlify(z_root() . '/display/' . $target_item['mid']),
|
||||
));
|
||||
|
||||
$x = [ 'xml' => $atom, 'channel' => $channel, 'observer_hash' => $observer_hash, 'params' => $params ];
|
||||
call_hooks('atom_feed_top',$x);
|
||||
|
||||
$atom = $x['xml'];
|
||||
|
||||
// a much simpler interface
|
||||
call_hooks('atom_feed', $atom);
|
||||
|
||||
|
||||
if($items) {
|
||||
$type = 'html';
|
||||
foreach($items as $item) {
|
||||
if($item['item_private'])
|
||||
continue;
|
||||
$atom .= atom_entry($item, $type, null, '', true, '', false);
|
||||
}
|
||||
}
|
||||
|
||||
call_hooks('atom_feed_end', $atom);
|
||||
|
||||
$atom .= '</feed>' . "\r\n";
|
||||
|
||||
header('Content-type: application/atom+xml');
|
||||
echo $atom;
|
||||
killme();
|
||||
|
||||
}
|
||||
|
||||
if($updateable) {
|
||||
@@ -323,17 +389,13 @@ class Display extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
|
||||
$o .= '<div id="content-complete"></div>';
|
||||
|
||||
return $o;
|
||||
|
||||
|
||||
/*
|
||||
elseif((! $update) && (! {
|
||||
|
||||
if((($update && $load) || $checkjs->disabled()) && (! $items)) {
|
||||
|
||||
$r = q("SELECT id, item_flags FROM item WHERE id = '%s' OR mid = '%s' LIMIT 1",
|
||||
dbesc($item_hash),
|
||||
$r = q("SELECT id, item_deleted FROM item WHERE mid = '%s' LIMIT 1",
|
||||
dbesc($item_hash)
|
||||
);
|
||||
|
||||
if($r) {
|
||||
if(intval($r[0]['item_deleted'])) {
|
||||
notice( t('Item has been removed.') . EOL );
|
||||
@@ -347,8 +409,9 @@ class Display extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
return $o;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -98,6 +98,11 @@ class Editblock extends \Zotlabs\Web\Controller {
|
||||
|
||||
$mimetype = $itm[0]['mimetype'];
|
||||
|
||||
$content = $itm[0]['body'];
|
||||
if($itm[0]['mimetype'] === 'text/markdown')
|
||||
$content = \Zotlabs\Lib\MarkdownSoap::unescape($itm[0]['body']);
|
||||
|
||||
|
||||
$rp = 'blocks/' . $channel['channel_address'];
|
||||
|
||||
$x = array(
|
||||
@@ -117,7 +122,7 @@ class Editblock extends \Zotlabs\Web\Controller {
|
||||
'ptyp' => $itm[0]['type'],
|
||||
'mimeselect' => true,
|
||||
'mimetype' => $itm[0]['mimetype'],
|
||||
'body' => undo_post_tagging($itm[0]['body']),
|
||||
'body' => undo_post_tagging($content),
|
||||
'post_id' => $post_id,
|
||||
'visitor' => true,
|
||||
'title' => htmlspecialchars($itm[0]['title'],ENT_COMPAT,'UTF-8'),
|
||||
|
||||
@@ -119,6 +119,7 @@ class Editlayout extends \Zotlabs\Web\Controller {
|
||||
'hide_weblink' => true,
|
||||
'hide_attach' => true,
|
||||
'hide_preview' => true,
|
||||
'disable_comments' => true,
|
||||
'ptyp' => $itm[0]['obj_type'],
|
||||
'body' => undo_post_tagging($itm[0]['body']),
|
||||
'post_id' => $post_id,
|
||||
|
||||
@@ -31,7 +31,15 @@ class Editpost extends \Zotlabs\Web\Controller {
|
||||
dbesc(get_observer_hash())
|
||||
);
|
||||
|
||||
if(! count($itm)) {
|
||||
// don't allow web editing of potentially binary content (item_obscured = 1)
|
||||
// @FIXME how do we do it instead?
|
||||
|
||||
if((! $itm) || intval($itm[0]['item_obscured'])) {
|
||||
notice( t('Item is not editable') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
if($itm[0]['resource_type'] === 'photo' && $itm[0]['resource_id']) {
|
||||
notice( t('Item is not editable') . EOL);
|
||||
return;
|
||||
}
|
||||
@@ -44,14 +52,6 @@ class Editpost extends \Zotlabs\Web\Controller {
|
||||
|
||||
$channel = \App::get_channel();
|
||||
|
||||
if(intval($itm[0]['item_obscured'])) {
|
||||
$key = get_config('system','prvkey');
|
||||
if($itm[0]['title'])
|
||||
$itm[0]['title'] = crypto_unencapsulate(json_decode($itm[0]['title'],true),$key);
|
||||
if($itm[0]['body'])
|
||||
$itm[0]['body'] = crypto_unencapsulate(json_decode($itm[0]['body'],true),$key);
|
||||
}
|
||||
|
||||
$category = '';
|
||||
$catsenabled = ((feature_enabled($owner_uid,'categories')) ? 'categories' : '');
|
||||
|
||||
|
||||
@@ -100,24 +100,19 @@ class Editwebpage extends \Zotlabs\Web\Controller {
|
||||
intval($owner)
|
||||
);
|
||||
|
||||
if(! $itm) {
|
||||
// don't allow web editing of potentially binary content (item_obscured = 1)
|
||||
// @FIXME how do we do it instead?
|
||||
|
||||
if((! $itm) || intval($itm[0]['item_obscured'])) {
|
||||
notice( t('Permission denied.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
if(intval($itm[0]['item_obscured'])) {
|
||||
$key = get_config('system','prvkey');
|
||||
if($itm[0]['title'])
|
||||
$itm[0]['title'] = crypto_unencapsulate(json_decode($itm[0]['title'],true),$key);
|
||||
if($itm[0]['body'])
|
||||
$itm[0]['body'] = crypto_unencapsulate(json_decode($itm[0]['body'],true),$key);
|
||||
}
|
||||
|
||||
$item_id = q("select * from iconfig where cat = 'system' and k = 'WEBPAGE' and iid = %d limit 1",
|
||||
intval($itm[0]['id'])
|
||||
);
|
||||
if($item_id)
|
||||
$page_title = $item_id[0]['v'];
|
||||
$page_title = urldecode($item_id[0]['v']);
|
||||
|
||||
$mimetype = $itm[0]['mimetype'];
|
||||
|
||||
@@ -129,9 +124,11 @@ class Editwebpage extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
|
||||
$layout = $itm[0]['layout_mid'];
|
||||
|
||||
$tpl = get_markup_template("jot.tpl");
|
||||
|
||||
$content = $itm[0]['body'];
|
||||
if($itm[0]['mimetype'] === 'text/markdown')
|
||||
$content = \Zotlabs\Lib\MarkdownSoap::unescape($itm[0]['body']);
|
||||
|
||||
$rp = 'webpages/' . $which;
|
||||
|
||||
$x = array(
|
||||
@@ -147,7 +144,7 @@ class Editwebpage extends \Zotlabs\Web\Controller {
|
||||
'hide_location' => true,
|
||||
'hide_voting' => true,
|
||||
'ptyp' => $itm[0]['type'],
|
||||
'body' => undo_post_tagging($itm[0]['body']),
|
||||
'body' => undo_post_tagging($content),
|
||||
'post_id' => $post_id,
|
||||
'visitor' => ($is_owner) ? true : false,
|
||||
'acl' => populate_acl($itm[0],false,\Zotlabs\Lib\PermissionDescription::fromGlobalPermission('view_pages')),
|
||||
|
||||
@@ -83,7 +83,7 @@ class Embedphotos extends \Zotlabs\Web\Controller {
|
||||
return '';
|
||||
|
||||
if($args['album'])
|
||||
$album = $args['album'];
|
||||
$album = (($args['album'] === '/') ? '' : $args['album']);
|
||||
if($args['title'])
|
||||
$title = $args['title'];
|
||||
|
||||
@@ -92,6 +92,7 @@ class Embedphotos extends \Zotlabs\Web\Controller {
|
||||
* It is a limitation of the photo table using a name for a photo album instead of a folder hash
|
||||
*/
|
||||
if($album) {
|
||||
require_once('include/attach.php');
|
||||
$x = q("select hash from attach where filename = '%s' and uid = %d limit 1",
|
||||
dbesc($album),
|
||||
intval($owner_uid)
|
||||
|
||||
@@ -272,7 +272,7 @@ class Events extends \Zotlabs\Web\Controller {
|
||||
return;
|
||||
}
|
||||
|
||||
nav_set_selected('all_events');
|
||||
nav_set_selected('Events');
|
||||
|
||||
if((argc() > 2) && (argv(1) === 'ignore') && intval(argv(2))) {
|
||||
$r = q("update event set dismissed = 1 where id = %d and uid = %d",
|
||||
|
||||
@@ -1,40 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
|
||||
require_once('include/items.php');
|
||||
|
||||
|
||||
class Feed extends \Zotlabs\Web\Controller {
|
||||
|
||||
function init() {
|
||||
|
||||
$params = array();
|
||||
$params = [];
|
||||
|
||||
$params['begin'] = ((x($_REQUEST,'date_begin')) ? $_REQUEST['date_begin'] : NULL_DATE);
|
||||
$params['end'] = ((x($_REQUEST,'date_end')) ? $_REQUEST['date_end'] : '');
|
||||
$params['type'] = ((stristr(argv(0),'json')) ? 'json' : 'xml');
|
||||
$params['pages'] = ((x($_REQUEST,'pages')) ? intval($_REQUEST['pages']) : 0);
|
||||
$params['top'] = ((x($_REQUEST,'top')) ? intval($_REQUEST['top']) : 0);
|
||||
$params['start'] = ((x($params,'start')) ? intval($params['start']) : 0);
|
||||
$params['records'] = ((x($params,'records')) ? intval($params['records']) : 40);
|
||||
$params['direction'] = ((x($params,'direction')) ? dbesc($params['direction']) : 'desc');
|
||||
$params['cat'] = ((x($_REQUEST,'cat')) ? escape_tags($_REQUEST['cat']) : '');
|
||||
|
||||
$channel = '';
|
||||
$params['begin'] = ((x($_REQUEST,'date_begin')) ? $_REQUEST['date_begin'] : NULL_DATE);
|
||||
$params['end'] = ((x($_REQUEST,'date_end')) ? $_REQUEST['date_end'] : '');
|
||||
$params['type'] = ((stristr(argv(0),'json')) ? 'json' : 'xml');
|
||||
$params['pages'] = ((x($_REQUEST,'pages')) ? intval($_REQUEST['pages']) : 0);
|
||||
$params['top'] = ((x($_REQUEST,'top')) ? intval($_REQUEST['top']) : 0);
|
||||
$params['start'] = ((x($_REQUEST,'start')) ? intval($_REQUEST['start']) : 0);
|
||||
$params['records'] = ((x($_REQUEST,'records')) ? intval($_REQUEST['records']) : 40);
|
||||
$params['direction'] = ((x($_REQUEST,'direction')) ? dbesc($_REQUEST['direction']) : 'desc');
|
||||
$params['cat'] = ((x($_REQUEST,'cat')) ? escape_tags($_REQUEST['cat']) : '');
|
||||
$params['compat'] = ((x($_REQUEST,'compat')) ? intval($_REQUEST['compat']) : 0);
|
||||
|
||||
if(! in_array($params['direction'],['asc','desc'])) {
|
||||
$params['direction'] = 'desc';
|
||||
}
|
||||
|
||||
if(argc() > 1) {
|
||||
$r = q("select * from channel left join xchan on channel_hash = xchan_hash where channel_address = '%s' limit 1",
|
||||
dbesc(argv(1))
|
||||
);
|
||||
if(!($r && count($r)))
|
||||
|
||||
if(observer_prohibited(true)) {
|
||||
killme();
|
||||
|
||||
$channel = $r[0];
|
||||
|
||||
if(observer_prohibited(true))
|
||||
}
|
||||
|
||||
$channel = channelx_by_nick(argv(1));
|
||||
if(! $channel) {
|
||||
killme();
|
||||
}
|
||||
|
||||
|
||||
logger('mod_feed: public feed request from ' . $_SERVER['REMOTE_ADDR'] . ' for ' . $channel['channel_address']);
|
||||
logger('public feed request from ' . $_SERVER['REMOTE_ADDR'] . ' for ' . $channel['channel_address']);
|
||||
|
||||
echo get_public_feed($channel,$params);
|
||||
|
||||
@@ -43,6 +47,4 @@ class Feed extends \Zotlabs\Web\Controller {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -10,7 +10,8 @@ class File_upload extends \Zotlabs\Web\Controller {
|
||||
|
||||
function post() {
|
||||
|
||||
// logger('file upload: ' . print_r($_REQUEST,true));
|
||||
logger('file upload: ' . print_r($_REQUEST,true));
|
||||
logger('file upload: ' . print_r($_FILES,true));
|
||||
|
||||
$channel = (($_REQUEST['channick']) ? channelx_by_nick($_REQUEST['channick']) : null);
|
||||
|
||||
@@ -28,15 +29,77 @@ class File_upload extends \Zotlabs\Web\Controller {
|
||||
$_REQUEST['group_deny'] = expand_acl($channel['channel_deny_gid']);
|
||||
}
|
||||
|
||||
$_REQUEST['allow_cid'] = perms2str($_REQUEST['contact_allow']);
|
||||
$_REQUEST['allow_gid'] = perms2str($_REQUEST['group_allow']);
|
||||
$_REQUEST['deny_cid'] = perms2str($_REQUEST['contact_deny']);
|
||||
$_REQUEST['deny_gid'] = perms2str($_REQUEST['group_deny']);
|
||||
|
||||
if($_REQUEST['filename']) {
|
||||
$_REQUEST['allow_cid'] = perms2str($_REQUEST['contact_allow']);
|
||||
$_REQUEST['allow_gid'] = perms2str($_REQUEST['group_allow']);
|
||||
$_REQUEST['deny_cid'] = perms2str($_REQUEST['contact_deny']);
|
||||
$_REQUEST['deny_gid'] = perms2str($_REQUEST['group_deny']);
|
||||
$r = attach_mkdir($channel,get_observer_hash(),$_REQUEST);
|
||||
$r = attach_mkdir($channel, get_observer_hash(), $_REQUEST);
|
||||
if($r['success']) {
|
||||
$hash = $r['data']['hash'];
|
||||
|
||||
$sync = attach_export_data($channel,$hash);
|
||||
if($sync) {
|
||||
build_sync_packet($channel['channel_id'],array('file' => array($sync)));
|
||||
}
|
||||
goaway(z_root() . '/cloud/' . $channel['channel_address'] . '/' . $r['data']['display_path']);
|
||||
|
||||
}
|
||||
}
|
||||
else {
|
||||
$r = attach_store($channel,get_observer_hash(), '', $_REQUEST);
|
||||
|
||||
$matches = [];
|
||||
$partial = false;
|
||||
|
||||
|
||||
|
||||
if(array_key_exists('HTTP_CONTENT_RANGE',$_SERVER)) {
|
||||
$pm = preg_match('/bytes (\d*)\-(\d*)\/(\d*)/',$_SERVER['HTTP_CONTENT_RANGE'],$matches);
|
||||
if($pm) {
|
||||
logger('Content-Range: ' . print_r($matches,true));
|
||||
$partial = true;
|
||||
}
|
||||
}
|
||||
|
||||
if($partial) {
|
||||
$x = save_chunk($channel,$matches[1],$matches[2],$matches[3]);
|
||||
|
||||
if($x['partial']) {
|
||||
header('Range: bytes=0-' . (($x['length']) ? $x['length'] - 1 : 0));
|
||||
json_return_and_die($result);
|
||||
}
|
||||
else {
|
||||
header('Range: bytes=0-' . (($x['size']) ? $x['size'] - 1 : 0));
|
||||
|
||||
$_FILES['userfile'] = [
|
||||
'name' => $x['name'],
|
||||
'type' => $x['type'],
|
||||
'tmp_name' => $x['tmp_name'],
|
||||
'error' => $x['error'],
|
||||
'size' => $x['size']
|
||||
];
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(! array_key_exists('userfile',$_FILES)) {
|
||||
$_FILES['userfile'] = [
|
||||
'name' => $_FILES['files']['name'],
|
||||
'type' => $_FILES['files']['type'],
|
||||
'tmp_name' => $_FILES['files']['tmp_name'],
|
||||
'error' => $_FILES['files']['error'],
|
||||
'size' => $_FILES['files']['size']
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
$r = attach_store($channel, get_observer_hash(), '', $_REQUEST);
|
||||
if($r['success']) {
|
||||
$sync = attach_export_data($channel,$r['data']['hash']);
|
||||
if($sync)
|
||||
build_sync_packet($channel['channel_id'],array('file' => array($sync)));
|
||||
|
||||
}
|
||||
}
|
||||
goaway(z_root() . '/' . $_REQUEST['return_url']);
|
||||
|
||||
|
||||
@@ -49,8 +49,10 @@ class Filer extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
$tpl = get_markup_template("filer_dialog.tpl");
|
||||
$o = replace_macros($tpl, array(
|
||||
'$field' => array('term', t("Save to Folder:"), '', '', $filetags, t('- select -')),
|
||||
'$field' => array('term', t('Enter a folder name'), '', '', $filetags, 'placeholder="' . t('or select an existing folder (doubleclick)') . '"'),
|
||||
'$submit' => t('Save'),
|
||||
'$title' => t('Save to Folder'),
|
||||
'$cancel' => t('Cancel')
|
||||
));
|
||||
|
||||
echo $o;
|
||||
|
||||
@@ -5,14 +5,6 @@ namespace Zotlabs\Module;
|
||||
*
|
||||
*/
|
||||
|
||||
require_once('include/attach.php');
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @param object &$a
|
||||
*/
|
||||
|
||||
class Filestorage extends \Zotlabs\Web\Controller {
|
||||
|
||||
function post() {
|
||||
@@ -26,7 +18,7 @@ class Filestorage extends \Zotlabs\Web\Controller {
|
||||
|
||||
$recurse = ((x($_POST, 'recurse')) ? intval($_POST['recurse']) : 0);
|
||||
$resource = ((x($_POST, 'filehash')) ? notags($_POST['filehash']) : '');
|
||||
$notify = ((x($_POST, 'notify')) ? intval($_POST['notify']) : 0);
|
||||
$notify = ((x($_POST, 'notify_edit')) ? intval($_POST['notify_edit']) : 0);
|
||||
|
||||
if(! $resource) {
|
||||
notice(t('Item not found.') . EOL);
|
||||
@@ -36,19 +28,19 @@ class Filestorage extends \Zotlabs\Web\Controller {
|
||||
$channel = \App::get_channel();
|
||||
|
||||
$acl = new \Zotlabs\Access\AccessList($channel);
|
||||
$acl->set_from_array($_REQUEST);
|
||||
$acl->set_from_array($_POST);
|
||||
$x = $acl->get();
|
||||
|
||||
$cloudPath = get_parent_cloudpath($channel_id, $channel['channel_address'], $resource);
|
||||
$url = get_cloud_url($channel_id, $channel['channel_address'], $resource);
|
||||
|
||||
//get the object before permissions change so we can catch eventual former allowed members
|
||||
$object = get_file_activity_object($channel_id, $resource, $cloudPath);
|
||||
$object = get_file_activity_object($channel_id, $resource, $url);
|
||||
|
||||
attach_change_permissions($channel_id, $resource, $x['allow_cid'], $x['allow_gid'], $x['deny_cid'], $x['deny_gid'], $recurse, true);
|
||||
|
||||
file_activity($channel_id, $object, $x['allow_cid'], $x['allow_gid'], $x['deny_cid'], $x['deny_gid'], 'post', $notify);
|
||||
|
||||
goaway($cloudPath);
|
||||
goaway(dirname($url));
|
||||
}
|
||||
|
||||
function get() {
|
||||
@@ -107,11 +99,16 @@ class Filestorage extends \Zotlabs\Web\Controller {
|
||||
$f = $r[0];
|
||||
$channel = \App::get_channel();
|
||||
|
||||
$parentpath = get_parent_cloudpath($channel['channel_id'], $channel['channel_address'], $f['hash']);
|
||||
$url = get_cloud_url($channel['channel_id'], $channel['channel_address'], $f['hash']);
|
||||
|
||||
attach_delete($owner, $f['hash']);
|
||||
|
||||
goaway($parentpath);
|
||||
$sync = attach_export_data($channel, $f['hash'], true);
|
||||
if($sync) {
|
||||
build_sync_packet($channel['channel_id'], array('file' => array($sync)));
|
||||
}
|
||||
|
||||
goaway(dirname($url));
|
||||
}
|
||||
|
||||
if(argc() > 3 && argv(3) === 'edit') {
|
||||
@@ -130,8 +127,7 @@ class Filestorage extends \Zotlabs\Web\Controller {
|
||||
$f = $r[0];
|
||||
$channel = \App::get_channel();
|
||||
|
||||
$cloudpath = get_cloudpath($f) . (intval($f['is_dir']) ? '?f=&davguest=1' : '');
|
||||
$parentpath = get_parent_cloudpath($channel['channel_id'], $channel['channel_address'], $f['hash']);
|
||||
$cloudpath = get_cloudpath($f);
|
||||
|
||||
$aclselect_e = populate_acl($f, false, \Zotlabs\Lib\PermissionDescription::fromGlobalPermission('view_storage'));
|
||||
$is_a_dir = (intval($f['is_dir']) ? true : false);
|
||||
@@ -146,7 +142,6 @@ class Filestorage extends \Zotlabs\Web\Controller {
|
||||
'$header' => t('Edit file permissions'),
|
||||
'$file' => $f,
|
||||
'$cloudpath' => z_root() . '/' . $encoded_path,
|
||||
'$parentpath' => $parentpath,
|
||||
'$uid' => $channel['channel_id'],
|
||||
'$channelnick' => $channel['channel_address'],
|
||||
'$permissions' => t('Permissions'),
|
||||
@@ -165,7 +160,7 @@ class Filestorage extends \Zotlabs\Web\Controller {
|
||||
'$submit' => t('Submit'),
|
||||
'$attach_btn_title' => t('Share this file'),
|
||||
'$link_btn_title' => t('Show URL to this file'),
|
||||
'$notify' => array('notify', t('Notify your contacts about this file'), 0, '', array(t('No'), t('Yes'))),
|
||||
'$notify' => array('notify_edit', t('Show in your contacts shared folder'), 0, '', array(t('No'), t('Yes'))),
|
||||
));
|
||||
|
||||
echo $o;
|
||||
|
||||
@@ -28,16 +28,51 @@ class Getfile extends \Zotlabs\Web\Controller {
|
||||
|
||||
function post() {
|
||||
|
||||
logger('post: ' . print_r($_POST,true),LOGGER_DEBUG,LOG_INFO);
|
||||
|
||||
$header_verified = false;
|
||||
|
||||
$hash = $_POST['hash'];
|
||||
$time = $_POST['time'];
|
||||
$sig = $_POST['signature'];
|
||||
$resource = $_POST['resource'];
|
||||
$revision = intval($_POST['revision']);
|
||||
|
||||
$resolution = (-1);
|
||||
|
||||
if(! $hash)
|
||||
killme();
|
||||
|
||||
foreach([ 'REDIRECT_REMOTE_USER', 'HTTP_AUTHORIZATION' ] as $head) {
|
||||
if(array_key_exists($head,$_SERVER) && substr(trim($_SERVER[$head]),0,9) === 'Signature') {
|
||||
if($head !== 'HTTP_AUTHORIZATION') {
|
||||
$_SERVER['HTTP_AUTHORIZATION'] = $_SERVER[$head];
|
||||
continue;
|
||||
}
|
||||
|
||||
$sigblock = \Zotlabs\Web\HTTPSig::parse_sigheader($_SERVER[$head]);
|
||||
if($sigblock) {
|
||||
$keyId = $sigblock['keyId'];
|
||||
|
||||
if($keyId) {
|
||||
$r = q("select * from hubloc left join xchan on hubloc_hash = xchan_hash
|
||||
where hubloc_addr = '%s' limit 1",
|
||||
dbesc(str_replace('acct:','',$keyId))
|
||||
);
|
||||
if($r) {
|
||||
$hubloc = $r[0];
|
||||
$verified = \Zotlabs\Web\HTTPSig::verify('',$hubloc['xchan_pubkey']);
|
||||
if($verified && $verified['header_signed'] && $verified['header_valid'] && $hash == $hubloc['hubloc_hash']) {
|
||||
$header_verified = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
logger('post: ' . print_r($_POST,true),LOGGER_DEBUG,LOG_INFO);
|
||||
if($header_verified) {
|
||||
logger('HTTPSig verified');
|
||||
}
|
||||
|
||||
$channel = channelx_by_hash($hash);
|
||||
|
||||
@@ -46,6 +81,11 @@ class Getfile extends \Zotlabs\Web\Controller {
|
||||
killme();
|
||||
}
|
||||
|
||||
if(substr($resource,-2,1) == '-') {
|
||||
$resolution = intval(substr($resource,-1,1));
|
||||
$resource = substr($resource,0,-2);
|
||||
}
|
||||
|
||||
$slop = intval(get_pconfig($channel['channel_id'],'system','getfile_time_slop'));
|
||||
if($slop < 1)
|
||||
$slop = 3;
|
||||
@@ -53,16 +93,46 @@ class Getfile extends \Zotlabs\Web\Controller {
|
||||
$d1 = datetime_convert('UTC','UTC',"now + $slop minutes");
|
||||
$d2 = datetime_convert('UTC','UTC',"now - $slop minutes");
|
||||
|
||||
if(($time > $d1) || ($time < $d2)) {
|
||||
logger('time outside allowable range');
|
||||
killme();
|
||||
}
|
||||
if(! $header_verified) {
|
||||
if(($time > $d1) || ($time < $d2)) {
|
||||
logger('time outside allowable range');
|
||||
killme();
|
||||
}
|
||||
|
||||
if(! rsa_verify($hash . '.' . $time,base64url_decode($sig),$channel['channel_pubkey'])) {
|
||||
logger('verify failed.');
|
||||
if(! rsa_verify($hash . '.' . $time,base64url_decode($sig),$channel['channel_pubkey'])) {
|
||||
logger('verify failed.');
|
||||
killme();
|
||||
}
|
||||
}
|
||||
|
||||
if($resolution > 0) {
|
||||
$r = q("select * from photo where resource_id = '%s' and uid = %d limit 1",
|
||||
dbesc($resource),
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
if($r) {
|
||||
header('Content-type: ' . $r[0]['mimetype']);
|
||||
|
||||
if(intval($r[0]['os_storage'])) {
|
||||
$fname = dbunescbin($r[0]['content']);
|
||||
if(strpos($fname,'store') !== false)
|
||||
$istream = fopen($fname,'rb');
|
||||
else
|
||||
$istream = fopen('store/' . $channel['channel_address'] . '/' . $fname,'rb');
|
||||
$ostream = fopen('php://output','wb');
|
||||
if($istream && $ostream) {
|
||||
pipe_streams($istream,$ostream);
|
||||
fclose($istream);
|
||||
fclose($ostream);
|
||||
}
|
||||
}
|
||||
else {
|
||||
echo dbunescbin($r[0]['content']);
|
||||
}
|
||||
}
|
||||
killme();
|
||||
}
|
||||
|
||||
|
||||
$r = attach_by_hash($resource,$channel['channel_hash'],$revision);
|
||||
|
||||
if(! $r['success']) {
|
||||
@@ -73,7 +143,7 @@ class Getfile extends \Zotlabs\Web\Controller {
|
||||
|
||||
$unsafe_types = array('text/html','text/css','application/javascript');
|
||||
|
||||
if(in_array($r['data']['filetype'],$unsafe_types)) {
|
||||
if(in_array($r['data']['filetype'],$unsafe_types) && (! channel_codeallowed($channel['channel_id']))) {
|
||||
header('Content-type: text/plain');
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -56,6 +56,7 @@ class Group extends \Zotlabs\Web\Controller {
|
||||
);
|
||||
if($r)
|
||||
info( t('Privacy group updated.') . EOL );
|
||||
build_sync_packet(local_channel(),null,true);
|
||||
}
|
||||
|
||||
goaway(z_root() . '/group/' . argv(1) . '/' . argv(2));
|
||||
@@ -63,7 +64,8 @@ class Group extends \Zotlabs\Web\Controller {
|
||||
return;
|
||||
}
|
||||
|
||||
function get() {
|
||||
function get() {
|
||||
|
||||
$change = false;
|
||||
|
||||
logger('mod_group: ' . \App::$cmd,LOGGER_DEBUG);
|
||||
|
||||
@@ -14,6 +14,8 @@ class Hcard extends \Zotlabs\Web\Controller {
|
||||
return;
|
||||
}
|
||||
|
||||
logger('hcard_request: ' . $which, LOGGER_DEBUG);
|
||||
|
||||
$profile = '';
|
||||
$channel = \App::get_channel();
|
||||
|
||||
@@ -59,12 +61,10 @@ class Hcard extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
|
||||
|
||||
function get() {
|
||||
|
||||
require_once('include/widgets.php');
|
||||
return widget_profile(array());
|
||||
|
||||
|
||||
function get() {
|
||||
|
||||
$x = new \Zotlabs\Widget\Profile();
|
||||
return $x->widget(array());
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ require_once('include/help.php');
|
||||
class Help extends \Zotlabs\Web\Controller {
|
||||
|
||||
function get() {
|
||||
nav_set_selected('help');
|
||||
nav_set_selected('Help');
|
||||
|
||||
if($_REQUEST['search']) {
|
||||
$o .= '<div id="help-content" class="generic-content-wrapper">';
|
||||
@@ -44,42 +44,42 @@ class Help extends \Zotlabs\Web\Controller {
|
||||
|
||||
return $o;
|
||||
}
|
||||
|
||||
|
||||
if(argc() > 2 && argv(argc()-2) === 'assets') {
|
||||
$path = '';
|
||||
for($x = 1; $x < argc(); $x ++) {
|
||||
if(strlen($path))
|
||||
$path .= '/';
|
||||
$path .= argv($x);
|
||||
}
|
||||
$realpath = 'doc/' . $path;
|
||||
//Set the content-type header as appropriate
|
||||
$imageInfo = getimagesize($realpath);
|
||||
switch ($imageInfo[2]) {
|
||||
case IMAGETYPE_JPEG:
|
||||
header("Content-Type: image/jpeg");
|
||||
break;
|
||||
case IMAGETYPE_GIF:
|
||||
header("Content-Type: image/gif");
|
||||
break;
|
||||
case IMAGETYPE_PNG:
|
||||
header("Content-Type: image/png");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
header("Content-Length: " . filesize($realpath));
|
||||
|
||||
|
||||
if(argc() > 2 && argv(argc()-2) === 'assets') {
|
||||
$path = '';
|
||||
for($x = 1; $x < argc(); $x ++) {
|
||||
if(strlen($path))
|
||||
$path .= '/';
|
||||
$path .= argv($x);
|
||||
}
|
||||
$realpath = 'doc/' . $path;
|
||||
//Set the content-type header as appropriate
|
||||
$imageInfo = getimagesize($realpath);
|
||||
switch ($imageInfo[2]) {
|
||||
case IMAGETYPE_JPEG:
|
||||
header("Content-Type: image/jpeg");
|
||||
break;
|
||||
case IMAGETYPE_GIF:
|
||||
header("Content-Type: image/gif");
|
||||
break;
|
||||
case IMAGETYPE_PNG:
|
||||
header("Content-Type: image/png");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
header("Content-Length: " . filesize($realpath));
|
||||
|
||||
// dump the picture and stop the script
|
||||
readfile($realpath);
|
||||
killme();
|
||||
}
|
||||
// dump the picture and stop the script
|
||||
readfile($realpath);
|
||||
killme();
|
||||
}
|
||||
|
||||
$headings = [
|
||||
'about' => t('About'),
|
||||
'member' => t('Members'),
|
||||
'admin' => t('Administrators'),
|
||||
'about' => t('About'),
|
||||
'member' => t('Members'),
|
||||
'admin' => t('Administrators'),
|
||||
'developer' => t('Developers'),
|
||||
'tutorials' => t('Tutorials')
|
||||
];
|
||||
@@ -87,13 +87,16 @@ class Help extends \Zotlabs\Web\Controller {
|
||||
if(array_key_exists(argv(1), $headings))
|
||||
$heading = $headings[argv(1)];
|
||||
|
||||
$content = get_help_content();
|
||||
$content = get_help_content();
|
||||
|
||||
$language = determine_help_language()['language'];
|
||||
|
||||
return replace_macros(get_markup_template('help.tpl'), array(
|
||||
'$title' => t('$Projectname Documentation'),
|
||||
'$title' => t('$Projectname Documentation'),
|
||||
'$tocHeading' => t('Contents'),
|
||||
'$content' => $content,
|
||||
'$heading' => $heading
|
||||
'$content' => $content,
|
||||
'$heading' => $heading,
|
||||
'$language' => $language
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
301
Zotlabs/Module/Hq.php
Normal file
301
Zotlabs/Module/Hq.php
Normal file
@@ -0,0 +1,301 @@
|
||||
<?php
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
require_once("include/bbcode.php");
|
||||
require_once('include/security.php');
|
||||
require_once('include/conversation.php');
|
||||
require_once('include/acl_selectors.php');
|
||||
require_once('include/items.php');
|
||||
|
||||
|
||||
class Hq extends \Zotlabs\Web\Controller {
|
||||
|
||||
function init() {
|
||||
if(! local_channel())
|
||||
return;
|
||||
|
||||
\App::$profile_uid = local_channel();
|
||||
}
|
||||
|
||||
function post() {
|
||||
|
||||
if(!local_channel())
|
||||
return;
|
||||
|
||||
if($_REQUEST['notify_id']) {
|
||||
q("update notify set seen = 1 where id = %d and uid = %d",
|
||||
intval($_REQUEST['notify_id']),
|
||||
intval(local_channel())
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function get($update = 0, $load = false) {
|
||||
|
||||
if(!local_channel())
|
||||
return;
|
||||
|
||||
if($load)
|
||||
$_SESSION['loadtime'] = datetime_convert();
|
||||
|
||||
if(argc() > 1 && argv(1) !== 'load') {
|
||||
$item_hash = argv(1);
|
||||
}
|
||||
|
||||
if($_REQUEST['mid'])
|
||||
$item_hash = $_REQUEST['mid'];
|
||||
|
||||
$item_normal = item_normal();
|
||||
$item_normal_update = item_normal_update();
|
||||
|
||||
if(! $item_hash) {
|
||||
$r = q("SELECT mid FROM item
|
||||
WHERE uid = %d
|
||||
AND mid = parent_mid
|
||||
ORDER BY created DESC LIMIT 1",
|
||||
intval(local_channel())
|
||||
);
|
||||
|
||||
if($r[0]['mid']) {
|
||||
$item_hash = 'b64.' . base64url_encode($r[0]['mid']);
|
||||
}
|
||||
}
|
||||
|
||||
if($item_hash) {
|
||||
|
||||
if(strpos($item_hash,'b64.') === 0)
|
||||
$decoded = @base64url_decode(substr($item_hash,4));
|
||||
|
||||
if($decoded)
|
||||
$item_hash = $decoded;
|
||||
|
||||
$target_item = null;
|
||||
|
||||
$r = q("select id, uid, mid, parent_mid, thr_parent, verb, item_type, item_deleted, item_blocked from item where mid like '%s' limit 1",
|
||||
dbesc($item_hash . '%')
|
||||
);
|
||||
|
||||
if($r) {
|
||||
$target_item = $r[0];
|
||||
}
|
||||
|
||||
//if the item is to be moderated redirect to /moderate
|
||||
if($target_item['item_blocked'] == ITEM_MODERATED) {
|
||||
goaway(z_root() . '/moderate/' . $target_item['id']);
|
||||
}
|
||||
|
||||
$static = ((array_key_exists('static',$_REQUEST)) ? intval($_REQUEST['static']) : 0);
|
||||
|
||||
$simple_update = (($update) ? " AND item_unseen = 1 " : '');
|
||||
|
||||
if($update && $_SESSION['loadtime'])
|
||||
$simple_update = " AND (( item_unseen = 1 AND item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' ) OR item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' ) ";
|
||||
|
||||
if($static && $simple_update)
|
||||
$simple_update .= " and item_thread_top = 0 and author_xchan = '" . protect_sprintf(get_observer_hash()) . "' ";
|
||||
|
||||
$sys = get_sys_channel();
|
||||
$sql_extra = item_permissions_sql($sys['channel_id']);
|
||||
|
||||
$sys_item = false;
|
||||
|
||||
}
|
||||
|
||||
if(! $update) {
|
||||
$channel = \App::get_channel();
|
||||
|
||||
$channel_acl = [
|
||||
'allow_cid' => $channel['channel_allow_cid'],
|
||||
'allow_gid' => $channel['channel_allow_gid'],
|
||||
'deny_cid' => $channel['channel_deny_cid'],
|
||||
'deny_gid' => $channel['channel_deny_gid']
|
||||
];
|
||||
|
||||
$x = [
|
||||
'is_owner' => true,
|
||||
'allow_location' => ((intval(get_pconfig($channel['channel_id'],'system','use_browser_location'))) ? '1' : ''),
|
||||
'default_location' => $channel['channel_location'],
|
||||
'nickname' => $channel['channel_address'],
|
||||
'lockstate' => (($group || $cid || $channel['channel_allow_cid'] || $channel['channel_allow_gid'] || $channel['channel_deny_cid'] || $channel['channel_deny_gid']) ? 'lock' : 'unlock'),
|
||||
|
||||
'acl' => populate_acl($channel_acl),
|
||||
'permissions' => $channel_acl,
|
||||
'bang' => '',
|
||||
'visitor' => true,
|
||||
'profile_uid' => local_channel(),
|
||||
'return_path' => 'hq',
|
||||
'expanded' => true,
|
||||
'editor_autocomplete' => true,
|
||||
'bbco_autocomplete' => 'bbcode',
|
||||
'bbcode' => true,
|
||||
'jotnets' => true
|
||||
];
|
||||
|
||||
$o = replace_macros(get_markup_template("hq.tpl"),
|
||||
[
|
||||
'$no_messages' => (($target_item) ? false : true),
|
||||
'$no_messages_label' => t('Welcome to hubzilla!')
|
||||
]
|
||||
);
|
||||
|
||||
$o = '<div id="jot-popup">';
|
||||
$o .= status_editor($a,$x);
|
||||
$o .= '</div>';
|
||||
}
|
||||
|
||||
if(! $update && ! $load) {
|
||||
|
||||
nav_set_selected('HQ');
|
||||
|
||||
$static = ((local_channel()) ? channel_manual_conv_update(local_channel()) : 1);
|
||||
|
||||
if($target_item) {
|
||||
// if the target item is not a post (eg a like) we want to address its thread parent
|
||||
$mid = ((($target_item['verb'] == ACTIVITY_LIKE) || ($target_item['verb'] == ACTIVITY_DISLIKE)) ? $target_item['thr_parent'] : $target_item['mid']);
|
||||
|
||||
// if we got a decoded hash we must encode it again before handing to javascript
|
||||
if($decoded)
|
||||
$mid = 'b64.' . base64url_encode($mid);
|
||||
}
|
||||
else {
|
||||
$mid = '';
|
||||
}
|
||||
|
||||
$o .= '<div id="live-hq"></div>' . "\r\n";
|
||||
$o .= "<script> var profile_uid = " . local_channel()
|
||||
. "; var netargs = '?f='; var profile_page = " . \App::$pager['page'] . ";</script>\r\n";
|
||||
|
||||
\App::$page['htmlhead'] .= replace_macros(get_markup_template("build_query.tpl"),[
|
||||
'$baseurl' => z_root(),
|
||||
'$pgtype' => 'hq',
|
||||
'$uid' => local_channel(),
|
||||
'$gid' => '0',
|
||||
'$cid' => '0',
|
||||
'$cmin' => '0',
|
||||
'$cmax' => '99',
|
||||
'$star' => '0',
|
||||
'$liked' => '0',
|
||||
'$conv' => '0',
|
||||
'$spam' => '0',
|
||||
'$fh' => '0',
|
||||
'$nouveau' => '0',
|
||||
'$wall' => '0',
|
||||
'$static' => $static,
|
||||
'$page' => 1,
|
||||
'$list' => ((x($_REQUEST,'list')) ? intval($_REQUEST['list']) : 0),
|
||||
'$search' => '',
|
||||
'$xchan' => '',
|
||||
'$order' => '',
|
||||
'$file' => '',
|
||||
'$cats' => '',
|
||||
'$tags' => '',
|
||||
'$dend' => '',
|
||||
'$dbegin' => '',
|
||||
'$verb' => '',
|
||||
'$net' => '',
|
||||
'$mid' => $mid
|
||||
]);
|
||||
}
|
||||
|
||||
$updateable = false;
|
||||
|
||||
if($load && $target_item) {
|
||||
$r = null;
|
||||
|
||||
$r = q("SELECT item.id AS item_id FROM item
|
||||
WHERE uid = %d
|
||||
AND mid = '%s'
|
||||
$item_normal
|
||||
LIMIT 1",
|
||||
intval(local_channel()),
|
||||
dbesc($target_item['parent_mid'])
|
||||
);
|
||||
|
||||
if($r) {
|
||||
$updateable = true;
|
||||
}
|
||||
|
||||
if(!$r) {
|
||||
$sys_item = true;
|
||||
|
||||
$r = q("SELECT item.id AS item_id FROM item
|
||||
LEFT JOIN abook ON item.author_xchan = abook.abook_xchan
|
||||
WHERE mid = '%s' AND item.uid = %d $item_normal
|
||||
AND (abook.abook_blocked = 0 or abook.abook_flags is null)
|
||||
$sql_extra LIMIT 1",
|
||||
dbesc($target_item['parent_mid']),
|
||||
intval($sys['channel_id'])
|
||||
);
|
||||
}
|
||||
}
|
||||
elseif($update && $target_item) {
|
||||
$r = null;
|
||||
|
||||
$r = q("SELECT item.parent AS item_id FROM item
|
||||
WHERE uid = %d
|
||||
AND parent_mid = '%s'
|
||||
$item_normal_update
|
||||
$simple_update
|
||||
LIMIT 1",
|
||||
intval(local_channel()),
|
||||
dbesc($target_item['parent_mid'])
|
||||
);
|
||||
|
||||
if($r) {
|
||||
$updateable = true;
|
||||
}
|
||||
|
||||
if(!$r) {
|
||||
$sys_item = true;
|
||||
|
||||
$r = q("SELECT item.parent AS item_id FROM item
|
||||
LEFT JOIN abook ON item.author_xchan = abook.abook_xchan
|
||||
WHERE mid = '%s' AND item.uid = %d $item_normal_update $simple_update
|
||||
AND (abook.abook_blocked = 0 or abook.abook_flags is null)
|
||||
$sql_extra LIMIT 1",
|
||||
dbesc($target_item['parent_mid']),
|
||||
intval($sys['channel_id'])
|
||||
);
|
||||
}
|
||||
|
||||
$_SESSION['loadtime'] = datetime_convert();
|
||||
}
|
||||
else {
|
||||
$r = [];
|
||||
}
|
||||
|
||||
if($r) {
|
||||
$parents_str = ids_to_querystr($r,'item_id');
|
||||
if($parents_str) {
|
||||
$items = q("SELECT item.*, item.id AS item_id
|
||||
FROM item
|
||||
WHERE parent IN ( %s ) $item_normal ",
|
||||
dbesc($parents_str)
|
||||
);
|
||||
|
||||
xchan_query($items,true,(($sys_item) ? local_channel() : 0));
|
||||
$items = fetch_post_tags($items,true);
|
||||
$items = conv_sort($items,'created');
|
||||
}
|
||||
}
|
||||
else {
|
||||
$items = [];
|
||||
}
|
||||
|
||||
$o .= conversation($items, 'hq', $update, 'client');
|
||||
|
||||
if($updateable) {
|
||||
$x = q("UPDATE item SET item_unseen = 0 WHERE item_unseen = 1 AND uid = %d AND parent = %d ",
|
||||
intval(local_channel()),
|
||||
intval($r[0]['item_id'])
|
||||
);
|
||||
}
|
||||
|
||||
$o .= '<div id="content-complete"></div>';
|
||||
|
||||
return $o;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -26,6 +26,8 @@ class Impel extends \Zotlabs\Web\Controller {
|
||||
if(! $j)
|
||||
json_return_and_die($ret);
|
||||
|
||||
// logger('element: ' . print_r($j,true));
|
||||
|
||||
$channel = \App::get_channel();
|
||||
|
||||
$arr = array();
|
||||
@@ -144,18 +146,8 @@ class Impel extends \Zotlabs\Web\Controller {
|
||||
|
||||
// Verify ability to use html or php!!!
|
||||
|
||||
$execflag = false;
|
||||
|
||||
if($arr['mimetype'] === 'application/x-php') {
|
||||
$z = q("select account_id, account_roles, channel_pageflags from account left join channel on channel_account_id = account_id where channel_id = %d limit 1",
|
||||
intval(local_channel())
|
||||
);
|
||||
|
||||
if($z && (($z[0]['account_roles'] & ACCOUNT_ROLE_ALLOWCODE) || ($z[0]['channel_pageflags'] & PAGE_ALLOWCODE))) {
|
||||
$execflag = true;
|
||||
}
|
||||
}
|
||||
|
||||
$execflag = ((intval($channel['channel_id']) == intval(local_channel()) && ($channel['channel_pageflags'] & PAGE_ALLOWCODE)) ? true : false);
|
||||
|
||||
$i = q("select id, edited, item_deleted from item where mid = '%s' and uid = %d limit 1",
|
||||
dbesc($arr['mid']),
|
||||
intval(local_channel())
|
||||
|
||||
@@ -2,26 +2,32 @@
|
||||
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
// Import a channel, either by direct file upload or via
|
||||
// connection to original server.
|
||||
|
||||
|
||||
require_once('include/zot.php');
|
||||
require_once('include/channel.php');
|
||||
require_once('include/import.php');
|
||||
require_once('include/perm_upgrade.php');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Module for channel import.
|
||||
*
|
||||
* Import a channel, either by direct file upload or via
|
||||
* connection to another server.
|
||||
*/
|
||||
class Import extends \Zotlabs\Web\Controller {
|
||||
|
||||
/**
|
||||
* @brief Import channel into account.
|
||||
*
|
||||
* @param int $account_id
|
||||
*/
|
||||
function import_account($account_id) {
|
||||
|
||||
|
||||
if(! $account_id){
|
||||
logger("import_account: No account ID supplied");
|
||||
logger('No account ID supplied');
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
$max_friends = account_service_class_fetch($account_id,'total_channels');
|
||||
$max_feeds = account_service_class_fetch($account_id,'total_feeds');
|
||||
$data = null;
|
||||
@@ -32,35 +38,39 @@ class Import extends \Zotlabs\Web\Controller {
|
||||
$filename = basename($_FILES['filename']['name']);
|
||||
$filesize = intval($_FILES['filename']['size']);
|
||||
$filetype = $_FILES['filename']['type'];
|
||||
|
||||
|
||||
// import channel from file
|
||||
if($src) {
|
||||
|
||||
// This is OS specific and could also fail if your tmpdir isn't very large
|
||||
// mostly used for Diaspora which exports gzipped files.
|
||||
|
||||
|
||||
// This is OS specific and could also fail if your tmpdir isn't very
|
||||
// large mostly used for Diaspora which exports gzipped files.
|
||||
|
||||
if(strpos($filename,'.gz')){
|
||||
@rename($src,$src . '.gz');
|
||||
@system('gunzip ' . escapeshellarg($src . '.gz'));
|
||||
}
|
||||
|
||||
|
||||
if($filesize) {
|
||||
$data = @file_get_contents($src);
|
||||
}
|
||||
unlink($src);
|
||||
}
|
||||
|
||||
|
||||
// import channel from another server
|
||||
if(! $src) {
|
||||
$old_address = ((x($_REQUEST,'old_address')) ? $_REQUEST['old_address'] : '');
|
||||
if(! $old_address) {
|
||||
logger('mod_import: nothing to import.');
|
||||
logger('Nothing to import.');
|
||||
notice( t('Nothing to import.') . EOL);
|
||||
return;
|
||||
} else if(strpos($old_address, '@')) {
|
||||
// if you copy the identity address from your profile page, make it work for convenience
|
||||
$old_address = str_replace('@', '@', $old_address);
|
||||
}
|
||||
|
||||
|
||||
$email = ((x($_REQUEST,'email')) ? $_REQUEST['email'] : '');
|
||||
$password = ((x($_REQUEST,'password')) ? $_REQUEST['password'] : '');
|
||||
|
||||
|
||||
$channelname = substr($old_address,0,strpos($old_address,'@'));
|
||||
$servername = substr($old_address,strpos($old_address,'@')+1);
|
||||
|
||||
@@ -73,6 +83,7 @@ class Import extends \Zotlabs\Web\Controller {
|
||||
$api_path .= 'channel/export/basic?f=&channel=' . $channelname;
|
||||
if($import_posts)
|
||||
$api_path .= '&posts=1';
|
||||
|
||||
$binary = false;
|
||||
$redirects = 0;
|
||||
$opts = array('http_auth' => $email . ':' . $password);
|
||||
@@ -85,19 +96,18 @@ class Import extends \Zotlabs\Web\Controller {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(! $data) {
|
||||
logger('mod_import: empty file.');
|
||||
logger('Empty import file.');
|
||||
notice( t('Imported file is empty.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
$data = json_decode($data,true);
|
||||
|
||||
// logger('import: data: ' . print_r($data,true));
|
||||
// print_r($data);
|
||||
|
||||
|
||||
|
||||
//logger('import: data: ' . print_r($data,true));
|
||||
//print_r($data);
|
||||
|
||||
if(! array_key_exists('compatibility',$data)) {
|
||||
call_hooks('import_foreign_channel_data',$data);
|
||||
if($data['handled'])
|
||||
@@ -108,24 +118,23 @@ class Import extends \Zotlabs\Web\Controller {
|
||||
$v1 = substr($data['compatibility']['database'],-4);
|
||||
$v2 = substr(DB_UPDATE_VERSION,-4);
|
||||
if($v2 > $v1) {
|
||||
$t = sprintf( t('Warning: Database versions differ by %1$d updates.'), $v2 - $v1 );
|
||||
$t = sprintf( t('Warning: Database versions differ by %1$d updates.'), $v2 - $v1 );
|
||||
notice($t);
|
||||
}
|
||||
if(array_key_exists('server_role',$data['compatibility']) && $data['compatibility']['server_role'] == 'basic')
|
||||
$moving = true;
|
||||
|
||||
}
|
||||
|
||||
|
||||
if($moving)
|
||||
$seize = 1;
|
||||
|
||||
|
||||
// import channel
|
||||
|
||||
|
||||
$relocate = ((array_key_exists('relocate',$data)) ? $data['relocate'] : null);
|
||||
|
||||
if(array_key_exists('channel',$data)) {
|
||||
|
||||
|
||||
$max_identities = account_service_class_fetch($account_id,'total_identities');
|
||||
|
||||
|
||||
if($max_identities !== false) {
|
||||
$r = q("select channel_id from channel where channel_account_id = %d",
|
||||
intval($account_id)
|
||||
@@ -137,46 +146,40 @@ class Import extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
|
||||
$channel = import_channel($data['channel'], $account_id, $seize);
|
||||
|
||||
}
|
||||
else {
|
||||
$moving = false;
|
||||
$channel = \App::get_channel();
|
||||
}
|
||||
|
||||
|
||||
if(! $channel) {
|
||||
logger('mod_import: channel not found. ', print_r($channel,true));
|
||||
logger('Channel not found. ', print_r($channel,true));
|
||||
notice( t('No channel. Import failed.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if(is_array($data['config'])) {
|
||||
import_config($channel,$data['config']);
|
||||
}
|
||||
|
||||
logger('import step 2');
|
||||
|
||||
|
||||
|
||||
|
||||
logger('import step 2');
|
||||
|
||||
if(array_key_exists('channel',$data)) {
|
||||
if($data['photo']) {
|
||||
require_once('include/photo/photo_driver.php');
|
||||
import_channel_photo(base64url_decode($data['photo']['data']),$data['photo']['type'],$account_id,$channel['channel_id']);
|
||||
}
|
||||
|
||||
|
||||
if(is_array($data['profile']))
|
||||
import_profiles($channel,$data['profile']);
|
||||
}
|
||||
|
||||
|
||||
logger('import step 3');
|
||||
|
||||
|
||||
if(is_array($data['hubloc'])) {
|
||||
import_hublocs($channel,$data['hubloc'],$seize,$moving);
|
||||
}
|
||||
|
||||
|
||||
logger('import step 4');
|
||||
|
||||
// create new hubloc for the new channel at this site
|
||||
@@ -200,7 +203,7 @@ class Import extends \Zotlabs\Web\Controller {
|
||||
);
|
||||
|
||||
// reset the original primary hubloc if it is being seized
|
||||
|
||||
|
||||
if($seize) {
|
||||
$r = q("update hubloc set hubloc_primary = 0 where hubloc_primary = 1 and hubloc_hash = '%s' and hubloc_url != '%s' ",
|
||||
dbesc($channel['channel_hash']),
|
||||
@@ -210,20 +213,18 @@ class Import extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
|
||||
logger('import step 5');
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// import xchans and contact photos
|
||||
|
||||
|
||||
if(array_key_exists('channel',$data) && $seize) {
|
||||
|
||||
|
||||
// replace any existing xchan we may have on this site if we're seizing control
|
||||
|
||||
|
||||
$r = q("delete from xchan where xchan_hash = '%s'",
|
||||
dbesc($channel['channel_hash'])
|
||||
);
|
||||
|
||||
|
||||
$r = xchan_store_lowlevel(
|
||||
[
|
||||
'xchan_hash' => $channel['channel_hash'],
|
||||
@@ -242,23 +243,22 @@ class Import extends \Zotlabs\Web\Controller {
|
||||
'xchan_photo_date' => datetime_convert(),
|
||||
'xchan_name_date' => datetime_convert()
|
||||
]
|
||||
);
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
logger('import step 6');
|
||||
|
||||
|
||||
|
||||
// import xchans
|
||||
$xchans = $data['xchan'];
|
||||
if($xchans) {
|
||||
foreach($xchans as $xchan) {
|
||||
|
||||
|
||||
$hash = make_xchan_hash($xchan['xchan_guid'],$xchan['xchan_guid_sig']);
|
||||
if($xchan['xchan_network'] === 'zot' && $hash !== $xchan['xchan_hash']) {
|
||||
logger('forged xchan: ' . print_r($xchan,true));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if(! array_key_exists('xchan_hidden',$xchan)) {
|
||||
$xchan['xchan_hidden'] = (($xchan['xchan_flags'] & 0x0001) ? 1 : 0);
|
||||
$xchan['xchan_orphan'] = (($xchan['xchan_flags'] & 0x0002) ? 1 : 0);
|
||||
@@ -268,57 +268,67 @@ class Import extends \Zotlabs\Web\Controller {
|
||||
$xchan['xchan_pubforum'] = (($xchan['xchan_flags'] & 0x0020) ? 1 : 0);
|
||||
$xchan['xchan_deleted'] = (($xchan['xchan_flags'] & 0x1000) ? 1 : 0);
|
||||
}
|
||||
|
||||
|
||||
$r = q("select xchan_hash from xchan where xchan_hash = '%s' limit 1",
|
||||
dbesc($xchan['xchan_hash'])
|
||||
);
|
||||
if($r)
|
||||
continue;
|
||||
|
||||
create_table_from_array('xchan',$xchan);
|
||||
|
||||
create_table_from_array('xchan',$xchan);
|
||||
|
||||
require_once('include/photo/photo_driver.php');
|
||||
$photos = import_xchan_photo($xchan['xchan_photo_l'],$xchan['xchan_hash']);
|
||||
if($photos[4])
|
||||
$photodate = NULL_DATE;
|
||||
else
|
||||
$photodate = $xchan['xchan_photo_date'];
|
||||
|
||||
$r = q("update xchan set xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s', xchan_photo_date = '%s' where xchan_hash = '%s'",
|
||||
dbesc($photos[0]),
|
||||
dbesc($photos[1]),
|
||||
dbesc($photos[2]),
|
||||
dbesc($photos[3]),
|
||||
dbesc($photodate),
|
||||
dbesc($xchan['xchan_hash'])
|
||||
);
|
||||
|
||||
|
||||
if($xchan['xchan_hash'] === $channel['channel_hash']) {
|
||||
$r = q("update xchan set xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s' where xchan_hash = '%s'",
|
||||
dbesc(z_root() . '/photo/profile/l/' . $channel['channel_id']),
|
||||
dbesc(z_root() . '/photo/profile/m/' . $channel['channel_id']),
|
||||
dbesc(z_root() . '/photo/profile/s/' . $channel['channel_id']),
|
||||
dbesc($xchan['xchan_hash'])
|
||||
);
|
||||
}
|
||||
else {
|
||||
$photos = import_xchan_photo($xchan['xchan_photo_l'],$xchan['xchan_hash']);
|
||||
if($photos[4])
|
||||
$photodate = NULL_DATE;
|
||||
else
|
||||
$photodate = $xchan['xchan_photo_date'];
|
||||
|
||||
$r = q("update xchan set xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s', xchan_photo_date = '%s' where xchan_hash = '%s'",
|
||||
dbesc($photos[0]),
|
||||
dbesc($photos[1]),
|
||||
dbesc($photos[2]),
|
||||
dbesc($photos[3]),
|
||||
dbesc($photodate),
|
||||
dbesc($xchan['xchan_hash'])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
logger('import step 7');
|
||||
logger('import step 7');
|
||||
}
|
||||
|
||||
|
||||
$friends = 0;
|
||||
$feeds = 0;
|
||||
|
||||
|
||||
// import contacts
|
||||
$abooks = $data['abook'];
|
||||
if($abooks) {
|
||||
foreach($abooks as $abook) {
|
||||
|
||||
$abook_copy = $abook;
|
||||
|
||||
|
||||
$abconfig = null;
|
||||
if(array_key_exists('abconfig',$abook) && is_array($abook['abconfig']) && count($abook['abconfig']))
|
||||
$abconfig = $abook['abconfig'];
|
||||
|
||||
|
||||
unset($abook['abook_id']);
|
||||
unset($abook['abook_rating']);
|
||||
unset($abook['abook_rating_text']);
|
||||
unset($abook['abconfig']);
|
||||
unset($abook['abook_their_perms']);
|
||||
unset($abook['abook_my_perms']);
|
||||
unset($abook['abook_not_here']);
|
||||
|
||||
$abook['abook_account'] = $account_id;
|
||||
$abook['abook_channel'] = $channel['channel_id'];
|
||||
@@ -332,7 +342,11 @@ class Import extends \Zotlabs\Web\Controller {
|
||||
$abook['abook_self'] = (($abook['abook_flags'] & 0x0080 ) ? 1 : 0);
|
||||
$abook['abook_feed'] = (($abook['abook_flags'] & 0x0100 ) ? 1 : 0);
|
||||
}
|
||||
|
||||
|
||||
if(array_key_exists('abook_instance',$abook) && $abook['abook_instance'] && strpos($abook['abook_instance'],z_root()) === false) {
|
||||
$abook['abook_not_here'] = 1;
|
||||
}
|
||||
|
||||
if($abook['abook_self']) {
|
||||
$role = get_pconfig($channel['channel_id'],'system','permissions_role');
|
||||
if(($role === 'forum') || ($abook['abook_my_perms'] & PERMS_W_TAGWALL)) {
|
||||
@@ -340,24 +354,24 @@ class Import extends \Zotlabs\Web\Controller {
|
||||
dbesc($abook['abook_xchan'])
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if($max_friends !== false && $friends > $max_friends)
|
||||
continue;
|
||||
if($max_feeds !== false && intval($abook['abook_feed']) && ($feeds > $max_feeds))
|
||||
continue;
|
||||
}
|
||||
|
||||
create_table_from_array('abook',$abook);
|
||||
|
||||
abook_store_lowlevel($abook);
|
||||
|
||||
$friends ++;
|
||||
if(intval($abook['abook_feed']))
|
||||
$feeds ++;
|
||||
|
||||
translate_abook_perms_inbound($channel,$abook_copy);
|
||||
|
||||
|
||||
if($abconfig) {
|
||||
// @fixme does not handle sync of del_abconfig
|
||||
/// @FIXME does not handle sync of del_abconfig
|
||||
foreach($abconfig as $abc) {
|
||||
set_abconfig($channel['channel_id'],$abc['xchan'],$abc['cat'],$abc['k'],$abc['v']);
|
||||
}
|
||||
@@ -366,20 +380,21 @@ class Import extends \Zotlabs\Web\Controller {
|
||||
|
||||
logger('import step 8');
|
||||
}
|
||||
|
||||
|
||||
// import groups
|
||||
$groups = $data['group'];
|
||||
if($groups) {
|
||||
$saved = array();
|
||||
foreach($groups as $group) {
|
||||
$saved[$group['hash']] = array('old' => $group['id']);
|
||||
if(array_key_exists('name',$group)) {
|
||||
if(array_key_exists('name', $group)) {
|
||||
$group['gname'] = $group['name'];
|
||||
unset($group['name']);
|
||||
}
|
||||
unset($group['id']);
|
||||
$group['uid'] = $channel['channel_id'];
|
||||
|
||||
create_table_from_array('groups',$group);
|
||||
create_table_from_array('groups', $group);
|
||||
}
|
||||
$r = q("select * from groups where uid = %d",
|
||||
intval($channel['channel_id'])
|
||||
@@ -388,10 +403,10 @@ class Import extends \Zotlabs\Web\Controller {
|
||||
foreach($r as $rr) {
|
||||
$saved[$rr['hash']]['new'] = $rr['id'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// import group members
|
||||
$group_members = $data['group_member'];
|
||||
if($group_members) {
|
||||
foreach($group_members as $group_member) {
|
||||
@@ -401,36 +416,36 @@ class Import extends \Zotlabs\Web\Controller {
|
||||
if($x['old'] == $group_member['gid'])
|
||||
$group_member['gid'] = $x['new'];
|
||||
}
|
||||
create_table_from_array('group_member',$group_member);
|
||||
create_table_from_array('group_member', $group_member);
|
||||
}
|
||||
}
|
||||
|
||||
logger('import step 9');
|
||||
|
||||
|
||||
if(is_array($data['obj']))
|
||||
import_objs($channel,$data['obj']);
|
||||
|
||||
|
||||
if(is_array($data['likes']))
|
||||
import_likes($channel,$data['likes']);
|
||||
|
||||
|
||||
if(is_array($data['app']))
|
||||
import_apps($channel,$data['app']);
|
||||
|
||||
|
||||
if(is_array($data['chatroom']))
|
||||
import_chatrooms($channel,$data['chatroom']);
|
||||
|
||||
|
||||
if(is_array($data['conv']))
|
||||
import_conv($channel,$data['conv']);
|
||||
|
||||
|
||||
if(is_array($data['mail']))
|
||||
import_mail($channel,$data['mail']);
|
||||
|
||||
|
||||
if(is_array($data['event']))
|
||||
import_events($channel,$data['event']);
|
||||
|
||||
|
||||
if(is_array($data['event_item']))
|
||||
import_items($channel,$data['event_item'],false,$relocate);
|
||||
|
||||
|
||||
if(is_array($data['menu']))
|
||||
import_menus($channel,$data['menu']);
|
||||
|
||||
@@ -439,56 +454,62 @@ class Import extends \Zotlabs\Web\Controller {
|
||||
|
||||
if(is_array($data['webpages']))
|
||||
import_items($channel,$data['webpages'],false,$relocate);
|
||||
|
||||
|
||||
$addon = array('channel' => $channel,'data' => $data);
|
||||
call_hooks('import_channel',$addon);
|
||||
|
||||
|
||||
$saved_notification_flags = notifications_off($channel['channel_id']);
|
||||
|
||||
|
||||
if($import_posts && array_key_exists('item',$data) && $data['item'])
|
||||
import_items($channel,$data['item'],false,$relocate);
|
||||
|
||||
|
||||
notifications_on($channel['channel_id'],$saved_notification_flags);
|
||||
|
||||
|
||||
|
||||
if(array_key_exists('item_id',$data) && $data['item_id'])
|
||||
import_item_ids($channel,$data['item_id']);
|
||||
|
||||
|
||||
// send out refresh requests
|
||||
// notify old server that it may no longer be primary.
|
||||
|
||||
|
||||
\Zotlabs\Daemon\Master::Summon(array('Notifier','location',$channel['channel_id']));
|
||||
|
||||
|
||||
// This will indirectly perform a refresh_all *and* update the directory
|
||||
|
||||
|
||||
\Zotlabs\Daemon\Master::Summon(array('Directory', $channel['channel_id']));
|
||||
|
||||
|
||||
|
||||
|
||||
notice( t('Import completed.') . EOL);
|
||||
|
||||
|
||||
change_channel($channel['channel_id']);
|
||||
|
||||
|
||||
goaway(z_root() . '/network' );
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Handle POST action on channel import page.
|
||||
*/
|
||||
function post() {
|
||||
|
||||
$account_id = get_account_id();
|
||||
if(! $account_id)
|
||||
return;
|
||||
|
||||
|
||||
check_form_security_token_redirectOnErr('/import', 'channel_import');
|
||||
|
||||
$this->import_account($account_id);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Generate channel import page.
|
||||
*
|
||||
* @return string with parsed HTML.
|
||||
*/
|
||||
function get() {
|
||||
|
||||
|
||||
if(! get_account_id()) {
|
||||
notice( t('You must be logged in to use this feature.'));
|
||||
notice( t('You must be logged in to use this feature.') . EOL);
|
||||
return '';
|
||||
}
|
||||
|
||||
|
||||
$o = replace_macros(get_markup_template('channel_import.tpl'),array(
|
||||
'$title' => t('Import Channel'),
|
||||
'$desc' => t('Use this form to import an existing channel from a different server/hub. You may retrieve the channel identity from the old server/hub via the network or provide an export file.'),
|
||||
@@ -501,14 +522,14 @@ class Import extends \Zotlabs\Web\Controller {
|
||||
'$label_import_primary' => t('Make this hub my primary location'),
|
||||
'$label_import_moving' => t('Move this channel (disable all previous locations)'),
|
||||
'$label_import_posts' => t('Import a few months of posts if possible (limited by available memory'),
|
||||
'$pleasewait' => t('This process may take several minutes to complete. Please submit the form only once and leave this page open until finished.'),
|
||||
'$pleasewait' => t('This process may take several minutes to complete. Please submit the form only once and leave this page open until finished.'),
|
||||
'$email' => '',
|
||||
'$pass' => '',
|
||||
'$form_security_token' => get_form_security_token('channel_import'),
|
||||
'$submit' => t('Submit')
|
||||
));
|
||||
|
||||
|
||||
return $o;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -3,54 +3,60 @@ namespace Zotlabs\Module;
|
||||
|
||||
require_once('include/import.php');
|
||||
|
||||
|
||||
/**
|
||||
* @brief Module for importing items.
|
||||
*
|
||||
* Import existing posts and content from an export file.
|
||||
*/
|
||||
class Import_items extends \Zotlabs\Web\Controller {
|
||||
|
||||
function post() {
|
||||
|
||||
|
||||
if(! local_channel())
|
||||
return;
|
||||
|
||||
|
||||
check_form_security_token_redirectOnErr('/import_items', 'import_items');
|
||||
|
||||
$data = null;
|
||||
|
||||
|
||||
$src = $_FILES['filename']['tmp_name'];
|
||||
$filename = basename($_FILES['filename']['name']);
|
||||
$filesize = intval($_FILES['filename']['size']);
|
||||
$filetype = $_FILES['filename']['type'];
|
||||
|
||||
|
||||
if($src) {
|
||||
// This is OS specific and could also fail if your tmpdir isn't very large
|
||||
// mostly used for Diaspora which exports gzipped files.
|
||||
|
||||
|
||||
if(strpos($filename,'.gz')){
|
||||
@rename($src,$src . '.gz');
|
||||
@system('gunzip ' . escapeshellarg($src . '.gz'));
|
||||
}
|
||||
|
||||
|
||||
if($filesize) {
|
||||
$data = @file_get_contents($src);
|
||||
}
|
||||
unlink($src);
|
||||
}
|
||||
|
||||
|
||||
if(! $src) {
|
||||
|
||||
|
||||
$old_address = ((x($_REQUEST,'old_address')) ? $_REQUEST['old_address'] : '');
|
||||
|
||||
|
||||
if(! $old_address) {
|
||||
logger('mod_import: nothing to import.');
|
||||
logger('Nothing to import.');
|
||||
notice( t('Nothing to import.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
$email = ((x($_REQUEST,'email')) ? $_REQUEST['email'] : '');
|
||||
$password = ((x($_REQUEST,'password')) ? $_REQUEST['password'] : '');
|
||||
|
||||
|
||||
$year = ((x($_REQUEST,'year')) ? $_REQUEST['year'] : '');
|
||||
|
||||
|
||||
$channelname = substr($old_address,0,strpos($old_address,'@'));
|
||||
$servername = substr($old_address,strpos($old_address,'@')+1);
|
||||
|
||||
|
||||
$scheme = 'https://';
|
||||
$api_path = '/api/red/channel/export/items?f=&channel=' . $channelname . '&year=' . intval($year);
|
||||
$binary = false;
|
||||
@@ -64,68 +70,66 @@ class Import_items extends \Zotlabs\Web\Controller {
|
||||
$data = $ret['body'];
|
||||
else
|
||||
notice( t('Unable to download data from old server') . EOL);
|
||||
|
||||
}
|
||||
|
||||
|
||||
if(! $data) {
|
||||
logger('mod_import: empty file.');
|
||||
logger('Empty file.');
|
||||
notice( t('Imported file is empty.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
$data = json_decode($data,true);
|
||||
|
||||
// logger('import: data: ' . print_r($data,true));
|
||||
// print_r($data);
|
||||
|
||||
|
||||
$data = json_decode($data, true);
|
||||
|
||||
//logger('import: data: ' . print_r($data,true));
|
||||
//print_r($data);
|
||||
|
||||
if(! is_array($data))
|
||||
return;
|
||||
|
||||
|
||||
if(array_key_exists('compatibility',$data) && array_key_exists('database',$data['compatibility'])) {
|
||||
$v1 = substr($data['compatibility']['database'],-4);
|
||||
$v2 = substr(DB_UPDATE_VERSION,-4);
|
||||
if($v2 > $v1) {
|
||||
$t = sprintf( t('Warning: Database versions differ by %1$d updates.'), $v2 - $v1 );
|
||||
notice($t);
|
||||
$t = sprintf( t('Warning: Database versions differ by %1$d updates.'), $v2 - $v1 );
|
||||
notice($t . EOL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$channel = \App::get_channel();
|
||||
|
||||
|
||||
|
||||
if(array_key_exists('item',$data) && $data['item']) {
|
||||
import_items($channel,$data['item'],false,((array_key_exists('relocate',$data)) ? $data['relocate'] : null));
|
||||
}
|
||||
|
||||
|
||||
if(array_key_exists('item_id',$data) && $data['item_id']) {
|
||||
import_item_ids($channel,$data['item_id']);
|
||||
}
|
||||
|
||||
|
||||
info( t('Import completed') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Generate item import page.
|
||||
*
|
||||
* @return string with parsed HTML.
|
||||
*/
|
||||
function get() {
|
||||
|
||||
|
||||
if(! local_channel()) {
|
||||
notice( t('Permission denied') . EOL);
|
||||
return login();
|
||||
}
|
||||
|
||||
$o = replace_macros(get_markup_template('item_import.tpl'),array(
|
||||
|
||||
$o = replace_macros(get_markup_template('item_import.tpl'), array(
|
||||
'$title' => t('Import Items'),
|
||||
'$desc' => t('Use this form to import existing posts and content from an export file.'),
|
||||
'$label_filename' => t('File to Upload'),
|
||||
'$form_security_token' => get_form_security_token('import_items'),
|
||||
'$submit' => t('Submit')
|
||||
));
|
||||
|
||||
|
||||
return $o;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ class Invite extends \Zotlabs\Web\Controller {
|
||||
if(! $recip)
|
||||
continue;
|
||||
|
||||
if(! valid_email($recip)) {
|
||||
if(! validate_email($recip)) {
|
||||
notice( sprintf( t('%s : Not a valid email address.'), $recip) . EOL);
|
||||
continue;
|
||||
}
|
||||
@@ -88,12 +88,14 @@ class Invite extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
|
||||
|
||||
function get() {
|
||||
function get() {
|
||||
|
||||
if(! local_channel()) {
|
||||
notice( t('Permission denied.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
nav_set_selected('Invite');
|
||||
|
||||
$tpl = get_markup_template('invite.tpl');
|
||||
$invonly = false;
|
||||
|
||||
@@ -33,7 +33,7 @@ class Item extends \Zotlabs\Web\Controller {
|
||||
// This will change. Figure out who the observer is and whether or not
|
||||
// they have permission to post here. Else ignore the post.
|
||||
|
||||
if((! local_channel()) && (! remote_channel()) && (! x($_REQUEST,'commenter')))
|
||||
if((! local_channel()) && (! remote_channel()) && (! x($_REQUEST,'anonname')))
|
||||
return;
|
||||
|
||||
$uid = local_channel();
|
||||
@@ -59,6 +59,7 @@ class Item extends \Zotlabs\Web\Controller {
|
||||
|
||||
$profile_uid = ((x($_REQUEST,'profile_uid')) ? intval($_REQUEST['profile_uid']) : 0);
|
||||
require_once('include/channel.php');
|
||||
|
||||
$sys = get_sys_channel();
|
||||
if($sys && $profile_uid && ($sys['channel_id'] == $profile_uid) && is_site_admin()) {
|
||||
$uid = intval($sys['channel_id']);
|
||||
@@ -77,7 +78,7 @@ class Item extends \Zotlabs\Web\Controller {
|
||||
|
||||
call_hooks('post_local_start', $_REQUEST);
|
||||
|
||||
// logger('postvars ' . print_r($_REQUEST,true), LOGGER_DATA);
|
||||
// logger('postvars ' . print_r($_REQUEST,true), LOGGER_DATA);
|
||||
|
||||
$api_source = ((x($_REQUEST,'api_source') && $_REQUEST['api_source']) ? true : false);
|
||||
|
||||
@@ -110,6 +111,7 @@ class Item extends \Zotlabs\Web\Controller {
|
||||
$preview = ((x($_REQUEST,'preview')) ? intval($_REQUEST['preview']) : 0);
|
||||
$categories = ((x($_REQUEST,'category')) ? escape_tags($_REQUEST['category']) : '');
|
||||
$webpage = ((x($_REQUEST,'webpage')) ? intval($_REQUEST['webpage']) : 0);
|
||||
$item_obscured = ((x($_REQUEST,'obscured')) ? intval($_REQUEST['obscured']) : 0);
|
||||
$pagetitle = ((x($_REQUEST,'pagetitle')) ? escape_tags(urlencode($_REQUEST['pagetitle'])) : '');
|
||||
$layout_mid = ((x($_REQUEST,'layout_mid')) ? escape_tags($_REQUEST['layout_mid']): '');
|
||||
$plink = ((x($_REQUEST,'permalink')) ? escape_tags($_REQUEST['permalink']) : '');
|
||||
@@ -154,7 +156,7 @@ class Item extends \Zotlabs\Web\Controller {
|
||||
if(! x($_REQUEST,'type'))
|
||||
$_REQUEST['type'] = 'net-comment';
|
||||
|
||||
if($obj_type == ACTIVITY_OBJ_POST)
|
||||
if($obj_type == ACTIVITY_OBJ_NOTE)
|
||||
$obj_type = ACTIVITY_OBJ_COMMENT;
|
||||
|
||||
if($parent) {
|
||||
@@ -170,7 +172,7 @@ class Item extends \Zotlabs\Web\Controller {
|
||||
);
|
||||
}
|
||||
// if this isn't the real parent of the conversation, find it
|
||||
if($r !== false && count($r)) {
|
||||
if($r) {
|
||||
$parid = $r[0]['parent'];
|
||||
$parent_mid = $r[0]['mid'];
|
||||
if($r[0]['id'] != $r[0]['parent']) {
|
||||
@@ -178,9 +180,16 @@ class Item extends \Zotlabs\Web\Controller {
|
||||
intval($parid)
|
||||
);
|
||||
}
|
||||
|
||||
// if interacting with a pubstream item,
|
||||
// create a copy of the parent in your stream
|
||||
|
||||
if($r[0]['uid'] === $sys['channel_id'] && local_channel()) {
|
||||
$r = [ copy_of_pubitem(\App::get_channel(), $r[0]['mid']) ];
|
||||
}
|
||||
}
|
||||
|
||||
if(($r === false) || (! count($r))) {
|
||||
|
||||
if(! $r) {
|
||||
notice( t('Unable to locate original post.') . EOL);
|
||||
if($api_source)
|
||||
return ( [ 'success' => false, 'message' => 'invalid post id' ] );
|
||||
@@ -188,15 +197,12 @@ class Item extends \Zotlabs\Web\Controller {
|
||||
goaway(z_root() . "/" . $return_path );
|
||||
killme();
|
||||
}
|
||||
|
||||
// can_comment_on_post() needs info from the following xchan_query
|
||||
// This may be from the discover tab which means we need to correct the effective uid
|
||||
|
||||
xchan_query($r,true,(($r[0]['uid'] == local_channel()) ? 0 : local_channel()));
|
||||
|
||||
xchan_query($r,true);
|
||||
|
||||
$parent_item = $r[0];
|
||||
$parent = $r[0]['id'];
|
||||
|
||||
|
||||
// multi-level threading - preserve the info but re-parent to our single level threading
|
||||
|
||||
$thr_parent = $parent_mid;
|
||||
@@ -204,10 +210,29 @@ class Item extends \Zotlabs\Web\Controller {
|
||||
$route = $parent_item['route'];
|
||||
|
||||
}
|
||||
|
||||
$moderated = false;
|
||||
|
||||
if(! $observer)
|
||||
if(! $observer) {
|
||||
$observer = \App::get_observer();
|
||||
if(! $observer) {
|
||||
$observer = anon_identity_init($_REQUEST);
|
||||
if($observer) {
|
||||
$moderated = true;
|
||||
$remote_xchan = $remote_observer = $observer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(! $observer) {
|
||||
notice( t('Permission denied.') . EOL) ;
|
||||
if($api_source)
|
||||
return ( [ 'success' => false, 'message' => 'permission denied' ] );
|
||||
if(x($_REQUEST,'return'))
|
||||
goaway(z_root() . "/" . $return_path );
|
||||
killme();
|
||||
}
|
||||
|
||||
if($parent) {
|
||||
logger('mod_item: item_post parent=' . $parent);
|
||||
$can_comment = false;
|
||||
@@ -311,7 +336,7 @@ class Item extends \Zotlabs\Web\Controller {
|
||||
$walltowall = false;
|
||||
$walltowall_comment = false;
|
||||
|
||||
if($remote_xchan)
|
||||
if($remote_xchan && ! $moderated)
|
||||
$observer = $remote_observer;
|
||||
|
||||
if($observer) {
|
||||
@@ -471,34 +496,16 @@ class Item extends \Zotlabs\Web\Controller {
|
||||
if(! $mimetype)
|
||||
$mimetype = 'text/bbcode';
|
||||
|
||||
|
||||
$execflag = ((intval($uid) == intval($profile_uid)
|
||||
&& ($channel['channel_pageflags'] & PAGE_ALLOWCODE)) ? true : false);
|
||||
|
||||
if($preview) {
|
||||
$body = z_input_filter($profile_uid,$body,$mimetype);
|
||||
$body = z_input_filter($body,$mimetype,$execflag);
|
||||
}
|
||||
|
||||
|
||||
// Verify ability to use html or php!!!
|
||||
|
||||
$execflag = false;
|
||||
|
||||
if($mimetype !== 'text/bbcode') {
|
||||
$z = q("select account_id, account_roles, channel_pageflags from account left join channel on channel_account_id = account_id where channel_id = %d limit 1",
|
||||
intval($profile_uid)
|
||||
);
|
||||
if($z && (($z[0]['account_roles'] & ACCOUNT_ROLE_ALLOWCODE) || ($z[0]['channel_pageflags'] & PAGE_ALLOWCODE))) {
|
||||
if($uid && (get_account_id() == $z[0]['account_id'])) {
|
||||
$execflag = true;
|
||||
}
|
||||
else {
|
||||
notice( t('Executable content type not permitted to this channel.') . EOL);
|
||||
if($api_source)
|
||||
return ( [ 'success' => false, 'message' => 'forbidden content type' ] );
|
||||
if(x($_REQUEST,'return'))
|
||||
goaway(z_root() . "/" . $return_path );
|
||||
killme();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$gacl = $acl->get();
|
||||
$str_contact_allow = $gacl['allow_cid'];
|
||||
$str_group_allow = $gacl['allow_gid'];
|
||||
@@ -509,48 +516,20 @@ class Item extends \Zotlabs\Web\Controller {
|
||||
|
||||
require_once('include/text.php');
|
||||
|
||||
// Markdown doesn't work correctly. Do not re-enable unless you're willing to fix it and support it.
|
||||
|
||||
// Sample that will probably give you grief - you must preserve the linebreaks
|
||||
// and provide the correct markdown interpretation and you cannot allow unfiltered HTML
|
||||
|
||||
// Markdown
|
||||
// ========
|
||||
//
|
||||
// **bold** abcde
|
||||
// fghijkl
|
||||
// *italic*
|
||||
// <img src="javascript:alert('hacked');" />
|
||||
|
||||
// if($uid && $uid == $profile_uid && feature_enabled($uid,'markdown')) {
|
||||
// require_once('include/markdown.php');
|
||||
// $body = escape_tags(trim($body));
|
||||
// $body = str_replace("\n",'<br />', $body);
|
||||
// $body = preg_replace_callback('/\[share(.*?)\]/ism','\share_shield',$body);
|
||||
// $body = markdown_to_bb($body,true);
|
||||
// $body = preg_replace_callback('/\[share(.*?)\]/ism','\share_unshield',$body);
|
||||
// }
|
||||
if($uid && $uid == $profile_uid && feature_enabled($uid,'markdown')) {
|
||||
require_once('include/markdown.php');
|
||||
$body = preg_replace_callback('/\[share(.*?)\]/ism','\share_shield',$body);
|
||||
$body = markdown_to_bb($body,true,['preserve_lf' => true]);
|
||||
$body = preg_replace_callback('/\[share(.*?)\]/ism','\share_unshield',$body);
|
||||
|
||||
}
|
||||
|
||||
// BBCODE alert: the following functions assume bbcode input
|
||||
// and will require alternatives for alternative content-types (text/html, text/markdown, text/plain, etc.)
|
||||
// we may need virtual or template classes to implement the possible alternatives
|
||||
|
||||
// Work around doubled linefeeds in Tinymce 3.5b2
|
||||
// First figure out if it's a status post that would've been
|
||||
// created using tinymce. Otherwise leave it alone.
|
||||
|
||||
$plaintext = true;
|
||||
|
||||
// $plaintext = ((feature_enabled($profile_uid,'richtext')) ? false : true);
|
||||
// if((! $parent) && (! $api_source) && (! $plaintext)) {
|
||||
// $body = fix_mce_lf($body);
|
||||
// }
|
||||
|
||||
|
||||
|
||||
|
||||
// If we're sending a private top-level message with a single @-taggable channel as a recipient, @-tag it, if our pconfig is set.
|
||||
|
||||
|
||||
|
||||
if((! $parent) && (get_pconfig($profile_uid,'system','tagifonlyrecip')) && (substr_count($str_contact_allow,'<') == 1) && ($str_group_allow == '') && ($str_contact_deny == '') && ($str_group_deny == '')) {
|
||||
$x = q("select abook_id, abconfig.v from abook left join abconfig on abook_xchan = abconfig.xchan and abook_channel = abconfig.chan and cat= 'their_perms' and abconfig.k = 'tag_deliver' and abconfig.v = 1 and abook_xchan = '%s' and abook_channel = %d limit 1",
|
||||
dbesc(str_replace(array('<','>'),array('',''),$str_contact_allow)),
|
||||
@@ -603,15 +582,6 @@ class Item extends \Zotlabs\Web\Controller {
|
||||
* so we'll set the permissions regardless and realise that the media may not be
|
||||
* referenced in the post.
|
||||
*
|
||||
* What is preventing us from being able to upload photos into comments is dealing with
|
||||
* the photo and attachment permissions, since we don't always know who was in the
|
||||
* distribution for the top level post.
|
||||
*
|
||||
* We might be able to provide this functionality with a lot of fiddling:
|
||||
* - if the top level post is public (make the photo public)
|
||||
* - if the top level post was written by us or a wall post that belongs to us (match the top level post)
|
||||
* - if the top level post has privacy mentions, add those to the permissions.
|
||||
* - otherwise disallow the photo *or* make the photo public. This is the part that gets messy.
|
||||
*/
|
||||
|
||||
if(! $preview) {
|
||||
@@ -632,7 +602,7 @@ class Item extends \Zotlabs\Web\Controller {
|
||||
$attach_link = '';
|
||||
$hash = substr($mtch,0,strpos($mtch,','));
|
||||
$rev = intval(substr($mtch,strpos($mtch,',')));
|
||||
$r = attach_by_hash_nodata($hash,$rev);
|
||||
$r = attach_by_hash_nodata($hash, $observer['xchan_hash'], $rev);
|
||||
if($r['success']) {
|
||||
$attachments[] = array(
|
||||
'href' => z_root() . '/attach/' . $r['data']['hash'],
|
||||
@@ -657,14 +627,26 @@ class Item extends \Zotlabs\Web\Controller {
|
||||
// BBCODE end alert
|
||||
|
||||
if(strlen($categories)) {
|
||||
|
||||
$cats = explode(',',$categories);
|
||||
foreach($cats as $cat) {
|
||||
|
||||
if($webpage == ITEM_TYPE_CARD) {
|
||||
$catlink = z_root() . '/cards/' . $channel['channel_address'] . '?f=&cat=' . urlencode(trim($cat));
|
||||
}
|
||||
elseif($webpage == ITEM_TYPE_ARTICLE) {
|
||||
$catlink = z_root() . '/articles/' . $channel['channel_address'] . '?f=&cat=' . urlencode(trim($cat));
|
||||
}
|
||||
else {
|
||||
$catlink = $owner_xchan['xchan_url'] . '?f=&cat=' . urlencode(trim($cat));
|
||||
}
|
||||
|
||||
$post_tags[] = array(
|
||||
'uid' => $profile_uid,
|
||||
'ttype' => TERM_CATEGORY,
|
||||
'otype' => TERM_OBJ_POST,
|
||||
'term' => trim($cat),
|
||||
'url' => $owner_xchan['xchan_url'] . '?f=&cat=' . urlencode(trim($cat))
|
||||
'url' => $catlink
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -683,7 +665,7 @@ class Item extends \Zotlabs\Web\Controller {
|
||||
foreach($t as $t1) {
|
||||
$post_tags[] = array(
|
||||
'uid' => $profile_uid,
|
||||
'ttype' => $t1['type'],
|
||||
'ttype' => $t1['ttype'],
|
||||
'otype' => TERM_OBJ_POST,
|
||||
'term' => $t1['term'],
|
||||
'url' => $t1['url'],
|
||||
@@ -732,7 +714,9 @@ class Item extends \Zotlabs\Web\Controller {
|
||||
|
||||
if($parent_item)
|
||||
$parent_mid = $parent_item['mid'];
|
||||
|
||||
|
||||
|
||||
|
||||
// Fallback so that we alway have a thr_parent
|
||||
|
||||
if(!$thr_parent)
|
||||
@@ -742,6 +726,33 @@ class Item extends \Zotlabs\Web\Controller {
|
||||
|
||||
$item_thread_top = ((! $parent) ? 1 : 0);
|
||||
|
||||
|
||||
// fix permalinks for cards
|
||||
|
||||
if($webpage == ITEM_TYPE_CARD) {
|
||||
$plink = z_root() . '/cards/' . $channel['channel_address'] . '/' . (($pagetitle) ? $pagetitle : substr($mid,0,16));
|
||||
}
|
||||
if(($parent_item) && ($parent_item['item_type'] == ITEM_TYPE_CARD)) {
|
||||
$r = q("select v from iconfig where iconfig.cat = 'system' and iconfig.k = 'CARD' and iconfig.iid = %d limit 1",
|
||||
intval($parent_item['id'])
|
||||
);
|
||||
if($r) {
|
||||
$plink = z_root() . '/cards/' . $channel['channel_address'] . '/' . $r[0]['v'];
|
||||
}
|
||||
}
|
||||
|
||||
if($webpage == ITEM_TYPE_ARTICLE) {
|
||||
$plink = z_root() . '/articles/' . $channel['channel_address'] . '/' . (($pagetitle) ? $pagetitle : substr($mid,0,16));
|
||||
}
|
||||
if(($parent_item) && ($parent_item['item_type'] == ITEM_TYPE_ARTICLE)) {
|
||||
$r = q("select v from iconfig where iconfig.cat = 'system' and iconfig.k = 'ARTICLE' and iconfig.iid = %d limit 1",
|
||||
intval($parent_item['id'])
|
||||
);
|
||||
if($r) {
|
||||
$plink = z_root() . '/articles/' . $channel['channel_address'] . '/' . $r[0]['v'];
|
||||
}
|
||||
}
|
||||
|
||||
if ((! $plink) && ($item_thread_top)) {
|
||||
$plink = z_root() . '/channel/' . $channel['channel_address'] . '/?f=&mid=' . $mid;
|
||||
}
|
||||
@@ -816,7 +827,7 @@ class Item extends \Zotlabs\Web\Controller {
|
||||
$datarray['owner'] = $owner_xchan;
|
||||
$datarray['author'] = $observer;
|
||||
$datarray['attach'] = json_encode($datarray['attach']);
|
||||
$o = conversation($a,array($datarray),'search',false,'preview');
|
||||
$o = conversation(array($datarray),'search',false,'preview');
|
||||
// logger('preview: ' . $o, LOGGER_DEBUG);
|
||||
echo json_encode(array('preview' => $o));
|
||||
killme();
|
||||
@@ -859,20 +870,8 @@ class Item extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
|
||||
|
||||
if(mb_strlen($datarray['title']) > 255)
|
||||
$datarray['title'] = mb_substr($datarray['title'],0,255);
|
||||
|
||||
if(array_key_exists('item_private',$datarray) && $datarray['item_private']) {
|
||||
|
||||
$datarray['body'] = trim(z_input_filter($datarray['uid'],$datarray['body'],$datarray['mimetype']));
|
||||
|
||||
if($uid) {
|
||||
if($channel['channel_hash'] === $datarray['author_xchan']) {
|
||||
$datarray['sig'] = base64url_encode(rsa_sign($datarray['body'],$channel['channel_prvkey']));
|
||||
$datarray['item_verified'] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(mb_strlen($datarray['title']) > 191)
|
||||
$datarray['title'] = mb_substr($datarray['title'],0,191);
|
||||
|
||||
if($webpage) {
|
||||
Zlib\IConfig::Set($datarray,'system', webpage_to_namespace($webpage),
|
||||
@@ -889,7 +888,17 @@ class Item extends \Zotlabs\Web\Controller {
|
||||
|
||||
$x = item_store_update($datarray,$execflag);
|
||||
|
||||
item_create_edit_activity($x);
|
||||
// We only need edit activities for other federated protocols
|
||||
// which do not support edits natively. While this does federate
|
||||
// edits, it presents a number of issues locally - such as #757 and #758.
|
||||
// The SQL check for an edit activity would not perform that well so to fix these issues
|
||||
// requires an additional item flag (perhaps 'item_edit_activity') that we can add to the
|
||||
// query for searches and notifications.
|
||||
|
||||
// For now we'll just forget about trying to make edits work on network protocols that
|
||||
// don't support them.
|
||||
|
||||
// item_create_edit_activity($x);
|
||||
|
||||
if(! $parent) {
|
||||
$r = q("select * from item where id = %d",
|
||||
@@ -928,6 +937,11 @@ class Item extends \Zotlabs\Web\Controller {
|
||||
|
||||
if($parent) {
|
||||
|
||||
// prevent conversations which you are involved from being expired
|
||||
|
||||
if(local_channel())
|
||||
retain_item($parent);
|
||||
|
||||
// only send comment notification if this is a wall-to-wall comment,
|
||||
// otherwise it will happen during delivery
|
||||
|
||||
@@ -1015,6 +1029,10 @@ class Item extends \Zotlabs\Web\Controller {
|
||||
\Zotlabs\Daemon\Master::Summon(array('Notifier', $notify_type, $post_id));
|
||||
|
||||
logger('post_complete');
|
||||
|
||||
if($moderated) {
|
||||
info(t('Your comment is awaiting approval.') . EOL);
|
||||
}
|
||||
|
||||
// figure out how to return, depending on from whence we came
|
||||
|
||||
@@ -1070,21 +1088,28 @@ class Item extends \Zotlabs\Web\Controller {
|
||||
|
||||
// if this is a different page type or it's just a local delete
|
||||
// but not by the item author or owner, do a simple deletion
|
||||
|
||||
|
||||
$complex = false;
|
||||
|
||||
if(intval($i[0]['item_type']) || ($local_delete && (! $can_delete))) {
|
||||
drop_item($i[0]['id']);
|
||||
}
|
||||
else {
|
||||
// complex deletion that needs to propagate and be performed in phases
|
||||
drop_item($i[0]['id'],true,DROPITEM_PHASE1);
|
||||
$r = q("select * from item where id = %d",
|
||||
intval($i[0]['id'])
|
||||
);
|
||||
if($r) {
|
||||
xchan_query($r);
|
||||
$sync_item = fetch_post_tags($r);
|
||||
build_sync_packet($i[0]['uid'],array('item' => array(encode_item($sync_item[0],true))));
|
||||
}
|
||||
$complex = true;
|
||||
}
|
||||
|
||||
$r = q("select * from item where id = %d",
|
||||
intval($i[0]['id'])
|
||||
);
|
||||
if($r) {
|
||||
xchan_query($r);
|
||||
$sync_item = fetch_post_tags($r);
|
||||
build_sync_packet($i[0]['uid'],array('item' => array(encode_item($sync_item[0],true))));
|
||||
}
|
||||
|
||||
if($complex) {
|
||||
tag_deliver($i[0]['uid'],$i[0]['id']);
|
||||
}
|
||||
}
|
||||
@@ -1114,7 +1139,29 @@ class Item extends \Zotlabs\Web\Controller {
|
||||
$ret['message'] = t('Unable to obtain post information from database.');
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
// auto-upgrade beginner (techlevel 0) accounts - if they have at least two friends and ten posts
|
||||
// and have uploaded something (like a profile photo), promote them to level 1.
|
||||
|
||||
$a = q("select account_id, account_level from account where account_id = (select channel_account_id from channel where channel_id = %d limit 1)",
|
||||
intval($channel_id)
|
||||
);
|
||||
if((! intval($a[0]['account_level'])) && intval($r[0]['total']) > 10) {
|
||||
$x = q("select count(abook_id) as total from abook where abook_channel = %d",
|
||||
intval($channel_id)
|
||||
);
|
||||
if($x && intval($x[0]['total']) > 2) {
|
||||
$y = q("select count(id) as total from attach where uid = %d",
|
||||
intval($channel_id)
|
||||
);
|
||||
if($y && intval($y[0]['total']) > 1) {
|
||||
q("update account set account_level = 1 where account_id = %d limit 1",
|
||||
intval($a[0]['account_id'])
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!$iswebpage) {
|
||||
$max = engr_units_to_bytes(service_class_fetch($channel_id,'total_items'));
|
||||
if(! service_class_allows($channel_id,'total_items',$r[0]['total'])) {
|
||||
|
||||
@@ -5,6 +5,7 @@ namespace Zotlabs\Module;
|
||||
class Lang extends \Zotlabs\Web\Controller {
|
||||
|
||||
function get() {
|
||||
nav_set_selected('Language');
|
||||
return lang_selector();
|
||||
}
|
||||
|
||||
|
||||
@@ -125,6 +125,7 @@ class Layouts extends \Zotlabs\Web\Controller {
|
||||
'hide_weblink' => true,
|
||||
'hide_attach' => true,
|
||||
'hide_preview' => true,
|
||||
'disable_comments' => true,
|
||||
'ptlabel' => t('Layout Name'),
|
||||
'profile_uid' => intval($owner),
|
||||
'expanded' => true,
|
||||
@@ -161,12 +162,12 @@ class Layouts extends \Zotlabs\Web\Controller {
|
||||
'created' => $rr['created'],
|
||||
'edited' => $rr['edited'],
|
||||
'mimetype' => $rr['mimetype'],
|
||||
'pagetitle' => $rr['sid'],
|
||||
'pagetitle' => urldecode($rr['v']),
|
||||
'mid' => $rr['mid']
|
||||
);
|
||||
$pages[$rr['iid']][] = array(
|
||||
'url' => $rr['iid'],
|
||||
'title' => $rr['v'],
|
||||
'title' => urldecode($rr['v']),
|
||||
'descr' => $rr['title'],
|
||||
'mid' => $rr['mid'],
|
||||
'created' => $rr['created'],
|
||||
|
||||
@@ -12,7 +12,10 @@ class Like extends \Zotlabs\Web\Controller {
|
||||
function get() {
|
||||
|
||||
$o = '';
|
||||
|
||||
|
||||
$sys_channel = get_sys_channel();
|
||||
$sys_channel_id = (($sys_channel) ? $sys_channel['channel_id'] : 0);
|
||||
|
||||
$observer = \App::get_observer();
|
||||
$interactive = $_REQUEST['interactive'];
|
||||
if($interactive) {
|
||||
@@ -253,20 +256,29 @@ class Like extends \Zotlabs\Web\Controller {
|
||||
logger('like: verb ' . $verb . ' item ' . $item_id, LOGGER_DEBUG);
|
||||
|
||||
// get the item. Allow linked photos (which are normally hidden) to be liked
|
||||
|
||||
|
||||
$r = q("SELECT * FROM item WHERE id = %d
|
||||
and item_type = 0 and item_deleted = 0 and item_unpublished = 0
|
||||
and item_type in (0,6,7) and item_deleted = 0 and item_unpublished = 0
|
||||
and item_delayed = 0 and item_pending_remove = 0 and item_blocked = 0 LIMIT 1",
|
||||
intval($item_id)
|
||||
);
|
||||
|
||||
|
||||
// if interacting with a pubstream item,
|
||||
// create a copy of the parent in your stream. If not the conversation
|
||||
// parent, copy that as well.
|
||||
|
||||
if($r) {
|
||||
if($r[0]['uid'] === $sys_channel['channel_id'] && local_channel()) {
|
||||
$r = [ copy_of_pubitem(\App::get_channel(), $r[0]['mid']) ];
|
||||
}
|
||||
}
|
||||
|
||||
if(! $item_id || (! $r)) {
|
||||
logger('like: no item ' . $item_id);
|
||||
killme();
|
||||
}
|
||||
|
||||
|
||||
xchan_query($r,true,(($r[0]['uid'] == local_channel()) ? 0 : local_channel()));
|
||||
xchan_query($r,true);
|
||||
|
||||
$item = $r[0];
|
||||
|
||||
@@ -373,6 +385,10 @@ class Like extends \Zotlabs\Web\Controller {
|
||||
|
||||
$links = array(array('rel' => 'alternate','type' => 'text/html', 'href' => $item['plink']));
|
||||
$objtype = (($item['resource_type'] === 'photo') ? ACTIVITY_OBJ_PHOTO : ACTIVITY_OBJ_NOTE );
|
||||
|
||||
if($objtype === ACTIVITY_OBJ_NOTE && (! intval($item['item_thread_top'])))
|
||||
$objtype = ACTIVITY_OBJ_COMMENT;
|
||||
|
||||
|
||||
$body = $item['body'];
|
||||
|
||||
@@ -460,6 +476,8 @@ class Like extends \Zotlabs\Web\Controller {
|
||||
$arr['mid'] = $mid;
|
||||
$arr['aid'] = (($extended_like) ? $ch[0]['channel_account_id'] : $owner_aid);
|
||||
$arr['uid'] = $owner_uid;
|
||||
|
||||
|
||||
$arr['item_flags'] = $item_flags;
|
||||
$arr['item_wall'] = $item_wall;
|
||||
$arr['parent_mid'] = (($extended_like) ? $mid : $item['mid']);
|
||||
@@ -500,6 +518,11 @@ class Like extends \Zotlabs\Web\Controller {
|
||||
|
||||
$post = item_store($arr);
|
||||
$post_id = $post['item_id'];
|
||||
|
||||
// save the conversation from expiration
|
||||
|
||||
if(local_channel() && array_key_exists('item',$post) && (intval($post['item']['id']) != intval($post['item']['parent'])))
|
||||
retain_item($post['item']['parent']);
|
||||
|
||||
$arr['id'] = $post_id;
|
||||
|
||||
|
||||
@@ -95,7 +95,7 @@ class Linkinfo extends \Zotlabs\Web\Controller {
|
||||
echo $arr['text'];
|
||||
killme();
|
||||
}
|
||||
|
||||
|
||||
if($process_oembed) {
|
||||
$x = oembed_process($url);
|
||||
if($x) {
|
||||
|
||||
@@ -72,7 +72,7 @@ class Lockview extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
|
||||
if($uid != local_channel()) {
|
||||
echo '<li>' . t('Remote privacy information not available.') . '</li>';
|
||||
echo '<div class="dropdown-item">' . t('Remote privacy information not available.') . '</div>';
|
||||
killme();
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@ class Lockview extends \Zotlabs\Web\Controller {
|
||||
// as unknown specific recipients. The sender will have the visibility list and will fall through to the
|
||||
// next section.
|
||||
|
||||
echo '<li>' . translate_scope((! $item['public_policy']) ? 'specific' : $item['public_policy']) . '</li>';
|
||||
echo '<div class="dropdown-item">' . translate_scope((! $item['public_policy']) ? 'specific' : $item['public_policy']) . '</div>';
|
||||
killme();
|
||||
}
|
||||
|
||||
@@ -93,7 +93,7 @@ class Lockview extends \Zotlabs\Web\Controller {
|
||||
$deny_users = expand_acl($item['deny_cid']);
|
||||
$deny_groups = expand_acl($item['deny_gid']);
|
||||
|
||||
$o = '<li>' . t('Visible to:') . '</li>';
|
||||
$o = '<div class="dropdown-item">' . t('Visible to:') . '</div>';
|
||||
$l = array();
|
||||
|
||||
stringify_array_elms($allowed_groups,true);
|
||||
@@ -114,24 +114,24 @@ class Lockview extends \Zotlabs\Web\Controller {
|
||||
$r = q("SELECT profile_name FROM profile WHERE profile_guid IN ( " . implode(', ', $profile_groups) . " )");
|
||||
if($r)
|
||||
foreach($r as $rr)
|
||||
$l[] = '<li><b>' . t('Profile','acl') . ' ' . $rr['profile_name'] . '</b></li>';
|
||||
$l[] = '<div class="dropdown-item"><b>' . t('Profile','acl') . ' ' . $rr['profile_name'] . '</b></div>';
|
||||
}
|
||||
|
||||
if(count($allowed_groups)) {
|
||||
$r = q("SELECT gname FROM groups WHERE hash IN ( " . implode(', ', $allowed_groups) . " )");
|
||||
if($r)
|
||||
foreach($r as $rr)
|
||||
$l[] = '<li><b>' . $rr['gname'] . '</b></li>';
|
||||
$l[] = '<div class="dropdown-item"><b>' . $rr['gname'] . '</b></div>';
|
||||
}
|
||||
if(count($allowed_users)) {
|
||||
$r = q("SELECT xchan_name FROM xchan WHERE xchan_hash IN ( " . implode(', ',$allowed_users) . " )");
|
||||
if($r)
|
||||
foreach($r as $rr)
|
||||
$l[] = '<li>' . $rr['xchan_name'] . '</li>';
|
||||
$l[] = '<div class="dropdown-item">' . $rr['xchan_name'] . '</div>';
|
||||
if($atokens) {
|
||||
foreach($atokens as $at) {
|
||||
if(in_array("'" . $at['xchan_hash'] . "'",$allowed_users)) {
|
||||
$l[] = '<li>' . $at['xchan_name'] . '</li>';
|
||||
$l[] = '<div class="dropdown-item">' . $at['xchan_name'] . '</div>';
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -150,7 +150,7 @@ class Lockview extends \Zotlabs\Web\Controller {
|
||||
$r = q("SELECT profile_name FROM profile WHERE profile_guid IN ( " . implode(', ', $profile_groups) . " )");
|
||||
if($r)
|
||||
foreach($r as $rr)
|
||||
$l[] = '<li><b><strike>' . t('Profile','acl') . ' ' . $rr['profile_name'] . '</strike></b></li>';
|
||||
$l[] = '<div class="dropdown-item"><b><strike>' . t('Profile','acl') . ' ' . $rr['profile_name'] . '</strike></b></div>';
|
||||
}
|
||||
|
||||
|
||||
@@ -159,18 +159,18 @@ class Lockview extends \Zotlabs\Web\Controller {
|
||||
$r = q("SELECT gname FROM groups WHERE hash IN ( " . implode(', ', $deny_groups) . " )");
|
||||
if($r)
|
||||
foreach($r as $rr)
|
||||
$l[] = '<li><b><strike>' . $rr['gname'] . '</strike></b></li>';
|
||||
$l[] = '<div class="dropdown-item"><b><strike>' . $rr['gname'] . '</strike></b></div>';
|
||||
}
|
||||
if(count($deny_users)) {
|
||||
$r = q("SELECT xchan_name FROM xchan WHERE xchan_hash IN ( " . implode(', ', $deny_users) . " )");
|
||||
if($r)
|
||||
foreach($r as $rr)
|
||||
$l[] = '<li><strike>' . $rr['xchan_name'] . '</strike></li>';
|
||||
$l[] = '<div class="dropdown-item"><strike>' . $rr['xchan_name'] . '</strike></div>';
|
||||
|
||||
if($atokens) {
|
||||
foreach($atokens as $at) {
|
||||
if(in_array("'" . $at['xchan_hash'] . "'",$deny_users)) {
|
||||
$l[] = '<li><strike>' . $at['xchan_name'] . '</strike></li>';
|
||||
$l[] = '<div class="dropdown-item"><strike>' . $at['xchan_name'] . '</strike></div>';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user