mirror of
https://framagit.org/hubzilla/core.git
synced 2026-06-21 17:07:39 -04:00
Compare commits
612 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a29c0371f1 | ||
|
|
a8f7af2079 | ||
|
|
7ae7fac234 | ||
|
|
d1fb4e9b03 | ||
|
|
ed0bff798b | ||
|
|
3f0bb1bb1d | ||
|
|
9a0b61e4af | ||
|
|
b81291cd5c | ||
|
|
a8a0ca8291 | ||
|
|
1c61be4113 | ||
|
|
91cc365143 | ||
|
|
f4a27afee9 | ||
|
|
be654f1769 | ||
|
|
73628db7e2 | ||
|
|
571c72f853 | ||
|
|
b788b38edf | ||
|
|
09861abab7 | ||
|
|
202035fc68 | ||
|
|
5ab1d509d2 | ||
|
|
1b83d88fe6 | ||
|
|
482962648f | ||
|
|
326f3cfc85 | ||
|
|
4ba8526745 | ||
|
|
0269825bc0 | ||
|
|
5cb3143c04 | ||
|
|
d1a2aecfa0 | ||
|
|
0fe4957274 | ||
|
|
e9f1bac062 | ||
|
|
58692e3565 | ||
|
|
7db733c9a0 | ||
|
|
abfbe9c937 | ||
|
|
f437705007 | ||
|
|
46ed79c87a | ||
|
|
e2b4d33627 | ||
|
|
7690dca67b | ||
|
|
c0bdcfedeb | ||
|
|
9b66b5eee3 | ||
|
|
2db59f3b76 | ||
|
|
44e21f6198 | ||
|
|
279f32b13d | ||
|
|
3a6187af3d | ||
|
|
516f776c94 | ||
|
|
cc62793d6f | ||
|
|
d87daaedd1 | ||
|
|
cf84ff3344 | ||
|
|
e419b2c18c | ||
|
|
58324473a9 | ||
|
|
62d842de31 | ||
|
|
aa678ba0ff | ||
|
|
e4391e6336 | ||
|
|
aa0412d83b | ||
|
|
861f5232d3 | ||
|
|
9831ad515d | ||
|
|
6650916435 | ||
|
|
64cc0b794a | ||
|
|
29363a185d | ||
|
|
e41082dccc | ||
|
|
97ccbf1bfb | ||
|
|
a20ef706fd | ||
|
|
adad8f2ebc | ||
|
|
0533db5d38 | ||
|
|
fb9c12df15 | ||
|
|
5a2a8717e3 | ||
|
|
0d50d29538 | ||
|
|
54aa998b52 | ||
|
|
10f1e2d51b | ||
|
|
9fd8634b62 | ||
|
|
fd07940b10 | ||
|
|
6f6051f7e3 | ||
|
|
f9778fda83 | ||
|
|
ea3fb53e4b | ||
|
|
a7d5bf6854 | ||
|
|
0e7a963173 | ||
|
|
4aa2733699 | ||
|
|
1eb6067c31 | ||
|
|
bd29551f9a | ||
|
|
32ccdd1f57 | ||
|
|
deaf0e99fd | ||
|
|
d99a1d8de0 | ||
|
|
0012030826 | ||
|
|
ec41170121 | ||
|
|
1d5ea5efae | ||
|
|
01ad485f65 | ||
|
|
447c59fd9b | ||
|
|
3de40bdf04 | ||
|
|
ba6c346b46 | ||
|
|
1c9f773900 | ||
|
|
ec651f219e | ||
|
|
ee8a9384d5 | ||
|
|
bba34a7a8e | ||
|
|
dfa12b2919 | ||
|
|
9b9f29a0b2 | ||
|
|
4a9aad2a33 | ||
|
|
69617b5c34 | ||
|
|
222ace3770 | ||
|
|
2e7d2a63c3 | ||
|
|
0523b4b2f1 | ||
|
|
a703835b5c | ||
|
|
bf3f3564e0 | ||
|
|
102d41ccb9 | ||
|
|
cfad5ba8b8 | ||
|
|
b4c1baada1 | ||
|
|
1ca3eeedff | ||
|
|
298b53e93a | ||
|
|
f13096a6f3 | ||
|
|
470f14b919 | ||
|
|
53311a30ad | ||
|
|
5634a4bb61 | ||
|
|
738e14348d | ||
|
|
787e2ef961 | ||
|
|
db4e9aeaad | ||
|
|
7850b04853 | ||
|
|
b6f18a9a0b | ||
|
|
b8d8be7013 | ||
|
|
84feff9500 | ||
|
|
81ba293561 | ||
|
|
8b3c099a12 | ||
|
|
2772a72095 | ||
|
|
e361ee9253 | ||
|
|
3edd4ce78f | ||
|
|
381cc3e6f8 | ||
|
|
d09694587d | ||
|
|
63451db3f6 | ||
|
|
7660afdb0f | ||
|
|
72d995d35f | ||
|
|
2a32df75f1 | ||
|
|
e16da7a166 | ||
|
|
5b55726a93 | ||
|
|
bbe93d0e1d | ||
|
|
5dd422e2d8 | ||
|
|
a564f495a7 | ||
|
|
995555f357 | ||
|
|
40f3857691 | ||
|
|
5d884c2f3d | ||
|
|
8f006a98c4 | ||
|
|
ebac0bdcca | ||
|
|
3575ef8a39 | ||
|
|
60bb8f25f7 | ||
|
|
2d3dd673e4 | ||
|
|
9d47de65d9 | ||
|
|
c6d9100649 | ||
|
|
44283dbbbb | ||
|
|
0cda431456 | ||
|
|
bbfe4de310 | ||
|
|
36b388ab8c | ||
|
|
c0b3d7e1b4 | ||
|
|
9abd95fad3 | ||
|
|
50d9b29347 | ||
|
|
90a5ba01a3 | ||
|
|
6c2673ae2a | ||
|
|
256c228efd | ||
|
|
3fdd110e07 | ||
|
|
1cd3b41825 | ||
|
|
4148211086 | ||
|
|
4ba9a5ef75 | ||
|
|
6a6dbec033 | ||
|
|
df891f4ad2 | ||
|
|
08461c7049 | ||
|
|
5462453bf2 | ||
|
|
e4f3605054 | ||
|
|
f65ede9c38 | ||
|
|
a6ad37c691 | ||
|
|
ba0812c447 | ||
|
|
dbde9a0940 | ||
|
|
d3f38c9f43 | ||
|
|
971e7321c6 | ||
|
|
eeb1c463e3 | ||
|
|
99d9456b3a | ||
|
|
97eef2b88c | ||
|
|
c25ef1d9a8 | ||
|
|
661b0084f3 | ||
|
|
f714e97d63 | ||
|
|
a507063174 | ||
|
|
3caf51b075 | ||
|
|
92ec46b62e | ||
|
|
9b06d952a2 | ||
|
|
531710142c | ||
|
|
59827b6dfd | ||
|
|
61bef7d4b0 | ||
|
|
f200dd4395 | ||
|
|
a8ac0ed549 | ||
|
|
6f2ba0c619 | ||
|
|
0a14ac1f60 | ||
|
|
02140b2f76 | ||
|
|
c6b89b99b9 | ||
|
|
51a840f46a | ||
|
|
b081c3e94b | ||
|
|
ec99e3ed62 | ||
|
|
97e1a6dfde | ||
|
|
56c86b6567 | ||
|
|
28599fe652 | ||
|
|
d3e7ef70e8 | ||
|
|
fea532af4d | ||
|
|
f5b22dfd5b | ||
|
|
48e62bb50a | ||
|
|
513078e1f7 | ||
|
|
23151100de | ||
|
|
eb68b66c58 | ||
|
|
1ddb43b0d3 | ||
|
|
9fcd470aca | ||
|
|
23419e4c26 | ||
|
|
34b42566b6 | ||
|
|
f7ff48f806 | ||
|
|
30cf56bdb5 | ||
|
|
77094f8d2b | ||
|
|
51cd4e8519 | ||
|
|
bd249b276d | ||
|
|
b6ae2bff01 | ||
|
|
21c1f89eba | ||
|
|
df61970b39 | ||
|
|
f82afca84d | ||
|
|
eca119d695 | ||
|
|
40162cd6b7 | ||
|
|
a41a05e6c0 | ||
|
|
a83cdbeb39 | ||
|
|
6d4fe5c56f | ||
|
|
3a8f6e6576 | ||
|
|
38eb79705e | ||
|
|
f7ddd44c2e | ||
|
|
2165733ddc | ||
|
|
d22b21c56f | ||
|
|
4188419b30 | ||
|
|
d98d7003ed | ||
|
|
1692380ac7 | ||
|
|
01a28ddf8d | ||
|
|
e8d19659c0 | ||
|
|
b673b6835d | ||
|
|
ef7494359f | ||
|
|
b8e8517725 | ||
|
|
def0454952 | ||
|
|
2f5862713e | ||
|
|
6729c27b77 | ||
|
|
fbfa391965 | ||
|
|
38beabb508 | ||
|
|
a8d5c83251 | ||
|
|
370a007ee2 | ||
|
|
7747a23a78 | ||
|
|
c573670821 | ||
|
|
a752d44313 | ||
|
|
9406ff714b | ||
|
|
cc29e27acc | ||
|
|
b2563528ee | ||
|
|
70ad69d38c | ||
|
|
cb0c43bc68 | ||
|
|
7efffbf102 | ||
|
|
2d8deb6082 | ||
|
|
5de79cdb10 | ||
|
|
6837c2ef1e | ||
|
|
4e9440396c | ||
|
|
32c23ef562 | ||
|
|
107f80892a | ||
|
|
fbcb711945 | ||
|
|
e95a494041 | ||
|
|
7732532964 | ||
|
|
bb09b8a385 | ||
|
|
b9b46a3f88 | ||
|
|
7bb461380e | ||
|
|
f5f79b39b8 | ||
|
|
14e55e8bd6 | ||
|
|
bc9d5f5a48 | ||
|
|
c2cdd41e81 | ||
|
|
256cd6baac | ||
|
|
843cc1481a | ||
|
|
cf4dc2caa8 | ||
|
|
1258f9bb21 | ||
|
|
5f41d06bb9 | ||
|
|
8f4fe106ef | ||
|
|
d74274c7e4 | ||
|
|
d59268a5d8 | ||
|
|
f364343b55 | ||
|
|
9debfa348a | ||
|
|
32e903e956 | ||
|
|
bd8fe768d3 | ||
|
|
848c038970 | ||
|
|
24fa201218 | ||
|
|
1a77fb4c1d | ||
|
|
76467b5a35 | ||
|
|
d5db25808a | ||
|
|
6824fb9f93 | ||
|
|
b2216f8203 | ||
|
|
0799a0a3be | ||
|
|
a2e0574fce | ||
|
|
68d7ab6b55 | ||
|
|
4a2c805270 | ||
|
|
7d5b266227 | ||
|
|
1f56ff5407 | ||
|
|
95f5f3d44d | ||
|
|
7a5213cc8e | ||
|
|
f1f19372ad | ||
|
|
276f44328e | ||
|
|
da3f1326e0 | ||
|
|
a013ddbb91 | ||
|
|
1c6faa3a00 | ||
|
|
b7f15ccac1 | ||
|
|
1fb7b9baae | ||
|
|
a1e4940bea | ||
|
|
287ffe93f6 | ||
|
|
2407379623 | ||
|
|
7162403292 | ||
|
|
004468f231 | ||
|
|
2d7e307e74 | ||
|
|
d7466ade46 | ||
|
|
01c0e5c46c | ||
|
|
86f840843f | ||
|
|
9a0f0181a5 | ||
|
|
25ebac8d0b | ||
|
|
edf6da7189 | ||
|
|
059da4d017 | ||
|
|
a59d1b22f6 | ||
|
|
dd4a66353a | ||
|
|
2cf54c465d | ||
|
|
d3491c9165 | ||
|
|
8ca877bdd3 | ||
|
|
b704f977da | ||
|
|
59e04aed1b | ||
|
|
436e91a1e1 | ||
|
|
6f4c45a489 | ||
|
|
157bbb14b5 | ||
|
|
5c22f59c4f | ||
|
|
aa62bad07b | ||
|
|
d3f2d2a2db | ||
|
|
c5d08fd5fd | ||
|
|
22729da2a2 | ||
|
|
c97cc1487c | ||
|
|
428b4dbad6 | ||
|
|
264abef817 | ||
|
|
548bf884a4 | ||
|
|
a0baa480e3 | ||
|
|
765dd5569b | ||
|
|
c19a1a6b82 | ||
|
|
8b61e546fe | ||
|
|
7206e8af3a | ||
|
|
7808689198 | ||
|
|
966d1586c0 | ||
|
|
edffd9f183 | ||
|
|
7edc505c2f | ||
|
|
4df78b06cf | ||
|
|
492609d20b | ||
|
|
0f76af261c | ||
|
|
9d00db06b2 | ||
|
|
141f3e21b2 | ||
|
|
fe6cbb414c | ||
|
|
e13d65eea3 | ||
|
|
4d6050f8e5 | ||
|
|
0ebce75c7d | ||
|
|
91bb4bdf50 | ||
|
|
be2b7c0b5f | ||
|
|
2d45f9f385 | ||
|
|
44b2503572 | ||
|
|
3f90da5643 | ||
|
|
d27a627c4f | ||
|
|
55ab5360d9 | ||
|
|
bfeeb76143 | ||
|
|
f2d3be2e67 | ||
|
|
60b818eb24 | ||
|
|
ebe70a41b9 | ||
|
|
da79662081 | ||
|
|
72f3f7c172 | ||
|
|
713a796d9f | ||
|
|
69c6d8b617 | ||
|
|
e084a85e79 | ||
|
|
a1f046992d | ||
|
|
cd5630476f | ||
|
|
f7f20c5917 | ||
|
|
44797fe988 | ||
|
|
c5333b5187 | ||
|
|
2d045a12bf | ||
|
|
a2fe22412f | ||
|
|
df69465357 | ||
|
|
e4361cb202 | ||
|
|
58cf9d832c | ||
|
|
cf5383fdbe | ||
|
|
6126070a1d | ||
|
|
459166116d | ||
|
|
776bc51172 | ||
|
|
df57c90d2d | ||
|
|
5a563b8e76 | ||
|
|
0653a2e0a9 | ||
|
|
d19dfc87a6 | ||
|
|
dc8c7a2d2e | ||
|
|
ba2ede0a8f | ||
|
|
6892ba4cd8 | ||
|
|
5ad9b48f1d | ||
|
|
7972de13ca | ||
|
|
ea54987ca4 | ||
|
|
b2474334a7 | ||
|
|
2a0d4a2011 | ||
|
|
be27fb5644 | ||
|
|
ebfa1a12b9 | ||
|
|
21f2df399d | ||
|
|
43521bb10b | ||
|
|
c95d7c69eb | ||
|
|
f12b0fe316 | ||
|
|
8944d7a7a2 | ||
|
|
6300f47cdc | ||
|
|
2b95580cc0 | ||
|
|
93b84f1262 | ||
|
|
1ffae1327f | ||
|
|
01a8292d65 | ||
|
|
9d3ce55978 | ||
|
|
7e6febe2a6 | ||
|
|
e73df9ed1d | ||
|
|
b101a8f6fb | ||
|
|
ddeab48f9b | ||
|
|
d074c53889 | ||
|
|
039eb58524 | ||
|
|
29c9e7c0a2 | ||
|
|
f15a06c0c2 | ||
|
|
ab89eb050a | ||
|
|
eca1f84328 | ||
|
|
3bde7b8f18 | ||
|
|
9db1148650 | ||
|
|
502fed198d | ||
|
|
411c510778 | ||
|
|
dd6e3d873d | ||
|
|
f9b092c619 | ||
|
|
edc7c0837b | ||
|
|
f535d438b2 | ||
|
|
119ffd2d2d | ||
|
|
2c3bec3d7c | ||
|
|
f1564b4cff | ||
|
|
c9252d49f7 | ||
|
|
411abdf8a7 | ||
|
|
1fcc863298 | ||
|
|
e37c1ed981 | ||
|
|
0c5a2925ad | ||
|
|
272ffe6983 | ||
|
|
368bb18935 | ||
|
|
22f172d697 | ||
|
|
fe9abcfaae | ||
|
|
dfbe2eaf98 | ||
|
|
a9711895cf | ||
|
|
8882ffc0de | ||
|
|
fdd7faab51 | ||
|
|
d004017b01 | ||
|
|
f2d27d543d | ||
|
|
1db3409f36 | ||
|
|
cfa2ac2d0a | ||
|
|
ebc66d7008 | ||
|
|
3f0eb84ecf | ||
|
|
fbc6c60805 | ||
|
|
02e82e496e | ||
|
|
8e586008dd | ||
|
|
50c7c33ed1 | ||
|
|
ca52d39abe | ||
|
|
28d07fd6b2 | ||
|
|
5a7b994e59 | ||
|
|
4512a4cdd4 | ||
|
|
342fda94e4 | ||
|
|
cc264b2d60 | ||
|
|
33c34984e6 | ||
|
|
fe392a3144 | ||
|
|
eeed7077ca | ||
|
|
dba1854837 | ||
|
|
c107bcfbd9 | ||
|
|
912ebfebff | ||
|
|
76bf892f9f | ||
|
|
12a9b49c6d | ||
|
|
aecf9e32ef | ||
|
|
879bc71927 | ||
|
|
4da7fcb41d | ||
|
|
3a84e7051e | ||
|
|
161050df07 | ||
|
|
29284319a5 | ||
|
|
86e73fd313 | ||
|
|
62e141a89c | ||
|
|
cd8b7687c1 | ||
|
|
4436cd9ade | ||
|
|
ddbe3c7426 | ||
|
|
b8c7b2f81d | ||
|
|
696c6e88ea | ||
|
|
a83eb14ff6 | ||
|
|
8e6dc0b66b | ||
|
|
41ec5403e1 | ||
|
|
77eb6c5761 | ||
|
|
89c6cda303 | ||
|
|
d49afead67 | ||
|
|
0a10215371 | ||
|
|
64f5d80ff2 | ||
|
|
28a593e1ce | ||
|
|
f738902107 | ||
|
|
364972a292 | ||
|
|
0eb0256502 | ||
|
|
679fb7d0d2 | ||
|
|
45247d1595 | ||
|
|
3be6ef6bfc | ||
|
|
c5827c8b4f | ||
|
|
bb381daae3 | ||
|
|
d0090f09fb | ||
|
|
afb86aa908 | ||
|
|
3b97a9f766 | ||
|
|
d3c779f635 | ||
|
|
4f285911f0 | ||
|
|
8ccddfefd9 | ||
|
|
4351a83d16 | ||
|
|
ddefe3b3ac | ||
|
|
b77c5ae61e | ||
|
|
dd2d12350c | ||
|
|
ade91f8190 | ||
|
|
d04aef4c44 | ||
|
|
689a6dc085 | ||
|
|
0b487122f6 | ||
|
|
ac4a8fde3a | ||
|
|
31aaf40ade | ||
|
|
af7c7642bb | ||
|
|
d939173c0e | ||
|
|
a87efe45e0 | ||
|
|
55515a25d1 | ||
|
|
7d7a254238 | ||
|
|
564a5ea4d5 | ||
|
|
d9c59a19fb | ||
|
|
83b5adf194 | ||
|
|
a26d1794fe | ||
|
|
06a1258a9a | ||
|
|
d31d3df4ea | ||
|
|
91801d2e2c | ||
|
|
95c686de6e | ||
|
|
bcb94f8238 | ||
|
|
1d2260b44e | ||
|
|
81c10fc739 | ||
|
|
191a2fd5be | ||
|
|
97be144913 | ||
|
|
8c99228c8a | ||
|
|
f984502499 | ||
|
|
315ce6d880 | ||
|
|
3da8f9b13c | ||
|
|
a14b87baf2 | ||
|
|
90fd23e0cd | ||
|
|
d96e985be0 | ||
|
|
c8788204a9 | ||
|
|
be99c7fe12 | ||
|
|
48963f62f9 | ||
|
|
00ae6bdac6 | ||
|
|
a606173e07 | ||
|
|
d8e6fd5df0 | ||
|
|
ec950de205 | ||
|
|
62e7fa6a23 | ||
|
|
2935c5fe1a | ||
|
|
021584d782 | ||
|
|
a5c111ef4f | ||
|
|
7868e47643 | ||
|
|
b4e3cd000f | ||
|
|
9c3568800c | ||
|
|
9cf105f8ea | ||
|
|
a8456782b5 | ||
|
|
2afdba48f0 | ||
|
|
4250895243 | ||
|
|
bfeb89075f | ||
|
|
721f61a71d | ||
|
|
a6e5d26aea | ||
|
|
d586f64e40 | ||
|
|
a0900ba052 | ||
|
|
40b00ab362 | ||
|
|
18208fab84 | ||
|
|
8f810a3dcf | ||
|
|
c598bbb8a9 | ||
|
|
e6f388d869 | ||
|
|
24e2eedd0f | ||
|
|
c75f76f740 | ||
|
|
006efbd906 | ||
|
|
28386d7471 | ||
|
|
f9545dc359 | ||
|
|
e527a52f6a | ||
|
|
a7ed50ecd4 | ||
|
|
06dcaaa821 | ||
|
|
36ac48779c | ||
|
|
88669fa033 | ||
|
|
225aa28a1b | ||
|
|
f1245206ce | ||
|
|
7f453949a1 | ||
|
|
38f385f67d | ||
|
|
5f5342c0d3 | ||
|
|
15e003f030 | ||
|
|
5edbc00865 | ||
|
|
723a49ccee | ||
|
|
ff487a0271 | ||
|
|
337735094b | ||
|
|
01b5b13475 | ||
|
|
fd9f792f90 | ||
|
|
e8ded61efb | ||
|
|
b0e098bb68 | ||
|
|
0cd82ec680 | ||
|
|
76484f1541 | ||
|
|
28943af494 | ||
|
|
9abff11f86 | ||
|
|
d49c5b3d8e | ||
|
|
c766cf9565 | ||
|
|
e4674142c6 | ||
|
|
089509ab87 | ||
|
|
0d119d83b0 | ||
|
|
b0d5b9fd2c | ||
|
|
fb1e6ca6c1 | ||
|
|
c49e4f52ae | ||
|
|
da6abe5462 | ||
|
|
763c700372 | ||
|
|
2696deb2a1 | ||
|
|
5c937c5642 | ||
|
|
f510cd3111 | ||
|
|
3206a46a92 | ||
|
|
9cbbc92062 | ||
|
|
0fa34c6880 | ||
|
|
dcb5f62413 | ||
|
|
07f5bdde60 | ||
|
|
0513463256 | ||
|
|
53a796afcc | ||
|
|
a4c3058f84 | ||
|
|
32522b61f2 | ||
|
|
11c1573b55 | ||
|
|
006ca4421a | ||
|
|
5ec3d3e36d | ||
|
|
49d11ed9f8 | ||
|
|
024af91df8 |
@@ -2,7 +2,10 @@
|
||||
|
||||
Run hubzilla-setup.sh for an unattended installation of hubzilla.
|
||||
|
||||
The script is known to work with Debian stable (Jessie).
|
||||
The script is known to work with Debian 8.3 stable (Jessie)
|
||||
|
||||
+ Home-PC (Debian-8.3.0-amd64)
|
||||
+ DigitalOcean droplet (Debian 8.3 x64 / 512 MB Memory / 20 GB Disk / NYC3)
|
||||
|
||||
# Step-by-Step Overwiew
|
||||
|
||||
@@ -19,13 +22,20 @@ Software
|
||||
+ Fresh installation of Debian on your mini-pc
|
||||
+ Router with open ports 80 and 443 for your Debian
|
||||
|
||||
## The basic steps
|
||||
## The basic steps (quick overview)
|
||||
|
||||
+ Register your own domain (for example at selfHOST) or a free subdomain (for example at freeDNS)
|
||||
+ Clone hubzilla to /var/www/html
|
||||
+ Copy hubzilla-config.txt and hubzilla-setup.sh to your Debian (future hub)
|
||||
+ Edit hubzilla-config.txt. Enter your values there: db pass, domain, values for dyn DNS
|
||||
+ Run hubzilla-setup.sh as root ... wait, wait, wait until the script is finised
|
||||
+ Log on to your new debian (server)
|
||||
- apt-get install git
|
||||
- mkdir -p /var/www/html
|
||||
- cd /var/www/html
|
||||
- git clone https://github.com/redmatrix/hubzilla.git .
|
||||
- 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
|
||||
- hubzilla-setup.sh as root
|
||||
- ... wait, wait, wait until the script is finised
|
||||
- reboot
|
||||
+ Open your domain with a browser and step throught the initial configuration of hubzilla.
|
||||
|
||||
# Step-by-Step in Detail
|
||||
@@ -76,6 +86,8 @@ There are two way to get a domain
|
||||
|
||||
### Method 1: Get yourself an own Domain (recommended)
|
||||
|
||||
...for example at selfHOST.de
|
||||
|
||||
### Method 2 Register a (free) Subdomain
|
||||
|
||||
Register a free subdomain for example at
|
||||
@@ -118,8 +130,12 @@ Clone hubzilla from git ("git pull" will update it later)
|
||||
Change to the install script
|
||||
|
||||
cd html/.homeinstall/
|
||||
|
||||
Copy the template file
|
||||
|
||||
cp hubzilla-config.txt.template hubzilla-config.txt
|
||||
|
||||
Change the file "hubzilla-config.txt". Enter your values there.
|
||||
Change the file "hubzilla-config.txt". Read the instructions there and enter your values.
|
||||
|
||||
nano hubzilla-config.txt
|
||||
|
||||
@@ -146,10 +162,3 @@ Leave db type "MySQL" untouched.
|
||||
|
||||
Follow the instructions in the next pages.
|
||||
|
||||
# The Script explained
|
||||
|
||||
This chapter shows you
|
||||
|
||||
- What the script does exactly
|
||||
- Explanations on technical details. May be this will encourage you to play with bash scripts?
|
||||
|
||||
|
||||
@@ -9,7 +9,9 @@ db_pass=
|
||||
###############################################
|
||||
### MANDATORY - let's encrypt #################
|
||||
#
|
||||
# Hubilla does not allow ecrypted communication, httpS.
|
||||
# Hubilla requires encrypted communication via secure HTTP (HTTPS).
|
||||
# This script automates installation of an SSL certificate from
|
||||
# Let's Encrypt (https://letsencrypt.org)
|
||||
#
|
||||
# Please give the domain name of your hub
|
||||
#
|
||||
@@ -136,12 +138,12 @@ backup_device_pass=
|
||||
### OPTIONAL - do not mess with things below ##
|
||||
# (...if you are not certain)
|
||||
#
|
||||
# Usally you are done here
|
||||
# All what comes below is OPTIONAL
|
||||
# Usually you are done here
|
||||
# Everything below is OPTIONAL
|
||||
#
|
||||
###############################################
|
||||
#
|
||||
# Database for huzilla
|
||||
# Database for hubzilla
|
||||
hubzilla_db_name=hubzilla
|
||||
hubzilla_db_user=hubzilla
|
||||
hubzilla_db_pass=$db_pass
|
||||
@@ -168,7 +170,7 @@ phpmyadminpass=$db_pass
|
||||
# * in eclipse: switch php debugger from zend to xdebug
|
||||
# * in eclipse: add local hubzilla github repository
|
||||
#
|
||||
# Wich user will use eclipse?
|
||||
# Which user will use eclipse?
|
||||
# Leave this empty if you do not want to prepare hubzilla for debugging
|
||||
#
|
||||
#developer_name=
|
||||
@@ -5,7 +5,7 @@
|
||||
#
|
||||
# This file automates the installation of hubzilla under Debian Linux
|
||||
#
|
||||
# 1) Edit the file "hubzilla-config.txt"
|
||||
# 1) Copy the file "hubzilla-config.txt.template" to "hubzilla-config.txt"
|
||||
# Follow the instuctions there
|
||||
#
|
||||
# 2) Switch to user "root" by typing "su -"
|
||||
@@ -92,12 +92,12 @@
|
||||
# Credits
|
||||
# -------
|
||||
#
|
||||
# The srcipt is based on Thomas Willinghams script "debian-setup.sh"
|
||||
# The script is based on Thomas Willinghams script "debian-setup.sh"
|
||||
# which he used to install the red#matrix.
|
||||
#
|
||||
# The script uses another script from https://github.com/lukas2511/letsencrypt.sh
|
||||
#
|
||||
# The documentation of bash is here
|
||||
# The documentation for bash is here
|
||||
# https://www.gnu.org/software/bash/manual/bash.html
|
||||
#
|
||||
function check_sanity {
|
||||
@@ -120,6 +120,15 @@ function check_sanity {
|
||||
|
||||
function check_config {
|
||||
print_info "config check..."
|
||||
# Check for required parameters
|
||||
if [ -z "$db_pass" ]
|
||||
then
|
||||
die "db_pass not set in $configfile"
|
||||
fi
|
||||
if [ -z "$le_domain" ]
|
||||
then
|
||||
die "le_domain not set in $configfile"
|
||||
fi
|
||||
# backup is important and should be checked
|
||||
if [ -n "$backup_device_name" ]
|
||||
then
|
||||
@@ -215,11 +224,34 @@ function print_warn {
|
||||
echo -e '\e[0m'
|
||||
}
|
||||
|
||||
function stop_hubzilla {
|
||||
if [ -d /etc/apache2 ]
|
||||
then
|
||||
print_info "stopping apache webserver..."
|
||||
service apache2 stop
|
||||
fi
|
||||
if [ -f /etc/init.d/mysql ]
|
||||
then
|
||||
print_info "stopping mysql db..."
|
||||
/etc/init.d/mysql stop
|
||||
fi
|
||||
}
|
||||
|
||||
function install_apache {
|
||||
print_info "installing apache..."
|
||||
nocheck_install "apache2 apache2-utils"
|
||||
}
|
||||
|
||||
function install_curl {
|
||||
print_info "installing curl..."
|
||||
nocheck_install "curl"
|
||||
}
|
||||
|
||||
function install_sendmail {
|
||||
print_info "installing sendmail..."
|
||||
nocheck_install "sendmail sendmail-bin"
|
||||
}
|
||||
|
||||
function install_php {
|
||||
# openssl and mbstring are included in libapache2-mod-php5
|
||||
# to_to: php5-suhosin
|
||||
@@ -542,7 +574,8 @@ function install_hubzilla {
|
||||
chmod -R 777 store
|
||||
touch .htconfig.php
|
||||
chmod ou+w .htconfig.php
|
||||
cd ..
|
||||
install_hubzilla_plugins
|
||||
cd /var/www/
|
||||
chown -R www-data:www-data html
|
||||
chown root:www-data /var/www/html/
|
||||
chown root:www-data /var/www/html/.htaccess
|
||||
@@ -556,6 +589,73 @@ 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
|
||||
@@ -743,6 +843,7 @@ 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 "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
|
||||
@@ -804,9 +905,11 @@ check_sanity
|
||||
# Read config file edited by user
|
||||
configfile=hubzilla-config.txt
|
||||
source $configfile
|
||||
|
||||
selfhostdir=/etc/selfhost
|
||||
selfhostscript=selfhost-updater.sh
|
||||
hubzilladaily=hubzilla-daily.sh
|
||||
plugins_update=.homeinstall/plugins_update.sh
|
||||
snapshotconfig=/etc/rsnapshot_hubzilla.conf
|
||||
snapshotconfig_external_device=/etc/rsnapshot_hubzilla_external_device.conf
|
||||
backup_mount_point=/media/hubzilla_backup
|
||||
@@ -816,7 +919,10 @@ sslconf=/etc/apache2/sites-available/default-ssl.conf
|
||||
#set -x # activate debugging from here
|
||||
|
||||
check_config
|
||||
stop_hubzilla
|
||||
update_upgrade
|
||||
install_curl
|
||||
install_sendmail
|
||||
install_apache
|
||||
install_php
|
||||
install_mysql
|
||||
|
||||
@@ -24,6 +24,9 @@ AddType audio/ogg .oga
|
||||
# Also place auth information into REMOTE_USER for sites running
|
||||
# in CGI mode.
|
||||
|
||||
RewriteCond %{REQUEST_URI} ^/\.well\-known/.*
|
||||
RewriteRule ^(.*)$ index.php?q=$1 [E=REMOTE_USER:%{HTTP:Authorization},L,QSA]
|
||||
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
RewriteRule ^(.*)$ index.php?q=$1 [E=REMOTE_USER:%{HTTP:Authorization},L,QSA]
|
||||
|
||||
@@ -181,6 +181,7 @@ echo "chmod done, permissions set to 777 on poller script."
|
||||
# to make Hubzilla on OpenShift a more pleasant experience
|
||||
echo "Changing default configuration to conserve space and autocreate a social private channel upon account registration"
|
||||
cd ${OPENSHIFT_REPO_DIR}
|
||||
util/config system auto_channel_create
|
||||
util/config system default_permissions_role social_private
|
||||
util/config system workflow_channel_next channel
|
||||
util/config system expire_delivery_reports 3
|
||||
|
||||
168
CHANGELOG
Normal file
168
CHANGELOG
Normal file
@@ -0,0 +1,168 @@
|
||||
Hubzilla 1.4
|
||||
[This list may appear brief, but encompasses a huge amount of re-writing and re-factoring
|
||||
of the internal code structure to gain long-term performance and stability and provide a standard
|
||||
interface to alternate protocol federation plugins which were made possible by the UNO configuration.
|
||||
UNO is a configuration of hubzilla introduced in 1.3 with reduced complexity and which provides
|
||||
improved protocol federation potential to other networks by virtue of removing nomadic identity
|
||||
(which is not possible to model or work around using other network protocols).]
|
||||
|
||||
Implement channel move operation for UNO configuration
|
||||
Remove bookmark references in UNO (which has no bookmarks by default)
|
||||
UI cleanup profiles/chat/manage
|
||||
Refactor webfinger probes and salmon backend for GNU-social federation
|
||||
SECURITY: DAV authentication exploit
|
||||
Context help added
|
||||
More help pages
|
||||
Provide 'posts only' feed
|
||||
Refactor App to remove globals
|
||||
Refactor Session to remove globals
|
||||
provide a fullscreen mode for selected modules and functions
|
||||
Regression: some addon routes broken
|
||||
fix "remember me"
|
||||
Autocomplete tool extended to bbcode/comanche
|
||||
Clone sync of file/photo updates
|
||||
system rename (e.g. http to https or DNS name change) missing some connection photos
|
||||
calendar module not blocked to public whhen block_public enabled
|
||||
Use timeago.js in reshare content so that timestamps will be correct on federated reshares
|
||||
Rework detection of JavaScript to avoid reload penalty under normal operation
|
||||
Changed primary directory server to a hubzilla server
|
||||
Plugins:
|
||||
Diaspora - switch to alternate XML parser to avoid storing compound objects
|
||||
GNU-Social - Huge amounts of work, federation somewhat working now, several issues remain
|
||||
Friendica - Initial federation work (not yet published)
|
||||
|
||||
Hubzilla 1.3
|
||||
Admin Security configuration page created which consolidates several previously hidden settings:
|
||||
Communication white/black lists
|
||||
Channel white/black lists
|
||||
OEmbed white/black lists
|
||||
Admin Profile Fields page created which manages the availability and order of standard profile fields and allows new fields to be created/managed
|
||||
"Poke" module reworked - page UI updated and "poke basic" setting introduced which limits the available poke "verbs".
|
||||
"Mood" module UI reworked
|
||||
"profile_photo" module UI reworked
|
||||
"cover_photo" module UI reworked
|
||||
"new_channel" module UI reworked
|
||||
"register" module UI reworked
|
||||
"pubsites" module UI reworked
|
||||
item-meta ("iconfig") created which implements arbitrary storage for item metadata for plugins
|
||||
abook-meta ("abconfig") created which implements arbitrary storage for connection metadata for plugins
|
||||
"Strict transport security header" made optional as it conflicts with some existing Apache/nginx configurations
|
||||
"Hubzilla UNO" (Hubzilla with radically simplified and locked site settings) implemented as an install configuration.
|
||||
.well-known directory conflict worked out to support LetsEncrypt cert ownership checks without disrupting webfinger and other internal uses of .well-known
|
||||
Lots of work on 'zcards' which are self-contained HTML representations of a channel including cover photos, profile photos, and some text information
|
||||
Long standing bug uncovered which failed to properly restrict the lower time limit for public feed requests
|
||||
A number of fixes to "readmore" to fix page jumping
|
||||
Bugfix: persons other than the channel owner who have permission to upload photos to a channel could not do so if the js_upload plugin/addon was enabled
|
||||
Siteinfo incorrectly identifying secondary directory servers
|
||||
Allow admin to set and lock features when UNO is configured
|
||||
Atom feeds: alter how events are formatted to be compatible with GNU-social
|
||||
Allow guest/visitor access to view personal calendar
|
||||
Moved several more classes to "composer format" and provided an autoloader.
|
||||
Bugfix: require existing password to change password
|
||||
Bugfix: allow relative_date() to be translated to Polish which has more than two plural forms.
|
||||
Plugin API: add "requires" keyword to module header to indicate dependent addons
|
||||
ActivityStreams improvements and cleanup: photo and file activities
|
||||
UI cleanup for editing profile when multiple profiles enabled
|
||||
Removed the "markdown" feature as there are numerous issues and no maintainer.
|
||||
Provide "footer" bbcode to ease theming of post footer content
|
||||
Bugfix: install issues caused by composer code refactor and typo in postgres load file
|
||||
Plugins:
|
||||
keepout - "block public on steroids"
|
||||
pubsubhubbub - provides PuSH support to Atom feeds, required for GNU-social federation
|
||||
GNUsocial protocol - under development
|
||||
Diaspora protocol - some work to ease migration to the new signing format
|
||||
Diaspost - disabled; numerous issues and no maintainer
|
||||
smileybutton - theme work and fixed compatibility with other jot-tools plugins
|
||||
|
||||
|
||||
Hubzilla 1.2
|
||||
Provide extra HTTP security headers (several of them).
|
||||
Allow a site to disable delivery reports if disk space is limited
|
||||
Regression: Wrong theme when viewing single post as non-member
|
||||
Some Diaspora profile photos use relative URLs - force absolute
|
||||
Add locked features to siteinfo report to aid remote debugging
|
||||
Provide version compatibility checking to plugins (minversion, maxversion, and minphpversion)
|
||||
Account config storage
|
||||
Provide optional integrated registration and channel create form
|
||||
cli utility for managing addons
|
||||
issue with sharing photo "items"
|
||||
cover photo manager: upload, crop, and store
|
||||
cover photo widget created
|
||||
rework the connections list page and provide a few management features there
|
||||
fixed issue with Comanche layout definitions loaded by plugins
|
||||
provide ability to separate delivery functions from item_store() and item_store_update() - some forum messages were being redelivered when cloned.
|
||||
call build_sync_packet() on pdledit changes
|
||||
Abstract the project name and version so these can be customised or removed
|
||||
Allow hiding the ratings links on a per-site basis
|
||||
db_type not present in international setup templates - was unable to choose postgres.
|
||||
item_photo_menu logically divided into a) actions on the post, b) actions related to the author
|
||||
bug: default channel not reset to 0 when last channel removed
|
||||
create widget containing only the contact block
|
||||
regression: public forums granted send stream permissions to connections
|
||||
workaround Firefox's refusal to honour disabling autocomplete of passwords
|
||||
regression: photo's uploaded to a channel by a guest (with file write permissions) not saved correctly.
|
||||
provide mechanisms for custom .well-known handlers (needed for LetsEncrypt ownership verification)
|
||||
proc_run modified to use exec() instead of proc_open() - causing issues on some PHP installations
|
||||
remote delegation failure under a specific set of circumstances which we were finally able to duplicate
|
||||
Delegation section of Channel Manager was missing names and contained useless notification icons.
|
||||
Change "expire" channel setting to show system limit if there is one.
|
||||
Regression: provide a one-click ignore of pending connection
|
||||
Config to control directory keyword generation on client and server.
|
||||
"Collections" renamed to "Privacy Groups", documentation improved
|
||||
widget_item - allow use of page title instead of message id
|
||||
Add site black/white list checking to all .well-known services
|
||||
reduce incidents of screen jumping when "showmore" is activated
|
||||
add oembed provider for photos
|
||||
|
||||
Addons:
|
||||
|
||||
CSS theming of pageheader plugin
|
||||
xmpp addon ported from Friendica
|
||||
Diaspora private mail issues after the third reply
|
||||
Occasional issue with Diaspora connection requests
|
||||
Add notification email to Diaspora PMs
|
||||
Allow anonymising platform and version for statistics
|
||||
msgfooter addon created
|
||||
removed embedly plugin
|
||||
sync clones after superblock addition
|
||||
"keepout" plugin created
|
||||
|
||||
|
||||
Hubzilla 1.1
|
||||
|
||||
Rewrote and simplified the Queue manager and delivery system
|
||||
Rewrote and simplified the outer layers of the Zot protocol
|
||||
Use a standard version numbering scheme in addition to the snapshot tags
|
||||
Provide a channel blacklist for blocking channels with abusive or illegal content at the hub level
|
||||
Make the black/white lists pluggable
|
||||
Update template library
|
||||
Support for letsencrypt certs in various places
|
||||
Cleanup of login and register pages
|
||||
Better error responses for permission denied on channel file repositories
|
||||
Disabled the public stream by default for new installs (can be enabled if desired)
|
||||
Cleanup of API authentication and rework the old OAuth1 stuff
|
||||
Add API "status with media" support compatible with Twitter and conflicting method for GNU-social
|
||||
Rework photo ActivityStreams objects to align better with ActivityStreams producers/consumers
|
||||
Several minor API fixes to work better with AndStatus client
|
||||
Invitation only site - experimental support added, needs more work
|
||||
Fix delivery loop condition due to corrupted data which resulted in recursive upstream delivery
|
||||
Provide more support for external (git) widget collections.
|
||||
Extend the Queue API to 3rd-party network addons which have experienced downtime recently.
|
||||
Regression: Inherited permissions were not explicitly set
|
||||
Regression: "Xyz posted on your wall" notification sent when creating webpages at another channel
|
||||
Regression: Custom permissions not pre-populated on channel creation with named role.
|
||||
Provide "Public" string when a post can be made public, instead of "visible to default audience"
|
||||
Allow hub admin to specify a default role type for the first channel created, reducing complexity
|
||||
Ability for a hub admin to set feature defaults and lock them, reducing complexity
|
||||
Change default expiration of delivery reports to 10 days to accomodate sites with reduced resources
|
||||
Addons/Plugins:
|
||||
Pageheader addon ported from Friendica
|
||||
Hubwall (allow admin to send email to all accounts on this hub) created
|
||||
GNU-social - queueing added
|
||||
Diaspora - fixes for various failures to update profile photos, updates to queue API
|
||||
Cross Domain Authenticated Chess (Andrew Manning's repository)
|
||||
|
||||
And... the normal "lots of bugs fixed, translations updated, and documentation improved"
|
||||
|
||||
|
||||
|
||||
16
README.md
16
README.md
@@ -3,26 +3,26 @@
|
||||
Hubzilla - Community Server
|
||||
===========================
|
||||
|
||||
Help us redefine the web - using integrated and united community websites.
|
||||
--------------------------------------------------------------------------
|
||||
Connected and linked web communities.
|
||||
-------------------------------------
|
||||
|
||||
<p align="center" markdown="1">
|
||||
<em><a href="https://github.com/redmatrix/hubzilla/blob/master/install/INSTALL.txt">Installing Hubzilla</a></em>
|
||||
</p>
|
||||
|
||||
**What are Hubs?**
|
||||
**What are Hubz?**
|
||||
|
||||
Hubs are independent general-purpose websites that not only connect with their associated members and viewers, but also connect together to exchange personal communications and other information with each other.
|
||||
Hubz are independent general-purpose websites that not only connect with their associated members and viewers, but also connect together to exchange personal communications and other information with each other.
|
||||
This allows hub members on any hub to securely and privately share anything; with anybody, on any hub - anywhere; or share stuff publicly with anybody on the internet if desired.
|
||||
|
||||
**Hubzilla** is the server software which makes this possible. It is a sophisticated and unique combination of an open source content management system and a decentralised identity, communications, and permissions framework and protocol suite, built using common webserver technology (PHP/MySQL/Apache, although Mariadb or Postgres and Nginx could also be used - we're pretty easy). The end result is a level of systems integration, privacy control, and communications features that you wouldn't think are possible in either a content management system or a decentralised communications network. It also brings a new level of cooperation and privacy to the web and introduces the concept of personally owned "single sign-on" to web services across the entire internet.
|
||||
**Hubzilla** is the server software which makes this possible. It is a sophisticated and unique combination of an open source content management system and a decentralised identity, communications, and permissions framework and protocol suite, built using common webserver technology (PHP/MySQL/Apache and popular variants). The end result is a level of systems integration, privacy control, and communications features that you wouldn't think are possible in either a content management system or a decentralised communications network. It also brings a new level of cooperation and privacy to the web and introduces the concept of personally owned "single sign-on" to web services across the entire internet.
|
||||
|
||||
Hubzilla hubs are
|
||||
Hubzilla hubz are
|
||||
|
||||
* decentralised
|
||||
* inherently social
|
||||
* optionally inter-networked with other hubs
|
||||
* privacy-enabled (privacy exclusions work across the entire internet to any registered identity on any compatible hubs)
|
||||
* optionally inter-networked with other hubz
|
||||
* privacy-enabled (privacy exclusions work across the entire internet to any registered identity on any compatible hubz)
|
||||
|
||||
Possible website applications include
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Access;
|
||||
|
||||
|
||||
class AccessList {
|
||||
|
||||
@@ -88,61 +90,3 @@ class AccessList {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Used to wrap ACL elements in angle brackets for storage.
|
||||
*
|
||||
* @param[in,out] array &$item
|
||||
*/
|
||||
function sanitise_acl(&$item) {
|
||||
if (strlen($item))
|
||||
$item = '<' . notags(trim($item)) . '>';
|
||||
else
|
||||
unset($item);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convert an ACL array to a storable string.
|
||||
*
|
||||
* @param array $p
|
||||
* @return array
|
||||
*/
|
||||
function perms2str($p) {
|
||||
$ret = '';
|
||||
|
||||
if (is_array($p))
|
||||
$tmp = $p;
|
||||
else
|
||||
$tmp = explode(',', $p);
|
||||
|
||||
if (is_array($tmp)) {
|
||||
array_walk($tmp, 'sanitise_acl');
|
||||
$ret = implode('', $tmp);
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Turn user/group ACLs stored as angle bracketed text into arrays.
|
||||
*
|
||||
* turn string array of angle-bracketed elements into string array
|
||||
* e.g. "<123xyz><246qyo><sxo33e>" => array(123xyz,246qyo,sxo33e);
|
||||
*
|
||||
* @param string $s
|
||||
* @return array
|
||||
*/
|
||||
function expand_acl($s) {
|
||||
$ret = array();
|
||||
|
||||
if(strlen($s)) {
|
||||
$t = str_replace('<','',$s);
|
||||
$a = explode('>',$t);
|
||||
foreach($a as $aa) {
|
||||
if($aa)
|
||||
$ret[] = $aa;
|
||||
}
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
63
Zotlabs/Project/System.php
Normal file
63
Zotlabs/Project/System.php
Normal file
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Project;
|
||||
|
||||
class System {
|
||||
|
||||
function get_platform_name() {
|
||||
if(is_array(\App::$config) && is_array(\App::$config['system']) && \App::$config['system']['platform_name'])
|
||||
return \App::$config['system']['platform_name'];
|
||||
return PLATFORM_NAME;
|
||||
}
|
||||
|
||||
function get_site_name() {
|
||||
if(is_array(\App::$config) && is_array(\App::$config['system']) && \App::$config['system']['sitename'])
|
||||
return \App::$config['system']['sitename'];
|
||||
return '';
|
||||
}
|
||||
|
||||
function get_project_version() {
|
||||
if(is_array(\App::$config) && is_array(\App::$config['system']) && \App::$config['system']['hide_version'])
|
||||
return '';
|
||||
return RED_VERSION;
|
||||
}
|
||||
|
||||
function get_update_version() {
|
||||
if(is_array(\App::$config) && is_array(\App::$config['system']) && \App::$config['system']['hide_version'])
|
||||
return '';
|
||||
return DB_UPDATE_VERSION;
|
||||
}
|
||||
|
||||
|
||||
function get_notify_icon() {
|
||||
if(is_array(\App::$config) && is_array(\App::$config['system']) && \App::$config['system']['email_notify_icon_url'])
|
||||
return \App::$config['system']['email_notify_icon_url'];
|
||||
return z_root() . '/images/hz-white-32.png';
|
||||
}
|
||||
|
||||
function get_site_icon() {
|
||||
if(is_array(\App::$config) && is_array(\App::$config['system']) && \App::$config['system']['site_icon_url'])
|
||||
return \App::$config['system']['site_icon_url'];
|
||||
return z_root() . '/images/hz-32.png';
|
||||
}
|
||||
|
||||
|
||||
function get_server_role() {
|
||||
if(UNO)
|
||||
return 'basic';
|
||||
return 'advanced';
|
||||
}
|
||||
|
||||
// return the standardised version. Since we can't easily compare
|
||||
// before the STD_VERSION definition was applied, we have to treat
|
||||
// all prior release versions the same. You can dig through them
|
||||
// with other means (such as RED_VERSION) if necessary.
|
||||
|
||||
function get_std_version() {
|
||||
if(defined('STD_VERSION'))
|
||||
return STD_VERSION;
|
||||
return '0.0.0';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace RedMatrix\RedDAV;
|
||||
namespace Zotlabs\Storage;
|
||||
|
||||
use Sabre\DAV;
|
||||
|
||||
/**
|
||||
* @brief Authentication backend class for RedDAV.
|
||||
* @brief Authentication backend class for DAV.
|
||||
*
|
||||
* This class also contains some data which is not necessary for authentication
|
||||
* like timezone settings.
|
||||
@@ -15,7 +15,7 @@ use Sabre\DAV;
|
||||
* @link http://github.com/friendica/red
|
||||
* @license http://opensource.org/licenses/mit-license.php The MIT License (MIT)
|
||||
*/
|
||||
class RedBasicAuth extends DAV\Auth\Backend\AbstractBasic {
|
||||
class BasicAuth extends DAV\Auth\Backend\AbstractBasic {
|
||||
|
||||
/**
|
||||
* @brief This variable holds the currently logged-in channel_address.
|
||||
@@ -45,18 +45,18 @@ class RedBasicAuth extends DAV\Auth\Backend\AbstractBasic {
|
||||
public $observer = '';
|
||||
/**
|
||||
*
|
||||
* @see RedBrowser::set_writeable()
|
||||
* @see Browser::set_writeable()
|
||||
* @var \Sabre\DAV\Browser\Plugin
|
||||
*/
|
||||
public $browser;
|
||||
/**
|
||||
* channel_id of the current visited path. Set in RedDirectory::getDir().
|
||||
* channel_id of the current visited path. Set in Directory::getDir().
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $owner_id = 0;
|
||||
/**
|
||||
* channel_name of the current visited path. Set in RedDirectory::getDir().
|
||||
* channel_name of the current visited path. Set in Directory::getDir().
|
||||
*
|
||||
* Used for creating the path in cloud/
|
||||
*
|
||||
@@ -110,7 +110,7 @@ class RedBasicAuth extends DAV\Auth\Backend\AbstractBasic {
|
||||
if ($x) {
|
||||
// @fixme this foreach should not be needed?
|
||||
foreach ($x as $record) {
|
||||
if (($record['account_flags'] == ACCOUNT_OK) || ($record['account_flags'] == ACCOUNT_UNVERIFIED)
|
||||
if ((($record['account_flags'] == ACCOUNT_OK) || ($record['account_flags'] == ACCOUNT_UNVERIFIED))
|
||||
&& (hash('whirlpool', $record['account_salt'] . $password) === $record['account_password'])) {
|
||||
logger('password verified for ' . $username);
|
||||
return $this->setAuthenticated($r[0]);
|
||||
@@ -197,7 +197,7 @@ class RedBasicAuth extends DAV\Auth\Backend\AbstractBasic {
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Prints out all RedBasicAuth variables to logger().
|
||||
* @brief Prints out all BasicAuth variables to logger().
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace RedMatrix\RedDAV;
|
||||
namespace Zotlabs\Storage;
|
||||
|
||||
use Sabre\DAV;
|
||||
|
||||
@@ -15,7 +15,7 @@ use Sabre\DAV;
|
||||
* @link http://github.com/friendica/red
|
||||
* @license http://opensource.org/licenses/mit-license.php The MIT License (MIT)
|
||||
*/
|
||||
class RedBrowser extends DAV\Browser\Plugin {
|
||||
class Browser extends DAV\Browser\Plugin {
|
||||
|
||||
/**
|
||||
* @see set_writeable()
|
||||
@@ -243,7 +243,7 @@ class RedBrowser extends DAV\Browser\Plugin {
|
||||
));
|
||||
|
||||
$a = get_app();
|
||||
$a->page['content'] = $html;
|
||||
\App::$page['content'] = $html;
|
||||
load_pdl($a);
|
||||
|
||||
$theme_info_file = "view/theme/" . current_theme() . "/php/theme.php";
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace RedMatrix\RedDAV;
|
||||
namespace Zotlabs\Storage;
|
||||
|
||||
use Sabre\DAV;
|
||||
|
||||
@@ -16,7 +16,7 @@ use Sabre\DAV;
|
||||
* @link http://github.com/friendica/red
|
||||
* @license http://opensource.org/licenses/mit-license.php The MIT License (MIT)
|
||||
*/
|
||||
class RedDirectory extends DAV\Node implements DAV\ICollection, DAV\IQuota {
|
||||
class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota {
|
||||
|
||||
/**
|
||||
* @brief The path inside /cloud
|
||||
@@ -53,7 +53,7 @@ class RedDirectory extends DAV\Node implements DAV\ICollection, DAV\IQuota {
|
||||
logger('directory ' . $ext_path, LOGGER_DATA);
|
||||
$this->ext_path = $ext_path;
|
||||
// remove "/cloud" from the beginning of the path
|
||||
$modulename = get_app()->module;
|
||||
$modulename = \App::$module;
|
||||
$this->red_path = ((strpos($ext_path, '/' . $modulename) === 0) ? substr($ext_path, strlen($modulename) + 1) : $ext_path);
|
||||
if (! $this->red_path) {
|
||||
$this->red_path = '/';
|
||||
@@ -114,9 +114,9 @@ class RedDirectory extends DAV\Node implements DAV\ICollection, DAV\IQuota {
|
||||
throw new DAV\Exception\Forbidden('Permission denied.');
|
||||
}
|
||||
|
||||
$modulename = get_app()->module;
|
||||
$modulename = \App::$module;
|
||||
if ($this->red_path === '/' && $name === $modulename) {
|
||||
return new RedDirectory('/' . $modulename, $this->auth);
|
||||
return new Directory('/' . $modulename, $this->auth);
|
||||
}
|
||||
|
||||
$x = RedFileData($this->ext_path . '/' . $name, $this->auth);
|
||||
@@ -168,6 +168,14 @@ class RedDirectory extends DAV\Node implements DAV\ICollection, DAV\IQuota {
|
||||
intval($this->auth->owner_id)
|
||||
);
|
||||
|
||||
|
||||
$ch = channelx_by_n($this->auth->owner_id);
|
||||
if($ch) {
|
||||
$sync = attach_export_data($ch,$this->folder_hash);
|
||||
if($sync)
|
||||
build_sync_packet($ch['channel_id'],array('file' => array($sync)));
|
||||
}
|
||||
|
||||
$this->red_path = $new_path;
|
||||
}
|
||||
|
||||
@@ -332,9 +340,15 @@ class RedDirectory extends DAV\Node implements DAV\ICollection, DAV\IQuota {
|
||||
|
||||
require_once('include/photos.php');
|
||||
$args = array( 'resource_id' => $hash, 'album' => $album, 'os_path' => $f, 'filename' => $name, 'getimagesize' => $x, 'directory' => $direct);
|
||||
$p = photo_upload($c[0],get_app()->get_observer(),$args);
|
||||
$p = photo_upload($c[0],\App::get_observer(),$args);
|
||||
}
|
||||
|
||||
$sync = attach_export_data($c[0],$hash);
|
||||
|
||||
if($sync)
|
||||
build_sync_packet($c[0]['channel_id'],array('file' => array($sync)));
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -356,7 +370,14 @@ class RedDirectory extends DAV\Node implements DAV\ICollection, DAV\IQuota {
|
||||
|
||||
if ($r) {
|
||||
$result = attach_mkdir($r[0], $this->auth->observer, array('filename' => $name, 'folder' => $this->folder_hash));
|
||||
if (! $result['success']) {
|
||||
|
||||
if($result['success']) {
|
||||
$sync = attach_export_data($r[0],$ret['data']['hash']);
|
||||
if($sync) {
|
||||
build_sync_packet($r[0]['channel_id'],array('file' => array($sync)));
|
||||
}
|
||||
}
|
||||
else {
|
||||
logger('error ' . print_r($result, true), LOGGER_DEBUG);
|
||||
}
|
||||
}
|
||||
@@ -380,6 +401,15 @@ class RedDirectory extends DAV\Node implements DAV\ICollection, DAV\IQuota {
|
||||
}
|
||||
|
||||
attach_delete($this->auth->owner_id, $this->folder_hash);
|
||||
|
||||
$ch = channelx_by_n($this->auth->owner_id);
|
||||
if($ch) {
|
||||
$sync = attach_export_data($ch,$this->folder_hash,true);
|
||||
if($sync)
|
||||
build_sync_packet($ch['channel_id'],array('file' => array($sync)));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -393,7 +423,7 @@ class RedDirectory extends DAV\Node implements DAV\ICollection, DAV\IQuota {
|
||||
public function childExists($name) {
|
||||
// On /cloud we show a list of available channels.
|
||||
// @todo what happens if no channels are available?
|
||||
$modulename = get_app()->module;
|
||||
$modulename = \App::$module;
|
||||
if ($this->red_path === '/' && $name === $modulename) {
|
||||
//logger('We are at ' $modulename . ' show a channel list', LOGGER_DEBUG);
|
||||
return true;
|
||||
@@ -417,7 +447,7 @@ class RedDirectory extends DAV\Node implements DAV\ICollection, DAV\IQuota {
|
||||
|
||||
logger('GetDir: ' . $this->ext_path, LOGGER_DEBUG);
|
||||
$this->auth->log();
|
||||
$modulename = get_app()->module;
|
||||
$modulename = \App::$module;
|
||||
|
||||
$file = $this->ext_path;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace RedMatrix\RedDAV;
|
||||
namespace Zotlabs\Storage;
|
||||
|
||||
use Sabre\DAV;
|
||||
|
||||
@@ -15,7 +15,7 @@ use Sabre\DAV;
|
||||
* @link http://github.com/friendica/red
|
||||
* @license http://opensource.org/licenses/mit-license.php The MIT License (MIT)
|
||||
*/
|
||||
class RedFile extends DAV\Node implements DAV\IFile {
|
||||
class File extends DAV\Node implements DAV\IFile {
|
||||
|
||||
/**
|
||||
* The file from attach table.
|
||||
@@ -84,6 +84,20 @@ class RedFile extends DAV\Node implements DAV\IFile {
|
||||
dbesc($this->data['hash']),
|
||||
intval($this->data['id'])
|
||||
);
|
||||
|
||||
if($this->data->is_photo) {
|
||||
$r = q("update photo set filename = '%s' where resource_id = '%s' and uid = %d",
|
||||
dbesc($newName),
|
||||
dbesc($this->data['hash']),
|
||||
intval($this->auth->owner_id)
|
||||
);
|
||||
}
|
||||
$ch = channelx_by_n($this->auth->owner_id);
|
||||
if($ch) {
|
||||
$sync = attach_export_data($ch,$this->data['hash']);
|
||||
if($sync)
|
||||
build_sync_packet($ch['channel_id'],array('file' => array($sync)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -173,7 +187,7 @@ class RedFile extends DAV\Node implements DAV\IFile {
|
||||
if($is_photo) {
|
||||
require_once('include/photos.php');
|
||||
$args = array( 'resource_id' => $this->data['hash'], 'album' => $album, 'os_path' => $f, 'filename' => $r[0]['filename'], 'getimagesize' => $gis, 'directory' => $direct );
|
||||
$p = photo_upload($c[0],get_app()->get_observer(),$args);
|
||||
$p = photo_upload($c[0],\App::get_observer(),$args);
|
||||
}
|
||||
|
||||
// update the folder's lastmodified timestamp
|
||||
@@ -205,6 +219,12 @@ class RedFile extends DAV\Node implements DAV\IFile {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$sync = attach_export_data($c[0],$this->data['hash']);
|
||||
|
||||
if($sync)
|
||||
build_sync_packet($c[0]['channel_id'],array('file' => array($sync)));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -318,5 +338,12 @@ class RedFile extends DAV\Node implements DAV\IFile {
|
||||
}
|
||||
|
||||
attach_delete($this->auth->owner_id, $this->data['hash']);
|
||||
|
||||
$ch = channelx_by_n($this->auth->owner_id);
|
||||
if($ch) {
|
||||
$sync = attach_export_data($ch,$this->data['hash'],true);
|
||||
if($sync)
|
||||
build_sync_packet($ch['channel_id'],array('file' => array($sync)));
|
||||
}
|
||||
}
|
||||
}
|
||||
36
Zotlabs/Web/CheckJS.php
Normal file
36
Zotlabs/Web/CheckJS.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Web;
|
||||
|
||||
|
||||
class CheckJS {
|
||||
|
||||
private static $jsdisabled = 0;
|
||||
|
||||
function __construct($test = 0) {
|
||||
if(intval($_REQUEST['jsdisabled']))
|
||||
$this->jsdisabled = 1;
|
||||
if(intval($_COOKIE['jsdisabled']))
|
||||
$this->jsdisabled = 1;
|
||||
|
||||
if(! $this->jsdisabled) {
|
||||
$page = urlencode(\App::$query_string);
|
||||
|
||||
if($test) {
|
||||
\App::$page['htmlhead'] .= "\r\n" . '<meta http-equiv="refresh" content="0; url=' . z_root() . '/nojs?f=&redir=' . $page . '">' . "\r\n";
|
||||
}
|
||||
else {
|
||||
\App::$page['htmlhead'] .= "\r\n" . '<noscript><meta http-equiv="refresh" content="0; url=' . z_root() . '/nojs?f=&redir=' . $page . '"></noscript>' . "\r\n";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function disabled() {
|
||||
return self::$jsdisabled;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
66
Zotlabs/Web/HttpMeta.php
Normal file
66
Zotlabs/Web/HttpMeta.php
Normal file
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Web;
|
||||
|
||||
|
||||
class HttpMeta {
|
||||
|
||||
private $vars = null;
|
||||
private $og = null;
|
||||
|
||||
function __construct() {
|
||||
|
||||
$this->vars = array();
|
||||
$this->og = array();
|
||||
|
||||
}
|
||||
|
||||
function set($property,$value) {
|
||||
if(strpos($property,'og:') === 0)
|
||||
$this->og[$property] = $value;
|
||||
else
|
||||
$this->vars[$property] = $value;
|
||||
}
|
||||
|
||||
function check_required() {
|
||||
if(
|
||||
($this->og)
|
||||
&& array_key_exists('og:title',$this->og)
|
||||
&& array_key_exists('og:type', $this->og)
|
||||
&& array_key_exists('og:image',$this->og)
|
||||
&& array_key_exists('og:url', $this->og)
|
||||
)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
function get_field($field) {
|
||||
if(strpos($field,'og:') === 0)
|
||||
$arr = $this->og;
|
||||
else
|
||||
$arr = $this->vars;
|
||||
|
||||
if($arr && array_key_exists($field,$arr) && $arr[$field])
|
||||
return $arr[$field];
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
function get() {
|
||||
$o = '';
|
||||
if($this->vars) {
|
||||
foreach($this->vars as $k => $v) {
|
||||
$o .= '<meta property="' . $k . '" content="' . urlencode($v) . '" />' . "\r\n" ;
|
||||
}
|
||||
}
|
||||
if($this->check_required()) {
|
||||
foreach($this->og as $k => $v) {
|
||||
$o .= '<meta property="' . $k . '" content="' . urlencode($v) . '" />' . "\r\n" ;
|
||||
}
|
||||
}
|
||||
if($o)
|
||||
return "\r\n" . $o;
|
||||
return $o;
|
||||
}
|
||||
|
||||
}
|
||||
203
Zotlabs/Web/Router.php
Normal file
203
Zotlabs/Web/Router.php
Normal file
@@ -0,0 +1,203 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Web;
|
||||
|
||||
|
||||
class Router {
|
||||
|
||||
function __construct(&$a) {
|
||||
|
||||
/**
|
||||
*
|
||||
* We have already parsed the server path into App::$argc and App::$argv
|
||||
*
|
||||
* App::$argv[0] is our module name. We will load the file mod/{App::$argv[0]}.php
|
||||
* and use it for handling our URL request.
|
||||
* The module file contains a few functions that we call in various circumstances
|
||||
* and in the following order:
|
||||
*
|
||||
* "module"_init
|
||||
* "module"_post (only called if there are $_POST variables)
|
||||
* "module"_content - the string return of this function contains our page body
|
||||
*
|
||||
* Modules which emit other serialisations besides HTML (XML,JSON, etc.) should do
|
||||
* so within the module init and/or post functions and then invoke killme() to terminate
|
||||
* further processing.
|
||||
*/
|
||||
|
||||
$module = \App::$module;
|
||||
|
||||
if(strlen($module)) {
|
||||
|
||||
/**
|
||||
*
|
||||
* We will always have a module name.
|
||||
* First see if we have a plugin which is masquerading as a module.
|
||||
*
|
||||
*/
|
||||
|
||||
if(is_array(\App::$plugins) && in_array($module,\App::$plugins) && file_exists("addon/{$module}/{$module}.php")) {
|
||||
include_once("addon/{$module}/{$module}.php");
|
||||
if(function_exists($module . '_module'))
|
||||
\App::$module_loaded = true;
|
||||
}
|
||||
|
||||
if((strpos($module,'admin') === 0) && (! is_site_admin())) {
|
||||
\App::$module_loaded = false;
|
||||
notice( t('Permission denied.') . EOL);
|
||||
goaway(z_root());
|
||||
}
|
||||
|
||||
/**
|
||||
* If the site has a custom module to over-ride the standard module, use it.
|
||||
* Otherwise, look for the standard program module in the 'mod' directory
|
||||
*/
|
||||
|
||||
if(! (\App::$module_loaded)) {
|
||||
if(file_exists("mod/site/{$module}.php")) {
|
||||
include_once("mod/site/{$module}.php");
|
||||
\App::$module_loaded = true;
|
||||
}
|
||||
elseif(file_exists("mod/{$module}.php")) {
|
||||
include_once("mod/{$module}.php");
|
||||
\App::$module_loaded = true;
|
||||
}
|
||||
else logger("mod/{$module}.php not found.");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This provides a place for plugins to register module handlers which don't otherwise exist on the system.
|
||||
* If the plugin sets 'installed' to true we won't throw a 404 error for the specified module even if
|
||||
* there is no specific module file or matching plugin name.
|
||||
* The plugin should catch at least one of the module hooks for this URL.
|
||||
*/
|
||||
|
||||
$x = array('module' => $module, 'installed' => false);
|
||||
call_hooks('module_loaded', $x);
|
||||
if($x['installed'])
|
||||
\App::$module_loaded = true;
|
||||
|
||||
/**
|
||||
* The URL provided does not resolve to a valid module.
|
||||
*
|
||||
* On Dreamhost sites, quite often things go wrong for no apparent reason and they send us to '/internal_error.html'.
|
||||
* We don't like doing this, but as it occasionally accounts for 10-20% or more of all site traffic -
|
||||
* we are going to trap this and redirect back to the requested page. As long as you don't have a critical error on your page
|
||||
* this will often succeed and eventually do the right thing.
|
||||
*
|
||||
* Otherwise we are going to emit a 404 not found.
|
||||
*/
|
||||
|
||||
if(! (\App::$module_loaded)) {
|
||||
|
||||
// Stupid browser tried to pre-fetch our Javascript img template. Don't log the event or return anything - just quietly exit.
|
||||
if((x($_SERVER, 'QUERY_STRING')) && preg_match('/{[0-9]}/', $_SERVER['QUERY_STRING']) !== 0) {
|
||||
killme();
|
||||
}
|
||||
|
||||
if((x($_SERVER, 'QUERY_STRING')) && ($_SERVER['QUERY_STRING'] === 'q=internal_error.html') && \App::$config['system']['dreamhost_error_hack']) {
|
||||
logger('index.php: dreamhost_error_hack invoked. Original URI =' . $_SERVER['REQUEST_URI']);
|
||||
goaway(z_root() . $_SERVER['REQUEST_URI']);
|
||||
}
|
||||
|
||||
logger('index.php: page not found: ' . $_SERVER['REQUEST_URI'] . ' ADDRESS: ' . $_SERVER['REMOTE_ADDR'] . ' QUERY: ' . $_SERVER['QUERY_STRING'], LOGGER_DEBUG);
|
||||
header($_SERVER['SERVER_PROTOCOL'] . ' 404 ' . t('Not Found'));
|
||||
$tpl = get_markup_template('404.tpl');
|
||||
\App::$page['content'] = replace_macros($tpl, array(
|
||||
'$message' => t('Page not found.')
|
||||
));
|
||||
|
||||
// pretend this is a module so it will initialise the theme
|
||||
\App::$module = '404';
|
||||
\App::$module_loaded = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function Dispatch(&$a) {
|
||||
|
||||
/**
|
||||
* Call module functions
|
||||
*/
|
||||
|
||||
if(\App::$module_loaded) {
|
||||
\App::$page['page_title'] = \App::$module;
|
||||
$placeholder = '';
|
||||
|
||||
/**
|
||||
* No theme has been specified when calling the module_init functions
|
||||
* For this reason, please restrict the use of templates to those which
|
||||
* do not provide any presentation details - as themes will not be able
|
||||
* to over-ride them.
|
||||
*/
|
||||
|
||||
if(function_exists(\App::$module . '_init')) {
|
||||
$arr = array('init' => true, 'replace' => false);
|
||||
call_hooks(\App::$module . '_mod_init', $arr);
|
||||
if(! $arr['replace']) {
|
||||
$func = \App::$module . '_init';
|
||||
$func($a);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Do all theme initialiasion here before calling any additional module functions.
|
||||
* The module_init function may have changed the theme.
|
||||
* Additionally any page with a Comanche template may alter the theme.
|
||||
* So we'll check for those now.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* In case a page has overloaded a module, see if we already have a layout defined
|
||||
* otherwise, if a PDL file exists for this module, use it
|
||||
* The member may have also created a customised PDL that's stored in the config
|
||||
*/
|
||||
|
||||
load_pdl($a);
|
||||
|
||||
/**
|
||||
* load current theme info
|
||||
*/
|
||||
|
||||
$theme_info_file = 'view/theme/' . current_theme() . '/php/theme.php';
|
||||
if (file_exists($theme_info_file)){
|
||||
require_once($theme_info_file);
|
||||
}
|
||||
|
||||
if(function_exists(str_replace('-', '_', current_theme()) . '_init')) {
|
||||
$func = str_replace('-', '_', current_theme()) . '_init';
|
||||
$func($a);
|
||||
}
|
||||
elseif (x(\App::$theme_info, 'extends') && file_exists('view/theme/' . \App::$theme_info['extends'] . '/php/theme.php')) {
|
||||
require_once('view/theme/' . \App::$theme_info['extends'] . '/php/theme.php');
|
||||
if(function_exists(str_replace('-', '_', \App::$theme_info['extends']) . '_init')) {
|
||||
$func = str_replace('-', '_', \App::$theme_info['extends']) . '_init';
|
||||
$func($a);
|
||||
}
|
||||
}
|
||||
|
||||
if(($_SERVER['REQUEST_METHOD'] === 'POST') && (! \App::$error)
|
||||
&& (function_exists(\App::$module . '_post'))
|
||||
&& (! x($_POST, 'auth-params'))) {
|
||||
call_hooks(\App::$module . '_mod_post', $_POST);
|
||||
$func = \App::$module . '_post';
|
||||
$func($a);
|
||||
}
|
||||
|
||||
if((! \App::$error) && (function_exists(\App::$module . '_content'))) {
|
||||
$arr = array('content' => \App::$page['content'], 'replace' => false);
|
||||
call_hooks(\App::$module . '_mod_content', $arr);
|
||||
\App::$page['content'] = $arr['content'];
|
||||
if(! $arr['replace']) {
|
||||
$func = \App::$module . '_content';
|
||||
$arr = array('content' => $func($a));
|
||||
}
|
||||
call_hooks(\App::$module . '_mod_aftercontent', $arr);
|
||||
\App::$page['content'] .= $arr['content'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
160
Zotlabs/Web/Session.php
Normal file
160
Zotlabs/Web/Session.php
Normal file
@@ -0,0 +1,160 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Web;
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief This file includes session related functions.
|
||||
*
|
||||
* Session management functions. These provide database storage of PHP
|
||||
* session info.
|
||||
*/
|
||||
|
||||
|
||||
class Session {
|
||||
|
||||
private static $handler = null;
|
||||
private static $session_started = false;
|
||||
|
||||
function init() {
|
||||
|
||||
$gc_probability = 50;
|
||||
|
||||
ini_set('session.gc_probability', $gc_probability);
|
||||
ini_set('session.use_only_cookies', 1);
|
||||
ini_set('session.cookie_httponly', 1);
|
||||
|
||||
/*
|
||||
* Set our session storage functions.
|
||||
*/
|
||||
|
||||
$handler = new \Zotlabs\Web\SessionHandler();
|
||||
self::$handler = $handler;
|
||||
|
||||
$x = session_set_save_handler($handler,true);
|
||||
if(! $x)
|
||||
logger('Session save handler initialisation failed.',LOGGER_NORMAL,LOG_ERR);
|
||||
|
||||
// Force cookies to be secure (https only) if this site is SSL enabled.
|
||||
// Must be done before session_start().
|
||||
|
||||
$arr = session_get_cookie_params();
|
||||
session_set_cookie_params(
|
||||
((isset($arr['lifetime'])) ? $arr['lifetime'] : 0),
|
||||
((isset($arr['path'])) ? $arr['path'] : '/'),
|
||||
((isset($arr['domain'])) ? $arr['domain'] : App::get_hostname()),
|
||||
((isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on') ? true : false),
|
||||
((isset($arr['httponly'])) ? $arr['httponly'] : true)
|
||||
);
|
||||
}
|
||||
|
||||
function start() {
|
||||
session_start();
|
||||
self::$session_started = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Resets the current session.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
function nuke() {
|
||||
self::new_cookie(0); // 0 means delete on browser exit
|
||||
if($_SESSION && count($_SESSION)) {
|
||||
foreach($_SESSION as $k => $v) {
|
||||
unset($_SESSION[$k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function new_cookie($xtime) {
|
||||
|
||||
$newxtime = (($xtime> 0) ? (time() + $xtime) : 0);
|
||||
|
||||
$old_sid = session_id();
|
||||
|
||||
if(self::$handler && self::$session_started) {
|
||||
session_regenerate_id(true);
|
||||
|
||||
// force SessionHandler record creation with the new session_id
|
||||
// which occurs as a side effect of read()
|
||||
|
||||
self::$handler->read(session_id());
|
||||
}
|
||||
else
|
||||
logger('no session handler');
|
||||
|
||||
if (x($_COOKIE, 'jsdisabled')) {
|
||||
setcookie('jsdisabled', $_COOKIE['jsdisabled'], $newxtime);
|
||||
}
|
||||
setcookie(session_name(),session_id(),$newxtime);
|
||||
|
||||
$arr = array('expire' => $xtime);
|
||||
call_hooks('new_cookie', $arr);
|
||||
|
||||
}
|
||||
|
||||
function extend_cookie() {
|
||||
|
||||
// if there's a long-term cookie, extend it
|
||||
|
||||
$xtime = (($_SESSION['remember_me']) ? (60 * 60 * 24 * 365) : 0 );
|
||||
|
||||
if($xtime)
|
||||
setcookie(session_name(),session_id(),(time() + $xtime));
|
||||
$arr = array('expire' => $xtime);
|
||||
call_hooks('extend_cookie', $arr);
|
||||
|
||||
}
|
||||
|
||||
|
||||
function return_check() {
|
||||
|
||||
// check a returning visitor against IP changes.
|
||||
// If the change results in being blocked from re-entry with the current cookie
|
||||
// nuke the session and logout.
|
||||
// Returning at all indicates the session is still valid.
|
||||
|
||||
// first check if we're enforcing that sessions can't change IP address
|
||||
// @todo what to do with IPv6 addresses
|
||||
|
||||
if($_SESSION['addr'] && $_SESSION['addr'] != $_SERVER['REMOTE_ADDR']) {
|
||||
logger('SECURITY: Session IP address changed: ' . $_SESSION['addr'] . ' != ' . $_SERVER['REMOTE_ADDR']);
|
||||
|
||||
$partial1 = substr($_SESSION['addr'], 0, strrpos($_SESSION['addr'], '.'));
|
||||
$partial2 = substr($_SERVER['REMOTE_ADDR'], 0, strrpos($_SERVER['REMOTE_ADDR'], '.'));
|
||||
|
||||
$paranoia = intval(get_pconfig($_SESSION['uid'], 'system', 'paranoia'));
|
||||
|
||||
if(! $paranoia)
|
||||
$paranoia = intval(get_config('system', 'paranoia'));
|
||||
|
||||
switch($paranoia) {
|
||||
case 0:
|
||||
// no IP checking
|
||||
break;
|
||||
case 2:
|
||||
// check 2 octets
|
||||
$partial1 = substr($partial1, 0, strrpos($partial1, '.'));
|
||||
$partial2 = substr($partial2, 0, strrpos($partial2, '.'));
|
||||
if($partial1 == $partial2)
|
||||
break;
|
||||
case 1:
|
||||
// check 3 octets
|
||||
if($partial1 == $partial2)
|
||||
break;
|
||||
case 3:
|
||||
default:
|
||||
// check any difference at all
|
||||
logger('Session address changed. Paranoid setting in effect, blocking session. '
|
||||
. $_SESSION['addr'] . ' != ' . $_SERVER['REMOTE_ADDR']);
|
||||
self::nuke();
|
||||
goaway(z_root());
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
88
Zotlabs/Web/SessionHandler.php
Normal file
88
Zotlabs/Web/SessionHandler.php
Normal file
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Web;
|
||||
|
||||
|
||||
class SessionHandler implements \SessionHandlerInterface {
|
||||
|
||||
|
||||
function open ($s, $n) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// IMPORTANT: if we read the session and it doesn't exist, create an empty record.
|
||||
// We rely on this due to differing PHP implementation of session_regenerate_id()
|
||||
// some which call read explicitly and some that do not. So we call it explicitly
|
||||
// just after sid regeneration to force a record to exist.
|
||||
|
||||
function read ($id) {
|
||||
|
||||
if($id) {
|
||||
$r = q("SELECT `data` FROM `session` WHERE `sid`= '%s'", dbesc($id));
|
||||
|
||||
if($r) {
|
||||
return $r[0]['data'];
|
||||
}
|
||||
else {
|
||||
q("INSERT INTO `session` (sid, expire) values ('%s', '%s')",
|
||||
dbesc($id),
|
||||
dbesc(time() + 300)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
|
||||
function write ($id, $data) {
|
||||
|
||||
if(! $id || ! $data) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Unless we authenticate somehow, only keep a session for 5 minutes
|
||||
// The viewer can extend this by performing any web action using the
|
||||
// original cookie, but this allows us to cleanup the hundreds or
|
||||
// thousands of empty sessions left around from web crawlers which are
|
||||
// assigned cookies on each page that they never use.
|
||||
|
||||
$expire = time() + 300;
|
||||
|
||||
if($_SESSION) {
|
||||
if(array_key_exists('remember_me',$_SESSION) && intval($_SESSION['remember_me']))
|
||||
$expire = time() + (60 * 60 * 24 * 365);
|
||||
elseif(local_channel())
|
||||
$expire = time() + (60 * 60 * 24 * 3);
|
||||
elseif(remote_channel())
|
||||
$expire = time() + (60 * 60 * 24 * 1);
|
||||
}
|
||||
|
||||
q("UPDATE `session`
|
||||
SET `data` = '%s', `expire` = '%s' WHERE `sid` = '%s'",
|
||||
dbesc($data),
|
||||
dbesc($expire),
|
||||
dbesc($id)
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
function close() {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
function destroy ($id) {
|
||||
q("DELETE FROM `session` WHERE `sid` = '%s'", dbesc($id));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
function gc($expire) {
|
||||
q("DELETE FROM session WHERE expire < %d", dbesc(time()));
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -132,7 +132,7 @@ class Auth {
|
||||
// tell them to logout if they're logged in locally as anything but the target remote account
|
||||
// in which case just shut up because they don't need to be doing this at all.
|
||||
|
||||
if (get_app()->channel['channel_hash'] == $hubloc['xchan_hash']) {
|
||||
if (\App::$channel['channel_hash'] == $hubloc['xchan_hash']) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
@@ -242,9 +242,9 @@ class Auth {
|
||||
|
||||
$arr = array('xchan' => $hubloc, 'url' => $this->desturl, 'session' => $_SESSION);
|
||||
call_hooks('magic_auth_success',$arr);
|
||||
get_app()->set_observer($hubloc);
|
||||
\App::set_observer($hubloc);
|
||||
require_once('include/security.php');
|
||||
get_app()->set_groups(init_groups_visitor($_SESSION['visitor_id']));
|
||||
\App::set_groups(init_groups_visitor($_SESSION['visitor_id']));
|
||||
info(sprintf( t('Welcome %s. Remote authentication successful.'),$hubloc['xchan_name']));
|
||||
logger('mod_zot: auth success from ' . $hubloc['xchan_addr']);
|
||||
$this->success = true;
|
||||
@@ -341,5 +341,5 @@ class Auth {
|
||||
* Service_class can be used by cooperating sites to provide different access rights based on account rights and subscription plans. It is
|
||||
* a string whose contents are not defined by protocol. Example: "basic" or "gold".
|
||||
*
|
||||
* @param[in,out] App &$a
|
||||
* @param[in,out] \App &$a
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Zot;
|
||||
|
||||
class DReport {
|
||||
|
||||
@@ -41,9 +41,10 @@ class Receiver {
|
||||
if(! $this->messagetype)
|
||||
$this->error = true;
|
||||
|
||||
$this->sender = ((array_key_exists('sender',$this->data)) ? $this->data['sender'] : null);
|
||||
$this->recipients = ((array_key_exists('recipients',$this->data)) ? $this->data['recipients'] : null);
|
||||
|
||||
if($this->data) {
|
||||
$this->sender = ((array_key_exists('sender',$this->data)) ? $this->data['sender'] : null);
|
||||
$this->recipients = ((array_key_exists('recipients',$this->data)) ? $this->data['recipients'] : null);
|
||||
}
|
||||
|
||||
if($this->sender)
|
||||
$this->ValidateSender();
|
||||
|
||||
42
Zotlabs/Zot/Verify.php
Normal file
42
Zotlabs/Zot/Verify.php
Normal file
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Zot;
|
||||
|
||||
|
||||
class Verify {
|
||||
|
||||
function create($type,$channel_id,$token,$meta) {
|
||||
return q("insert into verify ( type, channel, token, meta, created ) values ( '%s', %d, '%s', '%s', '%s' )",
|
||||
dbesc($type),
|
||||
intval($channel_id),
|
||||
dbesc($token),
|
||||
dbesc($meta),
|
||||
dbesc(datetime_convert())
|
||||
);
|
||||
}
|
||||
|
||||
function match($type,$channel_id,$token,$meta) {
|
||||
$r = q("select id from verify where type = '%s' and channel = %d and token = '%s' and meta = '%s' limit 1",
|
||||
dbesc($type),
|
||||
intval($channel_id),
|
||||
dbesc($token),
|
||||
dbesc($meta)
|
||||
);
|
||||
if($r) {
|
||||
q("delete from verify where id = %d",
|
||||
intval($r[0]['id'])
|
||||
);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function purge($type,$interval) {
|
||||
q("delete from verify where type = '%s' and created < %s - INTERVAL %s",
|
||||
dbesc($type),
|
||||
db_utcnow(),
|
||||
db_quoteinterval($interval)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,9 +2,6 @@
|
||||
|
||||
namespace Zotlabs\Zot;
|
||||
|
||||
require_once('Zotlabs/Zot/IHandler.php');
|
||||
|
||||
|
||||
class ZotHandler implements IHandler {
|
||||
|
||||
function Ping() {
|
||||
|
||||
@@ -18,7 +18,7 @@ view/php/default.php
|
||||
<html>
|
||||
<head>
|
||||
<title><?php if(x($page,'title')) echo $page['title'] ?></title>
|
||||
<script>var baseurl="<?php echo $a->get_baseurl() ?>";</script>
|
||||
<script>var baseurl="<?php echo z_root() ?>";</script>
|
||||
<?php if(x($page,'htmlhead')) echo $page['htmlhead'] ?>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
@@ -38,7 +38,7 @@ Inside it, put the following information - edit as needed
|
||||
|
||||
function mytheme_init(&$a) {
|
||||
|
||||
$a->theme_info['extends'] = 'redbasic';
|
||||
App::$theme_info['extends'] = 'redbasic';
|
||||
|
||||
|
||||
}
|
||||
@@ -63,7 +63,6 @@ In it, put the following:
|
||||
|
||||
That's it. This tells the software to read the PCSS information for the redbasic theme first, and then read our CSS file which will just consist of changes we want to make from our parent theme (redbasic).
|
||||
|
||||
|
||||
Now create the actual CSS file for your theme. Put it in view/theme/mytheme/css/style.css (where we just told the software to look for it). For our example, we'll just change the body background color so you can see that it works. You can use any CSS you'd like.
|
||||
|
||||
|
||||
@@ -74,4 +73,29 @@ Now create the actual CSS file for your theme. Put it in view/theme/mytheme/css
|
||||
|
||||
You've just successfully created a derived theme. This needs to be enabled in the admin "themes" panel, and then anybody on the site can use it by selecting it in Settings->Display Settings as their default theme.
|
||||
|
||||
**Lesson 2**
|
||||
|
||||
If you want to use the redbasic schemas for your derived theme, you have to do a bit more.
|
||||
|
||||
Do everything as above, but don't create view/theme/mytheme/php/style.php, but copy instead view/theme/redbasic/php/style.php to view/theme/mytheme/php/style.php. Modify that file and remove (or comment out) these two lines:
|
||||
|
||||
if(local_channel() && App::$channel && App::$channel['channel_theme'] != 'redbasic')
|
||||
set_pconfig(local_channel(), 'redbasic', 'schema', '---');
|
||||
|
||||
Also add this line at the bottom:
|
||||
|
||||
echo @file_get_contents('view/theme/mytheme/css/style.css');
|
||||
|
||||
To show the schema selector you have to copy view/theme/redbasic/tpl/theme_settings.tpl to view/theme/mytheme/tpl/theme_settings.tpl. Modify that file and replace the lines:
|
||||
|
||||
{{if $theme == redbasic}}
|
||||
{{include file="field_select.tpl" field=$schema}}
|
||||
{{/if}}
|
||||
|
||||
with:
|
||||
|
||||
{{include file="field_select.tpl" field=$schema}}
|
||||
|
||||
|
||||
|
||||
#include doc/macros/main_footer.bb;
|
||||
|
||||
@@ -12,7 +12,7 @@ There are certain scenarios where you might want your own directory-server that
|
||||
|
||||
* On the hub that will be the Directory Server, open the .htconfig.php file and set:
|
||||
|
||||
`$a->config['system']['directory_mode'] = DIRECTORY_MODE_PRIMARY;`
|
||||
`App::$config['system']['directory_mode'] = DIRECTORY_MODE_PRIMARY;`
|
||||
|
||||
|
||||
By default it should already be set as **DIRECTORY_MODE_NORMAL**, so just edit that line to say **DIRECTORY_MODE_PRIMARY**
|
||||
|
||||
@@ -48,10 +48,9 @@ Content (especially status posts) that you share with other networks or that you
|
||||
|
||||
Comments to posts that were created by others and posts which are designated as forum posts belong to you as the creator/author, but the distribution of these posts is not under your direct control. These posts/comments MAY be re-distributed to others, and MAY be visible to anybody on the internet. In the case of comments, the creator of the "first message" in the thread to which you are replying controls the distribution of all comments and replies to that message.
|
||||
|
||||
|
||||
**Private Information**
|
||||
|
||||
$Projectname developers will ensure that any content you provide which is designated as PRIVATE will be protected against eavesdropping - to the best of their ability. Private content is generally hidden or obscured even from hub administrators. It is also stripped from email notifications. It is difficult but NOT impossible for this content to be seen by a hub administrator. End to end encryption is provided as an optional feature and this CANNOT be seen, even by a determined administrator.
|
||||
$Projectname developers will ensure that any content you provide which is designated as PRIVATE will be protected against eavesdropping - to the best of their ability. Private channel content CAN be seen in the database of every involved hub administrator, but private messages are obscured in the database. The latter means that it is very difficult, but NOT impossible for this content to be seen by a hub administrator. Private channel content and private messages are also stripped from email notifications. End to end encryption is provided as an optional feature and this CANNOT be seen, even by a determined administrator.
|
||||
|
||||
##Identity Privacy
|
||||
|
||||
|
||||
78
doc/ca/Privacy.md
Normal file
78
doc/ca/Privacy.md
Normal file
@@ -0,0 +1,78 @@
|
||||
Política de Privacitat
|
||||
======================
|
||||
|
||||
|
||||
##Sumari##
|
||||
|
||||
|
||||
Q: Qui pot veure el meu contingut?
|
||||
|
||||
A: Per defecte TOTHOM A INTERNET, EXCEPTE que ho hagis restringit. $Projectname permet te triar el nivell de privacitat que desitgis. El contingut restringit no serà visible als "espies de la xarxa " ni als anunciants. Estarà protegit contra l'espionatge per estranys - de la millor manera que sabem. Administradors de nodes amb habilitats i paciència suficients poden ser capaços d'espiar a algunes comunicacions privades però han de invertir molt esforç per fer-ho. Hi maneres de Privacitat en $Projectname que són fins i tot resistents a escoltes il·legals pels administradors de nodes hàbils i decidits.
|
||||
|
||||
Q: Pot el meu contingut ser censurat?
|
||||
|
||||
A: $Projectname (la xarxa de nodes) NO POT censurat el teu contingut. Els administradors de servidor i del node estan subjectes a les lleis locals i poden suprimir contingut censurable des del seu lloc/node. Qualsevol POT convertir-se en un administrador de node, inclòs tu; i per tant publicar contingut que d'altra manera podria ser censurat. Encara i això estaràs subjecte a les teves lleis locals. Es la teva decisió.
|
||||
|
||||
|
||||
##Definicions
|
||||
|
||||
**$Projectname**
|
||||
|
||||
Coneguda d'un altre forma com "la xarxa", Hubzilla és una col·lecció d'equips individuals/servidors (àlies nodes) que connecten entre si per formar una xarxa cooperativa més gran.
|
||||
|
||||
**node (hub)**
|
||||
|
||||
Un equip individual o un servidor connectat a $Projectname. Aquests són proporcionats per un **administrador del node** i poden ser públics o privats, de pagament o gratuïts.
|
||||
|
||||
**administrador del node**
|
||||
|
||||
L'operador del sistema d'un node individual.
|
||||
|
||||
##Polítiques
|
||||
|
||||
**Informació Pública**
|
||||
|
||||
Qualsevol informació o cualsevol cosa publicada per tu a $Projectname POT ser pública o visible a qualsevol a Internet. En la mesura que sigui possible, $Projectname te permet protegir el contingut i restringir qui pot veure-ho.
|
||||
|
||||
La teva foto de perfil, el nom del teu canal, i la ubicació (URL o adreça de xarxa) del seu canal són visibles per a qualsevol persona a Internet i els controls de privacitat no afectaràn la visualització d'aquests elements.
|
||||
|
||||
POTS proporcionar, a més, un altra informació de perfil. Qualsevol informació que proporcionis en el teu perfil públic **per defecte** POT ser transmesa a altres centres en $Projectname i, a més, és possible que aparegui en el directori del canal. POTS restringir la visualització d'aquesta informació de perfil. Es POT restringir (permets que visualitzin), només als membres del teu nucli, o només les connexions (amics), o altres conjunts limitats de espectadors com desitgis. Si vols que el teu perfil estigui restringit, has d'establir la configuració de privacitat adequada, o simplement NO PROPORCIONIS informació addicional.
|
||||
|
||||
**Contingut**
|
||||
|
||||
El contingut que proporciones (missatges d'estat, fotos, arxius, etc.) et pertany a tu. Per defecte a $Projectname és publica contingut de forma oberta i visible per qualsevol en internet (PÚBLIC). POTS controlar això a la seva configuració del canal i restringir els permisos per defecte o pot restringir la visibilitat de qualsevol article únic publicat per separat (PRIVAT). Els desenvolupadors $Projectname s'han d'assegurat que el contingut restringit és visible NOMÉs per als que estan a la llista d'autoritzats - han emprat el millor d'ells per això.
|
||||
|
||||
El contingut (especialment les entrades d'estat) que es comparteixen amb altres xarxes o que has fet visible a qualsevol a Internet (PÚBLIC) no poden ser retirats (esborrats) fàcilment un cop que ha estat publicats. Pot haver estat compartit amb altres xarxes i posat a disposició a través de feeds RSS/Atom. També pot haver estat sindicat en altres llocs $Projectname. Pot aparèixer en les xarxes d'espionatge i recerques a Internet. Si no desitges aquest comportament per defecte, si et plau, ajusta la configuració del canal i restringeix qui pot veure el teu contingut.
|
||||
|
||||
**Comentaris i entrades a Forums**
|
||||
|
||||
Els comentaris als llocs que es van crear per altres i entrades que es designen com missatges al fòrum pertanyen tant a tu com al creador/autor, però la distribució d'aquests llocs no està sota el teu control directe. Aquestes entrades/comentaris es poden tornar a distribuir als altres, i pot ser visible per qualsevol en internet. En el cas dels comentaris, el creador del "primer missatge" al fil al qual està responent controla la distribució de tots els comentaris i respostes a aquest missatge.
|
||||
|
||||
|
||||
**Informació Privada**
|
||||
|
||||
Els desenvolupadors de $Projectname aseguraràn que cualsevol contingut que creis designat com PRIVAT estarà protegit contra estaràn protegits contra les escoltes - han emprat el millor d'ells per això. El contingut privat generalment s'amaga o enfosqueix fins i tot als administradors de nodes. També s'eliminen les notificacions per correu electrònic. És difícil, però no impossible que aquest contingut sigui vist per un administrador de node. El xifrat extrem a extrem es facilita com una característica opcional i fa el contingut, NO VISIBLE, fins i tot per un administrador determinat a veure'l.
|
||||
|
||||
##Privacitat de la Identitat
|
||||
|
||||
La Privacitat per la teva identitat és un altre aspecte. En tenir una identitat descentralitzada a $Projectname, la seva privacitat s'estén més enllà del seu node d'inici. Si vols tenir el control complet de la teva privacitat i seguretat has d'executar el teu propi centre en un servidor dedicat. Per a moltes persones, això és complicat i pot esgotar les seves habilitats tècniques. Així que anem a enumerar algunes precaucions que pots fer per assegurar la teva privacitat tant com sigui possible.
|
||||
|
||||
Una identitat descentralitzat té molts avantatges i te dóna un munt de característiques interessants, però has de ser conscient del fet que la teva identitat és coneguda per altres centres de la xarxa $Projectname. Un d'aquests avantatges és que altres canals poden servir contingut personalitzat i permetrà veure el contingut privat (com fotos privades que altres volen compartir amb vostè). Per això els canals necessiten saber qui ets. Però entenem que de vegades aquests altres canals en saben més de tu del que pugui desitjar. Per exemple, el plug-in Visage pot dir-li al propietari d'un canal l'última vegada que vas visitar el seu perfil. Pots renunciar fàcilment a aquest baix nivell de seguiment, que creiem inofensiu.
|
||||
|
||||
* Pots activar [No Em Segueixis (anglès:Do Not Track (DNT))](http://donottrack.us/) al teu navegador web. Respectem aquesta nova política de privacitat proposada. Tots en navegadors moderns soporten DNT. Trobaràs als ajustos de privacitat del teu navegador web o sino pots consultar el manual del navegador. Això no afectarà la funcionalitat de $Projectname. Aquest ajust, segurament, es suficient per la majoria de la gent.
|
||||
|
||||
* Pots [deshabilitar publicacions](ajustos) del teu canal al nostre canal de directoris. Si vols que la gent trobi el teu canal, has de facilitar la teva direcció del canal a ell(a). Pensem que això es un bon indicador que, en aquest cas, vols es un extra de privacitat i automaticament s'activarà "No Em Segueixis" (DNT).
|
||||
|
||||
* Pots tenir un node blocat. Això significa que tots els canals i contingut en aquest node no es públic i invisible al món exterior. Això és quelcom que només ho pot fer l'administrador del teu node. També es respecta això i automàticament s'activa DNT si és sel·leccionat.
|
||||
|
||||
###Censura
|
||||
|
||||
$Projectname és una xarxa global que inclou a totes les religions i cultures. Això no implica que tots els membres de la xarxa pensin de la mateixa manera que tu pel que fa en temes polèmics, i algunes persones poden sentir una forta oposició al contingut que publiquis. En general, si desitjes publicar alguna cosa que saps que no és universalment acceptable, el millor enfocament consisteix a restringir l'audiència utilitzant els controls de privacitat a un petit cercle d'amics.
|
||||
|
||||
$Projectname com un proveïdor de la xarxa no pot censurar el contingut. No obstant això, els administradors de node poden censurar qualsevol contingut que apareix en el seu centre per complir amb les lleis locals o fins i tot el seu judici personal. La seva decisió serà inapel·lable. Si té problemes amb qualsevol administrador de node, pots moure el teu compte i publicacions a un altre lloc que estigui més d'acord amb les teves expectatives. Si us plau comprova (periòdicament) les [Condicions d'ús](help/TermsOfService) del teu centre per aprendre sobre les normes o directrius. Si el teu contingut consisteix en un material que és il·legal o que pugui causar problemes, es recomana ENCARIDAMENT a allotjar tu mateix (convertir-te en un administrador de node). Podràs trobar que el teu contingut està bloquejat en alguns centres, però $Projectname, com a xarxa, no pot bloquejar una vegada publicat.
|
||||
|
||||
$Projectname RECOMANA que els administradors de nodes ofereixin un període de gràcia de 1-2 dies entre advertir al titular d'un compte, que hi ha contingut que ha de ser eliminat, i l'eliminació física o desactivació del compte. Això li donarà al propietari del contingut l'oportunitat d'exportar els seus canal de meta-dades i importar-lo a un altre lloc. En rares ocasions el contingut pot ser de tal naturalesa que es justifiqui l'eliminació immediata del compte. Aquesta és una decisió del node, no és una decisió de $Projectname.
|
||||
|
||||
Si normalment i regularment publiques contingut per a adults o de caràcter ofensiu, es recomana ENCARIDAMENT que marquis el compte com "NSFW" (No segur per al treball). Això evitarà que es mostri la teva foto de perfil al directori, excepte per als espectadors que han optat per desactivar el "mode segur". Si la teva foto de perfil es considera per a adults o ofensiu pels administradors de directori, l'administrador del directori POT marcar la teva foto de perfil com NSFW. Actualment no hi ha un sistema oficial per revertir aquesta decisió. Així DEURIES marcar tu mateix, el teu compte, com a NSFW si és probable que no sigui apropiat per a audiències generals.
|
||||
|
||||
#include doc/macros/main_footer.bb;
|
||||
8
doc/ca/TermsOfService.md
Normal file
8
doc/ca/TermsOfService.md
Normal file
@@ -0,0 +1,8 @@
|
||||
Termes del Servei
|
||||
================
|
||||
Aquest node Hubzilla encara no te Termes del Servei. Estic buscant un model adient.....
|
||||
En resum empreu el servei respectant els altres i no cometeu il·legalitats. Aquest node no s'identifica amb les opinions dels usuaris ni es responsablilitza de les mateixes.
|
||||
|
||||
|
||||
#include doc/SiteTOS.md;
|
||||
|
||||
27
doc/ca/about.bb
Normal file
27
doc/ca/about.bb
Normal file
@@ -0,0 +1,27 @@
|
||||
[b]Que és[/b]
|
||||
|
||||
$Projectname és una xarxa de comunicacions descentralitzades, que permet comunicacions lliures de censura, amb privacitat, i per tant lliure de les urpes opressores de gegants contemporanis de comunicació corporativa. Aquests gegants funcionen principalment com xarxes d''espionatge per a cobrar a clients de totes les classes i tipus, a més de monopolitzar i centralitzar Internet; una característica que no formava part dels objectius originals i revolucionàries que van produir la World Wide Web.
|
||||
|
||||
$Projectname és gratuït i de codi obert. Està dissenyat per a creixèr des de una raspberry pi de 35€, fins el màxim de la gama de servidors AMD i servidors empresarials de múltiples nuclis que funcionen amb Intel Xeon. Pot ser utilitzat per a suportar la comunicació entre uns pocs individus, o l'escalar a molts milers i més.
|
||||
|
||||
$Projectname pretén ser àgil i capaç de treballar amb múltiples recursos informàtics. És fàcil d'utilitzar pels usuaris habituals d''ordinadors, així com per administradors de sistemes i desenvolupadors.
|
||||
|
||||
|
||||
La forma d'utilitzar depèn de com voleu utilitzar-lo.
|
||||
|
||||
Està escrit en el llenguatge de scripting PHP, pel que és trivial instal·lar-lo en qualsevol plataforma d'allotjament en ús avui en dia. Això inclou l'auto-allotjament a casa, en els proveïdors d'allotjament, com ara [url=http://mediatemple.com/]Media Temple[/url] i [url=http://www.dreamhost.com/]Dreamhost[/url], o en servidors virtuals i dedicats, oferts per gràcia de [url=https://www.linode.com]Linode[/url], [url=http://greenqloud.com]GreenQloud[/url] o [url=https://aws.amazon.com]Amazon AWS[/url].
|
||||
|
||||
|
||||
En altres paraules, $Projectname es pot executar en qualsevol plataforma informàtica que vingui amb un servidor web, una base de dades compatible amb MySQL i el llenguatge de scripting PHP.
|
||||
|
||||
|
||||
|
||||
De pas, $Projectname ofereix una sèrie de atractius únics:
|
||||
|
||||
[b]Identificació amb un sol clic d'usuari:[/b] vol dir que pot accedir a llocs en $Projectname simplement fent clic als enllaços a llocs remots. L''autenticació passa automàgicament en segon plà. Oblida't de recordar múltiples noms d'usuari amb múltiples contrasenyes en accedir a diferents llocs en línia.
|
||||
|
||||
[b]La clonació:[/b] de les identitats en línia. La seva presència en línia ja no ha d'estar lligat a un sol servidor, nom de domini o adreça IP. Pot clonar i importar la seva identitat (o canal com en diem) a un altre servidor (o, en un concentrasor com son coneguts els servidors a $Projectname). Ara, si el seu concentrador/servidor cau, no et preocupis, els teus contactes, missatges [i]*[/i], i els missatges de [i]*[/i] automàgicament segueixen estant disponibles i accessibles al seu canal clonat. [i](*: només es perden els missatges i els missatges a partir del moment en que va clonar el seu canal)[/i]
|
||||
|
||||
[b]Privacitat:[/b] les identitats a $Projectname (Zot identificadors) es poden eliminar, salvar/descarregar i clonar. L'usuari té el control total de les seves dades. Si vostè decideix esborrar tot el seu contingut i esborrar la seva ID Zot, tot el que has de fer és fer clic a un enllaç i s'eliminen immediatament d concentrador/servidor. No hi ha preguntes, sense problemes.
|
||||
|
||||
#include doc/macros/main_footer.bb;
|
||||
19
doc/ca/accounts_profiles_channels_basics.bb
Normal file
19
doc/ca/accounts_profiles_channels_basics.bb
Normal file
@@ -0,0 +1,19 @@
|
||||
[size=large][b]Comptes, Perfils i Canals[/b][/size]
|
||||
|
||||
Una vegada t'has registrat amb un [i]compte[/i] al servei, també has de crear un [i]perfil[/i] i un [i]canal[/i].
|
||||
|
||||
[b]Compte[/b]
|
||||
Tens i]un[/i] compte. Això consisteix en una adreça de correu electrònic i una contrasenya. Amb el teu compte pots accedit al teu perfil i al teu canal.
|
||||
[i]Pensa en el teu compte com una via per autenticar-te al teu lloc $Projectname. Et permet fer coses com, crear perfils i canals amb els que podràs amb altres persones.[/i]
|
||||
|
||||
[b]Perfil[/b]
|
||||
Segurament t'has registrat a altres serveis a internet, com fòrums, o comunicacions en línia. Per a tots ells proveeixes alguna informació de tu, data de naixement, país, edat, i que es el que d'agrada. [observer=1]If you like you can see your profile here: [baseurl]/profile/[observer.webname] and edit it by clicking on the pencil icon next to your avatar image. [/observer]
|
||||
Unlike other services $Projectname offers you the advantage of creating [i]many more profiles[/i]. That way you are able to distinguish between profiles targeted specially at everyone (your public profile), your work mates, your family and your partner.
|
||||
[i]Think of your profile as the basic information about yourself you tell other people.[/i]
|
||||
|
||||
[b]Channel[/b]
|
||||
During the registration you created your first [i]channel[/i]. Yes, besides several profiles you are able to have several channels. This might be a bit confusing in the beginning, but let's clear things up. You already have created one channel. You can use this one for the public, to communicate with people about every day life. But perhaps you are an avid book reader and many people are bored by that. So you open a [i]second channel[/i] just for the book lovers, where you all can talk about books as much as you like. Obviously this is a new stream of posts, with a new profile (... or new profile[i]s[/i] ...) and completely different contacts. Some connections might exist in both channels, but there will be some that are exclusive to only one of both. You yourself just switch between both of them just like you would in real life switch when talking to people you meet on the street or people you meet specially to talk about books. You can even connect to yourself, or better: to your other channel. :)
|
||||
[i]Think of a channel as different spaces dedicated to different topics where you meet with different people.[/i]
|
||||
|
||||
#include doc/macros/main_footer.bb;
|
||||
|
||||
15
doc/ca/admins.bb
Normal file
15
doc/ca/admins.bb
Normal file
@@ -0,0 +1,15 @@
|
||||
[h2]Documentació per a Administradors de Concentradors (dits Hubs en anglès)[/h2]
|
||||
|
||||
[h3]Administradors[/h3]
|
||||
|
||||
[zrl=[baseurl]/help/install]Instal·lació[/zrl]
|
||||
[zrl=[baseurl]/help/red2pi]Instal·lant $Projectname en una Raspberry Pi[/zrl]
|
||||
[zrl=[baseurl]/help/Hubzilla_on_OpenShift]$Projectname en OpenShift[/zrl]
|
||||
[zrl=[baseurl]/help/troubleshooting]Consells per solucionar problemes[/zrl]
|
||||
[zrl=[baseurl]/help/hidden_configs]Afinant Configuracions ocultes de $Projectname[/zrl]
|
||||
[zrl=[baseurl]/help/faq_admins]FAQ Per als Administradors[/zrl]
|
||||
[zrl=[baseurl]/help/service_classes]Classes de Serveis[/zrl]
|
||||
[zrl=[baseurl]/help/directories]Treballant amb i configuració de directoris[/zrl]
|
||||
[zrl=[baseurl]/help/theme_management]Gestió de Temes[/zrl]
|
||||
|
||||
|
||||
32
doc/ca/channels.bb
Normal file
32
doc/ca/channels.bb
Normal file
@@ -0,0 +1,32 @@
|
||||
[b]Canals[/b]
|
||||
|
||||
|
||||
|
||||
Els canals són simplement col·leccions de continguts emmagatzemats en un sol lloc. Un canal pot representar qualsevol cosa. Podria representi, un lloc web, un fòrum, àlbums de fotos, qualsevol cosa. Per a la majoria de la gent, el seu primer canal serà "Ell" mateix.
|
||||
|
||||
Les característiques més importants d'un canal que "em" representa són:
|
||||
|
||||
Comunicacions segures i privades "lliures d'spam"
|
||||
|
||||
Identitat i "un sol inici de sessió " a través de tota la xarxa
|
||||
|
||||
Controls de privacitat i permisos que s'estenen a tota la xarxa
|
||||
|
||||
Serveis de directori (com una guia telefònica)
|
||||
|
||||
En resum, una cadena que et representa a tú mateix és "jo, a l'Internet ".
|
||||
|
||||
Hauràs de crear el teu primer canal com a part del procés de registre. També pots crear canals additonal des del menú "Selecciona canal ".
|
||||
|
||||
Se li demanarà que proporcioni un nom de canal, i un curt sobrenom. Per a un canal que et representa a tu mateix, és una bona idea utilitzar el teu nom real per assegurar-se que els teus amics puguin trobar-te, i connectar al teu canal. El sobrenom curt s'utilitzarà per generar un nom "intermediari". Això és una mica com un nom d'usuari, i es veurà com una adreça de correu electrònic, prenent forma sobrenom@domini. Has de pensar una mica en que desitges utilitzar aquí. Imagina a algú demanant la teu nom intermediari i haver de dir-los que és "Crema-miss_issipi.123". "cremamississipi" seria una opció molt millor.
|
||||
|
||||
Una vegada que hagis creat el teu canal, se't portarà a la pàgina de configuració, que permet definir el teu canal, i establir els teus permisos predeterminats.
|
||||
|
||||
Un cop fet això, el canal està llest per utilitzar. En [observer=1][observer.url][/observer][observer=0]example.com/channel/username[/observer] trobaràs el teu canal de "flux". Aquí és on apareixerà la teva activitat recent, en ordre cronològic invers. Si publica a la casella "compartir", apareixerà l'entrada a la part superior del teu flux. També trobaràs enllaços a totes les altres àrees de comunicació per aquest canal. El fitxa "en quant a " conté el teu "perfil", la pàgina de fotos conté àlbums de fotos, i la pàgina d'esdeveniments conté esdeveniments compartits per tu i els teus contactes.
|
||||
|
||||
La pàgina "Xarxa" conté tots els missatges recents de tota la xarxa $Projectname, de nou amb sentit cronològic invers. Els missatges exactes que apareixen aquí depenen en gran mesura dels teus permisos. En la teva forma més permissiva, rebràs missatges de desconeguts. A l'altre extrem de l'escala, podràs veure els missatges de només els seus amics - o si ets realment antisocial, només els teus propis missatges.
|
||||
|
||||
Com s'ha esmentat al principi, són possibles molts altres tipus de canal, però, el procediment de creació és el mateix. La diferència entre els canals es troba principalment en els permisos assignats. Per exemple, una cadena per a l'intercanvi de documents amb els seus col.legues a la feina, és millor si canvieu valors més permissius per "Em pot escriure en el meu" públic "magatzem d'arxius ", que un compte personal. Per obtenir més informació, consulteu la secció de permisos.
|
||||
|
||||
|
||||
#include doc/macros/main_footer.bb;
|
||||
34
doc/ca/develop.bb
Normal file
34
doc/ca/develop.bb
Normal file
@@ -0,0 +1,34 @@
|
||||
[h2]Documentació per Desenvolupadors[/h2]
|
||||
|
||||
[h3]Documentació Tècnica[/h3]
|
||||
[zrl=[baseurl]/help/Zot---A-High-Level-Overview]Una vista en profunditat a Zot[/zrl]
|
||||
[zrl=[baseurl]/help/zot]Una introducció a Zot[/zrl]
|
||||
[zrl=[baseurl]/help/zot_structures]Estuctures a Zot[/zrl]
|
||||
[zrl=[baseurl]/help/comanche]Descripcions de Pàgina a Comanche[/zrl]
|
||||
[zrl=[baseurl]/help/Creating-Templates]Creant Plantilles a Comanche[/zrl]
|
||||
[zrl=[baseurl]/help/Widgets]Artilugis[/zrl]
|
||||
[zrl=[baseurl]/help/plugins]Complements[/zrl]
|
||||
[zrl=[baseurl]/help/hooklist]Ganxos (detallat - en construcció)[/zrl]
|
||||
[zrl=[baseurl]/help/doco]Documentació[/zrl]
|
||||
[zrl=[baseurl]/help/DerivedTheme1]Creant Temes Derivats[/zrl]
|
||||
[zrl=[baseurl]/help/schema_development]Esquemes[/zrl]
|
||||
[zrl=[baseurl]/help/Translations]Traduccions[/zrl]
|
||||
[zrl=[baseurl]/help/developers]Desenvolupadors[/zrl]
|
||||
[zrl=[baseurl]/help/intro_for_developers]Introducció per Desenvolupadors[/zrl]
|
||||
[zrl=[baseurl]/help/database]Documentació del esquema de la base de dades[/zrl]
|
||||
[zrl=[baseurl]/help/api_functions]Funcions de la API[/zrl]
|
||||
[zrl=[baseurl]/help/api_posting]Entrades a $Projectname emprant la API[/zrl]
|
||||
[zrl=[baseurl]/help/developer_function_primer]Funcions Red 101[/zrl]
|
||||
[zrl=[baseurl]/doc/html/]Refrència del Codi (Doxygen generat - ajust de cookies)[/zrl]
|
||||
[zrl=[baseurl]/help/to_do_doco]Llista de Pendents per a la Documentació del Projecte $Projectname[/zrl]
|
||||
[zrl=[baseurl]/help/to_do_code]Llista de Pendents per a Desenvolupadors[/zrl]
|
||||
[zrl=[baseurl]/help/roadmap]Full de ruta[/zrl]
|
||||
[zrl=[baseurl]/help/git_for_non_developers]Git per a No-Desenvolupadors[/zrl]
|
||||
[zrl=[baseurl]/help/dev_beginner]Manual pas-a-pas per a desenvolupadors principiants[/zrl]
|
||||
|
||||
[h3]Preguntes Més Freqüents (FAQ) Per Desenvolupadors[/h3]
|
||||
[zrl=[baseurl]/help/faq_developers]FAQ Per Desenvoupadors[/zrl]
|
||||
|
||||
[h3]Recursos Externs[/h3]
|
||||
[url=https://zothub.com/channel/one]Development Channel[/url]
|
||||
[url=https://federated.social/channel/postgres]Postgres-specific $Projectname Admin Support Channel[/url]
|
||||
202
doc/ca/features.bb
Normal file
202
doc/ca/features.bb
Normal file
@@ -0,0 +1,202 @@
|
||||
[b][size=36]Característiques[/size][/b]
|
||||
|
||||
[b][size=24]$Projectname en Poques Paraules[/size][/b]
|
||||
|
||||
TL;DR
|
||||
|
||||
$Projectname proveeix publicacions i comunicacions socials distribuïdes amb [b]permisos descentralitzats[/b].
|
||||
|
||||
Així, que vol dir "permisos descentralitzats"? Em donen la habilitat de compàrtir quelcom al meu lloc web (fotos, mitjans, arxius, pàgines web, etc.) Aamb persones específiques en llocs completament diferents - encara que no necesàriament amb [i]tothom[/i] en aquests llocs web; i no es necessita tenir un usuari i contrasenya en aquests altres llocs web per poder fer-ho ni per poder tafanejar el que ells han compartit amb mi. Ells tenen un usuari i contrasenya al seu lloc web i "màgica autenticació" entre llocs web afiliats a la xarxa. També, al esser centralitzat, no hi ha terceres parts que puguin saltar-se els permisos i veure el que estàs fent a la xarxa.
|
||||
|
||||
$Projectname combina moltes característiques dels blocs tradicionals, les xarxes socials i els mitjans de comunicació, sistemes de gestió de continguts i emmagatzematge en el núvol personal en un marc de treball fàcil d'utilitzar. Cada node de la xarxa pot funcionar independent o enllaçar amb altres nodes per crear una súper-xarxa; deixant la privacitat sota el control de l'editor original.
|
||||
|
||||
$Projectname és una aplicació de servidor web de codi obert escrit originalment en PHP/MySQL i és fàcilment instalable per aquells amb habilitats d'administració web bàsiques. També s'estén fàcilment a través de plugins i temes i altres eines de tercers.
|
||||
|
||||
[b][size=24]Característiques de $Projectname[/size][/b]
|
||||
|
||||
|
||||
$Projectname és un tot terreny per a la publicació web i una xarxa de comunicacions amb diverses característiques úniques. Està dissenyat per a ser utilitzat per la gamma més àmplia de persones a la web, dels blocaires no tècnics, als programadors de PHP experts i administradors de sistemes experimentats.
|
||||
|
||||
A aquesta pàgina s'enumeren algunes de les característiques fonamentals de $Projectname que s'inclouen amb la versió oficial. Igual que amb la majoria del programari lliure i de codi obert, pot haver moltes altres extensions, complements, plugins, temes i configuracions que estan limitats només per les necessitats i la imaginació dels membres.
|
||||
|
||||
[b][size=24]Construït per la Privacitat i la Llibertat[/size][/b]
|
||||
|
||||
Un dels objectius de disseny de $Projectname és permetre la comunicació fàcil a la web, mentre que preserva la intimitat, si així es desitja pels membres. Per aconseguir aquest objectiu, $Projectname inclou una sèrie de característiques que permeten nivells arbitraris de privacitat:
|
||||
|
||||
[b]Control Lliscant d'Afinitat[/b]
|
||||
|
||||
En afegir connexions en $Projectname, els membres tenen l'opció d'assignar nivells de "afinitat" (el prop que la seva amistat és amb el contacte) per a la nova connexió. Per exemple, quan s'afegeix a algú que resulta ser una persona a la que segueixes el seu bloc, podries assignar al seu canal un nivell d'afinitat de "Coneguts".
|
||||
|
||||
D'altra banda, quan s'afegeix el canal d'un amic, que pot ser col·locat sota el nivell d'afinitat de "Amics".
|
||||
|
||||
En aquest punt, l'eina [i]Control Lliscant d'Afinitat[/i] de $Projectname, que en general apareix a la part superior de la teva pàgina, ajusta el contingut de la pàgina per incloure als que estan dins del rang afinitat desitjada. No es mostraran Canals fora d'aquest rang, llevat que s'ajusti el Control Lliscant per incloure'ls.
|
||||
|
||||
El Control Lliscant D'Afinitat permet filtrar instantàniament grans quantitats de contingut, agrupats per nivells de proximitat.
|
||||
|
||||
[b]Filtre de Connexions[/b]
|
||||
|
||||
Tens la capacitat de controlar amb precisió el que apareix en el teu flux emprant opcionalment el "filtre de connexió". Quan s'activa, l'editor de connexió proporciona entrades per a la selecció de criteris que ha de ser aparellat amb la finalitat d'incloure o excloure un lloc específic d'un canal específic. Una vegada que un missatge s'ha permès, tots els comentaris a aquest lloc se'ls permet, independentment de si s'ajusten als criteris de selecció. Pots seleccionar paraules que si estàn presents al bloc o assegurar-te que està inclosses en el teu flux. Les expressions regulars es poden usar per al control encara més fi, així com hashtags o fins i tot l'idioma detectat del lloc.
|
||||
|
||||
[b]Llista de Control d'Accés[/b]
|
||||
|
||||
En compartir el contingut, els membres tenen l'opció de restringir qui veu el contingut. En fer clic al cadenat sota de la casella de compartir, un pot triar els destinataris desitjats del lloc, fent clic en els seus noms.
|
||||
|
||||
Un cop enviat, el missatge serà visible únicament pel remitent i els destinataris seleccionats. En altres paraules, el missatge no apareixerà al mur públic.
|
||||
|
||||
Llistes de Control d'Accés es poden aplicar als continguts i missatges, fotos, esdeveniments, pàgines web, sales de xat i arxius.
|
||||
|
||||
[b]Inici de Sessió Únic[/b]
|
||||
|
||||
Les Llistes de Control d'Accés treballen per a tots els canals a la xarxa gràcies a la nostra tecnologia única d'inici de sessió únic. La majoria dels enllaços interns proporcionen una identitat símbolica que pot ser verificada en altres llocs $Projectname i s'utilitza per controlar l'accés als recursos privats. Entres una vegada al teu concentrador. Després d'això, l'autenticació de tots els recursos de $Projectname és "màgia".
|
||||
|
||||
|
||||
[b]WebDAV activa l'Emagatzematge d'Arxius[/b]
|
||||
|
||||
Els arxius poden ser enviats a la teva àrea d'emmagatzematge personal utilitzant les teves utilitats del sistema operatiu (arrossegar i deixar anar en la majoria dels casos). Pots protegir aquests arxius amb la Llista de Control d'Accés amb qualsevol combinació de membres de $Projectname (incloent alguns membres d'altres terceres xarxes) o fer-los públics.
|
||||
|
||||
[b]Foto Àlbums[/b]
|
||||
|
||||
Salva Fotos en Àlbums. Totes les fotografies es poden protegir mitjançant llistes de control d'accés.
|
||||
|
||||
[b]Calendari d'Esdeveniments[/b]
|
||||
|
||||
Creació i gestió d'esdeveniments i tasques, que també poden ser protegits amb llistes de control d'accés. Els esdeveniments poden ser importats/exportats a un altre programari amb el format estàndard de la indústria vCalendar/iCal i compartida en els llocs amb els altres. Esdeveniments d'aniversari s'agreguen automàticament dels teus amics i es tradueixen a la seva zona horària correcta així sabràs exactament quan es produeix l'aniversari - no importa on et trobis en el món en relació amb la persona de l'aniversari. Els esdeveniments es creen normalment amb taulells d'assistència perquè els teus amics i connexions puguin confirmar la seva assistència a l'instant.
|
||||
|
||||
[b]Sales de Xat[/b]
|
||||
|
||||
Pots crear qualsevol nombre de sales de xat personals i permetre l'accés a través de llistes de control d'accés. Aquestes solen ser més segures que XMPP, IRC, i altres transports de missatgeria instantània, encara que també permetem l'ús d'aquests altres serveis a través de connectors.
|
||||
|
||||
[b]Constructor de Pàgines Web[/b]
|
||||
|
||||
$Projectname té moltes eines de creació de "Gestió de Contingut" per a la creació de pàgines web, incloent l'edició disposició, menús, blocs, widgets, i pàgina/contingut per regions. Totes aquestes poden ser d'accés controlat perquè les pàgines resultants siguin privades per al seu públic objectiu.
|
||||
|
||||
[b]Apps/Aplicacions[/b]
|
||||
|
||||
Apps poden ser construïdes i distribuïdes pels membres. Aquestes aplicacions són diferents del tradicional "bloqueig pel proveïdor" perquè són controlats completament per l'autor - que pot proporcionar control d'accés a les pàgines d'aplicacions de destinació i la càrrega consegüent per a aquest accés. La majoria de les aplicacions en $Projectname són gratuïtes i es poden crear fàcilment per aquells que no tenen coneixements de programació.
|
||||
|
||||
[b]Disposició[/b]
|
||||
|
||||
La disposició de la pàgina es basa en un llenguatge de descripció anomenat Comanche. $Projectname en si mateix està escrit amb dissenys de Comanche i es poden canviar. Això permet un nivell de personalització que no se sol trobar en els anomenats "entorns multiusuari".
|
||||
|
||||
[b]Favorits[/b]
|
||||
|
||||
Compartir i guardar/administrar els enllaços de favorits proporcionats en les converses.
|
||||
|
||||
|
||||
[b]Xifrat de missatges privats i Dubtes sobre la confidencialitat[/b]
|
||||
|
||||
El correu privat s'emmagatzema en un format ocult. Si bé això no és a prova de bales, en general, evita l'espionatge informal per l'administrador del lloc o ISP.
|
||||
|
||||
Cada canal de $Projectname té el seu propi conjunt únic de claus RSA (de 4096 bits) públiques i privades associades, que es genera quan es crea primer els canals. Això s'utilitza per protegir els missatges privats i missatges en trànsit.
|
||||
|
||||
A més, els missatges poden ser creats utilitzant "xifrat d'extrem a extrem", que no pot ser llegit per els operadors $Projectname o ISPs o algú que no coneixi el codi d'accés.
|
||||
|
||||
Els missatges públics en general, no es xifren en trànsit o en l'emmagatzematge.
|
||||
|
||||
Els missatges privats poden ser retirats (com si no s'hagués enviat), encara que no es garanteix que el destinatari no l'ha llegit abans que l'hagis retirat.
|
||||
|
||||
Entrades i missatges poden ser creats amb una data de venciment, moment en el qual s'eliminaran/borraran en el lloc del destinatari.
|
||||
|
||||
|
||||
[b]Servei de Federació[/b]
|
||||
|
||||
A més de l'afegit (addon) "connectors d'entrades creuades" a una varietat de xarxes alternatives, no hi ha suport natiu per a la importació de continguts de RSS/Atom i usar això per crear canals especials. A més, una implementació experimental, però de treball del protocol de la Diàspora permet la comunicació amb la gent en les xarxes socials friendica i Diàspora descentralitzats. Actualment això es va marcar experimental a causa de que aquestes xarxes no tenen el mateix nivell de funcions de privacitat i encriptació i habilitats com $Projectname i poden presentar riscos per a la privacitat.
|
||||
També hi ha suport experimental per a l'autenticació OpenID que es pot utilitzar en les llistes de control d'accés. Aquest és un treball en progrés. El seu concentrador $Projectname pot ser utilitzat com un proveïdor d'OpenID per autenticar als serveis externs que utilitzen aquesta tecnologia.
|
||||
Els canals poden tenir permisos per convertir-se en "canals derivats" on dos o més canals existents es combinen per crear un nou canal d'actualitat.
|
||||
|
||||
[b]Col·leccions[/b]
|
||||
|
||||
"Col·leccions" és la nostra implementació de grups de privacitat, que és similar a Google "Cercles" i "Aspectes" de Diaspora. Això li permet filtrar el flux entrant per col·leccions o grups, i automàticament configurar la llista de control d'accés sortint a només aquells en la Col·lecció quan publiqui. Pots obviar tot això en qualsevol moment (abans d'enviar l'entrada).
|
||||
|
||||
|
||||
[b]Serveis de Directori [/b]
|
||||
|
||||
Oferim fàcil accés a un directori de membres i proporcionem eines descentralitzades capaçes de proporcionar amics "suggerits". Els directoris són llocs normals $Projectname que han optat per acceptar la funció de servidor de directori. Això requereix més recursos que la majoria dels llocs típics pel que no és el predeterminat. Els Directoris estan sincronitzats i reflecteixen el que tots ells contenen amb informació actualitzada sobre tota la xarxa (subjecte a demores normals de propagació).
|
||||
|
||||
|
||||
[b]TLS/SSL[/b]
|
||||
|
||||
Els concentradors de $Projectname que empran TLS/SSL, les comunicacions entre client i servidor son encriptades via TLS/SSL. Donades les recents revelacions en els mitjans de comunicació en relació amb, la vigilància global i l'elusió de xifrat pel NSA i GCHQ, és raonable suposar que les comunicacions HTTPS-protegides es poden veure compromeses de diverses maneres. Les comunicacions privades són en conseqüència xifrades en un nivell superior abans d'enviar-les fora del lloc.
|
||||
|
||||
[b]Ajustos del Canals[/b]
|
||||
|
||||
Quan es crea un canal, es tria un rol al que s'apliquen una sèrie d'ajustos de seguretat i privacitat preconfigurats. Aquests són elegits per les millors pràctiques per mantenir la privacitat en els nivells requerits.
|
||||
|
||||
Si escolliu un paper privacitat "personalitzat", cada canal permet permisos de gra fi que es fixaràn per a diferents aspectes de la comunicació. Per exemple, sota la capçalera "Ajusts de Seguretat i Privacitat", cada aspecte a la banda esquerra de la pàgina, té sis (6) Opcions possibles de visualització/accés, que es poden seleccionar fent clic al menú desplegable. També hi ha una sèrie d'altres opcions de privacitat que pots editar.
|
||||
|
||||
Les opcions són:
|
||||
- Ningú, excepte tu mateix.
|
||||
- Només aquells que es permeten específicament.
|
||||
- Qualsevol persona en la seva llibreta d'adreces.
|
||||
- Qualsevol en aquest lloc web.
|
||||
- Qualsevol persona en aquesta xarxa.
|
||||
- Qualsevol autenticat.
|
||||
- Qualsevol persona a Internet.
|
||||
|
||||
[b]Forums Públics i Privats[/b]
|
||||
|
||||
Els fòrums són típicament canals que poden estar obertes a la participació de múltiples autors. Actualment existeixen dos mecanismes per pujar als fòrums: 1) els missatges "de mur a mur" i 2) a través de les etiquetes de foro @menció. Els fòrums poden ser creats per qualsevol persona i s'utilitzats per a qualsevol propòsit. El directori conté una opció per buscar fòrums públics. Als Fòrums privats només es poden fer entrades pels membres i sovint només son vistos pels membres.
|
||||
|
||||
|
||||
[b]Clonat de Comptes[/b]
|
||||
|
||||
Els Comptes a $Projectname es refereixen com a [i]identitats nómades[/i], perquè la identitat d'un membre no està lligada al concentrador/servidor on es va crear originalment. Per exemple, quan es crea un compte de Facebook o Gmail, que està lligat a aquests serveis. No poden funcionar sense Facebook.com o Gmail.com.
|
||||
|
||||
Per contra, imagina que has creat una identitat a $Projectname anomenada [b]tina@Hubzillahub.com[/b]. Aquesta es pot clonar a un altre hub de $Projectname amb el mateix nom o un altre de diferent: per exemple [b]viuPerSempre@HubzillaHub.info[/b]
|
||||
|
||||
Tots dos canals estan ara sincronitzats, el que significa que tots els seus contactes i preferències es dupliquen en el teu clon. No importa si s'envia un missatge des del seu hub original o el nou centre. Els missatges/emtrades seran reflectits/des en tots dos comptes.
|
||||
|
||||
Aquesta és una característica bastant revolucionària, si tenim en compte alguns dels escenaris:
|
||||
|
||||
- Què passa si el concentrador/servidor on la identitat es basa cau sobtadament fora de línia? Sense clonació, un membre no pot comunicar fins que aquest centre torna a estar de nou en línia (sens dubte molts de vosaltres heu vist i maleït el Twitter "Fail Whale"). Amb la clonació, es pot iniciar la sessió al compte clonat, i la vida continua feliços per sempre. - L'administrador del teu concentrador/servidor ja no es pot permetre el luxe de pagar el concentrador/servidor $Projectname que ofereix gratuitament. Llavors anuncia que el centre serà tancant en dues setmanes. Això li dóna temps suficient als socis/partíceps per clonar la seva identitat/s i preservar les seves relacions de $Projectname, amics i contingut. - Què passa si la teva identitat està subjecta a la censura del govern? El teu proveïdor del concentrador/servidor pot ser obligat a eliminar el teu compte, juntament amb les identitats i dades associades. Amb la clonació, a $Projectname ofereixes [b]resistència a la censura[/b]. Pots tenir centenars de clons, si vols, amb noms totalment diferents, i existents en molts centres diferents, escampats a tot l'Internet.
|
||||
|
||||
$Projectname ofereix noves i interesants possibilitats per a la privacitat. Pots llegir més a la pàgina <<Bones Pràctiques en Comunicacions Privades>>.
|
||||
|
||||
A tenir en compte. Per a una explicació completa de la clonació d'identitat, llegir el <HOW TO CLONE MY IDENTITY>.
|
||||
|
||||
[b]Perfils Multiples[/b]
|
||||
|
||||
Es poden crear qualsevol nombre de perfils amb informació diferent i es poden fer-se visible/s a alguns de les teves connexions/amics. Un perfil "per defecte" es pot veure per qualsevol persona i pot contenir informació limitada, amb més informació disponible per grups o persones seleccionades. Això vol dir que el perfil (i el contingut del lloc) per als teus amics bevedors de cervesa pot ser diferents del que presentes als seus companys de treball, i també completament diferent del que és visible per al públic en general.
|
||||
|
||||
[b]Còpies de Seguretat del Compte[/b]
|
||||
|
||||
Hubzilla ofereix una còpia de seguretat del compte, amb un simple clic, on pots descarregar una còpia de seguretat completa del teu perfil(s).
|
||||
|
||||
Les còpies de seguretat es poden utilitzar per clonar o restaurar un perfil.
|
||||
|
||||
[b]Eliminació del Compte[/b]
|
||||
|
||||
Els comptes poden ser [b]esborrats immediatament[/b] fent clic en un enllaç. [b]Això és així[/b]. Tot el contingut associat s'elimina de la xarxa (això inclou els missatges i qualsevol altre tipus de contingut produït pel perfil suprimit). Depenent del nombre de connexions que té, el procés d'eliminació de contingut remot podria portar el seu temps, però està previst que passi tan aviat com sigui possible.
|
||||
|
||||
[b][size=20]Creació de Contingut[/size][/b]
|
||||
|
||||
[b]Escribint Entrades[/b]
|
||||
|
||||
$Projectname suporta un nombre de diferents alternatives per afegir contingut amb text enriquit. La opció per defecte es una variant personalitzada de _BBcode, ajustada per al seu ús a $Projectname. Pots activar l'ús de Markdown (un llenguatge de marques) fàcil de treballar amb ell. Un editor visual també es pot emprar. El editor visual tradicionalment emprat en $Projectname va tenir seriosos problemes i ha estat eliminat. Estem actualment buscant un substitut.
|
||||
|
||||
Quant creem "llocs Web", El contingut espot afegir en HTML, Markdown, BBcode, i/o text plà.
|
||||
|
||||
[b]Esborrat del contingut[/b]
|
||||
Qualsevol contingut creat a $Projectname roman sota el control del membre (o canal) que el va crear originalment. En qualsevol moment, un membre pot esborrar un missatge o un rang de missatges. El procés d'esborrat assegura que el contingut es eliminat, indiferentment de on es va publicar si en el canal primari (l'inicial)del concentrador/servidor o en altre qualsevol on el canal es va autenticar remotament via Zot ($Projectname communicació i protocol d'autenticació).
|
||||
|
||||
[b]Multimedia[/b]
|
||||
Igual que qualsevol altre sistema modern de blocs, xarxes socials, o d'un servei de micro-blogging, $Projectname és compatible amb la càrrega d'arxius, la incorporació dels vídeos, l'enllaç de pàgines web.
|
||||
|
||||
[b]Vista Prèvia/Edició[/b]
|
||||
Les entrades es poder pre visualitzar abans d'enviar-les i reeditar desprès de ser enviades.
|
||||
|
||||
[b]Votacions/Consens[/b]
|
||||
El missatges poden convertir-se en "consensos", són articles que ofereixen als lectors una forma de retroalimentació, es recopilen en comptadors de "d'acord", "en desacord" i "abstenir-se". Que permeten mesurar l'interès per les idees i crear enquestes informals.
|
||||
|
||||
|
||||
[b]Estenent $Projectname[/b]
|
||||
|
||||
$Projectname es pot estendre per diferents nombre de vies, a través de la personalització del lloc, la teva personalització, ajustos optatius, temes i addons/plugins.
|
||||
|
||||
[b]API[/b]
|
||||
|
||||
Una API està disponible per al seu ús per serveis de terceres part. Està basat originalment en una de les primeres API's de Twitter(de la que existeixen cents d'eines de terceres parts). S'està ampliant actualment per proporcionar accés a les instal·lacions i capacitats que són específiques de $Projectname. L'accés pot ser proporcionada per usuari/contrasenya o OAuth i es proporciona registre de clients d'aplicacions OAuth.
|
||||
|
||||
|
||||
|
||||
#include doc/macros/main_footer.bb;
|
||||
3
doc/ca/first-post.bb
Normal file
3
doc/ca/first-post.bb
Normal file
@@ -0,0 +1,3 @@
|
||||
[size=large]La teva primera entrada[/size]
|
||||
|
||||
... pendent de ser escrita ...
|
||||
20
doc/ca/general.bb
Normal file
20
doc/ca/general.bb
Normal file
@@ -0,0 +1,20 @@
|
||||
[h2]Informació del Projecte/Lloc[/h2]
|
||||
|
||||
[zrl=[baseurl]/help/Privacy]Politica de Privacitat[/zrl]
|
||||
|
||||
[zrl=[baseurl]/help/history]Història de $Projectname[/zrl]
|
||||
|
||||
[h3]Recursos Externs[/h3]
|
||||
[zrl=[baseurl]/help/external-resource-links]Enllaços a Recursos Externs[/zrl]
|
||||
|
||||
[url=https://github.com/redmatrix/hubzilla]Lloc Web Principal[/url]
|
||||
|
||||
[url=https://github.com/redmatrix/hubzilla-addons]Complements del Lloc Web[/url]
|
||||
|
||||
[url=[baseurl]/help/credits]Credits en $Projectname[/url]
|
||||
|
||||
[h3]Sobre Aquest Node $Projectname[/h3]
|
||||
[zrl=[baseurl]/help/TermsOfService]Termes de Servei per a AQUEST Node[/zrl]
|
||||
[zrl=[baseurl]/siteinfo]Informació del Node[/zrl]
|
||||
[zrl=[baseurl]/siteinfo/json]Informació Tècnica Detallada en format JSON d'aquest Node[/zrl]
|
||||
|
||||
12
doc/ca/main.bb
Normal file
12
doc/ca/main.bb
Normal file
@@ -0,0 +1,12 @@
|
||||
[zrl=[baseurl]/help/about][b]Que és $Projectname?[/b][/zrl]
|
||||
$Projectname és una plataforma de comunicació i publicació descentralitzada que et permet mantenir el control de les teves necessitats de comunicació, gràcies a l'encriptació automàtica i control d'accés de gra fi. Éts tu, i només tu qui decideixes qui pot veure les teves coses.
|
||||
|
||||
[zrl=[baseurl]/help/features][b]Característiques de $Projectname[/b][/zrl]
|
||||
|
||||
$Projectname ja s'està executant com una xarxa distribuïda global i demostra la seva versatilitat i escalabilitat des de independent fins a grans llocs.
|
||||
Penseu en plataformes independents de comunicació de la família, de comunitats en línia distribuïdes, fòrums de suport, blocs i pàgines web. O proveïdors de continguts professionals amb canals premium comercials i accés de continguts específics. El que vulguis, $Projectname és allà per atendre la teva creativitat.
|
||||
|
||||
[zrl=[baseurl]/help/what_is_zot][b]Tens Zot? Be, Deuries.[/b][/zrl]
|
||||
Zot és el gran nou protocol de communicació inventat especialment per a $Projectname. Com a membre, ja no estàs lligat a un sol lloc o concentrador (hub) gràcies a les "identitats nòmades". Migra fàcilment a un altre servidor i manté els teus contactes intactes, o clona i executa el mateix canal en diversos servidors. Encara que un d'ells tanqui, no es perd res. A més, una vegada que estàs dins de $Projectname no hi ha necessitat d'autenticar dues vegades, fins i tot quan s'accedeix des d'un altre lloc $Projectname. Zot és el que difèrencia $Projectname de qualsevol altre projecte.
|
||||
|
||||
|
||||
25
doc/ca/members.bb
Normal file
25
doc/ca/members.bb
Normal file
@@ -0,0 +1,25 @@
|
||||
[h2]Documentació per a Membres del Concentrador[/h2]
|
||||
|
||||
[h3]Començant[/h3]
|
||||
[zrl=[baseurl]/help/registration]Registrant un Compte[/zrl]
|
||||
[zrl=[baseurl]/help/accounts_profiles_channels_basics]Tu a $Projectname: breument comptes, perfils i canals[/zrl]
|
||||
[zrl=[baseurl]/help/profiles]Perfils[/zrl]
|
||||
[zrl=[baseurl]/help/channels]Canals[/zrl]
|
||||
[zrl=[baseurl]/help/roles]Permisos per roles i tipus de Canals[/zrl]
|
||||
[zrl=[baseurl]/help/first-post]La teva primera entrada[/zrl]
|
||||
[zrl=[baseurl]/help/connecting_to_channels]Connectant Amb Altres Canals[/zrl]
|
||||
[zrl=[baseurl]/help/permissions]Permisos I Encriptació: Tu Tens El Control[/zrl]
|
||||
[zrl=[baseurl]/help/cloud]Emmagatzegament Al Núbol[/zrl]
|
||||
[zrl=[baseurl]/help/remove_account]Esborrar un Canal o un Compte[/zrl]
|
||||
|
||||
[h3]Ajuda per als Membres[/h3]
|
||||
[zrl=[baseurl]/help/tags_and_mentions]Etiquetes i Mencions[/zrl]
|
||||
[zrl=[baseurl]/help/webpages]Pàgines Web[/zrl]
|
||||
[zrl=[baseurl]/help/bbcode]Referència BBcode per a entrades i comentaris[/zrl]
|
||||
[zrl=[baseurl]/help/checking_account_quota_usage]Comprovant la Quota d'Ús del Compte[/zrl]
|
||||
[zrl=[baseurl]/help/cloud_desktop_clients]Clients d'Escriptori al Núbol[/zrl]
|
||||
[zrl=[baseurl]/help/AdvancedSearch]Cerca Avançada al Directori[/zrl]
|
||||
[zrl=[baseurl]/help/addons]Ajuda pels Addons[/zrl]
|
||||
[zrl=[baseurl]/help/diaspora_compat]Compatibilitat de Comunicacions amb Diaspora (Diaspora i Friendica)[/zrl]
|
||||
[zrl=[baseurl]/help/faq_members]FAQ Per Membres[/zrl]
|
||||
[zrl=[baseurl]/help/bugs]Errors, Assumptes, i les coses que arriben de cop a la nit...[/zrl]
|
||||
37
doc/ca/profiles.bb
Normal file
37
doc/ca/profiles.bb
Normal file
@@ -0,0 +1,37 @@
|
||||
[b]Profiles[/b]
|
||||
|
||||
$Projectname has unlimited profiles. You may use different profiles to show different "sides of yourself" to different audiences. This is different to having different channels. Different channels allow for completely different sets of information. You may have a channel for yourself, a channel for your sports team, a channel for your website, or whatever else. A profile allows for finely graded "sides" of each channel. For example, your default public profile might say "Hello, I'm Fred, and I like laughing". You may show your close friends a profile that adds "and I also enjoy dwarf tossing".
|
||||
|
||||
You always have a profile known as your "default" or "public" profile. This profile is always available to the general public and cannot be hidden (there may be rare exceptions on privately run or disconnected sites). You may, and probably should restrict the information you make available on your public profile.
|
||||
|
||||
That said, if you want other friends to be able to find you, it helps to have the following information in your public profile...
|
||||
|
||||
[ul][*]Your real name or at least a nickname everybody knows
|
||||
[*]A photo of you
|
||||
[*]Your location on the planet, at least to a country level.[/ul]
|
||||
|
||||
In addition, if you'd like to meet people that share some general interests with you, please take a moment and add some "Keywords" to your profile. Such as "music, linux, photography" or whatever. You can add as many keywords as you like.
|
||||
|
||||
To create an alternate profile, first go to [zrl=[baseurl]/settings/features]Settings > Additional Features[/zrl] and enable "Multiple Profiles" there, otherwise you won't have the ability to use more than just your default profile.
|
||||
|
||||
Then select "Edit Profiles" from the menu of your $Projectname site. You may edit an existing profile, change the profile photo, add things to a profile or create a new profile. You may also create a "clone" of an existing profile if you only wish to change a few items but don't wish to enter all the information again. To do that, click on the profile you want to clone and choose "Clone this profile" there.
|
||||
|
||||
In the list of your profiles, you can also choose the contacts who can see a specific profile. Just click on "Edit visibility" next to the profile in question (only available for the profiles that are not your default profile) and then click on user images to add them to or remove them from the group of people who can see this profile.
|
||||
|
||||
Once a profile has been selected, when the person views your profile, they will see the private profile you have assigned. If they are not authenticated, they will see your public profile.
|
||||
|
||||
There is a setting which allows you to publish your profile to a directory and ensure that it can be found by others. You can change this setting on the "Settings" page.
|
||||
|
||||
If you do not wish to be found be people unless you give them your channel address, you may leave your profile unpublished.
|
||||
|
||||
[b]Keywords and Directory Search[/b]
|
||||
|
||||
On the directory page, you may search for people with published profiles. Currently, only the name field and the keywords are searched. You may also include such keywords in your default profile - which may be used to search for common interests with other members. Keywords are used in the channel suggestion tool and although they aren't visible in the directory, they are shown if people visit your profile page.
|
||||
|
||||
On your Connnections page and in the directory there is a link to "Suggestions" or "Channel Suggestions", respectively. This will find channels who have matching and/or similar keywords. The more keywords you provide, the more relevant the search results that are returned. These are sorted by relevance.
|
||||
|
||||
See Also
|
||||
|
||||
[zrl=[baseurl]/help/AdvancedSearch]Advanced Searching[/zrl]
|
||||
|
||||
#include doc/macros/main_footer.bb;
|
||||
35
doc/ca/registration.bb
Normal file
35
doc/ca/registration.bb
Normal file
@@ -0,0 +1,35 @@
|
||||
[size=large][b]Registre[/b][/size]
|
||||
|
||||
No tots els llocs $Projectname permeten la inscripció oberta. Si es permet el registre, veureu un enllaç de " Registre " immediatament sota de l'entrada a la pàgina principal del lloc. Seguint aquest enllaç et portarà a la pàgina de registre del lloc. En alguns llocs es pot redirigir a un altre lloc que permet registres. Com tots els llocs $Projectname estan vinculats, no importa on resideix el teu compte.
|
||||
|
||||
[b]La Teva Adreça de Correu Electrònic[/b]
|
||||
|
||||
Si us plau introdueix la teva adreça de correu electrònic vàlida. La teva adreça de correu electrònic mai es farà pública. Aquesta adreça s'utilitzarà per activar el teu compte, que (opcionalment) enviarà notificacions de correu electrònic per als missatges entrants o articles, [i]i per recuperar contrasenyes perdudes[/i].
|
||||
|
||||
[b]Contrasenya[/b]
|
||||
|
||||
Introdueix una contrasenya de la teva elecció, i repeix-la en la segona casella per assegurar-te que es va escriure correctament. Com $Projectname ofereix una identitat descentralitzada, Es pot accedir al teu compte en molts altres llocs web no només en el que t'has donat d'alta.
|
||||
|
||||
[b]Termes Del Servei[/b]
|
||||
|
||||
Clica a l'enllaç per llegir els [zrl=[baseurl]/help/TermsOfService]Termes de Servei[/zrl] del lloc. Una vegada llegits, marca la casella al formulari de registre per confirmar.
|
||||
|
||||
[b]Registre[/b]
|
||||
|
||||
Una vegada que hagis proporcionat els detalls necessaris, fes clic al botó "Registrar-se". Alguns llocs poden requerir l'aprovació de l'administrador abans de processar el registre, s'avisarà si aquest és el cas. Si us plau, mira el teu correu electrònic (incloent carpetes d'spam) per poder finalitzar la teva aprovació de registre.
|
||||
|
||||
[b]Crear un Canal[/b]
|
||||
|
||||
A continuació, se et presentarà la pantalla " Afegir un canal". Normalment, el primer canal serà un que et representa - pel que l'ús del seu propi nom (o pseudònim) com el nom del canal és una bona idea. El nom de la cadena ha de ser pensat com un títol o descripció breu del teu canal. El " triar un sobrenom curt " és similar a un "nom d'usuari ". Farem servir tot el que entra aquí per crear una adreça de canal, que altres persones utilitzaran per connectar-se amb tu, i que utilitzaràs per iniciar sessió en altres llocs. Això s'assembla a una adreça de correu electrònic, i pren la forma nickname@siteyouregisteredat.xyz
|
||||
|
||||
Quan es crea el teu canal se't portarà directament a la pàgina de configuració on pots definir permisos, habilitar les funcions, etc. Totes aquestes coses es tracten a la secció corresponent dels fitxers d'ajuda.
|
||||
|
||||
Veure Tambè
|
||||
[zrl=[baseurl]/help/accounts_profiles_channels_basics]Lo Basic sobre Identitats dins $Projectname[/zrl]
|
||||
[zrl=[baseurl]/help/accounts]Comptes[/zrl]
|
||||
[zrl=[baseurl]/help/profiles]Perfils[/zrl]
|
||||
[zrl=[baseurl]/help/permissions]Permisos[/zrl]
|
||||
[zrl=[baseurl]/help/remove_account]Eliminar Compte[/zrl]
|
||||
|
||||
#include doc/macros/main_footer.bb;
|
||||
|
||||
61
doc/ca/what_is_zot.bb
Normal file
61
doc/ca/what_is_zot.bb
Normal file
@@ -0,0 +1,61 @@
|
||||
[b]Qué és Zot?[/b]
|
||||
|
||||
Zot és el protocol que fa funcionar $Projectname, proveeix tres Característiques esencials: Comunicacions, Identitat, i Control d'Accéss.
|
||||
|
||||
Les funcionalitats que proveeix es poden describir de la següent manera:
|
||||
|
||||
- una relació en línia es només un munt de permisos
|
||||
- internet és només un altre carpeta
|
||||
|
||||
[b][size=20]Comunicacions[/size][/b]
|
||||
|
||||
Zot és un protocol revolucionari que ofereix [i]comunicacions descentralitzades[/i] i [i]gestió d'identitat[/i] en tota la malla (o entrallat de connexions). El resultat es una plataforma que proveeix serveis web comparables amb els que ofereixen les grans companyies, però sense elles ni els seus problemes de privacitat, la seva insaciable necessitat de beneficis, ni la seva idea dels jardins-privats.
|
||||
|
||||
Comunicacions i xarxes socials són una part integral del teixit. Qualsevol canal (i qualsevol servei ofert per aquest canal) por fer ús complert de les grans caracteristiques de comunicació social a escala global. Aquestes comunicacions poden ser públiques o privades - i comunicacions privades no es limiten a encriptar totalment l'enviament, sino que també encripten l'emmagatzegament per tal d'impedir que, administradors de sistemes murris o proveidors de servei, accidental o intencionadament tafanegin o revelin dades personals.
|
||||
|
||||
Zot permet un ampli vental de serveis en segon plà per a la xarxa, des de oferir suggeriments d'amics, a serveis de directori. També pot realitzar altres coses que normalment només són possibles en un proveïdor centralitzat, com missatges "de mur a mur". Perfils particulars/múltiples es poden crear fàcilment i el contingut del web es pot adaptar a l'espectador a través del [i]Control Lliscant d'Afinitat[/i].
|
||||
|
||||
No trobaràs, de cap manera, aquestes característiques en altres serveis de comunicació descentralitzades. A més de proporcionar la descentralització de concentradors (servidors), potser la característica més innovadora i interessant de Zot és el subministrament de serveis [i]d'identitat descentralitzada[/i].
|
||||
|
||||
[b][size=20]Identitat[/size][/b]
|
||||
|
||||
La capa que permet identitat mitjançant Zot es única. Facilita [i]l'identificació única invisible[/i] al llarg de tots els llocs de la malla.
|
||||
|
||||
També ofereix [i]identitat nómada[/i], de tal forma que les teves comunicacions amb amics, familiars , i qualsevol amb el que et comuniquis no s'han de veure afectats per la pérdua (caiguda, desconnexió) temporal/permanent del teu node de comunicació primari.
|
||||
|
||||
Les parts importants de la teva identitat i les relacions es poden copiar a una memòria USB, o el teu ordinador portàtil, i poden aparèixer en qualsevol node de la xarxa en qualsevol moment - amb tots els teus amics i preferències intactes.
|
||||
|
||||
Fonamentalment, aquestes instàncies (identitats) nòmades es mantenen en sincronia per tal que qualsevol instància pugui fer-se càrrec si un altre està en perill o danyada. Això el protegeix contra no només d'una fallada del sistema, sinó també de sobrecàrregues temporals del lloc i/o la manipulació governamental o censura.
|
||||
|
||||
Identitat nòmada, inici de sessió únic, i nodes $Projectname descentralitzats, al nostre parer, introduir un alt grau de grau de [i]resiliència[/i] i [i]persistència[/i] en les comunicacions d'Internet, que són profundament necessàries en direcció contrària de les tendències mundials cap a la centralització corporativa, així com la vigilància governamental indiscriminada i la censura.
|
||||
|
||||
Com naveges per la xarxa, els canals de visualització i el seu contingut únic, que es produeix sobre la marxa, fins i tot a través de centres de servidors completament diferents. No hi ha contrasenyes per entrar. No hi ha res a escriure. No tens que posar teu nom en cada nou lloc que visites.
|
||||
|
||||
Com Zot pot fer això? En diem [i]identificació-màgica[/i], perquè $Projectname oculta els detalls de les complexitats que van a l'inici únic de sessió, les identitats nòmades, i l'experiència de navegació a la xarxa. Aquest és un dels objectius de disseny de $Projectname: per augmentar la privacitat i la llibertat a la xarxa, alhora que redueix la complexitat i el tedi interposat per la necessitat d'introduir noves contrasenyes i noms d'usuari per a cada vista diferent, que pots visitar en línia.
|
||||
|
||||
Entrar com a usuari només una vegada en el teu centre d'origen (o qualsevol centre de recolçament nòmada que hagis triat). Això permet accedir a tots els serveis autenticats en qualsevol lloc de la malla - com ara anar a comprar, blocs, fòrums, i l'accés a la informació privada. Això és igual que els serveis oferts pels grans proveïdors de les empreses amb enormes bases de dades d'usuaris; però, pots ser un membre d'aquesta comunitat, així com un servidor en aquesta xarxa emprant un RasberryPi de 35$. La teva contrasenya no s'emmagatzema en un miler de diferents llocs, o encara pitjor, només en uns pocs llocs com Google i Facebook, fora del teu control directe.
|
||||
|
||||
No pots ser silenciat. No pots ser eliminat de la xarxa, llevat que triïs per sortir, tu mateix.
|
||||
|
||||
[b][size=20]Control d'Accés[/size][/b]
|
||||
|
||||
La capa de identitat de Zot permet proporcionar permisos específics a qualsevol contingut que desitgis publicar - i aquests permisos s'estenen per $ProjectName. Això és com tenir un sol súper gran espai web format per un exèrcit de petits llocs web individuals - i on cada canal a la xarxa pot controlar completament les seves preferències de privacitat i ús compartit dels recursos web que creen.
|
||||
|
||||
Actualment, la xarxa suporta comunicacions, àlbums de fotos, esdeveniments, i arxius. Això s'ampliarà en el futur per proporcionar serveis de gestió de continguts (pàgines web) i instal·lacions d'emmagatzematge en el núvol, com biblioteques WebDAV i multimèdia. Cada objecte i la forma en què es comparteix i amb qui està completament sota el teu control.
|
||||
|
||||
Aquest tipus de control està disponible en grans proveïdors de serveis com Facebook i Google, ja que poseeixen la base de dades d'usuari. Dins de la xarxa, no hi ha necessitat d'un gran usuari de base de dades a la teva màquina - perquè la xarxa [i]és[/i] la teva base de dades d'usuari. Té essencialment infinita capacitat (limitada pel nombre total de nodes en línia a través d'Internet), i s'estén entre centenars, i potencialment milions d'ordinadors.
|
||||
|
||||
L'accés pot ser concedit o negat per a qualsevol recurs, a qualsevol canal, o qualsevol grup de canals; en qualsevol lloc dins de la malla. Altres podràn accedir al teu contingut si els permets fer-ho, i ni tan sols cal tenir un compte al node. Les teves fotos privades no es poden veure, perquè els permissos realment funcionen; no són un complement que s'ha afegit a l'últim moment. Si no ets a la llista d'espectadors permesos per a una foto en particular, tu no la veuràs.
|
||||
|
||||
[b][size=18]Recursos Addicionals i Enllaços[/size][/b]
|
||||
|
||||
Per més detalla, informació tècnica sobre Zot, clica sobre algún dels següents enllaços:
|
||||
|
||||
- [url=https://github.com/friendica/red/wiki/Zot---A-High-Level-Overview]Vista per experts (en anglès)[/url]
|
||||
|
||||
- [url=https://github.com/friendica/red/wiki/zot]Especificació pel desenvolupament de Zot (en anglès)[/url]
|
||||
|
||||
- [url=https://github.com/redmatrix/hubzilla/blob/master/include/zot.php]Referència per la implementació de Zot en PHP (en anglès)[/url]
|
||||
|
||||
|
||||
#include doc/macros/main_footer.bb;
|
||||
@@ -10,7 +10,7 @@ On many public servers there may be limits on disk usage.
|
||||
|
||||
The quickest and easiest way to share files is through file attachments. In the row of icons below the status post editor is a tool to upload attachments. Click the tool, select a file and submit. After the file is uploaded, you will see an attachment code placed inside the text region. Do not edit this line or it may break the ability for your friends to see the attachment. You can use the post permissions dialogue box or privacy hashtags to restrict the visibility of the file - which will be set to match the permissions of the post your are sending.
|
||||
|
||||
To delete attachments or change the permissions on the stored files, visit [observer.baseurl]/filestorage/{{username}}" replacing {{username}} with the nickname you provided during channel creation.
|
||||
To delete attachments or change the permissions on the stored files, visit [observer.baseurl]/cloud/{{username}}" replacing {{username}} with the nickname you provided during channel creation.
|
||||
|
||||
[b]Web Access[/b]
|
||||
|
||||
|
||||
3
doc/context/admin/security/help.html
Normal file
3
doc/context/admin/security/help.html
Normal file
@@ -0,0 +1,3 @@
|
||||
<h3>Security Settings</h3>
|
||||
<p>This page contains various administrator settings related to security.</p>
|
||||
<p>To save any changes you make to these settings, you must press the Submit button.</p>
|
||||
24
doc/context/channel/help.html
Normal file
24
doc/context/channel/help.html
Normal file
@@ -0,0 +1,24 @@
|
||||
<script>
|
||||
var contextualHelp1 = function (target, openSidePanel) {
|
||||
$("#help-content").removeClass('help-content-open'); // Close the help panel
|
||||
$("#navbar-collapse-1").removeClass('in'); // Collapse the navbar for small screens
|
||||
if (openSidePanel) {
|
||||
$("main").addClass('region_1-on'); // Open the side panel to highlight element
|
||||
} else {
|
||||
$("main").removeClass('region_1-on');
|
||||
}
|
||||
// Animate the page scroll to the element and then pulse the element to direct attention
|
||||
$('html,body').animate({scrollTop: $(target).offset().top - $('#navbar-collapse-1').height() - 20}, 'slow');
|
||||
for (i = 0; i < 3; i++) {
|
||||
$(target).fadeTo('slow', 0.1).fadeTo('slow', 1.0);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<dl class="dl-horizontal">
|
||||
<dt>General</dt>
|
||||
<dd>This is the home page of a channel. It is similar to someone's profile "wall" in a social network context. Posts created by the channel are displayed according to the observer's viewing permissions.</dd>
|
||||
<dt>Create a Post</dt>
|
||||
<dd>If you have permission to create posts on the channel page, then you will see the post editor at the top.</dd>
|
||||
<dt><a href='#' onclick='contextualHelp1("#tabs-collapse-1", 0); return false;' title="Click to highlight element...">Channel Content Tabs</a></dt>
|
||||
<dd>The channel content tabs are links to other content published by the channel. The <b>About</b> tab links to the channel profile. The <b>Photos</b> tab links to the channel photo galleries. The <b>Files</b> tab links to the general shared files published by the channel.</dd>
|
||||
</dl>
|
||||
22
doc/context/cloud/help.html
Normal file
22
doc/context/cloud/help.html
Normal file
@@ -0,0 +1,22 @@
|
||||
<script>
|
||||
var contextualHelp1 = function (target, openSidePanel) {
|
||||
$("#help-content").removeClass('help-content-open'); // Close the help panel
|
||||
$("#navbar-collapse-1").removeClass('in'); // Collapse the navbar for small screens
|
||||
if (openSidePanel) {
|
||||
$("main").addClass('region_1-on'); // Open the side panel to highlight element
|
||||
} else {
|
||||
$("main").removeClass('region_1-on');
|
||||
}
|
||||
// Animate the page scroll to the element and then pulse the element to direct attention
|
||||
$('html,body').animate({scrollTop: $(target).offset().top - $('#navbar-collapse-1').height() - 20}, 'slow');
|
||||
for (i = 0; i < 3; i++) {
|
||||
$(target).fadeTo('slow', 0.1).fadeTo('slow', 1.0);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<dl class="dl-horizontal">
|
||||
<dt>General</dt>
|
||||
<dd>This page displays a channel's "cloud" files. The files visible to the observer depend on the individual file permissions set by the channel owner. If you have permission to create/upload files you will see control buttons above the file list.</dd>
|
||||
<dt><a href='#' onclick='contextualHelp1("#tabs-collapse-1", 0); return false;' title="Click to highlight element...">Channel Content Tabs</a></dt>
|
||||
<dd>The channel content tabs are links to other content published by the channel. The <b>About</b> tab links to the channel profile. The <b>Photos</b> tab links to the channel photo galleries. The <b>Files</b> tab links to the general shared files published by the channel.</dd>
|
||||
</dl>
|
||||
10
doc/context/mail/help.html
Normal file
10
doc/context/mail/help.html
Normal file
@@ -0,0 +1,10 @@
|
||||
<dl class="dl-horizontal">
|
||||
<dt>General</dt>
|
||||
<dd>The messages displayed in private mail are visible only to you and the single recipient. </dd>
|
||||
<dt>Combined View</dt>
|
||||
<dd>Complete conversations can be viewed in a continuous thread by selecting <b>Combined View</b>. Available conversations are displayed beneath the menu in the side panel.</dd>
|
||||
<dt>Inbox/Outbox</dt>
|
||||
<dd>Individual sent messages are viewed by selecting <b>Outbox</b>, and incoming messages are viewed using the <b>Inbox</b> filter.</dd>
|
||||
<dt>New Message</dt>
|
||||
<dd>Individual messages have delivery reports that can be viewed using the drop-down menu. Messages can also be recalled from the same menu, which can prevent the recipient from viewing the message <i>if they have not already read it</i>.</dd>
|
||||
</dl>
|
||||
26
doc/context/network/help.html
Normal file
26
doc/context/network/help.html
Normal file
@@ -0,0 +1,26 @@
|
||||
<script>
|
||||
var contextualHelp1 = function (target, openSidePanel) {
|
||||
$("#help-content").removeClass('help-content-open'); // Close the help panel
|
||||
$("#navbar-collapse-1").removeClass('in'); // Collapse the navbar for small screens
|
||||
if (openSidePanel) {
|
||||
$("main").addClass('region_1-on'); // Open the side panel to highlight element
|
||||
} else {
|
||||
$("main").removeClass('region_1-on');
|
||||
}
|
||||
// Animate the page scroll to the element and then pulse the element to direct attention
|
||||
$('html,body').animate({scrollTop: $(target).offset().top - $('#navbar-collapse-1').height() - 20}, 'slow');
|
||||
for (i = 0; i < 3; i++) {
|
||||
$(target).fadeTo('slow', 0.1).fadeTo('slow', 1.0);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<dl class="dl-horizontal">
|
||||
<dt>General</dt>
|
||||
<dd>The network page displays a stream of posts and conversations, typically ordered by the most recently updated. This page is highly customizable.</dd>
|
||||
<dt><a href='#' onclick='contextualHelp1("#profile-jot-wrapper", 0); return false;' title="Click to highlight element...">Create a Post</a></dt>
|
||||
<dd>At the top of the page there is a text box that says "Share". Clicking this box opens a new post editor. The post editor is customizable, but the basic editor provides fields for a post body and an optional post <b>Title</b>. Buttons below the text area to the left provide shortcuts to text formatting and inserting links, images, and other data into the post. The buttons to the right provide a post preview, the post permissions setting, and a <b>Submit</b> button to send the post.</dd>
|
||||
<dt><a href='#' onclick='contextualHelp1("#group-sidebar", 1); return false;' title="Click to highlight element...">Privacy Groups</a></dt>
|
||||
<dd>The privacy groups you have created are displayed in the side panel. Selecting them filters posts to those created by channels in the chosen group.</dd>
|
||||
<dt><a href='#' onclick='$("#dbtn-acl").click(); return false;' title="Click to highlight element...">Post Permissions</a></dt>
|
||||
<dd>The access control list (ACL) is what you use to set who can see your new post. Pressing the ACL button beside the Submit button will display a dialog in which you can select what channels and/or privacy groups can see the post. You can also select who is explicitly denied access. For example, say you are planning a surprise party for a friend. You can send an invitation post to everyone in your <b>Friends</b> group <i>except</i> the friend you are surprising. In this case you "show" the <b>Friends</b> group but "don't show" that one person.</dd>
|
||||
</dl>
|
||||
22
doc/context/photos/help.html
Normal file
22
doc/context/photos/help.html
Normal file
@@ -0,0 +1,22 @@
|
||||
<script>
|
||||
var contextualHelp1 = function (target, openSidePanel) {
|
||||
$("#help-content").removeClass('help-content-open'); // Close the help panel
|
||||
$("#navbar-collapse-1").removeClass('in'); // Collapse the navbar for small screens
|
||||
if (openSidePanel) {
|
||||
$("main").addClass('region_1-on'); // Open the side panel to highlight element
|
||||
} else {
|
||||
$("main").removeClass('region_1-on');
|
||||
}
|
||||
// Animate the page scroll to the element and then pulse the element to direct attention
|
||||
$('html,body').animate({scrollTop: $(target).offset().top - $('#navbar-collapse-1').height() - 20}, 'slow');
|
||||
for (i = 0; i < 3; i++) {
|
||||
$(target).fadeTo('slow', 0.1).fadeTo('slow', 1.0);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<dl class="dl-horizontal">
|
||||
<dt>General</dt>
|
||||
<dd>This page displays a channel's photo albums. The images visible to the observer depend on the individual image permissions.</dd>
|
||||
<dt><a href='#' onclick='contextualHelp1("#tabs-collapse-1", 0); return false;' title="Click to highlight element...">Channel Content Tabs</a></dt>
|
||||
<dd>The channel content tabs are links to other content published by the channel. The <b>About</b> tab links to the channel profile. The <b>Photos</b> tab links to the channel photo galleries. The <b>Files</b> tab links to the general shared files published by the channel.</dd>
|
||||
</dl>
|
||||
22
doc/context/profile/help.html
Normal file
22
doc/context/profile/help.html
Normal file
@@ -0,0 +1,22 @@
|
||||
<script>
|
||||
var contextualHelp1 = function (target, openSidePanel) {
|
||||
$("#help-content").removeClass('help-content-open'); // Close the help panel
|
||||
$("#navbar-collapse-1").removeClass('in'); // Collapse the navbar for small screens
|
||||
if (openSidePanel) {
|
||||
$("main").addClass('region_1-on'); // Open the side panel to highlight element
|
||||
} else {
|
||||
$("main").removeClass('region_1-on');
|
||||
}
|
||||
// Animate the page scroll to the element and then pulse the element to direct attention
|
||||
$('html,body').animate({scrollTop: $(target).offset().top - $('#navbar-collapse-1').height() - 20}, 'slow');
|
||||
for (i = 0; i < 3; i++) {
|
||||
$(target).fadeTo('slow', 0.1).fadeTo('slow', 1.0);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<dl class="dl-horizontal">
|
||||
<dt>General</dt>
|
||||
<dd>This is the profile page of a channel. It typically displays information describing the channel. If the channel represents a person in a social network, for example, then the profile might provide contact information and other personal details about the person. Channels can have multiple profiles, where the displayed profile depends on the observer.</dd>
|
||||
<dt><a href='#' onclick='contextualHelp1("#tabs-collapse-1", 0); return false;' title="Click to highlight element...">Channel Content Tabs</a></dt>
|
||||
<dd>The channel content tabs are links to other content published by the channel. The <b>About</b> tab links to the channel profile. The <b>Photos</b> tab links to the channel photo galleries. The <b>Files</b> tab links to the general shared files published by the channel.</dd>
|
||||
</dl>
|
||||
@@ -7,8 +7,8 @@
|
||||
[h3]Externe Ressourcen[/h3]
|
||||
[zrl=[baseurl]/help/external-resource-links]Links zu externen Ressourcen[/zrl]
|
||||
|
||||
[url=https://github.com/redmatrix/redmatrix]Haupt-Website[/url]
|
||||
[url=https://github.com/redmatrix/redmatrix-addons]Addons-Website[/url]
|
||||
[url=https://github.com/redmatrix/hubzilla]Haupt-Website[/url]
|
||||
[url=https://github.com/redmatrix/hubzilla-addons]Addons-Website[/url]
|
||||
|
||||
[url=[baseurl]/help/credits]$Projectname Credits[/url]
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ Returns the global app structure ($a).
|
||||
|
||||
* App::get_observer()
|
||||
|
||||
(App:: is usually assigned to the global $a), so $a->get_observer() or get_app()->get_observer() - returns an xchan structure representing the current viewer if authenticated (locally or remotely).
|
||||
(App:: is usually assigned to the global $a), so App::get_observer() or App::get_observer() - returns an xchan structure representing the current viewer if authenticated (locally or remotely).
|
||||
|
||||
* get_config($family,$key), get_pconfig($uid,$family,$key)
|
||||
|
||||
|
||||
@@ -242,7 +242,7 @@ Befor you register a first user switch off the registration mails.
|
||||
Open /var/www/.htconfig.php
|
||||
and make sure "0" is set in this line
|
||||
[code]
|
||||
$a->config['system']['verify_email'] = 0;
|
||||
App::$config['system']['verify_email'] = 0;
|
||||
[/code]
|
||||
You should be able to change the file as "yourself" (instead of using root or www-data).
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ To configure this, please look in your .htconfig.php file for the following text
|
||||
// DIRECTORY_MODE_PRIMARY = main directory server
|
||||
// DIRECTORY_MODE_STANDALONE = "off the grid" or private directory services
|
||||
|
||||
$a->config['system']['directory_mode'] = DIRECTORY_MODE_STANDALONE;
|
||||
App::$config['system']['directory_mode'] = DIRECTORY_MODE_STANDALONE;
|
||||
[/code]
|
||||
|
||||
|
||||
|
||||
@@ -8,22 +8,22 @@ $a is a class defined in boot.php and passed all around $Projectname as a global
|
||||
|
||||
We don't ever create more than one instance and always modify the elements of the single instance. The mechanics of this are somewhat tricky. If you have a function that is passed $a and needs to modify $a you need to declare it as a reference with '&' e.g.
|
||||
|
||||
[code]function foo(&$a) { $a->something = 'x'; // whatever };
|
||||
[code]function foo(&$a) { App::$something = 'x'; // whatever };
|
||||
|
||||
*or* access it within your function as a global variable via get_app()
|
||||
|
||||
function foo() {
|
||||
$a = get_app();
|
||||
$a->something = 'x';
|
||||
App::$something = 'x';
|
||||
}
|
||||
|
||||
|
||||
function foo($a) { $a->something = 'x'; };
|
||||
function foo($a) { App::$something = 'x'; };
|
||||
|
||||
will *not* change the global app state.
|
||||
|
||||
function foo() {
|
||||
get_app()->something = 'x';
|
||||
App::$something = 'x';
|
||||
}
|
||||
[/code]
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ Short anser: No, there isn't. There are reasons. You are able to change permisso
|
||||
If a posting is public this is even harder, as the $Projectname is a global network and there is no way to follow a post, let alone reclaim it reliably. Other networks that may receive your post have no reliable way to delete or reclaim the post.
|
||||
|
||||
[h3]I downloaded my channel and imported it (cloned my identity) to another site but there is no content, no posts, no photos. What is wrong???[/h3]
|
||||
To be honest: Nothing. That's the way it is right now. Technically it is surely possible to take at least your own posts and maybe even files with you, but this has simply put not implemented yet. When creating this feature we thought that keeping all your contacts was more important. Your friends have already seen your old content. Once we find someone willing to implement this, it will be done. :)
|
||||
Posts and photos/files are provided separately from the channel basic information. This is due to memory limitations dealing with years of conversations and photo archives. Posts and conversations can be synced separately from the basic channel information. Photos and file archives can be transferred using a plugin tool such as 'redfiles', which is currently listed as "experimental". When creating this feature we thought that keeping all your contacts was the most important task. Your friends have already seen your old content. Posts/conversations were next in priority and these may now be synced. Files and photos are the last bit to get completely working. Once we find someone willing to finish implementing this, it will be done. :)
|
||||
[h3]I can't see private resources[/h3]
|
||||
You have probably disabled third party cookies. You need to enable them for remote authentication to work.
|
||||
[h3]There are a lot of foreign language posts. Let's auto-translate them.[/h3]
|
||||
|
||||
71
doc/federate.bb
Normal file
71
doc/federate.bb
Normal file
@@ -0,0 +1,71 @@
|
||||
[h2]Creating protocol federation services[/h2]
|
||||
|
||||
There are three main components to writing federation plugins. These are:
|
||||
|
||||
[1] Channel discovery and making connections
|
||||
[2] Sending posts/messages
|
||||
[3] Receiving posts/messages
|
||||
|
||||
In addition, federation drivers must handle
|
||||
|
||||
[4] differences in privacy policies (and content formats)
|
||||
|
||||
|
||||
[h3]Making connections[/h3]
|
||||
|
||||
The core application provides channel discovery in the following sequence:
|
||||
|
||||
[1] Zot channel discovery
|
||||
[2] Webfinger (channel@hub) lookup
|
||||
[2.1] RFC7033 webfinger
|
||||
[2.2] XRD based webfinger (old style)
|
||||
[3] URL discovery (currently only used to discover RSS feeds)
|
||||
[4] If all of these fail, the network is "unknown" and we are unable to communicate with or connect with the channel. An 'xchan' record [i]may[/i] still be created [b]if[/b] there is enough information known to identify a unique channel.
|
||||
|
||||
Any of the lookup services may be bound to a plugin and extended. When a channel is discovered, we create an 'xchan' record which is a platform neutral representation of the channel identity. If we need to send information to the channel, a 'hubloc' (hub location) record is also generally required. A 'follow' plugin hook is provided to bypass webfinger and this discovery sequence completely.
|
||||
|
||||
The final step in gluing this together is to create an 'abook' record, which attaches an xchan in a relationship to a local channel with a given set of permissions.
|
||||
|
||||
For networks which do not support nomadic identity, your plugin must also set "abook_instance" which is a comma-separated list of local URLs that the remote channel is connected with. For instance if your member was connected to my channel clone at https://example.com, the abook_instance for that connection would read 'https://example.com'. If you also connected to my clone at https://abc.example.com, the string would be changed to 'https://example.com,https://abc.example.com'. This allows local channels to differentiate which instance a given remote channel is connected with and avoid delivery failures to those channels from other clone instances.
|
||||
|
||||
A federation plugin for a webfinger based system needs only to examine the webfinger or XRD results and identify a protocol stack which can be used to connect or communicate. Then create an xchan record with the given 'xchan_network' type and a hubloc record with the same 'hubloc_network' with the information given. Currently the plugin will need to create the entire record, but in the future this will be extended so that the plugin only need identify a network name and the record will be populated with all other known values.
|
||||
|
||||
An xchan record is always required in order to connect. To connect, create an abook record with the desired permissions.
|
||||
|
||||
Additional information that your plugin requires for communication can be stored in the xconfig table and/or abconfig table if there is no convenient or appropriate table column in the xchan or hubloc tables.
|
||||
|
||||
When a connection is made, we generally call the notifier (include/notifier.php) to send a message to the remote channel. This is bound to the hook 'permissions_create'. Your plugin will need to handle this in order to send a "follow" or "make friends" message to the other network.
|
||||
|
||||
Notes: The first stage zot lookup will be replaced with a webfinger lookup. This work is in progress. A separate lookup was required initially as webfinger does not allow non-SSL connections. We will provide non-SSL zot lookups (usually test and development sites) via the "old" XRD based webfinger to avoid this limitation.
|
||||
|
||||
The core application will attempt to create xchan records for projects identified as members of the "open web"; currently Hubzilla, Friendica, Diaspora, GNU-Social and Pump.io. This is so that comments can be passed amongst project sites and the network correctly identified. A federation plugin is required to fully federate with other networks, but comments may be passed to sites without such a plugin installed so that there are no unexplained holes in conversations.
|
||||
|
||||
The core application must also provide signing ability for Diaspora comments since they require a special signing format and must be signed by the comment author regardless of whether that channel federates with Diaspora. The owner of the conversation may federate with Diaspora so the comments must be signed. This is unfortunate but necessary.
|
||||
|
||||
|
||||
[h3]Sending Messages[/h3]
|
||||
|
||||
Whenever any message is sent (with the sole exception of directory communications), we invoke the notifier (include/notifier.php), and pass it the type of message and generally an identifier to lookup the information being sent from the database (items or conversational things, private mail, permissions updates, etc.).
|
||||
|
||||
The notifier has several hooks which may be used by plugins in different ways, depending on how their delivery loop works. For different message types and complex delivery situations you may need to tie into multiple hooks. The 'permissions_create' hook was mentioned in the first section. There is also a 'permissions_update' message if permissions have changed and the other end of the link needs to be advised. Few services will provide or handle this (as their permissions are static), but it is also used for instance to send profile and profile photo update messages and you may wish to handle this.
|
||||
|
||||
The next plugin hook is 'notifier_process'. It is passed an array providing the complete state of the notifier and is called once per notifier invocation. It contains the complete list of recipients (with xchan_network set for each).
|
||||
|
||||
There is also 'notifier_hub' which like 'notifier_process' is passed the complete state of the notifier, but the difference is that it is called for each individual hub or distinct URL delivery and may be matched on the hubloc_network type. Hub delivery is much more efficient than recipient delivery but may not be suitable for all protocol stacks.
|
||||
|
||||
|
||||
Your plugin will be required to understand the message state and recipients and translate the sent item to the desired format. You will also be required to check privacy and block communication to anybody but the intended recipients - *if* it is a private communication. The plugin will often at this point stick the message into the queue and return the queue id to the notifier.
|
||||
|
||||
|
||||
Queue handlers exist already for simple posted data. If you create a queue entry with 'post' type we'll open an HTTP POST request and post the data provided and acknowledge success or failure. You can create other forms of communication by providing a different outq_driver type and handling the processing of queue requests yourself. Delivery reporting is available if you wish to acknowledge different error conditions, or anything beyond success/failure. Advanced delivery reporting will also require a custom queue type. The basic 'post' type only deals with success (communication successful with the remote site) and failure.
|
||||
|
||||
|
||||
|
||||
[h3]Receiving Messages[/h3]
|
||||
|
||||
|
||||
Receiving messages from the remote network will probably require a 'receive' endpoint or module dedicated to your network communication protocol. This is a URL route that your plugin may need to register with the'module_loaded' hook. You module will then take responsibility for importing any data which arrives at that endpoint and translating it to the format required for this project and storing the resulting data. The basic structure we use is an extensible activitystream item but with slightly different field names and several optional fields. It can be easily mapped to an activitystream. Additional data can be stored in the "iconfig" table. item_store() and item_store_update() are generally used to store the data and send appropriate notifications. Similiar facilities are available for private mail and profile information.
|
||||
|
||||
|
||||
|
||||
|
||||
61
doc/filesync.md
Normal file
61
doc/filesync.md
Normal file
@@ -0,0 +1,61 @@
|
||||
File Sync and Clone
|
||||
===================
|
||||
|
||||
|
||||
|
||||
File cloning across multiple instances of a channel is a very hard problem, due to the nature of PHP memory allocation. This needs to be handled dramatically differently than cloning or syncing of other information. (Processing one large video file or 40-50 photos could exhaust memory). Therefore we can't easily just dump all the data to a dump file and sequentially process it. Loading the dump file itself is likely to exhaust memory.
|
||||
|
||||
There are also two primary operations we are considering. The first is the hardest - saving and then importing all your channel information into a new channel clone. The second is synchronising file changes as they occur across two or more "active" clones.
|
||||
|
||||
For the first cut at this tool we will concentrate on the second case, while trying to maintain some measure of compatibility with the first case so that we can re-use the same tools.
|
||||
|
||||
Meta Data
|
||||
=========
|
||||
|
||||
|
||||
First we need the metadata for the file in order to precisely re-construct its structure on another site. This requires the following information:
|
||||
|
||||
'attach' structure (without file contents - which is the default) for the file itself **and** its parent directories so that we can re-create its precise place in the file system, since we do not know if the parent directory has been imported previously or ever.
|
||||
|
||||
'photo' structure for any photo elements which were created as a result of uploading this file into the system. This typically contains several different 'scales' or thumbnail images, some of which may be cropped for profile photo use or cover photo use. We need to retain the cropping information which is not present in the metadata, but only in the stored data. The actual thumbnail image data may or may not be included in the metadata. A cover photo of large scale (scale #7) could potentially cause memory issues. Not as bad as a 100M video, but if you have several of these they could add up.
|
||||
|
||||
'item' entries which are linked to this file. These can be file share activities, the "parent item" linked to photos, and any attached conversation items (photo likes, comments, etc.)
|
||||
|
||||
All of these items will require URL replacement and re-signing of the item as they are relocated to another site.
|
||||
|
||||
|
||||
File Data
|
||||
=========
|
||||
|
||||
Then we have the actual file data we need to reconstruct the file. This needs to be stored separately from the meta-data to avoid memory exhaustion when processing. The actual file data can be used to reconstruct the attach structure and the first four photo scales. If this is a photo, we need access to the "#4 scale" (profile photo) and the #7 scale (cover photo) as they were originally cropped. All other thumbnails can be generated from these.
|
||||
|
||||
|
||||
|
||||
File Sync
|
||||
=========
|
||||
|
||||
|
||||
We will consider this operation first because it is probably the most straightforward to implement. When a photo is added to or removed or changed from the source system, we will send a clone sync packet to all known clones containing the metadata - but **no file data** . We can only send one sync packet per file operation that needs to be synced.
|
||||
|
||||
The receiving end will create and perform URL translation on all the metadata structures and store them. Then it will need to fetch the actual data. Assuming CURL supports streaming, an authenticated request is sent to the original site and the original file is requested and streamed directly to disk (bypassing all processing). If photo scale #4 or scale #7 is required, these are requested and stored into their respective structures. We're assuming in this case that the cover photo large scale will not exhaust memory. If CURL cannot be made to support streaming, request packets need to be queued and sent to the origination site to obtain "chunks" of the file and re-assembled once all chunks have been retrieved.
|
||||
|
||||
The authenticated request depends on the mechanism. For CURL streaming, some signed secret with a timestamp will probably need to be generated and posted to the file origination site. Then the data can be retrieved with minimal internal processing and dumped directly to disk using stdio buffering. In the case of a zot request, the zot request packet will be validated, however scheduling chunk batches and re-assembling them could be tricky.
|
||||
|
||||
|
||||
File Backup/Restore
|
||||
===================
|
||||
|
||||
This is much more complicated as we do not have an authenticate web server to request data from. The metadata can be mostly the same, but we need some form of signalling that we will not be fetching the file via the web. This will likely require a client side process to parse each metadata file and locate a file on disk which it is associated with. Then the data would need to be streamed to the destination server with a special endpoint designed for this task. A java app might be the best option here to retain platform neutrality.
|
||||
|
||||
Another option would be to use WebDAV for this step. The metadata files would be uploaded first, and then the data files. If a data file corresponded to an existing metadata file, the metadata would be processed; the file stored appropriately, and the metadata file then removed. In this case, photos of scales 4 and 7 would need to be provided in the metadata.
|
||||
|
||||
|
||||
Optionally, this step could also be performed with a filesystem local to the destination server. This would be the highest performance, and a suite of shell-based tools (in the case of Linux) could perform the "client-side" of the task.
|
||||
|
||||
The complexity of this task mandates careful planning into how the data is organised and stored and if necessary backed up remotely or transmitted for backup by the source website.
|
||||
|
||||
|
||||
Backward Compatibility
|
||||
======================
|
||||
|
||||
There are some obvious issues with making data available for backup or cloning which existed on the system prior to the existence of restore/sync tools. To keep the tools themselves relatively uncomplicated (to the extent possible given the constraints) backward compatibility may have to be preformed by dedicated plugin or addon.
|
||||
@@ -14,7 +14,7 @@ Once you've done that, cd into the directory, and add an upstream.
|
||||
|
||||
[code]
|
||||
cd red
|
||||
git remote add upstream https://github.com/redmatrix/redmatrix
|
||||
git remote add upstream https://github.com/redmatrix/hubzilla
|
||||
[/code]
|
||||
|
||||
From now on, you can pull upstream changes with the command
|
||||
|
||||
@@ -83,7 +83,9 @@ This document assumes you're an administrator.
|
||||
'forum', 'forum_restricted' and 'forum_private'.
|
||||
Read more about permissions roles [zrl=[baseurl]/help/roles]here[/zrl].
|
||||
[b]system.workflow_channel_next[/b]
|
||||
The page to direct users to immediately after creating a channel.
|
||||
The page to direct new members to immediately after creating a channel.
|
||||
[b]system.workflow_register_next[/b]
|
||||
The page to direct members to immediately after creating an account (only when auto_channel_create or UNO is enabled).
|
||||
[b]system.max_daily_registrations[/b]
|
||||
Set the maximum number of new registrations allowed on any day.
|
||||
Useful to prevent oversubscription after a bout of publicity
|
||||
@@ -100,6 +102,10 @@ This document assumes you're an administrator.
|
||||
[b]system.paranoia[/b]
|
||||
As the pconfig, but on a site-wide basis. Can be overwritten
|
||||
by member settings.
|
||||
[b]system.transport_security_header[/b]
|
||||
if non-zero and SSL is being used, include a strict-transport-security header on webpages
|
||||
[b]system.poke_basic[/b]
|
||||
Reduce the number of poke verbs to exactly 1 ("poke"). Disable other verbs.
|
||||
[b]system.openssl_conf_file[/b]
|
||||
Specify a file containing OpenSSL configuration. Read the code first.
|
||||
If you can't read the code, don't play with it.
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
[h2]discover_by_webbie[/h2]
|
||||
14
doc/hook/discover_channel_webfinger.bb
Normal file
14
doc/hook/discover_channel_webfinger.bb
Normal file
@@ -0,0 +1,14 @@
|
||||
[h2]discover_channel_webfinger[/h2]
|
||||
|
||||
Called after performing channel discovery using RFC7033 webfinger and where the channel is not recognised as zot.
|
||||
|
||||
Passed an array:
|
||||
|
||||
address: URL or address that is being discovered
|
||||
success: set to true if the plugin discovers something
|
||||
webfinger: array of webfinger links (output of webfinger_rfc7033())
|
||||
|
||||
|
||||
if your plugin indicates success you are expected to generate and populate an xchan (and hubloc) record prior to returning.
|
||||
|
||||
|
||||
@@ -8,5 +8,5 @@ The hook data for this call consists of an array
|
||||
|
||||
This element contains the HTML content which was prepared for this page by calling the module_content() function. It is invoked after the content has been created. It does not contain the result of AJAX or asynchronous page load calls.
|
||||
|
||||
The current module may be determined by lookin at $a->module
|
||||
The current module may be determined by lookin at App::$module
|
||||
|
||||
|
||||
@@ -6,5 +6,5 @@ The hook data for this call consists of an array
|
||||
|
||||
This element contains the HTML content before calling the module_content() function. It is invoked before the content region has been populated. This may or may not be empty as there may be other processes or addons generating content prior to your hook handler is run. Be certain to preserve any current content. Typically anything you add here will be placed at the top of the content region of the page, but in any event prior to the main content region being generated.
|
||||
|
||||
The current module may be determined by lookin at $a->module
|
||||
The current module may be determined by lookin at App::$module
|
||||
|
||||
|
||||
@@ -127,7 +127,7 @@ Hooks allow plugins/addons to "hook into" the code at many points and alter the
|
||||
[zrl=[baseurl]/help/hook/directory_item]directory_item[/zrl]
|
||||
Called when generating a directory listing for display
|
||||
|
||||
[zrl=[baseurl]/help/hook/discover_by_webbie]discover_by_webbie[/zrl]
|
||||
[zrl=[baseurl]/help/hook/discover_channel_webfinger]discover_channel_webfinger[/zrl]
|
||||
Called when performing a webfinger lookup
|
||||
|
||||
[zrl=[baseurl]/help/hook/display_item]display_item[/zrl]
|
||||
|
||||
@@ -17,7 +17,6 @@ We need much more than this, but here are areas where developers can help. Pleas
|
||||
[li]Integrate the "open site" list with the register page[/li]
|
||||
[li]Support comments and member notes on documentation pages (to achieve an effect similar to php.net)[/li]
|
||||
[li]Support comments on webpages[/li]
|
||||
[li]implement oembed provider interface[/li]
|
||||
[li]refactor the oembed client interface so that we can safely sandbox remote content[/li]
|
||||
[li]Write more webpage layouts[/li]
|
||||
[li]Write more webpage widgets[/li]
|
||||
@@ -33,8 +32,6 @@ We need much more than this, but here are areas where developers can help. Pleas
|
||||
[li]API extensions, for Twitter API - search, friending, threading. For Red API, lots of stuff[/li]
|
||||
[li]Import channel from Diaspora/Friendica (Diaspora partially done)[/li]
|
||||
[li]MediaGoblin photo "crosspost" connector[/li]
|
||||
[li]Create management page/UI for extensible profile fields[/li]
|
||||
[li]Create interface to include/exclude and re-order standard profile fields[/li]
|
||||
[li]App taxonomy[/li]
|
||||
[li]Customisable App collection pages[/li]
|
||||
[li]replace the tinymce visual editor and/or make the visual editor pluggable and responsive to different output formats. We probably want library/bbedit for bbcode. This needs a fair bit of work to catch up with our "enhanced bbcode", but start with images, links, bold and highlight and work from there.[/li]
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php /** @file */
|
||||
|
||||
if(class_exists('BaseObject'))
|
||||
return;
|
||||
|
||||
|
||||
@@ -75,12 +75,12 @@ function vcard_from_xchan($xchan, $observer = null, $mode = '') {
|
||||
$a = get_app();
|
||||
|
||||
if(! $xchan) {
|
||||
if($a->poi) {
|
||||
$xchan = $a->poi;
|
||||
if(App::$poi) {
|
||||
$xchan = App::$poi;
|
||||
}
|
||||
elseif(is_array($a->profile) && $a->profile['channel_hash']) {
|
||||
elseif(is_array(App::$profile) && App::$profile['channel_hash']) {
|
||||
$r = q("select * from xchan where xchan_hash = '%s' limit 1",
|
||||
dbesc($a->profile['channel_hash'])
|
||||
dbesc(App::$profile['channel_hash'])
|
||||
);
|
||||
if($r)
|
||||
$xchan = $r[0];
|
||||
@@ -102,7 +102,7 @@ function vcard_from_xchan($xchan, $observer = null, $mode = '') {
|
||||
}
|
||||
|
||||
if(array_key_exists('channel_id',$xchan))
|
||||
$a->profile_uid = $xchan['channel_id'];
|
||||
App::$profile_uid = $xchan['channel_id'];
|
||||
|
||||
$url = (($observer)
|
||||
? z_root() . '/magic?f=&dest=' . $xchan['xchan_url'] . '&addr=' . $xchan['xchan_addr']
|
||||
@@ -111,7 +111,7 @@ function vcard_from_xchan($xchan, $observer = null, $mode = '') {
|
||||
|
||||
return replace_macros(get_markup_template('xchan_vcard.tpl'),array(
|
||||
'$name' => $xchan['xchan_name'],
|
||||
'$photo' => ((is_array($a->profile) && array_key_exists('photo',$a->profile)) ? $a->profile['photo'] : $xchan['xchan_photo_l']),
|
||||
'$photo' => ((is_array(App::$profile) && array_key_exists('photo',App::$profile)) ? App::$profile['photo'] : $xchan['xchan_photo_l']),
|
||||
'$follow' => $xchan['xchan_addr'],
|
||||
'$link' => zid($xchan['xchan_url']),
|
||||
'$connect' => $connect,
|
||||
@@ -235,7 +235,7 @@ function account_remove($account_id,$local = true,$unset_session=true) {
|
||||
unset($_SESSION['authenticated']);
|
||||
unset($_SESSION['uid']);
|
||||
notice( sprintf(t("User '%s' deleted"),$account_email) . EOL);
|
||||
goaway(get_app()->get_baseurl());
|
||||
goaway(z_root());
|
||||
}
|
||||
return $r;
|
||||
|
||||
@@ -263,7 +263,7 @@ function rrmdir($path)
|
||||
return false;
|
||||
}
|
||||
|
||||
function channel_remove($channel_id, $local = true, $unset_session=true) {
|
||||
function channel_remove($channel_id, $local = true, $unset_session=false) {
|
||||
|
||||
if(! $channel_id)
|
||||
return;
|
||||
@@ -333,19 +333,19 @@ function channel_remove($channel_id, $local = true, $unset_session=true) {
|
||||
);
|
||||
|
||||
// if this was the default channel, set another one as default
|
||||
if($a->account['account_default_channel'] == $channel_id) {
|
||||
if(App::$account['account_default_channel'] == $channel_id) {
|
||||
$r = q("select channel_id from channel where channel_account_id = %d and channel_removed = 0 limit 1",
|
||||
intval($a->account['account_id']),
|
||||
intval(App::$account['account_id']),
|
||||
intval(PAGE_REMOVED));
|
||||
if ($r) {
|
||||
$rr = q("update account set account_default_channel = %d where account_id = %d",
|
||||
intval($r[0]['channel_id']),
|
||||
intval($a->account['account_id']));
|
||||
intval(App::$account['account_id']));
|
||||
logger("Default channel deleted, changing default to channel_id " . $r[0]['channel_id']);
|
||||
}
|
||||
else {
|
||||
$rr = q("update account set account_default_channel = 0 where account_id = %d",
|
||||
intval($a->account['account_id'])
|
||||
intval(App::$account['account_id'])
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -389,9 +389,8 @@ function channel_remove($channel_id, $local = true, $unset_session=true) {
|
||||
proc_run('php','include/directory.php',$channel_id);
|
||||
|
||||
if($channel_id == local_channel() && $unset_session) {
|
||||
unset($_SESSION['authenticated']);
|
||||
unset($_SESSION['uid']);
|
||||
goaway($a->get_baseurl());
|
||||
\Zotlabs\Web\Session::nuke();
|
||||
goaway(z_root());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ require_once('include/items.php');
|
||||
*/
|
||||
|
||||
class Conversation extends BaseObject {
|
||||
|
||||
private $threads = array();
|
||||
private $mode = null;
|
||||
private $observer = null;
|
||||
@@ -47,33 +48,26 @@ class Conversation extends BaseObject {
|
||||
|
||||
$a = $this->get_app();
|
||||
|
||||
$this->observer = $a->get_observer();
|
||||
$this->observer = App::get_observer();
|
||||
$ob_hash = (($this->observer) ? $this->observer['xchan_hash'] : '');
|
||||
|
||||
switch($mode) {
|
||||
case 'network':
|
||||
// if(array_key_exists('firehose',$a->data) && intval($a->data['firehose'])) {
|
||||
// $this->profile_owner = intval($a->data['firehose']);
|
||||
// $this->writable = false;
|
||||
// }
|
||||
// else {
|
||||
$this->profile_owner = local_channel();
|
||||
$this->writable = true;
|
||||
// }
|
||||
$this->profile_owner = local_channel();
|
||||
$this->writable = true;
|
||||
break;
|
||||
case 'channel':
|
||||
$this->profile_owner = $a->profile['profile_uid'];
|
||||
$this->profile_owner = App::$profile['profile_uid'];
|
||||
$this->writable = perm_is_allowed($this->profile_owner,$ob_hash,'post_comments');
|
||||
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->profile_owner = $a->profile['uid'];
|
||||
$this->writable = perm_is_allowed($this->profile_owner,$ob_hash,'post_comments');
|
||||
break;
|
||||
case 'page':
|
||||
$this->profile_owner = $a->profile['uid'];
|
||||
$this->profile_owner = App::$profile['uid'];
|
||||
$this->writable = perm_is_allowed($this->profile_owner,$ob_hash,'post_comments');
|
||||
break;
|
||||
default:
|
||||
@@ -142,11 +136,11 @@ class Conversation extends BaseObject {
|
||||
public function add_thread($item) {
|
||||
$item_id = $item->get_id();
|
||||
if(!$item_id) {
|
||||
logger('[ERROR] Conversation::add_thread : Item has no ID!!', LOGGER_DEBUG);
|
||||
logger('Item has no ID!!', LOGGER_DEBUG, LOG_ERR);
|
||||
return false;
|
||||
}
|
||||
if($this->get_thread($item->get_id())) {
|
||||
logger('[WARN] Conversation::add_thread : Thread already exists ('. $item->get_id() .').', LOGGER_DEBUG);
|
||||
logger('Thread already exists ('. $item->get_id() .').', LOGGER_DEBUG, LOG_WARNING);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -177,11 +171,6 @@ class Conversation extends BaseObject {
|
||||
}
|
||||
}
|
||||
require_once('include/identity.php');
|
||||
// $sys = get_sys_channel();
|
||||
|
||||
// if($sys && $item->get_data_value('uid') == $sys['channel_id']) {
|
||||
// $item->set_commentable(false);
|
||||
// }
|
||||
|
||||
$item->set_conversation($this);
|
||||
$this->threads[] = $item;
|
||||
@@ -209,7 +198,7 @@ class Conversation extends BaseObject {
|
||||
$item_data = $item->get_template_data($conv_responses);
|
||||
}
|
||||
if(!$item_data) {
|
||||
logger('[ERROR] Conversation::get_template_data : Failed to get item template data ('. $item->get_id() .').', LOGGER_DEBUG);
|
||||
logger('Failed to get item template data ('. $item->get_id() .').', LOGGER_DEBUG, LOG_ERR);
|
||||
return false;
|
||||
}
|
||||
$result[] = $item_data;
|
||||
|
||||
@@ -8,7 +8,7 @@ require_once('include/photo/photo_driver.php');
|
||||
function import_diaspora($data) {
|
||||
$a = get_app();
|
||||
|
||||
$account = $a->get_account();
|
||||
$account = App::get_account();
|
||||
if(! $account)
|
||||
return false;
|
||||
|
||||
|
||||
@@ -97,7 +97,7 @@ class Item extends BaseObject {
|
||||
$mode = $conv->get_mode();
|
||||
|
||||
if(local_channel() && $observer['xchan_hash'] === $item['author_xchan'])
|
||||
$edpost = array($a->get_baseurl($ssl_state)."/editpost/".$item['id'], t("Edit"));
|
||||
$edpost = array(z_root()."/editpost/".$item['id'], t("Edit"));
|
||||
else
|
||||
$edpost = false;
|
||||
|
||||
@@ -241,7 +241,7 @@ class Item extends BaseObject {
|
||||
$has_bookmarks = false;
|
||||
if(is_array($item['term'])) {
|
||||
foreach($item['term'] as $t) {
|
||||
if($t['type'] == TERM_BOOKMARK)
|
||||
if(!UNO && $t['type'] == TERM_BOOKMARK)
|
||||
$has_bookmarks = true;
|
||||
}
|
||||
}
|
||||
@@ -681,14 +681,20 @@ class Item extends BaseObject {
|
||||
$qc = ((local_channel()) ? get_pconfig(local_channel(),'system','qcomment') : null);
|
||||
$qcomment = (($qc) ? explode("\n",$qc) : null);
|
||||
|
||||
$arr = array('comment_buttons' => '','id' => $this->get_id());
|
||||
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->get_mode() === 'display') ? $_SESSION['return_url'] : ''),
|
||||
'$type' => (($conv->get_mode() === 'channel') ? 'wall-comment' : 'net-comment'),
|
||||
'$id' => $this->get_id(),
|
||||
'$parent' => $this->get_id(),
|
||||
'$qcomment' => $qcomment,
|
||||
'$comment_buttons' => $comment_buttons,
|
||||
'$profile_uid' => $conv->get_profile_owner(),
|
||||
'$mylink' => $observer['xchan_url'],
|
||||
'$mytitle' => t('This is you'),
|
||||
@@ -708,7 +714,7 @@ class Item extends BaseObject {
|
||||
'$feature_encrypt' => ((feature_enabled($conv->get_profile_owner(),'content_encrypt')) ? true : false),
|
||||
'$encrypt' => t('Encrypt text'),
|
||||
'$cipher' => $conv->get_cipher(),
|
||||
'$sourceapp' => get_app()->sourcename
|
||||
'$sourceapp' => App::$sourcename
|
||||
|
||||
));
|
||||
|
||||
|
||||
@@ -248,7 +248,7 @@ function verify_email_address($arr) {
|
||||
|
||||
$res = mail($arr['email'], email_header_encode(sprintf( t('Registration confirmation for %s'), get_config('system','sitename'))),
|
||||
$email_msg,
|
||||
'From: ' . 'Administrator' . '@' . get_app()->get_hostname() . "\n"
|
||||
'From: ' . 'Administrator' . '@' . App::get_hostname() . "\n"
|
||||
. 'Content-type: text/plain; charset=UTF-8' . "\n"
|
||||
. 'Content-transfer-encoding: 8bit'
|
||||
);
|
||||
@@ -314,7 +314,7 @@ function send_reg_approval_email($arr) {
|
||||
|
||||
$res = mail($admin['email'], sprintf( t('Registration request at %s'), get_config('system','sitename')),
|
||||
$email_msg,
|
||||
'From: ' . t('Administrator') . '@' . get_app()->get_hostname() . "\n"
|
||||
'From: ' . t('Administrator') . '@' . App::get_hostname() . "\n"
|
||||
. 'Content-type: text/plain; charset=UTF-8' . "\n"
|
||||
. 'Content-transfer-encoding: 8bit'
|
||||
);
|
||||
@@ -341,7 +341,7 @@ function send_register_success_email($email,$password) {
|
||||
|
||||
$res = mail($email, sprintf( t('Registration details for %s'), get_config('system','sitename')),
|
||||
$email_msg,
|
||||
'From: ' . t('Administrator') . '@' . get_app()->get_hostname() . "\n"
|
||||
'From: ' . t('Administrator') . '@' . App::get_hostname() . "\n"
|
||||
. 'Content-type: text/plain; charset=UTF-8' . "\n"
|
||||
. 'Content-transfer-encoding: 8bit'
|
||||
);
|
||||
@@ -407,7 +407,7 @@ function account_allow($hash) {
|
||||
|
||||
pop_lang();
|
||||
|
||||
if(get_config('system','auto_channel_create'))
|
||||
if(get_config('system','auto_channel_create') || UNO)
|
||||
auto_channel_create($register[0]['uid']);
|
||||
|
||||
if ($res) {
|
||||
@@ -500,7 +500,7 @@ function account_approve($hash) {
|
||||
);
|
||||
|
||||
|
||||
if(get_config('system','auto_channel_create'))
|
||||
if(get_config('system','auto_channel_create') || UNO)
|
||||
auto_channel_create($register[0]['uid']);
|
||||
|
||||
info( t('Account verified. Please login.') . EOL );
|
||||
@@ -655,7 +655,7 @@ function account_service_class_allows($aid, $property, $usage = false) {
|
||||
function service_class_fetch($uid, $property) {
|
||||
$a = get_app();
|
||||
if($uid == local_channel()) {
|
||||
$service_class = $a->account['account_service_class'];
|
||||
$service_class = App::$account['account_service_class'];
|
||||
}
|
||||
else {
|
||||
$r = q("select account_service_class as service_class
|
||||
|
||||
@@ -23,7 +23,7 @@ function group_select($selname,$selclass,$preselected = false,$size = 4) {
|
||||
|
||||
// e.g. 'network_pre_group_deny', 'profile_pre_group_allow'
|
||||
|
||||
call_hooks($a->module . '_pre_' . $selname, $arr);
|
||||
call_hooks(App::$module . '_pre_' . $selname, $arr);
|
||||
|
||||
if($r) {
|
||||
foreach($r as $rr) {
|
||||
@@ -39,7 +39,7 @@ function group_select($selname,$selclass,$preselected = false,$size = 4) {
|
||||
}
|
||||
$o .= "</select>\r\n";
|
||||
|
||||
call_hooks($a->module . '_post_' . $selname, $o);
|
||||
call_hooks(App::$module . '_post_' . $selname, $o);
|
||||
|
||||
|
||||
return $o;
|
||||
@@ -127,7 +127,7 @@ function contact_selector($selname, $selclass, $preselected = false, $options) {
|
||||
|
||||
// e.g. 'network_pre_contact_deny', 'profile_pre_contact_allow'
|
||||
|
||||
call_hooks($a->module . '_pre_' . $selname, $arr);
|
||||
call_hooks(App::$module . '_pre_' . $selname, $arr);
|
||||
|
||||
if(count($r)) {
|
||||
foreach($r as $rr) {
|
||||
@@ -145,7 +145,7 @@ function contact_selector($selname, $selclass, $preselected = false, $options) {
|
||||
|
||||
$o .= "</select>\r\n";
|
||||
|
||||
call_hooks($a->module . '_post_' . $selname, $o);
|
||||
call_hooks(App::$module . '_post_' . $selname, $o);
|
||||
|
||||
return $o;
|
||||
}*/
|
||||
@@ -182,7 +182,7 @@ function contact_select($selname, $selclass, $preselected = false, $size = 4, $p
|
||||
|
||||
// e.g. 'network_pre_contact_deny', 'profile_pre_contact_allow'
|
||||
|
||||
call_hooks($a->module . '_pre_' . $selname, $arr);
|
||||
call_hooks(App::$module . '_pre_' . $selname, $arr);
|
||||
|
||||
if($r) {
|
||||
foreach($r as $rr) {
|
||||
@@ -200,7 +200,7 @@ function contact_select($selname, $selclass, $preselected = false, $size = 4, $p
|
||||
|
||||
$o .= "</select>\r\n";
|
||||
|
||||
call_hooks($a->module . '_post_' . $selname, $o);
|
||||
call_hooks(App::$module . '_post_' . $selname, $o);
|
||||
|
||||
return $o;
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ function profile_activity($changed, $value) {
|
||||
|
||||
require_once('include/items.php');
|
||||
|
||||
$self = $a->get_channel();
|
||||
$self = App::get_channel();
|
||||
|
||||
if(! count($self))
|
||||
return;
|
||||
|
||||
100
include/api.php
100
include/api.php
@@ -34,7 +34,7 @@ require_once('include/api_auth.php');
|
||||
|
||||
function api_user() {
|
||||
$aid = get_account_id();
|
||||
$channel = get_app()->get_channel();
|
||||
$channel = App::get_channel();
|
||||
|
||||
if(($aid) && (x($_REQUEST,'channel'))) {
|
||||
|
||||
@@ -79,7 +79,7 @@ require_once('include/api_auth.php');
|
||||
$type="json";
|
||||
|
||||
foreach ($API as $p=>$info){
|
||||
if (strpos($a->query_string, $p)===0){
|
||||
if (strpos(App::$query_string, $p)===0){
|
||||
$called_api= explode("/",$p);
|
||||
//unset($_SERVER['PHP_AUTH_USER']);
|
||||
if ($info['auth'] === true && api_user() === false) {
|
||||
@@ -88,18 +88,18 @@ require_once('include/api_auth.php');
|
||||
|
||||
load_contact_links(api_user());
|
||||
|
||||
$channel = $a->get_channel();
|
||||
$channel = App::get_channel();
|
||||
|
||||
logger('API call for ' . $channel['channel_name'] . ': ' . $a->query_string);
|
||||
logger('API call for ' . $channel['channel_name'] . ': ' . App::$query_string);
|
||||
logger('API parameters: ' . print_r($_REQUEST,true));
|
||||
|
||||
$type="json";
|
||||
|
||||
if (strpos($a->query_string, ".xml")>0) $type="xml";
|
||||
if (strpos($a->query_string, ".json")>0) $type="json";
|
||||
if (strpos($a->query_string, ".rss")>0) $type="rss";
|
||||
if (strpos($a->query_string, ".atom")>0) $type="atom";
|
||||
if (strpos($a->query_string, ".as")>0) $type="as";
|
||||
if (strpos(App::$query_string, ".xml")>0) $type="xml";
|
||||
if (strpos(App::$query_string, ".json")>0) $type="json";
|
||||
if (strpos(App::$query_string, ".rss")>0) $type="rss";
|
||||
if (strpos(App::$query_string, ".atom")>0) $type="atom";
|
||||
if (strpos(App::$query_string, ".as")>0) $type="as";
|
||||
|
||||
$r = call_user_func($info['func'], $a, $type);
|
||||
if ($r===false) return;
|
||||
@@ -141,7 +141,7 @@ require_once('include/api_auth.php');
|
||||
}
|
||||
}
|
||||
header("HTTP/1.1 404 Not Found");
|
||||
logger('API call not implemented: '.$a->query_string." - ".print_r($_REQUEST,true));
|
||||
logger('API call not implemented: '.App::$query_string." - ".print_r($_REQUEST,true));
|
||||
$r = '<status><error>not implemented</error></status>';
|
||||
switch($type){
|
||||
case "xml":
|
||||
@@ -171,12 +171,12 @@ require_once('include/api_auth.php');
|
||||
$arr['$user'] = $user_info;
|
||||
$arr['$rss'] = array(
|
||||
'alternate' => $user_info['url'],
|
||||
'self' => $a->get_baseurl(). "/". $a->query_string,
|
||||
'base' => $a->get_baseurl(),
|
||||
'self' => z_root(). "/". App::$query_string,
|
||||
'base' => z_root(),
|
||||
'updated' => api_date(null),
|
||||
'atom_updated' => datetime_convert('UTC','UTC','now',ATOM_TIME),
|
||||
'language' => $user_info['language'],
|
||||
'logo' => $a->get_baseurl()."/images/rm-64.png",
|
||||
'logo' => z_root()."/images/rm-64.png",
|
||||
);
|
||||
|
||||
return $arr;
|
||||
@@ -213,7 +213,7 @@ require_once('include/api_auth.php');
|
||||
$extra_query .= " AND abook_channel = ".intval(api_user());
|
||||
}
|
||||
|
||||
if (is_null($user) && argc() > (count($called_api)-1) && (strstr($a->cmd,'/users'))){
|
||||
if (is_null($user) && argc() > (count($called_api)-1) && (strstr(App::$cmd,'/users'))){
|
||||
$argid = count($called_api);
|
||||
list($xx, $null) = explode(".",argv($argid));
|
||||
if(is_numeric($xx)){
|
||||
@@ -318,7 +318,7 @@ require_once('include/api_auth.php');
|
||||
'location' => ($usr) ? $usr[0]['channel_location'] : '',
|
||||
'profile_image_url' => $uinfo[0]['xchan_photo_l'],
|
||||
'url' => $uinfo[0]['xchan_url'],
|
||||
'contact_url' => $a->get_baseurl() . "/connections/".$uinfo[0]['abook_id'],
|
||||
'contact_url' => z_root() . "/connections/".$uinfo[0]['abook_id'],
|
||||
'protected' => false,
|
||||
'friends_count' => intval($countfriends),
|
||||
'created_at' => api_date($uinfo[0]['abook_created']),
|
||||
@@ -326,7 +326,7 @@ require_once('include/api_auth.php');
|
||||
'time_zone' => 'UTC', //$uinfo[0]['timezone'],
|
||||
'geo_enabled' => false,
|
||||
'statuses_count' => intval($countitms), //#XXX: fix me
|
||||
'lang' => get_app()->language,
|
||||
'lang' => App::$language,
|
||||
'description' => (($profile) ? $profile[0]['pdesc'] : ''),
|
||||
'followers_count' => intval($countfollowers),
|
||||
'favourites_count' => intval($starred),
|
||||
@@ -486,7 +486,7 @@ require_once('include/api_auth.php');
|
||||
|
||||
function api_account_logout(&$a, $type){
|
||||
require_once('include/auth.php');
|
||||
nuke_session();
|
||||
\Zotlabs\Web\Session::nuke();
|
||||
return api_apply_template("user", $type, array('$user' => null));
|
||||
|
||||
}
|
||||
@@ -635,13 +635,13 @@ require_once('include/api_auth.php');
|
||||
|
||||
|
||||
function api_albums(&$a,$type) {
|
||||
json_return_and_die(photos_albums_list($a->get_channel(),$a->get_observer()));
|
||||
json_return_and_die(photos_albums_list(App::get_channel(),App::get_observer()));
|
||||
}
|
||||
api_register_func('api/red/albums','api_albums', true);
|
||||
|
||||
function api_photos(&$a,$type) {
|
||||
$album = $_REQUEST['album'];
|
||||
json_return_and_die(photos_list_photos($a->get_channel(),$a->get_observer(),$album));
|
||||
json_return_and_die(photos_list_photos(App::get_channel(),App::get_observer(),$album));
|
||||
}
|
||||
api_register_func('api/red/photos','api_photos', true);
|
||||
|
||||
@@ -768,7 +768,7 @@ require_once('include/api_auth.php');
|
||||
}
|
||||
$txt = html2bbcode($txt);
|
||||
|
||||
$a->argv[1] = $user_info['screen_name'];
|
||||
App::$argv[1] = $user_info['screen_name'];
|
||||
|
||||
$_REQUEST['silent']='1'; //tell wall_upload function to return img info instead of echo
|
||||
$_FILES['userfile'] = $_FILES['media'];
|
||||
@@ -872,7 +872,7 @@ require_once('include/api_auth.php');
|
||||
// upload each image if we have any
|
||||
$_REQUEST['silent']='1'; //tell wall_upload function to return img info instead of echo
|
||||
require_once('mod/wall_attach.php');
|
||||
$a->data['api_info'] = $user_info;
|
||||
App::$data['api_info'] = $user_info;
|
||||
$media = wall_attach_post($a);
|
||||
|
||||
if(strlen($media)>0)
|
||||
@@ -885,7 +885,7 @@ require_once('include/api_auth.php');
|
||||
// upload each image if we have any
|
||||
$_REQUEST['silent']='1'; //tell wall_upload function to return img info instead of echo
|
||||
require_once('mod/wall_attach.php');
|
||||
$a->data['api_info'] = $user_info;
|
||||
App::$data['api_info'] = $user_info;
|
||||
$media = wall_attach_post($a);
|
||||
|
||||
if(strlen($media)>0)
|
||||
@@ -960,7 +960,7 @@ require_once('include/api_auth.php');
|
||||
$arr['records'] = 999999;
|
||||
$arr['item_type'] = '*';
|
||||
|
||||
$i = items_fetch($arr,$a->get_channel(),get_observer_hash());
|
||||
$i = items_fetch($arr,App::get_channel(),get_observer_hash());
|
||||
|
||||
if(! $i)
|
||||
json_return_and_die(array());
|
||||
@@ -1230,7 +1230,7 @@ require_once('include/api_auth.php');
|
||||
$sql_extra .= ' AND `item`.`parent` = `item`.`id`';
|
||||
|
||||
if (api_user() != $user_info['uid']) {
|
||||
$observer = get_app()->get_observer();
|
||||
$observer = App::get_observer();
|
||||
require_once('include/permissions.php');
|
||||
if(! perm_is_allowed($user_info['uid'],(($observer) ? $observer['xchan_hash'] : ''),'view_stream'))
|
||||
return '';
|
||||
@@ -1272,8 +1272,8 @@ require_once('include/api_auth.php');
|
||||
break;
|
||||
case "as":
|
||||
$as = api_format_as($a, $ret, $user_info);
|
||||
$as['title'] = $a->config['sitename']." Home Timeline";
|
||||
$as['link']['url'] = $a->get_baseurl()."/".$user_info["screen_name"]."/all";
|
||||
$as['title'] = App::$config['sitename']." Home Timeline";
|
||||
$as['link']['url'] = z_root()."/".$user_info["screen_name"]."/all";
|
||||
return($as);
|
||||
break;
|
||||
}
|
||||
@@ -1333,8 +1333,8 @@ require_once('include/api_auth.php');
|
||||
break;
|
||||
case "as":
|
||||
$as = api_format_as($a, $ret, $user_info);
|
||||
$as['title'] = $a->config['sitename']. " " . t('Public Timeline');
|
||||
$as['link']['url'] = $a->get_baseurl()."/";
|
||||
$as['title'] = App::$config['sitename']. " " . t('Public Timeline');
|
||||
$as['link']['url'] = z_root()."/";
|
||||
return($as);
|
||||
break;
|
||||
}
|
||||
@@ -1409,7 +1409,7 @@ require_once('include/api_auth.php');
|
||||
|
||||
//$include_entities = (x($_REQUEST,'include_entities')?$_REQUEST['include_entities']:false);
|
||||
|
||||
$observer = get_app()->get_observer();
|
||||
$observer = App::get_observer();
|
||||
|
||||
$item_normal = item_normal();
|
||||
|
||||
@@ -1526,7 +1526,7 @@ require_once('include/api_auth.php');
|
||||
|
||||
//$include_entities = (x($_REQUEST,'include_entities')?$_REQUEST['include_entities']:false);
|
||||
|
||||
$myurl = $a->get_baseurl() . '/channel/'. $a->user['nickname'];
|
||||
$myurl = z_root() . '/channel/'. App::$user['nickname'];
|
||||
$myurl = substr($myurl,strpos($myurl,'://')+3);
|
||||
$myurl = str_replace(array('www.','.'),array('','\\.'),$myurl);
|
||||
$diasp_url = str_replace('/channel/','/u/',$myurl);
|
||||
@@ -1561,8 +1561,8 @@ require_once('include/api_auth.php');
|
||||
break;
|
||||
case "as":
|
||||
$as = api_format_as($a, $ret, $user_info);
|
||||
$as["title"] = $a->config['sitename']." Mentions";
|
||||
$as['link']['url'] = $a->get_baseurl()."/";
|
||||
$as["title"] = App::$config['sitename']." Mentions";
|
||||
$as['link']['url'] = z_root()."/";
|
||||
return($as);
|
||||
break;
|
||||
}
|
||||
@@ -1633,7 +1633,7 @@ require_once('include/api_auth.php');
|
||||
$arr['cid'] = $user_info['id'];
|
||||
|
||||
|
||||
$r = items_fetch($arr,get_app()->get_channel(),get_observer_hash());
|
||||
$r = items_fetch($arr,App::get_channel(),get_observer_hash());
|
||||
|
||||
$ret = api_format_items($r,$user_info);
|
||||
|
||||
@@ -1752,7 +1752,7 @@ require_once('include/api_auth.php');
|
||||
$sql_extra .= ' AND `item`.`parent` = `item`.`id`';
|
||||
|
||||
if (api_user() != $user_info['uid']) {
|
||||
$observer = get_app()->get_observer();
|
||||
$observer = App::get_observer();
|
||||
require_once('include/permissions.php');
|
||||
if(! perm_is_allowed($user_info['uid'],(($observer) ? $observer['xchan_hash'] : ''),'view_stream'))
|
||||
return '';
|
||||
@@ -1783,8 +1783,8 @@ require_once('include/api_auth.php');
|
||||
break;
|
||||
case "as":
|
||||
$as = api_format_as($a, $ret, $user_info);
|
||||
$as['title'] = $a->config['sitename']." Home Timeline";
|
||||
$as['link']['url'] = $a->get_baseurl()."/".$user_info["screen_name"]."/all";
|
||||
$as['title'] = App::$config['sitename']." Home Timeline";
|
||||
$as['link']['url'] = z_root()."/".$user_info["screen_name"]."/all";
|
||||
return($as);
|
||||
break;
|
||||
}
|
||||
@@ -1801,7 +1801,7 @@ require_once('include/api_auth.php');
|
||||
function api_format_as($a, $ret, $user_info) {
|
||||
|
||||
$as = array();
|
||||
$as['title'] = $a->config['sitename']." Public Timeline";
|
||||
$as['title'] = App::$config['sitename']." Public Timeline";
|
||||
$items = array();
|
||||
foreach ($ret as $item) {
|
||||
$singleitem["actor"]["displayName"] = $item["user"]["name"];
|
||||
@@ -1857,7 +1857,7 @@ require_once('include/api_auth.php');
|
||||
$items[] = $singleitem;
|
||||
}
|
||||
$as['items'] = $items;
|
||||
$as['link']['url'] = $a->get_baseurl()."/".$user_info["screen_name"]."/all";
|
||||
$as['link']['url'] = z_root()."/".$user_info["screen_name"]."/all";
|
||||
$as['link']['rel'] = "alternate";
|
||||
$as['link']['type'] = "text/html";
|
||||
return($as);
|
||||
@@ -1978,8 +1978,8 @@ require_once('include/api_auth.php');
|
||||
'entities' => '',
|
||||
'objecttype' => (($item['obj_type']) ? $item['obj_type'] : ACTIVITY_OBJ_NOTE),
|
||||
'verb' => (($item['verb']) ? $item['verb'] : ACTIVITY_POST),
|
||||
'self' => $a->get_baseurl()."/api/statuses/show/".$item['id'].".".$type,
|
||||
'edit' => $a->get_baseurl()."/api/statuses/show/".$item['id'].".".$type,
|
||||
'self' => z_root()."/api/statuses/show/".$item['id'].".".$type,
|
||||
'edit' => z_root()."/api/statuses/show/".$item['id'].".".$type,
|
||||
);
|
||||
|
||||
$status = array_merge($status, $status2);
|
||||
@@ -2088,8 +2088,8 @@ require_once('include/api_auth.php');
|
||||
load_config('system');
|
||||
|
||||
$name = get_config('system','sitename');
|
||||
$server = $a->get_hostname();
|
||||
$logo = $a->get_baseurl() . '/images/rm-64.png';
|
||||
$server = App::get_hostname();
|
||||
$logo = z_root() . '/images/rm-64.png';
|
||||
$email = get_config('system','admin_email');
|
||||
$closed = ((get_config('system','register_policy') == REGISTER_CLOSED) ? 'true' : 'false');
|
||||
$private = ((get_config('system','block_public')) ? 'true' : 'false');
|
||||
@@ -2097,7 +2097,7 @@ require_once('include/api_auth.php');
|
||||
if(get_config('system','api_import_size'))
|
||||
$texlimit = string(get_config('system','api_import_size'));
|
||||
$ssl = ((get_config('system','have_ssl')) ? 'true' : 'false');
|
||||
$sslserver = (($ssl === 'true') ? str_replace('http:','https:',$a->get_baseurl()) : '');
|
||||
$sslserver = (($ssl === 'true') ? str_replace('http:','https:',z_root()) : '');
|
||||
|
||||
$config = array(
|
||||
'site' => array('name' => $name,'server' => $server, 'theme' => 'default', 'path' => '',
|
||||
@@ -2106,10 +2106,10 @@ require_once('include/api_auth.php');
|
||||
'private' => $private, 'textlimit' => $textlimit, 'sslserver' => $sslserver, 'ssl' => $ssl,
|
||||
'shorturllength' => '30',
|
||||
'hubzilla' => array(
|
||||
'PLATFORM_NAME' => get_platform_name(),
|
||||
'RED_VERSION' => get_project_version(),
|
||||
'PLATFORM_NAME' => Zotlabs\Project\System::get_platform_name(),
|
||||
'RED_VERSION' => Zotlabs\Project\System::get_project_version(),
|
||||
'ZOT_REVISION' => ZOT_REVISION,
|
||||
'DB_UPDATE_VERSION' => get_update_version()
|
||||
'DB_UPDATE_VERSION' => Zotlabs\Project\System::get_update_version()
|
||||
)
|
||||
));
|
||||
|
||||
@@ -2142,12 +2142,12 @@ require_once('include/api_auth.php');
|
||||
|
||||
if($type === 'xml') {
|
||||
header("Content-type: application/xml");
|
||||
echo '<?xml version="1.0" encoding="UTF-8"?>' . "\r\n" . '<version>' . get_project_version() . '</version>' . "\r\n";
|
||||
echo '<?xml version="1.0" encoding="UTF-8"?>' . "\r\n" . '<version>' . Zotlabs\Project\System::get_project_version() . '</version>' . "\r\n";
|
||||
killme();
|
||||
}
|
||||
elseif($type === 'json') {
|
||||
header("Content-type: application/json");
|
||||
echo '"' . get_project_version() . '"';
|
||||
echo '"' . Zotlabs\Project\System::get_project_version() . '"';
|
||||
killme();
|
||||
}
|
||||
}
|
||||
@@ -2270,9 +2270,9 @@ require_once('include/api_auth.php');
|
||||
if ($page<0) $page=0;
|
||||
|
||||
$start = $page*$count;
|
||||
$channel = $a->get_channel();
|
||||
$channel = App::get_channel();
|
||||
|
||||
$profile_url = $a->get_baseurl() . '/channel/' . $channel['channel_address'];
|
||||
$profile_url = z_root() . '/channel/' . $channel['channel_address'];
|
||||
if ($box=="sentbox") {
|
||||
$sql_extra = "`from_xchan`='".dbesc( $channel['channel_hash'] )."'";
|
||||
}
|
||||
|
||||
@@ -20,9 +20,9 @@ function api_login(&$a){
|
||||
if (!is_null($token)){
|
||||
$oauth->loginUser($token->uid);
|
||||
|
||||
$a->set_oauth_key($consumer->key);
|
||||
App::set_oauth_key($consumer->key);
|
||||
|
||||
call_hooks('logged_in', $a->user);
|
||||
call_hooks('logged_in', App::$user);
|
||||
return;
|
||||
}
|
||||
killme();
|
||||
|
||||
@@ -48,12 +48,12 @@ function parse_app_description($f) {
|
||||
$ret = array();
|
||||
|
||||
$baseurl = z_root();
|
||||
$channel = get_app()->get_channel();
|
||||
$channel = App::get_channel();
|
||||
$address = (($channel) ? $channel['channel_address'] : '');
|
||||
|
||||
//future expansion
|
||||
|
||||
$observer = get_app()->get_observer();
|
||||
$observer = App::get_observer();
|
||||
|
||||
|
||||
$lines = @file($f);
|
||||
@@ -217,7 +217,7 @@ function app_render($papp,$mode = 'view') {
|
||||
return '';
|
||||
break;
|
||||
case 'observer':
|
||||
$observer = get_app()->get_observer();
|
||||
$observer = App::get_observer();
|
||||
if(! $observer)
|
||||
return '';
|
||||
break;
|
||||
@@ -239,7 +239,7 @@ function app_render($papp,$mode = 'view') {
|
||||
$hosturl = z_root() . '/';
|
||||
}
|
||||
elseif(remote_channel()) {
|
||||
$observer = get_app()->get_observer();
|
||||
$observer = App::get_observer();
|
||||
if($observer && $observer['xchan_network'] === 'zot') {
|
||||
// some folks might have xchan_url redirected offsite, use the connurl
|
||||
$x = parse_url($observer['xchan_connurl']);
|
||||
@@ -354,7 +354,7 @@ function app_store($arr) {
|
||||
}
|
||||
|
||||
|
||||
$darray['app_id'] = ((x($arr,'guid')) ? $arr['guid'] : random_string(). '.' . get_app()->get_hostname());
|
||||
$darray['app_id'] = ((x($arr,'guid')) ? $arr['guid'] : random_string(). '.' . App::get_hostname());
|
||||
$darray['app_sig'] = ((x($arr,'sig')) ? $arr['sig'] : '');
|
||||
$darray['app_author'] = ((x($arr,'author')) ? $arr['author'] : get_observer_hash());
|
||||
$darray['app_name'] = ((x($arr,'name')) ? escape_tags($arr['name']) : t('Unknown'));
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
|
||||
require_once('include/permissions.php');
|
||||
require_once('include/security.php');
|
||||
require_once('include/group.php');
|
||||
|
||||
/**
|
||||
* @brief Guess the mimetype from file ending.
|
||||
@@ -845,7 +846,7 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) {
|
||||
|
||||
// Caution: This re-uses $sql_options set further above
|
||||
|
||||
$r = q("select id, aid, uid, hash, creator, filename, filetype, filesize, revision, folder, os_storage, is_photo, flags, created, edited, allow_cid, allow_gid, deny_cid, deny_gid from attach where uid = %d and hash = '%s' $sql_options limit 1",
|
||||
$r = q("select * from attach where uid = %d and hash = '%s' $sql_options limit 1",
|
||||
intval($channel_id),
|
||||
dbesc($hash)
|
||||
);
|
||||
@@ -863,6 +864,12 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) {
|
||||
// This would've been called already with a success result in photos_upload() if it was a photo.
|
||||
call_hooks('photo_upload_end',$ret);
|
||||
}
|
||||
|
||||
$sync = attach_export_data($channel,$hash);
|
||||
|
||||
if($sync)
|
||||
build_sync_packet($channel['channel_id'],array('file' => array($sync)));
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
@@ -1242,7 +1249,7 @@ function attach_delete($channel_id, $resource, $is_photo = 0) {
|
||||
$channel_address = (($c) ? $c[0]['channel_address'] : 'notfound');
|
||||
$photo_sql = (($is_photo) ? " and is_photo = 1 " : '');
|
||||
|
||||
$r = q("SELECT hash, flags, is_dir, is_photo, folder FROM attach WHERE hash = '%s' AND uid = %d $photo_sql limit 1",
|
||||
$r = q("SELECT hash, os_storage, flags, is_dir, is_photo, folder FROM attach WHERE hash = '%s' AND uid = %d $photo_sql limit 1",
|
||||
dbesc($resource),
|
||||
intval($channel_id)
|
||||
);
|
||||
@@ -1313,7 +1320,9 @@ function attach_delete($channel_id, $resource, $is_photo = 0) {
|
||||
intval($channel_id)
|
||||
);
|
||||
|
||||
file_activity($channel_id, $object, $object['allow_cid'], $object['allow_gid'], $object['deny_cid'], $object['deny_gid'], 'update', $notify=0);
|
||||
file_activity($channel_id, $object, $object['allow_cid'], $object['allow_gid'], $object['deny_cid'], $object['deny_gid'], 'update', $notify=1);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1468,13 +1477,13 @@ function pipe_streams($in, $out) {
|
||||
* @param string $deny_cid
|
||||
* @param string $deny_gid
|
||||
* @param string $verb
|
||||
* @param boolean $no_activity
|
||||
* @param boolean $notify
|
||||
*/
|
||||
function file_activity($channel_id, $object, $allow_cid, $allow_gid, $deny_cid, $deny_gid, $verb, $notify) {
|
||||
|
||||
require_once('include/items.php');
|
||||
|
||||
$poster = get_app()->get_observer();
|
||||
$poster = App::get_observer();
|
||||
|
||||
//if we got no object something went wrong
|
||||
if(!$object)
|
||||
@@ -1514,13 +1523,21 @@ function file_activity($channel_id, $object, $allow_cid, $allow_gid, $deny_cid,
|
||||
|
||||
$mid = item_message_id();
|
||||
|
||||
$arr = array();
|
||||
$objtype = ACTIVITY_OBJ_FILE;
|
||||
|
||||
$arr = array();
|
||||
$arr['aid'] = get_account_id();
|
||||
$arr['uid'] = $channel_id;
|
||||
$arr['item_wall'] = 1;
|
||||
$arr['item_origin'] = 1;
|
||||
$arr['item_unseen'] = 1;
|
||||
|
||||
$objtype = ACTIVITY_OBJ_FILE;
|
||||
$arr['author_xchan'] = $poster['xchan_hash'];
|
||||
$arr['owner_xchan'] = $poster['xchan_hash'];
|
||||
$arr['title'] = '';
|
||||
$arr['item_hidden'] = 1;
|
||||
$arr['obj_type'] = $objtype;
|
||||
$arr['resource_id'] = $object['hash'];
|
||||
$arr['resource_type'] = 'attach';
|
||||
|
||||
$private = (($arr_allow_cid[0] || $arr_allow_gid[0] || $arr_deny_cid[0] || $arr_deny_gid[0]) ? 1 : 0);
|
||||
|
||||
@@ -1548,36 +1565,27 @@ function file_activity($channel_id, $object, $allow_cid, $allow_gid, $deny_cid,
|
||||
|
||||
}
|
||||
|
||||
//send update activity and create a new one
|
||||
if($update && $verb == 'post' ) {
|
||||
//send update activity and create a new one
|
||||
|
||||
//updates should be sent to everybody with recursive perms and all eventual former allowed members ($object['allow_cid'] etc.).
|
||||
$u_arr_allow_cid = array_unique(array_merge($arr_allow_cid, expand_acl($object['allow_cid'])));
|
||||
$u_arr_allow_gid = array_unique(array_merge($arr_allow_gid, expand_acl($object['allow_gid'])));
|
||||
$u_arr_deny_cid = array_unique(array_merge($arr_deny_cid, expand_acl($object['deny_cid'])));
|
||||
$u_arr_deny_gid = array_unique(array_merge($arr_deny_gid, expand_acl($object['deny_gid'])));
|
||||
|
||||
$private = (($u_arr_allow_cid[0] || $u_arr_allow_gid[0] || $u_arr_deny_cid[0] || $u_arr_deny_gid[0]) ? 1 : 0);
|
||||
|
||||
$u_mid = item_message_id();
|
||||
|
||||
$arr['aid'] = get_account_id();
|
||||
$arr['uid'] = $channel_id;
|
||||
$arr['mid'] = $u_mid;
|
||||
$arr['parent_mid'] = $u_mid;
|
||||
$arr['author_xchan'] = $poster['xchan_hash'];
|
||||
$arr['owner_xchan'] = $poster['xchan_hash'];
|
||||
$arr['title'] = '';
|
||||
//updates should be visible to everybody -> perms may have changed
|
||||
$arr['allow_cid'] = '';
|
||||
$arr['allow_gid'] = '';
|
||||
$arr['deny_cid'] = '';
|
||||
$arr['deny_gid'] = '';
|
||||
$arr['item_hidden'] = 1;
|
||||
$arr['item_private'] = 0;
|
||||
$arr['allow_cid'] = perms2str($u_arr_allow_cid);
|
||||
$arr['allow_gid'] = perms2str($u_arr_allow_gid);
|
||||
$arr['deny_cid'] = perms2str($u_arr_deny_cid);
|
||||
$arr['deny_gid'] = perms2str($u_arr_deny_gid);
|
||||
$arr['item_private'] = $private;
|
||||
$arr['verb'] = ACTIVITY_UPDATE;
|
||||
$arr['obj_type'] = $objtype;
|
||||
$arr['object'] = $u_jsonobject;
|
||||
$arr['resource_id'] = $object['hash'];
|
||||
$arr['resource_type'] = 'attach';
|
||||
$arr['body'] = '';
|
||||
|
||||
$post = item_store($arr);
|
||||
@@ -1593,32 +1601,25 @@ function file_activity($channel_id, $object, $allow_cid, $allow_gid, $deny_cid,
|
||||
//notice( t('File activity updated') . EOL);
|
||||
}
|
||||
|
||||
//don't create new activity if notify was not enabled
|
||||
if(! $notify) {
|
||||
return;
|
||||
}
|
||||
|
||||
$arr = array();
|
||||
//don't create new activity if we have an update request but there is no item to update
|
||||
//this can e.g. happen when deleting images
|
||||
if(! $y && $verb == 'update') {
|
||||
return;
|
||||
}
|
||||
|
||||
$arr['aid'] = get_account_id();
|
||||
$arr['uid'] = $channel_id;
|
||||
$arr['mid'] = $mid;
|
||||
$arr['parent_mid'] = $mid;
|
||||
$arr['item_wall'] = 1;
|
||||
$arr['item_origin'] = 1;
|
||||
$arr['item_unseen'] = 1;
|
||||
$arr['author_xchan'] = $poster['xchan_hash'];
|
||||
$arr['owner_xchan'] = $poster['xchan_hash'];
|
||||
$arr['title'] = '';
|
||||
$arr['allow_cid'] = perms2str($arr_allow_cid);
|
||||
$arr['allow_gid'] = perms2str($arr_allow_gid);
|
||||
$arr['deny_cid'] = perms2str($arr_deny_cid);
|
||||
$arr['deny_gid'] = perms2str($arr_deny_gid);
|
||||
$arr['item_hidden'] = 1;
|
||||
$arr['item_private'] = $private;
|
||||
$arr['verb'] = (($update) ? ACTIVITY_UPDATE : ACTIVITY_POST);
|
||||
$arr['obj_type'] = $objtype;
|
||||
$arr['resource_id'] = $object['hash'];
|
||||
$arr['resource_type'] = 'attach';
|
||||
$arr['object'] = (($update) ? $u_jsonobject : $jsonobject);
|
||||
$arr['body'] = '';
|
||||
|
||||
@@ -1701,11 +1702,11 @@ function recursive_activity_recipients($arr_allow_cid, $arr_allow_gid, $arr_deny
|
||||
$ret = array();
|
||||
$parent_arr = array();
|
||||
$count_values = array();
|
||||
$poster = get_app()->get_observer();
|
||||
$poster = App::get_observer();
|
||||
|
||||
//turn allow_gid into allow_cid's
|
||||
foreach($arr_allow_gid as $gid) {
|
||||
$in_group = in_group($gid);
|
||||
$in_group = group_get_members($gid);
|
||||
$arr_allow_cid = array_unique(array_merge($arr_allow_cid, $in_group));
|
||||
}
|
||||
|
||||
@@ -1727,7 +1728,7 @@ function recursive_activity_recipients($arr_allow_cid, $arr_allow_gid, $arr_deny
|
||||
* */
|
||||
if($parent_arr['allow_gid']) {
|
||||
foreach($parent_arr['allow_gid'][$count] as $gid) {
|
||||
$in_group = in_group($gid);
|
||||
$in_group = group_get_members($gid);
|
||||
$parent_arr['allow_cid'][$count] = array_unique(array_merge($parent_arr['allow_cid'][$count], $in_group));
|
||||
}
|
||||
}
|
||||
@@ -1808,31 +1809,6 @@ function recursive_activity_recipients($arr_allow_cid, $arr_allow_gid, $arr_deny
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns members of a group.
|
||||
*
|
||||
* @param int $group_id id of the group to look up
|
||||
*/
|
||||
function in_group($group_id) {
|
||||
$group_members = array();
|
||||
|
||||
/** @TODO make these two queries one with a join. */
|
||||
$x = q("SELECT id FROM groups WHERE hash = '%s'",
|
||||
dbesc($group_id)
|
||||
);
|
||||
|
||||
$r = q("SELECT xchan FROM group_member WHERE gid = %d",
|
||||
intval($x[0]['id'])
|
||||
);
|
||||
|
||||
foreach($r as $ig) {
|
||||
$group_members[] = $ig['xchan'];
|
||||
}
|
||||
|
||||
return $group_members;
|
||||
}
|
||||
|
||||
|
||||
function filepath_macro($s) {
|
||||
|
||||
return str_replace(
|
||||
@@ -1844,3 +1820,89 @@ function filepath_macro($s) {
|
||||
|
||||
}
|
||||
|
||||
function attach_export_data($channel, $resource_id, $deleted = false) {
|
||||
|
||||
$ret = array();
|
||||
|
||||
$paths = array();
|
||||
|
||||
$hash_ptr = $resource_id;
|
||||
|
||||
$ret['fetch_url'] = z_root() . '/getfile';
|
||||
$ret['original_channel'] = $channel['channel_address'];
|
||||
|
||||
|
||||
if($deleted) {
|
||||
$ret['attach'] = array(array('hash' => $resource_id, 'deleted' => 1));
|
||||
return $ret;
|
||||
}
|
||||
|
||||
do {
|
||||
$r = q("select * from attach where hash = '%s' and uid = %d limit 1",
|
||||
dbesc($hash_ptr),
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
if(! $r)
|
||||
break;
|
||||
|
||||
if($hash_ptr === $resource_id) {
|
||||
$attach_ptr = $r[0];
|
||||
}
|
||||
|
||||
$hash_ptr = $r[0]['folder'];
|
||||
$paths[] = $r[0];
|
||||
} while($hash_ptr);
|
||||
|
||||
|
||||
|
||||
|
||||
$paths = array_reverse($paths);
|
||||
|
||||
$ret['attach'] = $paths;
|
||||
|
||||
|
||||
if($attach_ptr['is_photo']) {
|
||||
$r = q("select * from photo where resource_id = '%s' and uid = %d order by scale asc",
|
||||
dbesc($resource_id),
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
if($r) {
|
||||
for($x = 0; $x < count($r); $x ++) {
|
||||
$r[$x]['data'] = base64_encode($r[$x]['data']);
|
||||
}
|
||||
$ret['photo'] = $r;
|
||||
}
|
||||
|
||||
$r = q("select * from item where resource_id = '%s' and resource_type = 'photo' and uid = %d ",
|
||||
dbesc($resource_id),
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
if($r) {
|
||||
$ret['item'] = array();
|
||||
$items = q("select item.*, item.id as item_id from item where item.parent = %d ",
|
||||
intval($r[0]['id'])
|
||||
);
|
||||
if($items) {
|
||||
xchan_query($items);
|
||||
$items = fetch_post_tags($items,true);
|
||||
foreach($items as $rr)
|
||||
$ret['item'][] = encode_item($rr,true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $ret;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* strip off 'store/nickname/' from the provided path */
|
||||
|
||||
function get_attach_binname($s) {
|
||||
$p = $s;
|
||||
if(strpos($s,'store/') === 0) {
|
||||
$p = substr($s,6);
|
||||
$p = substr($p,strpos($p,'/')+1);
|
||||
}
|
||||
return $p;
|
||||
}
|
||||
@@ -12,33 +12,6 @@
|
||||
require_once('include/api_auth.php');
|
||||
require_once('include/security.php');
|
||||
|
||||
/**
|
||||
* @brief Resets the current session.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function nuke_session() {
|
||||
new_cookie(0); // 0 means delete on browser exit
|
||||
|
||||
unset($_SESSION['authenticated']);
|
||||
unset($_SESSION['account_id']);
|
||||
unset($_SESSION['uid']);
|
||||
unset($_SESSION['visitor_id']);
|
||||
unset($_SESSION['administrator']);
|
||||
unset($_SESSION['cid']);
|
||||
unset($_SESSION['theme']);
|
||||
unset($_SESSION['mobile_theme']);
|
||||
unset($_SESSION['show_mobile']);
|
||||
unset($_SESSION['page_flags']);
|
||||
unset($_SESSION['delegate']);
|
||||
unset($_SESSION['delegate_channel']);
|
||||
unset($_SESSION['my_url']);
|
||||
unset($_SESSION['my_address']);
|
||||
unset($_SESSION['addr']);
|
||||
unset($_SESSION['return_url']);
|
||||
unset($_SESSION['remote_service_class']);
|
||||
unset($_SESSION['remote_hub']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Verify login credentials.
|
||||
@@ -124,11 +97,11 @@ if((isset($_SESSION)) && (x($_SESSION, 'authenticated')) &&
|
||||
|
||||
// process a logout request
|
||||
|
||||
if(((x($_POST, 'auth-params')) && ($_POST['auth-params'] === 'logout')) || ($a->module === 'logout')) {
|
||||
if(((x($_POST, 'auth-params')) && ($_POST['auth-params'] === 'logout')) || (App::$module === 'logout')) {
|
||||
// process logout request
|
||||
$args = array('channel_id' => local_channel());
|
||||
call_hooks('logging_out', $args);
|
||||
nuke_session();
|
||||
\Zotlabs\Web\Session::nuke();
|
||||
info( t('Logged out.') . EOL);
|
||||
goaway(z_root());
|
||||
}
|
||||
@@ -144,7 +117,7 @@ if((isset($_SESSION)) && (x($_SESSION, 'authenticated')) &&
|
||||
intval(ACCOUNT_ROLE_ADMIN)
|
||||
);
|
||||
if($x) {
|
||||
new_cookie(60 * 60 * 24); // one day
|
||||
\Zotlabs\Web\Session::new_cookie(60 * 60 * 24); // one day
|
||||
$_SESSION['last_login_date'] = datetime_convert();
|
||||
unset($_SESSION['visitor_id']); // no longer a visitor
|
||||
authenticate_success($x[0], true, true);
|
||||
@@ -155,75 +128,41 @@ if((isset($_SESSION)) && (x($_SESSION, 'authenticated')) &&
|
||||
dbesc($_SESSION['visitor_id'])
|
||||
);
|
||||
if($r) {
|
||||
get_app()->set_observer($r[0]);
|
||||
App::set_observer($r[0]);
|
||||
}
|
||||
else {
|
||||
unset($_SESSION['visitor_id']);
|
||||
unset($_SESSION['authenticated']);
|
||||
}
|
||||
$a->set_groups(init_groups_visitor($_SESSION['visitor_id']));
|
||||
App::set_groups(init_groups_visitor($_SESSION['visitor_id']));
|
||||
}
|
||||
|
||||
// already logged in user returning
|
||||
|
||||
if(x($_SESSION, 'uid') || x($_SESSION, 'account_id')) {
|
||||
|
||||
// first check if we're enforcing that sessions can't change IP address
|
||||
// @todo what to do with IPv6 addresses
|
||||
if($_SESSION['addr'] && $_SESSION['addr'] != $_SERVER['REMOTE_ADDR']) {
|
||||
logger('SECURITY: Session IP address changed: ' . $_SESSION['addr'] . ' != ' . $_SERVER['REMOTE_ADDR']);
|
||||
|
||||
$partial1 = substr($_SESSION['addr'], 0, strrpos($_SESSION['addr'], '.'));
|
||||
$partial2 = substr($_SERVER['REMOTE_ADDR'], 0, strrpos($_SERVER['REMOTE_ADDR'], '.'));
|
||||
|
||||
$paranoia = intval(get_pconfig($_SESSION['uid'], 'system', 'paranoia'));
|
||||
if(! $paranoia)
|
||||
$paranoia = intval(get_config('system', 'paranoia'));
|
||||
|
||||
switch($paranoia) {
|
||||
case 0:
|
||||
// no IP checking
|
||||
break;
|
||||
case 2:
|
||||
// check 2 octets
|
||||
$partial1 = substr($partial1, 0, strrpos($partial1, '.'));
|
||||
$partial2 = substr($partial2, 0, strrpos($partial2, '.'));
|
||||
if($partial1 == $partial2)
|
||||
break;
|
||||
case 1:
|
||||
// check 3 octets
|
||||
if($partial1 == $partial2)
|
||||
break;
|
||||
case 3:
|
||||
default:
|
||||
// check any difference at all
|
||||
logger('Session address changed. Paranoid setting in effect, blocking session. '
|
||||
. $_SESSION['addr'] . ' != ' . $_SERVER['REMOTE_ADDR']);
|
||||
nuke_session();
|
||||
goaway(z_root());
|
||||
break;
|
||||
}
|
||||
}
|
||||
Zotlabs\Web\Session::return_check();
|
||||
|
||||
$r = q("select * from account where account_id = %d limit 1",
|
||||
intval($_SESSION['account_id'])
|
||||
);
|
||||
|
||||
if(($r) && (($r[0]['account_flags'] == ACCOUNT_OK) || ($r[0]['account_flags'] == ACCOUNT_UNVERIFIED))) {
|
||||
get_app()->account = $r[0];
|
||||
App::$account = $r[0];
|
||||
$login_refresh = false;
|
||||
if(! x($_SESSION,'last_login_date')) {
|
||||
$_SESSION['last_login_date'] = datetime_convert('UTC','UTC');
|
||||
}
|
||||
if(strcmp(datetime_convert('UTC','UTC','now - 12 hours'), $_SESSION['last_login_date']) > 0 ) {
|
||||
$_SESSION['last_login_date'] = datetime_convert();
|
||||
Zotlabs\Web\Session::extend_cookie();
|
||||
$login_refresh = true;
|
||||
}
|
||||
authenticate_success($r[0], false, false, false, $login_refresh);
|
||||
}
|
||||
else {
|
||||
$_SESSION['account_id'] = 0;
|
||||
nuke_session();
|
||||
\Zotlabs\Web\Session::nuke();
|
||||
goaway(z_root());
|
||||
}
|
||||
} // end logged in user returning
|
||||
@@ -231,7 +170,7 @@ if((isset($_SESSION)) && (x($_SESSION, 'authenticated')) &&
|
||||
else {
|
||||
|
||||
if(isset($_SESSION)) {
|
||||
nuke_session();
|
||||
\Zotlabs\Web\Session::nuke();
|
||||
}
|
||||
|
||||
// handle a fresh login request
|
||||
@@ -264,16 +203,16 @@ else {
|
||||
$record = $addon_auth['user_record'];
|
||||
}
|
||||
else {
|
||||
$record = get_app()->account = account_verify_password($_POST['username'], $_POST['password']);
|
||||
$record = App::$account = account_verify_password($_POST['username'], $_POST['password']);
|
||||
|
||||
if(get_app()->account) {
|
||||
$_SESSION['account_id'] = get_app()->account['account_id'];
|
||||
if(App::$account) {
|
||||
$_SESSION['account_id'] = App::$account['account_id'];
|
||||
}
|
||||
else {
|
||||
notice( t('Failed authentication') . EOL);
|
||||
}
|
||||
|
||||
logger('authenticate: ' . print_r(get_app()->account, true), LOGGER_DEBUG);
|
||||
logger('authenticate: ' . print_r(App::$account, true), LOGGER_ALL);
|
||||
}
|
||||
|
||||
if((! $record) || (! count($record))) {
|
||||
@@ -301,11 +240,13 @@ else {
|
||||
// (i.e. expire when the browser is closed), even when there's a time expiration
|
||||
// on the cookie
|
||||
|
||||
if($_POST['remember']) {
|
||||
new_cookie(31449600); // one year
|
||||
if($_POST['remember_me']) {
|
||||
$_SESSION['remember_me'] = 1;
|
||||
\Zotlabs\Web\Session::new_cookie(31449600); // one year
|
||||
}
|
||||
else {
|
||||
new_cookie(0); // 0 means delete on browser exit
|
||||
$_SESSION['remember_me'] = 0;
|
||||
\Zotlabs\Web\Session::new_cookie(0); // 0 means delete on browser exit
|
||||
}
|
||||
|
||||
// if we haven't failed up this point, log them in.
|
||||
|
||||
@@ -473,7 +473,7 @@ function format_event_diaspora($ev) {
|
||||
$ev['start'] , $bd_format ))
|
||||
: day_translate(datetime_convert('UTC', 'UTC',
|
||||
$ev['start'] , $bd_format)))
|
||||
. '](' . $a->get_baseurl() . '/localtime/?f=&time=' . urlencode(datetime_convert('UTC','UTC',$ev['start'])) . ")\n";
|
||||
. '](' . z_root() . '/localtime/?f=&time=' . urlencode(datetime_convert('UTC','UTC',$ev['start'])) . ")\n";
|
||||
|
||||
if(! $ev['nofinish'])
|
||||
$o .= t('Finishes:') . ' ' . '['
|
||||
@@ -481,7 +481,7 @@ function format_event_diaspora($ev) {
|
||||
$ev['finish'] , $bd_format ))
|
||||
: day_translate(datetime_convert('UTC', 'UTC',
|
||||
$ev['finish'] , $bd_format )))
|
||||
. '](' . $a->get_baseurl() . '/localtime/?f=&time=' . urlencode(datetime_convert('UTC','UTC',$ev['finish'])) . ")\n";
|
||||
. '](' . z_root() . '/localtime/?f=&time=' . urlencode(datetime_convert('UTC','UTC',$ev['finish'])) . ")\n";
|
||||
|
||||
if(strlen($ev['location']))
|
||||
$o .= t('Location:') . bb2diaspora($ev['location'])
|
||||
|
||||
@@ -37,7 +37,7 @@ function tryzrlvideo($match) {
|
||||
if($zrl)
|
||||
$link = zid($link);
|
||||
|
||||
return '<video controls="controls" preload="none" src="' . str_replace(' ','%20',$link) . '" style="width:100%; max-width:' . get_app()->videowidth . 'px"><a href="' . str_replace(' ','%20',$link) . '">' . $link . '</a></video>';
|
||||
return '<video controls="controls" preload="none" src="' . str_replace(' ','%20',$link) . '" style="width:100%; max-width:' . App::$videowidth . 'px"><a href="' . str_replace(' ','%20',$link) . '">' . $link . '</a></video>';
|
||||
}
|
||||
|
||||
// [noparse][i]italic[/i][/noparse] turns into
|
||||
@@ -243,9 +243,7 @@ function bb_ShareAttributes($match) {
|
||||
if ($matches[1] != "")
|
||||
$message_id = $matches[1];
|
||||
|
||||
|
||||
/** @FIXME - this should really be a wall-item-ago so it will get updated on the client */
|
||||
$reldate = (($posted) ? relative_date($posted) : '');
|
||||
$reldate = '<span class="autotime" title="' . datetime_convert('UTC', date_default_timezone_get(), $posted, 'c') . '" >' . datetime_convert('UTC', date_default_timezone_get(), $posted, 'r') . '</span>';
|
||||
|
||||
$headline = '<div class="shared_container"> <div class="shared_header">';
|
||||
|
||||
@@ -280,9 +278,9 @@ function bb_location($match) {
|
||||
function bb_iframe($match) {
|
||||
$a = get_app();
|
||||
|
||||
$sandbox = ((strpos($match[1], $a->get_hostname())) ? ' sandbox="allow-scripts" ' : '');
|
||||
$sandbox = ((strpos($match[1], App::get_hostname())) ? ' sandbox="allow-scripts" ' : '');
|
||||
|
||||
return '<iframe ' . $sandbox . ' src="' . $match[1] . '" width="' . $a->videowidth . '" height="' . $a->videoheight . '"><a href="' . $match[1] . '">' . $match[1] . '</a></iframe>';
|
||||
return '<iframe ' . $sandbox . ' src="' . $match[1] . '" width="' . App::$videowidth . '" height="' . App::$videoheight . '"><a href="' . $match[1] . '">' . $match[1] . '</a></iframe>';
|
||||
}
|
||||
|
||||
function bb_ShareAttributesSimple($match) {
|
||||
@@ -315,9 +313,9 @@ function bb_ShareAttributesSimple($match) {
|
||||
|
||||
function rpost_callback($match) {
|
||||
if ($match[2]) {
|
||||
return str_replace($match[0], get_rpost_path(get_app()->get_observer()) . '&title=' . urlencode($match[2]) . '&body=' . urlencode($match[3]), $match[0]);
|
||||
return str_replace($match[0], get_rpost_path(App::get_observer()) . '&title=' . urlencode($match[2]) . '&body=' . urlencode($match[3]), $match[0]);
|
||||
} else {
|
||||
return str_replace($match[0], get_rpost_path(get_app()->get_observer()) . '&body=' . urlencode($match[3]), $match[0]);
|
||||
return str_replace($match[0], get_rpost_path(App::get_observer()) . '&body=' . urlencode($match[3]), $match[0]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -401,7 +399,7 @@ function bb_observer($Text) {
|
||||
|
||||
$a = get_app();
|
||||
|
||||
$observer = $a->get_observer();
|
||||
$observer = App::get_observer();
|
||||
|
||||
if ((strpos($Text,'[/observer]') !== false) || (strpos($Text,'[/rpost]') !== false)) {
|
||||
if ($observer) {
|
||||
@@ -415,7 +413,7 @@ function bb_observer($Text) {
|
||||
}
|
||||
}
|
||||
|
||||
$channel = $a->get_channel();
|
||||
$channel = App::get_channel();
|
||||
|
||||
if (strpos($Text,'[/channel]') !== false) {
|
||||
if ($channel) {
|
||||
@@ -477,7 +475,7 @@ function bbcode($Text, $preserve_nl = false, $tryoembed = true, $cache = false)
|
||||
if($cache)
|
||||
$observer = false;
|
||||
else
|
||||
$observer = $a->get_observer();
|
||||
$observer = App::get_observer();
|
||||
|
||||
if ((strpos($Text,'[/observer]') !== false) || (strpos($Text,'[/rpost]') !== false)) {
|
||||
if ($observer) {
|
||||
@@ -494,7 +492,7 @@ function bbcode($Text, $preserve_nl = false, $tryoembed = true, $cache = false)
|
||||
if($cache)
|
||||
$channel = false;
|
||||
else
|
||||
$channel = $a->get_channel();
|
||||
$channel = App::get_channel();
|
||||
|
||||
if (strpos($Text,'[/channel]') !== false) {
|
||||
if ($channel) {
|
||||
@@ -593,6 +591,11 @@ function bbcode($Text, $preserve_nl = false, $tryoembed = true, $cache = false)
|
||||
$Text = preg_replace("/\[zrl\]([$URLSearchString]*)\[\/zrl\]/ism", '<a class="zrl" href="$1" target="_blank" >$1</a>', $Text);
|
||||
$Text = preg_replace("/\[zrl\=([$URLSearchString]*)\](.*?)\[\/zrl\]/ism", '<a class="zrl" href="$1" target="_blank" >$2</a>', $Text);
|
||||
}
|
||||
|
||||
// Remove bookmarks from UNO
|
||||
if (UNO)
|
||||
$Text = str_replace('<span class="bookmark-identifier">#^</span>', '', $Text);
|
||||
|
||||
// Perform MAIL Search
|
||||
if (strpos($Text,'[/mail]') !== false) {
|
||||
$Text = preg_replace("/\[mail\]([$MAILSearchString]*)\[\/mail\]/", '<a href="mailto:$1" target="_blank" >$1</a>', $Text);
|
||||
@@ -684,7 +687,11 @@ function bbcode($Text, $preserve_nl = false, $tryoembed = true, $cache = false)
|
||||
}
|
||||
// Check for centered text
|
||||
if (strpos($Text,'[/center]') !== false) {
|
||||
$Text = preg_replace("(\[center\](.*?)\[\/center\])ism", "<div style=\"text-align:center;\">$1</div>", $Text);
|
||||
$Text = preg_replace("(\[center\](.*?)\[\/center\])ism", "<div style=\"text-align:center;\">$1</div>", $Text);
|
||||
}
|
||||
// Check for footer
|
||||
if (strpos($Text,'[/footer]') !== false) {
|
||||
$Text = preg_replace("(\[footer\](.*?)\[\/footer\])ism", "<div class=\"wall-item-footer\">$1</div>", $Text);
|
||||
}
|
||||
// Check for list text
|
||||
$Text = str_replace("[*]", "<li>", $Text);
|
||||
@@ -841,7 +848,7 @@ function bbcode($Text, $preserve_nl = false, $tryoembed = true, $cache = false)
|
||||
// crypt
|
||||
if (strpos($Text,'[/crypt]') !== false) {
|
||||
$x = random_string();
|
||||
$Text = preg_replace("/\[crypt\](.*?)\[\/crypt\]/ism",'<br /><div id="' . $x . '"><img src="' .$a->get_baseurl() . '/images/lock_icon.gif" onclick="red_decrypt(\'rot13\',\'\',\'$1\',\'#' . $x . '\');" alt="' . t('Encrypted content') . '" title="' . t('Encrypted content') . '" /><br /></div>', $Text);
|
||||
$Text = preg_replace("/\[crypt\](.*?)\[\/crypt\]/ism",'<br /><div id="' . $x . '"><img src="' .z_root() . '/images/lock_icon.gif" onclick="red_decrypt(\'rot13\',\'\',\'$1\',\'#' . $x . '\');" alt="' . t('Encrypted content') . '" title="' . t('Encrypted content') . '" /><br /></div>', $Text);
|
||||
$Text = preg_replace_callback("/\[crypt (.*?)\](.*?)\[\/crypt\]/ism", 'bb_parse_crypt', $Text);
|
||||
}
|
||||
|
||||
@@ -921,7 +928,7 @@ function bbcode($Text, $preserve_nl = false, $tryoembed = true, $cache = false)
|
||||
// $Text = preg_replace("/\[youtube\]https?:\/\/youtu.be\/(.*?)\[\/youtube\]/ism", '[youtube]$1[/youtube]', $Text);
|
||||
|
||||
// if ($tryoembed)
|
||||
// $Text = preg_replace("/\[youtube\]([A-Za-z0-9\-_=]+)(.*?)\[\/youtube\]/ism", '<iframe width="' . $a->videowidth . '" height="' . $a->videoheight . '" src="http://www.youtube.com/embed/$1" frameborder="0"></iframe>', $Text);
|
||||
// $Text = preg_replace("/\[youtube\]([A-Za-z0-9\-_=]+)(.*?)\[\/youtube\]/ism", '<iframe width="' . App::$videowidth . '" height="' . App::$videoheight . '" src="http://www.youtube.com/embed/$1" frameborder="0"></iframe>', $Text);
|
||||
// else
|
||||
// $Text = preg_replace("/\[youtube\]([A-Za-z0-9\-_=]+)(.*?)\[\/youtube\]/ism", "http://www.youtube.com/watch?v=$1", $Text);
|
||||
// }
|
||||
@@ -935,7 +942,7 @@ function bbcode($Text, $preserve_nl = false, $tryoembed = true, $cache = false)
|
||||
// $Text = preg_replace("/\[vimeo\]https?:\/\/vimeo.com\/([0-9]+)(.*?)\[\/vimeo\]/ism", '[vimeo]$1[/vimeo]', $Text);
|
||||
|
||||
// if ($tryoembed)
|
||||
// $Text = preg_replace("/\[vimeo\]([0-9]+)(.*?)\[\/vimeo\]/ism", '<iframe width="' . $a->videowidth . '" height="' . $a->videoheight . '" src="http://player.vimeo.com/video/$1" frameborder="0" ></iframe>', $Text);
|
||||
// $Text = preg_replace("/\[vimeo\]([0-9]+)(.*?)\[\/vimeo\]/ism", '<iframe width="' . App::$videowidth . '" height="' . App::$videoheight . '" src="http://player.vimeo.com/video/$1" frameborder="0" ></iframe>', $Text);
|
||||
// else
|
||||
// $Text = preg_replace("/\[vimeo\]([0-9]+)(.*?)\[\/vimeo\]/ism", "http://vimeo.com/$1", $Text);
|
||||
// }
|
||||
|
||||
@@ -202,7 +202,7 @@ function chatroom_list($uid) {
|
||||
require_once('include/security.php');
|
||||
$sql_extra = permissions_sql($uid);
|
||||
|
||||
$r = q("select cr_name, cr_id, count(cp_id) as cr_inroom from chatroom left join chatpresence on cr_id = cp_room where cr_uid = %d $sql_extra group by cr_name, cr_id order by cr_name",
|
||||
$r = q("select allow_cid, allow_gid, deny_cid, deny_gid, cr_name, cr_expire, cr_id, count(cp_id) as cr_inroom from chatroom left join chatpresence on cr_id = cp_room where cr_uid = %d $sql_extra group by cr_name, cr_id order by cr_name",
|
||||
intval($uid)
|
||||
);
|
||||
|
||||
|
||||
@@ -9,25 +9,32 @@ function cli_startup() {
|
||||
global $a, $db, $default_timezone;
|
||||
|
||||
if(is_null($a)) {
|
||||
$a = new App;
|
||||
$a = new miniApp;
|
||||
}
|
||||
|
||||
App::init();
|
||||
|
||||
if(is_null($db)) {
|
||||
@include(".htconfig.php");
|
||||
|
||||
$a->timezone = ((x($default_timezone)) ? $default_timezone : 'UTC');
|
||||
date_default_timezone_set($a->timezone);
|
||||
$a->convert();
|
||||
|
||||
if(! defined('UNO'))
|
||||
define('UNO', 0);
|
||||
|
||||
App::$timezone = ((x($default_timezone)) ? $default_timezone : 'UTC');
|
||||
date_default_timezone_set(App::$timezone);
|
||||
|
||||
require_once('include/dba/dba_driver.php');
|
||||
$db = dba_factory($db_host, $db_port, $db_user, $db_pass, $db_data, $db_type);
|
||||
unset($db_host, $db_port, $db_user, $db_pass, $db_data, $db_type);
|
||||
};
|
||||
|
||||
require_once('include/session.php');
|
||||
\Zotlabs\Web\Session::init();
|
||||
|
||||
load_config('system');
|
||||
|
||||
$a->set_baseurl(get_config('system','baseurl'));
|
||||
App::set_baseurl(get_config('system','baseurl'));
|
||||
|
||||
load_hooks();
|
||||
|
||||
|
||||
@@ -56,34 +56,34 @@ function comanche_parser(&$a, $s, $pass = 0) {
|
||||
if($pass == 0) {
|
||||
$cnt = preg_match("/\[layout\](.*?)\[\/layout\]/ism", $s, $matches);
|
||||
if($cnt)
|
||||
$a->page['template'] = trim($matches[1]);
|
||||
App::$page['template'] = trim($matches[1]);
|
||||
|
||||
$cnt = preg_match("/\[template=(.*?)\](.*?)\[\/template\]/ism", $s, $matches);
|
||||
if($cnt) {
|
||||
$a->page['template'] = trim($matches[2]);
|
||||
$a->page['template_style'] = trim($matches[2]) . '_' . $matches[1];
|
||||
App::$page['template'] = trim($matches[2]);
|
||||
App::$page['template_style'] = trim($matches[2]) . '_' . $matches[1];
|
||||
}
|
||||
|
||||
$cnt = preg_match("/\[template\](.*?)\[\/template\]/ism", $s, $matches);
|
||||
if($cnt) {
|
||||
$a->page['template'] = trim($matches[1]);
|
||||
App::$page['template'] = trim($matches[1]);
|
||||
}
|
||||
|
||||
$cnt = preg_match("/\[theme=(.*?)\](.*?)\[\/theme\]/ism", $s, $matches);
|
||||
if($cnt) {
|
||||
$a->layout['schema'] = trim($matches[1]);
|
||||
$a->layout['theme'] = trim($matches[2]);
|
||||
App::$layout['schema'] = trim($matches[1]);
|
||||
App::$layout['theme'] = trim($matches[2]);
|
||||
}
|
||||
|
||||
$cnt = preg_match("/\[theme\](.*?)\[\/theme\]/ism", $s, $matches);
|
||||
if($cnt)
|
||||
$a->layout['theme'] = trim($matches[1]);
|
||||
App::$layout['theme'] = trim($matches[1]);
|
||||
|
||||
$cnt = preg_match_all("/\[webpage\](.*?)\[\/webpage\]/ism", $s, $matches, PREG_SET_ORDER);
|
||||
if($cnt) {
|
||||
// only the last webpage definition is used if there is more than one
|
||||
foreach($matches as $mtch) {
|
||||
$a->layout['webpage'] = comanche_webpage($a,$mtch[1]);
|
||||
App::$layout['webpage'] = comanche_webpage($a,$mtch[1]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ function comanche_parser(&$a, $s, $pass = 0) {
|
||||
$cnt = preg_match_all("/\[region=(.*?)\](.*?)\[\/region\]/ism", $s, $matches, PREG_SET_ORDER);
|
||||
if($cnt) {
|
||||
foreach($matches as $mtch) {
|
||||
$a->layout['region_' . $mtch[1]] = comanche_region($a,$mtch[2]);
|
||||
App::$layout['region_' . $mtch[1]] = comanche_region($a,$mtch[2]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,8 +122,8 @@ function comanche_menu($s, $class = '') {
|
||||
|
||||
function comanche_replace_region($match) {
|
||||
$a = get_app();
|
||||
if (array_key_exists($match[1], $a->page)) {
|
||||
return $a->page[$match[1]];
|
||||
if (array_key_exists($match[1], App::$page)) {
|
||||
return App::$page[$match[1]];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,7 +136,7 @@ function comanche_replace_region($match) {
|
||||
* @return channel_id
|
||||
*/
|
||||
function comanche_get_channel_id() {
|
||||
$channel_id = ((is_array(get_app()->profile)) ? get_app()->profile['profile_uid'] : 0);
|
||||
$channel_id = ((is_array(App::$profile)) ? App::$profile['profile_uid'] : 0);
|
||||
|
||||
if ((! $channel_id) && (local_channel()))
|
||||
$channel_id = local_channel();
|
||||
@@ -190,7 +190,7 @@ function comanche_block($s, $class = '') {
|
||||
}
|
||||
|
||||
if(trim($r[0]['body']) === '$content') {
|
||||
$o .= get_app()->page['content'];
|
||||
$o .= App::$page['content'];
|
||||
}
|
||||
else {
|
||||
$o .= prepare_text($r[0]['body'], $r[0]['mimetype']);
|
||||
@@ -378,6 +378,6 @@ function comanche_region(&$a, $s) {
|
||||
|
||||
|
||||
function register_page_template($arr) {
|
||||
get_app()->page_layouts[$arr['template']] = array($arr['variant']);
|
||||
App::$page_layouts[$arr['template']] = array($arr['variant']);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
* an identifier. This is for example for people who do not have a local account.
|
||||
* The storage is of size MEDIUMTEXT.
|
||||
* @code{.php}
|
||||
* $observer = $a->get_observer_hash();
|
||||
* $observer = App::get_observer_hash();
|
||||
* if ($observer) {
|
||||
* $var = get_xconfig($observer, 'category', 'key');
|
||||
* }@endcode
|
||||
@@ -38,7 +38,7 @@
|
||||
* @brief Loads the hub's configuration from database to a cached storage.
|
||||
*
|
||||
* Retrieve a category ($family) of config variables from database to a cached
|
||||
* storage in the global $a->config[$family].
|
||||
* storage in the global App::$config[$family].
|
||||
*
|
||||
* @param string $family
|
||||
* The category of the configuration value
|
||||
@@ -46,19 +46,19 @@
|
||||
function load_config($family) {
|
||||
global $a;
|
||||
|
||||
if(! array_key_exists($family, $a->config))
|
||||
$a->config[$family] = array();
|
||||
if(! array_key_exists($family, App::$config))
|
||||
App::$config[$family] = array();
|
||||
|
||||
if(! array_key_exists('config_loaded', $a->config[$family])) {
|
||||
if(! array_key_exists('config_loaded', App::$config[$family])) {
|
||||
$r = q("SELECT * FROM config WHERE cat = '%s'", dbesc($family));
|
||||
if($r !== false) {
|
||||
if($r) {
|
||||
foreach($r as $rr) {
|
||||
$k = $rr['k'];
|
||||
$a->config[$family][$k] = $rr['v'];
|
||||
App::$config[$family][$k] = $rr['v'];
|
||||
}
|
||||
}
|
||||
$a->config[$family]['config_loaded'] = true;
|
||||
App::$config[$family]['config_loaded'] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -68,7 +68,7 @@ function load_config($family) {
|
||||
* and a key.
|
||||
*
|
||||
* Get a particular config variable from the given category ($family) and the
|
||||
* $key from a cached storage in $a->config[$family]. If a key is found in the
|
||||
* $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.
|
||||
*
|
||||
@@ -83,16 +83,16 @@ function load_config($family) {
|
||||
function get_config($family, $key) {
|
||||
global $a;
|
||||
|
||||
if((! array_key_exists($family, $a->config)) || (! array_key_exists('config_loaded', $a->config[$family])))
|
||||
if((! array_key_exists($family, App::$config)) || (! array_key_exists('config_loaded', App::$config[$family])))
|
||||
load_config($family);
|
||||
|
||||
if(array_key_exists('config_loaded', $a->config[$family])) {
|
||||
if(! array_key_exists($key, $a->config[$family])) {
|
||||
if(array_key_exists('config_loaded', App::$config[$family])) {
|
||||
if(! array_key_exists($key, App::$config[$family])) {
|
||||
return false;
|
||||
}
|
||||
return ((! is_array($a->config[$family][$key])) && (preg_match('|^a:[0-9]+:{.*}$|s', $a->config[$family][$key]))
|
||||
? unserialize($a->config[$family][$key])
|
||||
: $a->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]
|
||||
);
|
||||
}
|
||||
return false;
|
||||
@@ -148,7 +148,7 @@ function set_config($family, $key, $value) {
|
||||
dbesc($dbvalue)
|
||||
);
|
||||
if($ret) {
|
||||
$a->config[$family][$key] = $value;
|
||||
App::$config[$family][$key] = $value;
|
||||
$ret = $value;
|
||||
}
|
||||
return $ret;
|
||||
@@ -161,7 +161,7 @@ function set_config($family, $key, $value) {
|
||||
);
|
||||
|
||||
if($ret) {
|
||||
$a->config[$family][$key] = $value;
|
||||
App::$config[$family][$key] = $value;
|
||||
$ret = $value;
|
||||
}
|
||||
return $ret;
|
||||
@@ -170,7 +170,7 @@ function set_config($family, $key, $value) {
|
||||
/**
|
||||
* @brief Deletes the given key from the hub's configuration database.
|
||||
*
|
||||
* Removes the configured value from the stored cache in $a->config[$family]
|
||||
* Removes the configured value from the stored cache in App::$config[$family]
|
||||
* and removes it from the database.
|
||||
*
|
||||
* @param string $family
|
||||
@@ -183,8 +183,8 @@ function del_config($family, $key) {
|
||||
global $a;
|
||||
$ret = false;
|
||||
|
||||
if(array_key_exists($family, $a->config) && array_key_exists($key, $a->config[$family]))
|
||||
unset($a->config[$family][$key]);
|
||||
if(array_key_exists($family, App::$config) && array_key_exists($key, App::$config[$family]))
|
||||
unset(App::$config[$family][$key]);
|
||||
$ret = q("DELETE FROM config WHERE cat = '%s' AND k = '%s'",
|
||||
dbesc($family),
|
||||
dbesc($key)
|
||||
@@ -197,7 +197,7 @@ function del_config($family, $key) {
|
||||
* @brief Loads all configuration values of a channel into a cached storage.
|
||||
*
|
||||
* All configuration values of the given channel are stored in global cache
|
||||
* which is available under the global variable $a->config[$uid].
|
||||
* which is available under the global variable App::$config[$uid].
|
||||
*
|
||||
* @param string $uid
|
||||
* The channel_id
|
||||
@@ -209,8 +209,8 @@ function load_pconfig($uid) {
|
||||
if($uid === false)
|
||||
return false;
|
||||
|
||||
if(! array_key_exists($uid, $a->config))
|
||||
$a->config[$uid] = array();
|
||||
if(! array_key_exists($uid, App::$config))
|
||||
App::$config[$uid] = array();
|
||||
|
||||
$r = q("SELECT * FROM pconfig WHERE uid = %d",
|
||||
intval($uid)
|
||||
@@ -220,11 +220,11 @@ function load_pconfig($uid) {
|
||||
foreach($r as $rr) {
|
||||
$k = $rr['k'];
|
||||
$c = $rr['cat'];
|
||||
if(! array_key_exists($c, $a->config[$uid])) {
|
||||
$a->config[$uid][$c] = array();
|
||||
$a->config[$uid][$c]['config_loaded'] = true;
|
||||
if(! array_key_exists($c, App::$config[$uid])) {
|
||||
App::$config[$uid][$c] = array();
|
||||
App::$config[$uid][$c]['config_loaded'] = true;
|
||||
}
|
||||
$a->config[$uid][$c][$k] = $rr['v'];
|
||||
App::$config[$uid][$c][$k] = $rr['v'];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -234,7 +234,7 @@ function load_pconfig($uid) {
|
||||
* ($family) and a key.
|
||||
*
|
||||
* Get a particular channel's config value from the given category ($family)
|
||||
* and the $key from a cached storage in $a->config[$uid].
|
||||
* and the $key from a cached storage in App::$config[$uid].
|
||||
*
|
||||
* Returns false if not set.
|
||||
*
|
||||
@@ -254,15 +254,15 @@ function get_pconfig($uid, $family, $key, $instore = false) {
|
||||
if($uid === false)
|
||||
return false;
|
||||
|
||||
if(! array_key_exists($uid, $a->config))
|
||||
if(! array_key_exists($uid, App::$config))
|
||||
load_pconfig($uid);
|
||||
|
||||
if((! array_key_exists($family, $a->config[$uid])) || (! array_key_exists($key, $a->config[$uid][$family])))
|
||||
if((! array_key_exists($family, App::$config[$uid])) || (! array_key_exists($key, App::$config[$uid][$family])))
|
||||
return false;
|
||||
|
||||
return ((! is_array($a->config[$uid][$family][$key])) && (preg_match('|^a:[0-9]+:{.*}$|s', $a->config[$uid][$family][$key]))
|
||||
? unserialize($a->config[$uid][$family][$key])
|
||||
: $a->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]
|
||||
);
|
||||
}
|
||||
|
||||
@@ -287,27 +287,38 @@ function get_pconfig($uid, $family, $key, $instore = false) {
|
||||
function set_pconfig($uid, $family, $key, $value) {
|
||||
global $a;
|
||||
|
||||
// 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.
|
||||
// we provide a function backtrace in the logs so that we can find
|
||||
// and fix the calling function.
|
||||
|
||||
if($uid === false) {
|
||||
btlogger('UID is FALSE!', LOGGER_NORMAL, LOG_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
// manage array value
|
||||
$dbvalue = ((is_array($value)) ? serialize($value) : $value);
|
||||
$dbvalue = ((is_bool($dbvalue)) ? intval($dbvalue) : $dbvalue);
|
||||
|
||||
if(get_pconfig($uid, $family, $key) === false) {
|
||||
if(! array_key_exists($uid, $a->config))
|
||||
$a->config[$uid] = array();
|
||||
if(! array_key_exists($family, $a->config[$uid]))
|
||||
$a->config[$uid][$family] = array();
|
||||
if(! array_key_exists($uid, App::$config))
|
||||
App::$config[$uid] = array();
|
||||
if(! array_key_exists($family, App::$config[$uid]))
|
||||
App::$config[$uid][$family] = array();
|
||||
|
||||
// keep a separate copy for all variables which were
|
||||
// set in the life of this page. We need this to
|
||||
// synchronise channel clones.
|
||||
|
||||
if(! array_key_exists('transient', $a->config[$uid]))
|
||||
$a->config[$uid]['transient'] = array();
|
||||
if(! array_key_exists($family, $a->config[$uid]['transient']))
|
||||
$a->config[$uid]['transient'][$family] = array();
|
||||
if(! array_key_exists('transient', App::$config[$uid]))
|
||||
App::$config[$uid]['transient'] = array();
|
||||
if(! array_key_exists($family, App::$config[$uid]['transient']))
|
||||
App::$config[$uid]['transient'][$family] = array();
|
||||
|
||||
$a->config[$uid][$family][$key] = $value;
|
||||
$a->config[$uid]['transient'][$family][$key] = $value;
|
||||
App::$config[$uid][$family][$key] = $value;
|
||||
App::$config[$uid]['transient'][$family][$key] = $value;
|
||||
|
||||
$ret = q("INSERT INTO pconfig ( uid, cat, k, v ) VALUES ( %d, '%s', '%s', '%s' ) ",
|
||||
intval($uid),
|
||||
@@ -332,13 +343,13 @@ function set_pconfig($uid, $family, $key, $value) {
|
||||
// set in the life of this page. We need this to
|
||||
// synchronise channel clones.
|
||||
|
||||
if(! array_key_exists('transient', $a->config[$uid]))
|
||||
$a->config[$uid]['transient'] = array();
|
||||
if(! array_key_exists($family, $a->config[$uid]['transient']))
|
||||
$a->config[$uid]['transient'][$family] = array();
|
||||
if(! array_key_exists('transient', App::$config[$uid]))
|
||||
App::$config[$uid]['transient'] = array();
|
||||
if(! array_key_exists($family, App::$config[$uid]['transient']))
|
||||
App::$config[$uid]['transient'][$family] = array();
|
||||
|
||||
$a->config[$uid][$family][$key] = $value;
|
||||
$a->config[$uid]['transient'][$family][$key] = $value;
|
||||
App::$config[$uid][$family][$key] = $value;
|
||||
App::$config[$uid]['transient'][$family][$key] = $value;
|
||||
|
||||
if($ret)
|
||||
return $value;
|
||||
@@ -349,7 +360,7 @@ function set_pconfig($uid, $family, $key, $value) {
|
||||
/**
|
||||
* @brief Deletes the given key from the channel's configuration.
|
||||
*
|
||||
* Removes the configured value from the stored cache in $a->config[$uid]
|
||||
* Removes the configured value from the stored cache in App::$config[$uid]
|
||||
* and removes it from the database.
|
||||
*
|
||||
* @param string $uid
|
||||
@@ -364,8 +375,8 @@ function del_pconfig($uid, $family, $key) {
|
||||
global $a;
|
||||
$ret = false;
|
||||
|
||||
if (x($a->config[$uid][$family], $key))
|
||||
unset($a->config[$uid][$family][$key]);
|
||||
if (x(App::$config[$uid][$family], $key))
|
||||
unset(App::$config[$uid][$family][$key]);
|
||||
$ret = q("DELETE FROM pconfig WHERE uid = %d AND cat = '%s' AND k = '%s'",
|
||||
intval($uid),
|
||||
dbesc($family),
|
||||
@@ -380,7 +391,7 @@ function del_pconfig($uid, $family, $key) {
|
||||
* @brief Loads a full xchan's configuration into a cached storage.
|
||||
*
|
||||
* All configuration values of the given observer hash are stored in global
|
||||
* cache which is available under the global variable $a->config[$xchan].
|
||||
* cache which is available under the global variable App::$config[$xchan].
|
||||
*
|
||||
* @param string $xchan
|
||||
* The observer's hash
|
||||
@@ -392,8 +403,8 @@ function load_xconfig($xchan) {
|
||||
if(! $xchan)
|
||||
return false;
|
||||
|
||||
if(! array_key_exists($xchan, $a->config))
|
||||
$a->config[$xchan] = array();
|
||||
if(! array_key_exists($xchan, App::$config))
|
||||
App::$config[$xchan] = array();
|
||||
|
||||
$r = q("SELECT * FROM xconfig WHERE xchan = '%s'",
|
||||
dbesc($xchan)
|
||||
@@ -403,11 +414,11 @@ function load_xconfig($xchan) {
|
||||
foreach($r as $rr) {
|
||||
$k = $rr['k'];
|
||||
$c = $rr['cat'];
|
||||
if(! array_key_exists($c, $a->config[$xchan])) {
|
||||
$a->config[$xchan][$c] = array();
|
||||
$a->config[$xchan][$c]['config_loaded'] = true;
|
||||
if(! array_key_exists($c, App::$config[$xchan])) {
|
||||
App::$config[$xchan][$c] = array();
|
||||
App::$config[$xchan][$c]['config_loaded'] = true;
|
||||
}
|
||||
$a->config[$xchan][$c][$k] = $rr['v'];
|
||||
App::$config[$xchan][$c][$k] = $rr['v'];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -417,7 +428,7 @@ function load_xconfig($xchan) {
|
||||
* name ($family) and a key.
|
||||
*
|
||||
* Get a particular observer's config value from the given category ($family)
|
||||
* and the $key from a cached storage in $a->config[$xchan].
|
||||
* and the $key from a cached storage in App::$config[$xchan].
|
||||
*
|
||||
* Returns false if not set.
|
||||
*
|
||||
@@ -435,15 +446,15 @@ function get_xconfig($xchan, $family, $key) {
|
||||
if(! $xchan)
|
||||
return false;
|
||||
|
||||
if(! array_key_exists($xchan, $a->config))
|
||||
if(! array_key_exists($xchan, App::$config))
|
||||
load_xconfig($xchan);
|
||||
|
||||
if((! array_key_exists($family, $a->config[$xchan])) || (! array_key_exists($key, $a->config[$xchan][$family])))
|
||||
if((! array_key_exists($family, App::$config[$xchan])) || (! array_key_exists($key, App::$config[$xchan][$family])))
|
||||
return false;
|
||||
|
||||
return ((! is_array($a->config[$xchan][$family][$key])) && (preg_match('|^a:[0-9]+:{.*}$|s', $a->config[$xchan][$family][$key]))
|
||||
? unserialize($a->config[$xchan][$family][$key])
|
||||
: $a->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]
|
||||
);
|
||||
}
|
||||
|
||||
@@ -473,12 +484,12 @@ function set_xconfig($xchan, $family, $key, $value) {
|
||||
$dbvalue = ((is_bool($dbvalue)) ? intval($dbvalue) : $dbvalue);
|
||||
|
||||
if(get_xconfig($xchan, $family, $key) === false) {
|
||||
if(! array_key_exists($xchan, $a->config))
|
||||
$a->config[$xchan] = array();
|
||||
if(! array_key_exists($family, $a->config[$xchan]))
|
||||
$a->config[$xchan][$family] = array();
|
||||
if(! array_key_exists($xchan, App::$config))
|
||||
App::$config[$xchan] = array();
|
||||
if(! array_key_exists($family, App::$config[$xchan]))
|
||||
App::$config[$xchan][$family] = array();
|
||||
|
||||
$a->config[$xchan][$family][$key] = $value;
|
||||
App::$config[$xchan][$family][$key] = $value;
|
||||
$ret = q("INSERT INTO xconfig ( xchan, cat, k, v ) VALUES ( '%s', '%s', '%s', '%s' ) ",
|
||||
dbesc($xchan),
|
||||
dbesc($family),
|
||||
@@ -497,7 +508,7 @@ function set_xconfig($xchan, $family, $key, $value) {
|
||||
dbesc($key)
|
||||
);
|
||||
|
||||
$a->config[$xchan][$family][$key] = $value;
|
||||
App::$config[$xchan][$family][$key] = $value;
|
||||
|
||||
if($ret)
|
||||
return $value;
|
||||
@@ -507,7 +518,7 @@ function set_xconfig($xchan, $family, $key, $value) {
|
||||
/**
|
||||
* @brief Deletes the given key from the observer's config.
|
||||
*
|
||||
* Removes the configured value from the stored cache in $a->config[$xchan]
|
||||
* Removes the configured value from the stored cache in App::$config[$xchan]
|
||||
* and removes it from the database.
|
||||
*
|
||||
* @param string $xchan
|
||||
@@ -522,8 +533,8 @@ function del_xconfig($xchan, $family, $key) {
|
||||
global $a;
|
||||
$ret = false;
|
||||
|
||||
if(x($a->config[$xchan][$family], $key))
|
||||
unset($a->config[$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),
|
||||
@@ -549,4 +560,68 @@ function set_aconfig($account_id, $family, $key, $value) {
|
||||
|
||||
function del_aconfig($account_id, $family, $key) {
|
||||
return del_xconfig('a_' . $account_id, $family, $key);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function load_abconfig($chash,$xhash) {
|
||||
$r = q("select * from abconfig where chan = '%s' and xchan = '%s'",
|
||||
dbesc($chash),
|
||||
dbesc($xhash)
|
||||
);
|
||||
return $r;
|
||||
}
|
||||
|
||||
function get_abconfig($chash,$xhash,$family,$key) {
|
||||
$r = q("select * from abconfig where chan = '%s' and xchan = '%s' and cat = '%s' and k = '%s' limit 1",
|
||||
dbesc($chash),
|
||||
dbesc($xhash),
|
||||
dbesc($family),
|
||||
dbesc($key)
|
||||
);
|
||||
if($r) {
|
||||
return ((preg_match('|^a:[0-9]+:{.*}$|s', $r[0]['v'])) ? unserialize($r[0]['v']) : $r[0]['v']);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
function set_abconfig($chash,$xhash,$family,$key,$value) {
|
||||
|
||||
$dbvalue = ((is_array($value)) ? serialize($value) : $value);
|
||||
$dbvalue = ((is_bool($dbvalue)) ? intval($dbvalue) : $dbvalue);
|
||||
|
||||
if(get_abconfig($chash,$xhash,$family,$key) === false) {
|
||||
$r = q("insert into abconfig ( chan, xchan, cat, k, v ) values ( '%s', '%s', '%s', '%s', '%s' ) ",
|
||||
dbesc($chash),
|
||||
dbesc($xhash),
|
||||
dbesc($family),
|
||||
dbesc($key),
|
||||
dbesc($dbvalue)
|
||||
);
|
||||
}
|
||||
else {
|
||||
$r = q("update abconfig set v = '%s' where chan = '%s' and xchan = '%s' and cat = '%s' and k = '%s' ",
|
||||
dbesc($dbvalue),
|
||||
dbesc($chash),
|
||||
dbesc($xhash),
|
||||
dbesc($family),
|
||||
dbesc($key)
|
||||
);
|
||||
}
|
||||
if($r)
|
||||
return $value;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
function del_abconfig($chash,$xhash,$family,$key) {
|
||||
|
||||
$r = q("delete from abconfig where chan = '%s' and xchan = '%s' and cat = '%s' and k = '%s' ",
|
||||
dbesc($chash),
|
||||
dbesc($xhash),
|
||||
dbesc($family),
|
||||
dbesc($key)
|
||||
);
|
||||
|
||||
return $r;
|
||||
}
|
||||
|
||||
@@ -73,16 +73,18 @@ function contact_poll_interval($current, $disabled = false) {
|
||||
function network_to_name($s) {
|
||||
|
||||
$nets = array(
|
||||
NETWORK_DFRN => t('Friendica'),
|
||||
NETWORK_OSTATUS => t('OStatus'),
|
||||
NETWORK_FEED => t('RSS/Atom'),
|
||||
NETWORK_MAIL => t('Email'),
|
||||
NETWORK_DIASPORA => t('Diaspora'),
|
||||
NETWORK_FACEBOOK => t('Facebook'),
|
||||
NETWORK_ZOT => t('Zot'),
|
||||
NETWORK_LINKEDIN => t('LinkedIn'),
|
||||
NETWORK_XMPP => t('XMPP/IM'),
|
||||
NETWORK_MYSPACE => t('MySpace'),
|
||||
NETWORK_DFRN => t('Friendica'),
|
||||
NETWORK_FRND => t('Friendica'),
|
||||
NETWORK_OSTATUS => t('OStatus'),
|
||||
NETWORK_GNUSOCIAL => t('GNU-Social'),
|
||||
NETWORK_FEED => t('RSS/Atom'),
|
||||
NETWORK_MAIL => t('Email'),
|
||||
NETWORK_DIASPORA => t('Diaspora'),
|
||||
NETWORK_FACEBOOK => t('Facebook'),
|
||||
NETWORK_ZOT => t('Zot'),
|
||||
NETWORK_LINKEDIN => t('LinkedIn'),
|
||||
NETWORK_XMPP => t('XMPP/IM'),
|
||||
NETWORK_MYSPACE => t('MySpace'),
|
||||
);
|
||||
|
||||
call_hooks('network_to_name', $nets);
|
||||
|
||||
@@ -10,7 +10,7 @@ function findpeople_widget() {
|
||||
if(get_config('system','invitation_only')) {
|
||||
$x = get_pconfig(local_channel(),'system','invites_remaining');
|
||||
if($x || is_site_admin()) {
|
||||
$a->page['aside'] .= '<div class="side-link" id="side-invite-remain">'
|
||||
App::$page['aside'] .= '<div class="side-link" id="side-invite-remain">'
|
||||
. sprintf( tt('%d invitation available','%d invitations available',$x), $x)
|
||||
. '</div>' . $inv;
|
||||
}
|
||||
@@ -68,7 +68,7 @@ function categories_widget($baseurl,$selected = '') {
|
||||
|
||||
$a = get_app();
|
||||
|
||||
if(! feature_enabled($a->profile['profile_uid'],'categories'))
|
||||
if(! feature_enabled(App::$profile['profile_uid'],'categories'))
|
||||
return '';
|
||||
|
||||
$item_normal = item_normal();
|
||||
@@ -83,9 +83,9 @@ function categories_widget($baseurl,$selected = '') {
|
||||
and item.item_wall = 1
|
||||
$item_normal
|
||||
order by term.term asc",
|
||||
intval($a->profile['profile_uid']),
|
||||
intval(App::$profile['profile_uid']),
|
||||
intval(TERM_CATEGORY),
|
||||
dbesc($a->profile['channel_hash'])
|
||||
dbesc(App::$profile['channel_hash'])
|
||||
);
|
||||
if($r && count($r)) {
|
||||
foreach($r as $rr)
|
||||
@@ -126,7 +126,7 @@ function common_friends_visitor_widget($profile_uid) {
|
||||
|
||||
return replace_macros(get_markup_template('remote_friends_common.tpl'), array(
|
||||
'$desc' => sprintf( tt("%d connection in common", "%d connections in common", $t), $t),
|
||||
'$base' => $a->get_baseurl(),
|
||||
'$base' => z_root(),
|
||||
'$uid' => $profile_uid,
|
||||
'$cid' => $observer,
|
||||
'$linkmore' => (($t > 5) ? 'true' : ''),
|
||||
|
||||
@@ -54,7 +54,7 @@ function item_redir_and_replace_images($body, $images, $cid) {
|
||||
$origbody = $body;
|
||||
$newbody = '';
|
||||
|
||||
$observer = get_app()->get_observer();
|
||||
$observer = App::get_observer();
|
||||
$obhash = (($observer) ? $observer['xchan_hash'] : '');
|
||||
$obaddr = (($observer) ? $observer['xchan_addr'] : '');
|
||||
|
||||
@@ -489,7 +489,7 @@ function conversation(&$a, $items, $mode, $update, $page_mode = 'traditional', $
|
||||
|
||||
$live_update_div = '<div id="live-network"></div>' . "\r\n"
|
||||
. "<script> var profile_uid = " . $_SESSION['uid']
|
||||
. "; var netargs = '" . substr($a->cmd,8)
|
||||
. "; var netargs = '" . substr(App::$cmd,8)
|
||||
. '?f='
|
||||
. ((x($_GET,'cid')) ? '&cid=' . $_GET['cid'] : '')
|
||||
. ((x($_GET,'search')) ? '&search=' . $_GET['search'] : '')
|
||||
@@ -504,12 +504,12 @@ function conversation(&$a, $items, $mode, $update, $page_mode = 'traditional', $
|
||||
. ((x($_GET,'cmax')) ? '&cmax=' . $_GET['cmax'] : '')
|
||||
. ((x($_GET,'file')) ? '&file=' . $_GET['file'] : '')
|
||||
. ((x($_GET,'uri')) ? '&uri=' . $_GET['uri'] : '')
|
||||
. "'; var profile_page = " . $a->pager['page'] . "; </script>\r\n";
|
||||
. "'; var profile_page = " . App::$pager['page'] . "; </script>\r\n";
|
||||
}
|
||||
}
|
||||
|
||||
elseif ($mode === 'channel') {
|
||||
$profile_owner = $a->profile['profile_uid'];
|
||||
$profile_owner = App::$profile['profile_uid'];
|
||||
$page_writeable = ($profile_owner == local_channel());
|
||||
|
||||
if (!$update) {
|
||||
@@ -519,8 +519,8 @@ function conversation(&$a, $items, $mode, $update, $page_mode = 'traditional', $
|
||||
// because browser prefetching might change it on us. We have to deliver it with the page.
|
||||
|
||||
$live_update_div = '<div id="live-channel"></div>' . "\r\n"
|
||||
. "<script> var profile_uid = " . $a->profile['profile_uid']
|
||||
. "; var netargs = '?f='; var profile_page = " . $a->pager['page'] . "; </script>\r\n";
|
||||
. "<script> var profile_uid = " . App::$profile['profile_uid']
|
||||
. "; var netargs = '?f='; var profile_page = " . App::$pager['page'] . "; </script>\r\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -532,7 +532,7 @@ function conversation(&$a, $items, $mode, $update, $page_mode = 'traditional', $
|
||||
}
|
||||
|
||||
elseif ($mode === 'page') {
|
||||
$profile_owner = $a->profile['uid'];
|
||||
$profile_owner = App::$profile['uid'];
|
||||
$page_writeable = ($profile_owner == local_channel());
|
||||
$live_update_div = '<div id="live-page"></div>' . "\r\n";
|
||||
}
|
||||
@@ -542,11 +542,11 @@ function conversation(&$a, $items, $mode, $update, $page_mode = 'traditional', $
|
||||
}
|
||||
|
||||
elseif ($mode === 'photos') {
|
||||
$profile_onwer = $a->profile['profile_uid'];
|
||||
$profile_onwer = App::$profile['profile_uid'];
|
||||
$page_writeable = ($profile_owner == local_channel());
|
||||
$live_update_div = '<div id="live-photos"></div>' . "\r\n";
|
||||
// for photos we've already formatted the top-level item (the photo)
|
||||
$content_html = $a->data['photo_html'];
|
||||
$content_html = App::$data['photo_html'];
|
||||
}
|
||||
|
||||
$page_dropping = ((local_channel() && local_channel() == $profile_owner) ? true : false);
|
||||
@@ -555,13 +555,13 @@ function conversation(&$a, $items, $mode, $update, $page_mode = 'traditional', $
|
||||
$page_dropping = false;
|
||||
|
||||
|
||||
$channel = $a->get_channel();
|
||||
$observer = $a->get_observer();
|
||||
$channel = App::get_channel();
|
||||
$observer = App::get_observer();
|
||||
|
||||
if($update)
|
||||
$return_url = $_SESSION['return_url'];
|
||||
else
|
||||
$return_url = $_SESSION['return_url'] = $a->query_string;
|
||||
$return_url = $_SESSION['return_url'] = App::$query_string;
|
||||
|
||||
load_contact_links(local_channel());
|
||||
|
||||
@@ -623,7 +623,7 @@ function conversation(&$a, $items, $mode, $update, $page_mode = 'traditional', $
|
||||
$nickname = $item['nickname'];
|
||||
}
|
||||
else
|
||||
$nickname = $a->user['nickname'];
|
||||
$nickname = App::$user['nickname'];
|
||||
|
||||
$profile_name = ((strlen($item['author-name'])) ? $item['author-name'] : $item['name']);
|
||||
if($item['author-link'] && (! $item['author-name']))
|
||||
@@ -844,12 +844,12 @@ function conversation(&$a, $items, $mode, $update, $page_mode = 'traditional', $
|
||||
|
||||
|
||||
$o .= replace_macros($page_template, array(
|
||||
'$baseurl' => $a->get_baseurl($ssl_state),
|
||||
'$baseurl' => z_root(),
|
||||
'$photo_item' => $content_html,
|
||||
'$live_update' => $live_update_div,
|
||||
'$remove' => t('remove'),
|
||||
'$mode' => $mode,
|
||||
'$user' => $a->user,
|
||||
'$user' => App::$user,
|
||||
'$threads' => $threads,
|
||||
'$wait' => t('Loading...'),
|
||||
'$dropping' => ($page_dropping?t('Delete Selected Items'):False),
|
||||
@@ -869,13 +869,13 @@ function best_link_url($item) {
|
||||
$clean_url = normalise_link($item['author-link']);
|
||||
|
||||
if((local_channel()) && (local_channel() == $item['uid'])) {
|
||||
if(isset($a->contacts) && x($a->contacts,$clean_url)) {
|
||||
if($a->contacts[$clean_url]['network'] === NETWORK_DFRN) {
|
||||
$best_url = $a->get_baseurl($ssl_state) . '/redir/' . $a->contacts[$clean_url]['id'];
|
||||
if(isset(App::$contacts) && x(App::$contacts,$clean_url)) {
|
||||
if(App::$contacts[$clean_url]['network'] === NETWORK_DFRN) {
|
||||
$best_url = z_root() . '/redir/' . App::$contacts[$clean_url]['id'];
|
||||
$sparkle = true;
|
||||
}
|
||||
else
|
||||
$best_url = $a->contacts[$clean_url]['url'];
|
||||
$best_url = App::$contacts[$clean_url]['url'];
|
||||
}
|
||||
}
|
||||
if(! $best_url) {
|
||||
@@ -907,9 +907,9 @@ function item_photo_menu($item){
|
||||
|
||||
if($local_channel) {
|
||||
$ssl_state = true;
|
||||
if(! count($a->contacts))
|
||||
if(! count(App::$contacts))
|
||||
load_contact_links($local_channel);
|
||||
$channel = $a->get_channel();
|
||||
$channel = App::get_channel();
|
||||
$channel_hash = (($channel) ? $channel['channel_hash'] : '');
|
||||
}
|
||||
|
||||
@@ -925,19 +925,19 @@ function item_photo_menu($item){
|
||||
|
||||
$profile_link = chanlink_hash($item['author_xchan']);
|
||||
if($item['uid'] > 0)
|
||||
$pm_url = $a->get_baseurl($ssl_state) . '/mail/new/?f=&hash=' . $item['author_xchan'];
|
||||
$pm_url = z_root() . '/mail/new/?f=&hash=' . $item['author_xchan'];
|
||||
|
||||
if($a->contacts && array_key_exists($item['author_xchan'],$a->contacts))
|
||||
$contact = $a->contacts[$item['author_xchan']];
|
||||
if(App::$contacts && array_key_exists($item['author_xchan'],App::$contacts))
|
||||
$contact = App::$contacts[$item['author_xchan']];
|
||||
else
|
||||
if($local_channel && $item['author']['xchan_addr'])
|
||||
$follow_url = z_root() . '/follow/?f=&url=' . $item['author']['xchan_addr'];
|
||||
|
||||
if($contact) {
|
||||
$poke_link = $a->get_baseurl($ssl_state) . '/poke/?f=&c=' . $contact['abook_id'];
|
||||
$poke_link = z_root() . '/poke/?f=&c=' . $contact['abook_id'];
|
||||
if (! intval($contact['abook_self']))
|
||||
$contact_url = $a->get_baseurl($ssl_state) . '/connedit/' . $contact['abook_id'];
|
||||
$posts_link = $a->get_baseurl($ssl_state) . '/network/?cid=' . $contact['abook_id'];
|
||||
$contact_url = z_root() . '/connedit/' . $contact['abook_id'];
|
||||
$posts_link = z_root() . '/network/?cid=' . $contact['abook_id'];
|
||||
|
||||
$clean_url = normalise_link($item['author-link']);
|
||||
}
|
||||
@@ -1110,6 +1110,11 @@ function status_editor($a, $x, $popup = false) {
|
||||
|
||||
$o = '';
|
||||
|
||||
require_once('include/Contact.php');
|
||||
$c = channelx_by_n($x['profile_uid']);
|
||||
if($c && $c['channel_moved'])
|
||||
return $o;
|
||||
|
||||
$geotag = (($x['allow_location']) ? replace_macros(get_markup_template('jot_geotag.tpl'), array()) : '');
|
||||
|
||||
$plaintext = true;
|
||||
@@ -1154,9 +1159,9 @@ function status_editor($a, $x, $popup = false) {
|
||||
|
||||
$tpl = get_markup_template('jot-header.tpl');
|
||||
|
||||
$a->page['htmlhead'] .= replace_macros($tpl, array(
|
||||
App::$page['htmlhead'] .= replace_macros($tpl, array(
|
||||
'$newpost' => 'true',
|
||||
'$baseurl' => $a->get_baseurl(true),
|
||||
'$baseurl' => z_root(),
|
||||
'$editselect' => (($plaintext) ? 'none' : '/(profile-jot-text|prvmail-text)/'),
|
||||
'$pretext' => ((x($x,'pretext')) ? $x['pretext'] : ''),
|
||||
'$geotag' => $geotag,
|
||||
@@ -1168,7 +1173,9 @@ function status_editor($a, $x, $popup = false) {
|
||||
'$term' => t('Tag term:'),
|
||||
'$fileas' => t('Save to Folder:'),
|
||||
'$whereareu' => t('Where are you right now?'),
|
||||
'$expireswhen' => t('Expires YYYY-MM-DD HH:MM')
|
||||
'$expireswhen' => t('Expires YYYY-MM-DD HH:MM'),
|
||||
'$editor_autocomplete'=> ((x($x,'editor_autocomplete')) ? $x['editor_autocomplete'] : ''),
|
||||
'$bbco_autocomplete'=> ((x($x,'bbco_autocomplete')) ? $x['bbco_autocomplete'] : ''),
|
||||
));
|
||||
|
||||
$tpl = get_markup_template('jot.tpl');
|
||||
@@ -1197,8 +1204,8 @@ function status_editor($a, $x, $popup = false) {
|
||||
call_hooks('jot_networks', $jotnets);
|
||||
|
||||
$o .= replace_macros($tpl, array(
|
||||
'$return_path' => ((x($x, 'return_path')) ? $x['return_path'] : $a->query_string),
|
||||
'$action' => $a->get_baseurl(true) . '/item',
|
||||
'$return_path' => ((x($x, 'return_path')) ? $x['return_path'] : App::$query_string),
|
||||
'$action' => z_root() . '/item',
|
||||
'$share' => (x($x,'button') ? $x['button'] : t('Share')),
|
||||
'$webpage' => $webpage,
|
||||
'$placeholdpagetitle' => ((x($x,'ptlabel')) ? $x['ptlabel'] : t('Page link name')),
|
||||
@@ -1241,7 +1248,7 @@ function status_editor($a, $x, $popup = false) {
|
||||
'$content' => ((x($x,'body')) ? htmlspecialchars($x['body'], ENT_COMPAT,'UTF-8') : ''),
|
||||
'$attachment' => ((x($x, 'attachment')) ? $x['attachment'] : ''),
|
||||
'$post_id' => '',
|
||||
'$baseurl' => $a->get_baseurl(true),
|
||||
'$baseurl' => z_root(),
|
||||
'$defloc' => $x['default_location'],
|
||||
'$visitor' => $x['visitor'],
|
||||
'$public' => t('Public post'),
|
||||
@@ -1269,6 +1276,7 @@ function status_editor($a, $x, $popup = false) {
|
||||
'$expiryModalOK' => t('OK'),
|
||||
'$expiryModalCANCEL' => t('Cancel'),
|
||||
'$expanded' => ((x($x, 'expanded')) ? $x['expanded'] : false),
|
||||
'$bbcode' => ((x($x, 'bbcode')) ? $x['bbcode'] : false)
|
||||
));
|
||||
|
||||
if ($popup === true) {
|
||||
@@ -1419,12 +1427,12 @@ function prepare_page($item) {
|
||||
$a = get_app();
|
||||
$naked = 1;
|
||||
// $naked = ((get_pconfig($item['uid'],'system','nakedpage')) ? 1 : 0);
|
||||
$observer = $a->get_observer();
|
||||
$observer = App::get_observer();
|
||||
//240 chars is the longest we can have before we start hitting problems with suhosin sites
|
||||
$preview = substr(urlencode($item['body']), 0, 240);
|
||||
$link = z_root() . '/' . $a->cmd;
|
||||
if(array_key_exists('webpage',$a->layout) && array_key_exists('authored',$a->layout['webpage'])) {
|
||||
if($a->layout['webpage']['authored'] === 'none')
|
||||
$link = z_root() . '/' . App::$cmd;
|
||||
if(array_key_exists('webpage',App::$layout) && array_key_exists('authored',App::$layout['webpage'])) {
|
||||
if(App::$layout['webpage']['authored'] === 'none')
|
||||
$naked = 1;
|
||||
// ... other possible options
|
||||
}
|
||||
@@ -1503,7 +1511,7 @@ function network_tabs() {
|
||||
|
||||
if ($no_active=='active') $all_active='active';
|
||||
|
||||
$cmd = $a->cmd;
|
||||
$cmd = App::$cmd;
|
||||
|
||||
// tabs
|
||||
$tabs = array();
|
||||
@@ -1587,15 +1595,25 @@ function network_tabs() {
|
||||
function profile_tabs($a, $is_owner = false, $nickname = null){
|
||||
|
||||
// Don't provide any profile tabs if we're running as the sys channel
|
||||
if ($a->is_sys)
|
||||
|
||||
if (App::$is_sys)
|
||||
return;
|
||||
|
||||
$channel = $a->get_channel();
|
||||
$channel = App::get_channel();
|
||||
|
||||
if (is_null($nickname))
|
||||
$nickname = $channel['channel_address'];
|
||||
|
||||
$uid = (($a->profile['profile_uid']) ? $a->profile['profile_uid'] : local_channel());
|
||||
|
||||
$uid = ((App::$profile['profile_uid']) ? App::$profile['profile_uid'] : local_channel());
|
||||
|
||||
if($uid == local_channel()) {
|
||||
$cal_link = '';
|
||||
}
|
||||
else {
|
||||
$cal_link = '/cal/' . $nickname;
|
||||
}
|
||||
|
||||
|
||||
if (get_pconfig($uid, 'system', 'noprofiletabs'))
|
||||
return;
|
||||
@@ -1603,8 +1621,8 @@ function profile_tabs($a, $is_owner = false, $nickname = null){
|
||||
if (x($_GET, 'tab'))
|
||||
$tab = notags(trim($_GET['tab']));
|
||||
|
||||
$url = $a->get_baseurl() . '/channel/' . $nickname;
|
||||
$pr = $a->get_baseurl() . '/profile/' . $nickname;
|
||||
$url = z_root() . '/channel/' . $nickname;
|
||||
$pr = z_root() . '/profile/' . $nickname;
|
||||
|
||||
$tabs = array(
|
||||
array(
|
||||
@@ -1630,27 +1648,38 @@ function profile_tabs($a, $is_owner = false, $nickname = null){
|
||||
if ($p['view_storage']) {
|
||||
$tabs[] = array(
|
||||
'label' => t('Photos'),
|
||||
'url' => $a->get_baseurl() . '/photos/' . $nickname,
|
||||
'url' => z_root() . '/photos/' . $nickname,
|
||||
'sel' => ((argv(0) == 'photos') ? 'active' : ''),
|
||||
'title' => t('Photo Albums'),
|
||||
'id' => 'photo-tab',
|
||||
);
|
||||
$tabs[] = array(
|
||||
'label' => t('Files'),
|
||||
'url' => $a->get_baseurl() . '/cloud/' . $nickname,
|
||||
'url' => z_root() . '/cloud/' . $nickname,
|
||||
'sel' => ((argv(0) == 'cloud' || argv(0) == 'sharedwithme') ? 'active' : ''),
|
||||
'title' => t('Files and Storage'),
|
||||
'id' => 'files-tab',
|
||||
);
|
||||
}
|
||||
|
||||
if ($p['chat']) {
|
||||
if($p['view_stream'] && $cal_link) {
|
||||
$tabs[] = array(
|
||||
'label' => t('Events'),
|
||||
'url' => z_root() . $cal_link,
|
||||
'sel' => ((argv(0) == 'cal' || argv(0) == 'events') ? 'active' : ''),
|
||||
'title' => t('Events'),
|
||||
'id' => 'event-tab',
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
if ($p['chat'] && feature_enabled($uid,'ajaxchat')) {
|
||||
require_once('include/chat.php');
|
||||
$has_chats = chatroom_list_count($uid);
|
||||
if ($has_chats) {
|
||||
$tabs[] = array(
|
||||
'label' => t('Chatrooms'),
|
||||
'url' => $a->get_baseurl() . '/chat/' . $nickname,
|
||||
'url' => z_root() . '/chat/' . $nickname,
|
||||
'sel' => ((argv(0) == 'chat') ? 'active' : '' ),
|
||||
'title' => t('Chatrooms'),
|
||||
'id' => 'chat-tab',
|
||||
@@ -1663,7 +1692,7 @@ function profile_tabs($a, $is_owner = false, $nickname = null){
|
||||
if ($is_owner && $has_bookmarks) {
|
||||
$tabs[] = array(
|
||||
'label' => t('Bookmarks'),
|
||||
'url' => $a->get_baseurl() . '/bookmarks',
|
||||
'url' => z_root() . '/bookmarks',
|
||||
'sel' => ((argv(0) == 'bookmarks') ? 'active' : ''),
|
||||
'title' => t('Saved Bookmarks'),
|
||||
'id' => 'bookmarks-tab',
|
||||
@@ -1673,7 +1702,7 @@ function profile_tabs($a, $is_owner = false, $nickname = null){
|
||||
if ($p['write_pages'] && feature_enabled($uid,'webpages')) {
|
||||
$tabs[] = array(
|
||||
'label' => t('Webpages'),
|
||||
'url' => $a->get_baseurl() . '/webpages/' . $nickname,
|
||||
'url' => z_root() . '/webpages/' . $nickname,
|
||||
'sel' => ((argv(0) == 'webpages') ? 'active' : ''),
|
||||
'title' => t('Manage Webpages'),
|
||||
'id' => 'webpages-tab',
|
||||
|
||||
@@ -20,7 +20,14 @@ function rsa_verify($data,$sig,$key,$alg = 'sha256') {
|
||||
|
||||
if(intval(OPENSSL_ALGO_SHA256) && $alg === 'sha256')
|
||||
$alg = OPENSSL_ALGO_SHA256;
|
||||
$verify = openssl_verify($data,$sig,$key,$alg);
|
||||
$verify = @openssl_verify($data,$sig,$key,$alg);
|
||||
|
||||
if(! $verify) {
|
||||
while($msg = openssl_error_string())
|
||||
logger('openssl_verify: ' . $msg,LOGGER_NORMAL,LOG_ERR);
|
||||
btlogger('openssl_verify: key: ' . $key, LOGGER_DEBUG, LOG_ERR);
|
||||
}
|
||||
|
||||
return $verify;
|
||||
}
|
||||
|
||||
@@ -241,6 +248,7 @@ function pkcs1_encode($Modulus,$PublicExponent) {
|
||||
}
|
||||
|
||||
|
||||
// http://stackoverflow.com/questions/27568570/how-to-convert-raw-modulus-exponent-to-rsa-public-key-pem-format
|
||||
function metopem($m,$e) {
|
||||
$der = pkcs8_encode($m,$e);
|
||||
$key = DerToPem($der,false);
|
||||
@@ -291,11 +299,33 @@ function metorsa($m,$e) {
|
||||
return $key;
|
||||
}
|
||||
|
||||
|
||||
|
||||
function salmon_key($pubkey) {
|
||||
pemtome($pubkey,$m,$e);
|
||||
return 'RSA' . '.' . base64url_encode($m,true) . '.' . base64url_encode($e,true) ;
|
||||
}
|
||||
|
||||
|
||||
function convert_salmon_key($key) {
|
||||
|
||||
if(strstr($key,','))
|
||||
$rawkey = substr($key,strpos($key,',')+1);
|
||||
else
|
||||
$rawkey = substr($key,5);
|
||||
|
||||
$key_info = explode('.',$rawkey);
|
||||
|
||||
$m = base64url_decode($key_info[1]);
|
||||
$e = base64url_decode($key_info[2]);
|
||||
|
||||
logger('key details: ' . print_r($key_info,true), LOGGER_DATA);
|
||||
$salmon_key = metopem($m,$e);
|
||||
return $salmon_key;
|
||||
|
||||
}
|
||||
|
||||
|
||||
function z_obscure($s) {
|
||||
return json_encode(crypto_encapsulate($s,get_config('system','pubkey')));
|
||||
}
|
||||
@@ -305,3 +335,4 @@ function z_unobscure($s) {
|
||||
return $s;
|
||||
return crypto_unencapsulate(json_decode($s,true),get_config('system','prvkey'));
|
||||
}
|
||||
|
||||
|
||||
@@ -119,6 +119,8 @@ function datetime_convert($from = 'UTC', $to = 'UTC', $s = 'now', $fmt = "Y-m-d
|
||||
* @return string
|
||||
*/
|
||||
function dob($dob) {
|
||||
$a = get_app();
|
||||
|
||||
list($year, $month, $day) = sscanf($dob, '%4d-%2d-%2d');
|
||||
$f = get_config('system', 'birthday_input_format');
|
||||
if (! $f)
|
||||
@@ -129,7 +131,15 @@ function dob($dob) {
|
||||
else
|
||||
$value = (($year) ? datetime_convert('UTC','UTC',$dob,'Y-m-d') : datetime_convert('UTC','UTC',$dob,'m-d'));
|
||||
|
||||
$o = '<input type="text" name="dob" value="' . $value . '" placeholder="' . t('YYYY-MM-DD or MM-DD') . '" />';
|
||||
$o = replace_macros(get_markup_template("field_input.tpl"), array('$field' => array(
|
||||
'dob',
|
||||
t('Birthday'),
|
||||
$value,
|
||||
((intval($value)) ? t('Age: ') . age($value,App::$user['timezone'],App::$user['timezone']) : ''),
|
||||
'',
|
||||
'placeholder="' . t('YYYY-MM-DD or MM-DD') .'"'
|
||||
)));
|
||||
|
||||
|
||||
// if ($dob && $dob != '0000-00-00')
|
||||
// $o = datesel($f,mktime(0,0,0,0,0,1900),mktime(),mktime(0,0,0,$month,$day,$year),'dob');
|
||||
@@ -269,15 +279,16 @@ function relative_date($posted_date, $format = null) {
|
||||
return t('less than a second ago');
|
||||
}
|
||||
|
||||
$a = array( 12 * 30 * 24 * 60 * 60 => array( t('year'), t('years')),
|
||||
30 * 24 * 60 * 60 => array( t('month'), t('months')),
|
||||
7 * 24 * 60 * 60 => array( t('week'), t('weeks')),
|
||||
24 * 60 * 60 => array( t('day'), t('days')),
|
||||
60 * 60 => array( t('hour'), t('hours')),
|
||||
60 => array( t('minute'), t('minutes')),
|
||||
1 => array( t('second'), t('seconds'))
|
||||
$a = array( 12 * 30 * 24 * 60 * 60 => 'y',
|
||||
30 * 24 * 60 * 60 => 'm',
|
||||
7 * 24 * 60 * 60 => 'w',
|
||||
24 * 60 * 60 => 'd',
|
||||
60 * 60 => 'h',
|
||||
60 => 'i',
|
||||
1 => 's'
|
||||
);
|
||||
|
||||
|
||||
foreach ($a as $secs => $str) {
|
||||
$d = $etime / $secs;
|
||||
if ($d >= 1) {
|
||||
@@ -285,11 +296,43 @@ function relative_date($posted_date, $format = null) {
|
||||
if (! $format)
|
||||
$format = t('%1$d %2$s ago', 'e.g. 22 hours ago, 1 minute ago');
|
||||
|
||||
return sprintf($format, $r, (($r == 1) ? $str[0] : $str[1]));
|
||||
return sprintf($format, $r, plural_dates($str,$r));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function plural_dates($k,$n) {
|
||||
|
||||
switch($k) {
|
||||
case 'y':
|
||||
return tt('year','years',$n,'relative_date');
|
||||
break;
|
||||
case 'm':
|
||||
return tt('month','months',$n,'relative_date');
|
||||
break;
|
||||
case 'w':
|
||||
return tt('week','weeks',$n,'relative_date');
|
||||
break;
|
||||
case 'd':
|
||||
return tt('day','days',$n,'relative_date');
|
||||
break;
|
||||
case 'h':
|
||||
return tt('hour','hours',$n,'relative_date');
|
||||
break;
|
||||
case 'i':
|
||||
return tt('minute','minutes',$n,'relative_date');
|
||||
break;
|
||||
case 's':
|
||||
return tt('second','seconds',$n,'relative_date');
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Returns timezone correct age in years.
|
||||
*
|
||||
@@ -516,7 +559,7 @@ function update_birthdays() {
|
||||
$ev['event_xchan'] = $rr['xchan_hash'];
|
||||
$ev['start'] = datetime_convert('UTC', 'UTC', $rr['abook_dob']);
|
||||
$ev['finish'] = datetime_convert('UTC', 'UTC', $rr['abook_dob'] . ' + 1 day ');
|
||||
$ev['adjust'] = 1;
|
||||
$ev['adjust'] = intval(feature_enabled($rr['abook_channel'],'smart_birthdays'));
|
||||
$ev['summary'] = sprintf( t('%1$s\'s birthday'), $rr['xchan_name']);
|
||||
$ev['description'] = sprintf( t('Happy Birthday %1$s'),
|
||||
'[zrl=' . $rr['xchan_url'] . ']' . $rr['xchan_name'] . '[/zrl]') ;
|
||||
|
||||
@@ -303,9 +303,9 @@ function q($sql) {
|
||||
if($stmt === false) {
|
||||
if(version_compare(PHP_VERSION, '5.4.0') >= 0)
|
||||
logger('dba: vsprintf error: ' .
|
||||
print_r(debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT, 1), true));
|
||||
print_r(debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT, 1), true),LOGGER_NORMAL,LOG_CRIT);
|
||||
else
|
||||
logger('dba: vsprintf error: ' . print_r(debug_backtrace(), true));
|
||||
logger('dba: vsprintf error: ' . print_r(debug_backtrace(), true),LOGGER_NORMAL,LOG_CRIT);
|
||||
}
|
||||
return $db->q($stmt);
|
||||
}
|
||||
@@ -314,7 +314,7 @@ function q($sql) {
|
||||
* This will happen occasionally trying to store the
|
||||
* session data after abnormal program termination
|
||||
*/
|
||||
logger('dba: no database: ' . print_r($args,true));
|
||||
logger('dba: no database: ' . print_r($args,true),LOGGER_NORMAL,LOG_CRIT);
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -385,6 +385,7 @@ function db_getfunc($f) {
|
||||
if(isset($lookup[$f]) && isset($lookup[$f][ACTIVE_DBTYPE]))
|
||||
return $lookup[$f][ACTIVE_DBTYPE];
|
||||
|
||||
logger('Unable to abstract DB function "'. $f . '" for dbtype ' . ACTIVE_DBTYPE, LOGGER_DEBUG);
|
||||
logger('Unable to abstract DB function "'. $f . '" for dbtype ' . ACTIVE_DBTYPE, LOGGER_DEBUG, LOG_ERR);
|
||||
return $f;
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ class dba_mysqli extends dba_driver {
|
||||
|
||||
|
||||
if($this->error) {
|
||||
logger('dba_mysqli: ERROR: ' . printable($sql) . "\n" . $this->error);
|
||||
logger('dba_mysqli: ERROR: ' . printable($sql) . "\n" . $this->error, LOGGER_NORMAL, LOG_ERR);
|
||||
if(file_exists('dbfail.out')) {
|
||||
file_put_contents('dbfail.out', datetime_convert() . "\n" . printable($sql) . "\n" . $this->error . "\n", FILE_APPEND);
|
||||
}
|
||||
@@ -40,13 +40,13 @@ class dba_mysqli extends dba_driver {
|
||||
|
||||
if(($result === true) || ($result === false)) {
|
||||
if($this->debug) {
|
||||
logger('dba_mysqli: DEBUG: ' . printable($sql) . ' returns ' . (($result) ? 'true' : 'false'));
|
||||
logger('dba_mysqli: DEBUG: ' . printable($sql) . ' returns ' . (($result) ? 'true' : 'false'), LOGGER_NORMAL,(($result) ? LOG_INFO : LOG_ERR));
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
if($this->debug) {
|
||||
logger('dba_mysqli: DEBUG: ' . printable($sql) . ' returned ' . $result->num_rows . ' results.');
|
||||
logger('dba_mysqli: DEBUG: ' . printable($sql) . ' returned ' . $result->num_rows . ' results.', LOGGER_NORMAL, LOG_INFO);
|
||||
}
|
||||
|
||||
$r = array();
|
||||
@@ -55,7 +55,7 @@ class dba_mysqli extends dba_driver {
|
||||
$r[] = $x;
|
||||
$result->free_result();
|
||||
if($this->debug) {
|
||||
logger('dba_mysqli: ' . printable(print_r($r,true)));
|
||||
logger('dba_mysqli: ' . printable(print_r($r,true)), LOGGER_NORMAL, LOG_INFO);
|
||||
}
|
||||
}
|
||||
return $r;
|
||||
|
||||
@@ -421,7 +421,7 @@ function local_dir_update($uid, $force) {
|
||||
$arr = array('channel_id' => $uid, 'hash' => $hash, 'profile' => $profile);
|
||||
call_hooks('local_dir_update', $arr);
|
||||
|
||||
$address = $p[0]['channel_address'] . '@' . get_app()->get_hostname();
|
||||
$address = $p[0]['channel_address'] . '@' . App::get_hostname();
|
||||
|
||||
if (perm_is_allowed($uid, '', 'view_profile')) {
|
||||
import_directory_profile($hash, $arr['profile'], $address, 0);
|
||||
@@ -436,6 +436,6 @@ function local_dir_update($uid, $force) {
|
||||
}
|
||||
}
|
||||
|
||||
$ud_hash = random_string() . '@' . get_app()->get_hostname();
|
||||
update_modtime($hash, $ud_hash, $p[0]['channel_address'] . '@' . get_app()->get_hostname(),(($force) ? UPDATE_FLAGS_FORCED : UPDATE_FLAGS_UPDATED));
|
||||
$ud_hash = random_string() . '@' . App::get_hostname();
|
||||
update_modtime($hash, $ud_hash, $p[0]['channel_address'] . '@' . App::get_hostname(),(($force) ? UPDATE_FLAGS_FORCED : UPDATE_FLAGS_UPDATED));
|
||||
}
|
||||
|
||||
@@ -56,13 +56,13 @@ function notification($params) {
|
||||
|
||||
$banner = t('$Projectname Notification');
|
||||
$product = t('$projectname'); // PLATFORM_NAME;
|
||||
$siteurl = $a->get_baseurl(true);
|
||||
$siteurl = z_root();
|
||||
$thanks = t('Thank You,');
|
||||
$sitename = get_config('system','sitename');
|
||||
$site_admin = sprintf( t('%s Administrator'), $sitename);
|
||||
|
||||
$sender_name = $product;
|
||||
$hostname = $a->get_hostname();
|
||||
$hostname = App::get_hostname();
|
||||
if(strpos($hostname,':'))
|
||||
$hostname = substr($hostname,0,strpos($hostname,':'));
|
||||
|
||||
@@ -419,12 +419,12 @@ function notification($params) {
|
||||
return;
|
||||
}
|
||||
|
||||
$itemlink = $a->get_baseurl() . '/notify/view/' . $notify_id;
|
||||
$itemlink = z_root() . '/notify/view/' . $notify_id;
|
||||
$msg = str_replace('$itemlink',$itemlink,$epreamble);
|
||||
|
||||
// wretched hack, but we don't want to duplicate all the preamble variations and we also don't want to screw up a translation
|
||||
|
||||
if (($a->language === 'en' || (! $a->language)) && strpos($msg,', '))
|
||||
if ((App::$language === 'en' || (! App::$language)) && strpos($msg,', '))
|
||||
$msg = substr($msg,strpos($msg,', ')+1);
|
||||
|
||||
$r = q("update notify set msg = '%s' where id = %d and uid = %d",
|
||||
@@ -441,7 +441,7 @@ function notification($params) {
|
||||
logger('notification: sending notification email');
|
||||
|
||||
$hn = get_pconfig($recip['channel_id'],'system','email_notify_host');
|
||||
if($hn && (! stristr(get_app()->get_hostname(),$hn))) {
|
||||
if($hn && (! stristr(App::get_hostname(),$hn))) {
|
||||
// this isn't the email notification host
|
||||
pop_lang();
|
||||
return;
|
||||
@@ -455,7 +455,7 @@ function notification($params) {
|
||||
// use $_SESSION['zid_override'] to force zid() to use
|
||||
// the recipient address instead of the current observer
|
||||
|
||||
$_SESSION['zid_override'] = $recip['channel_address'] . '@' . get_app()->get_hostname();
|
||||
$_SESSION['zid_override'] = $recip['channel_address'] . '@' . App::get_hostname();
|
||||
$_SESSION['zrl_override'] = z_root() . '/channel/' . $recip['channel_address'];
|
||||
|
||||
$textversion = zidify_links($textversion);
|
||||
@@ -529,7 +529,7 @@ function notification($params) {
|
||||
$tpl = get_markup_template('email_notify_html.tpl');
|
||||
$email_html_body = replace_macros($tpl,array(
|
||||
'$banner' => $datarray['banner'],
|
||||
'$notify_icon' => get_notify_icon(),
|
||||
'$notify_icon' => Zotlabs\Project\System::get_notify_icon(),
|
||||
'$product' => $datarray['product'],
|
||||
'$preamble' => $datarray['preamble'],
|
||||
'$sitename' => $datarray['sitename'],
|
||||
|
||||
@@ -67,7 +67,7 @@ function ical_wrapper($ev) {
|
||||
$o .= "BEGIN:VCALENDAR";
|
||||
$o .= "\r\nVERSION:2.0";
|
||||
$o .= "\r\nMETHOD:PUBLISH";
|
||||
$o .= "\r\nPRODID:-//" . get_config('system','sitename') . "//" . get_platform_name() . "//" . strtoupper(get_app()->language). "\r\n";
|
||||
$o .= "\r\nPRODID:-//" . get_config('system','sitename') . "//" . Zotlabs\Project\System::get_platform_name() . "//" . strtoupper(App::$language). "\r\n";
|
||||
if(array_key_exists('start', $ev))
|
||||
$o .= format_event_ical($ev);
|
||||
else {
|
||||
@@ -361,7 +361,7 @@ function event_store_event($arr) {
|
||||
if(array_key_exists('external_id',$arr))
|
||||
$hash = $arr['external_id'];
|
||||
else
|
||||
$hash = random_string() . '@' . get_app()->get_hostname();
|
||||
$hash = random_string() . '@' . App::get_hostname();
|
||||
|
||||
$r = q("INSERT INTO event ( uid,aid,event_xchan,event_hash,created,edited,start,finish,summary,description,location,type,
|
||||
adjust,nofinish, event_status, event_status_date, event_percent, event_repeat, event_sequence, event_priority, allow_cid,allow_gid,deny_cid,deny_gid)
|
||||
@@ -440,6 +440,17 @@ function event_addtocal($item_id, $uid) {
|
||||
$ev['event_hash'] = $item['resource_id'];
|
||||
}
|
||||
|
||||
if($ev->private)
|
||||
$ev['allow_cid'] = '<' . $channel['channel_hash'] . '>';
|
||||
else {
|
||||
$acl = new Zotlabs\Access\AccessList($channel);
|
||||
$x = $acl->get();
|
||||
$ev['allow_cid'] = $x['allow_cid'];
|
||||
$ev['allow_gid'] = $x['allow_gid'];
|
||||
$ev['deny_cid'] = $x['deny_cid'];
|
||||
$ev['deny_gid'] = $x['deny_gid'];
|
||||
}
|
||||
|
||||
$event = event_store_event($ev);
|
||||
if($event) {
|
||||
$r = q("update item set resource_id = '%s', resource_type = 'event' where id = %d and uid = %d",
|
||||
|
||||
@@ -25,7 +25,7 @@ function feature_enabled($uid,$feature) {
|
||||
}
|
||||
|
||||
function get_feature_default($feature) {
|
||||
$f = get_features();
|
||||
$f = get_features(false);
|
||||
foreach($f as $cat) {
|
||||
foreach($cat as $feat) {
|
||||
if(is_array($feat) && $feat[0] === $feature)
|
||||
@@ -38,6 +38,9 @@ function get_feature_default($feature) {
|
||||
|
||||
function get_features($filtered = true) {
|
||||
|
||||
if(UNO && $filtered)
|
||||
return array();
|
||||
|
||||
$arr = array(
|
||||
|
||||
// General
|
||||
@@ -53,7 +56,8 @@ function get_features($filtered = true) {
|
||||
array('private_notes', t('Private Notes'), t('Enables a tool to store notes and reminders (note: not encrypted)'),false,get_config('feature_lock','private_notes')),
|
||||
array('nav_channel_select', t('Navigation Channel Select'), t('Change channels directly from within the navigation dropdown menu'),false,get_config('feature_lock','nav_channel_select')),
|
||||
array('photo_location', t('Photo Location'), t('If location data is available on uploaded photos, link this to a map.'),false,get_config('feature_lock','photo_location')),
|
||||
|
||||
array('ajaxchat', t('Access Controlled Chatrooms'), t('Provide chatrooms and chat services with access control.'),true,get_config('feature_lock','ajaxchat')),
|
||||
array('smart_birthdays', t('Smart Birthdays'), t('Make birthday events timezone aware in case your friends are scattered across the planet.'),true,get_config('feature_lock','smart_birthdays')),
|
||||
array('expert', t('Expert Mode'), t('Enable Expert Mode to provide advanced configuration options'),false,get_config('feature_lock','expert')),
|
||||
array('premium_channel', t('Premium Channel'), t('Allows you to set restrictions and terms on those that connect with your channel'),false,get_config('feature_lock','premium_channel')),
|
||||
),
|
||||
@@ -62,7 +66,7 @@ function get_features($filtered = true) {
|
||||
'composition' => array(
|
||||
t('Post Composition Features'),
|
||||
// array('richtext', t('Richtext Editor'), t('Enable richtext editor'),falseget_config('feature_lock','richtext')),
|
||||
array('markdown', t('Use Markdown'), t('Allow use of "Markdown" to format posts'),false,get_config('feature_lock','markdown')),
|
||||
// array('markdown', t('Use Markdown'), t('Allow use of "Markdown" to format posts'),false,get_config('feature_lock','markdown')),
|
||||
array('large_photos', t('Large Photos'), t('Include large (1024px) photo thumbnails in posts. If not enabled, use small (640px) photo thumbnails'),false,get_config('feature_lock','large_photos')),
|
||||
array('channel_sources', t('Channel Sources'), t('Automatically import channel content from other channels or feeds'),false,get_config('feature_lock','channel_sources')),
|
||||
array('content_encrypt', t('Even More Encryption'), t('Allow optional encryption of content end-to-end with a shared secret key'),false,get_config('feature_lock','content_encrypt')),
|
||||
|
||||
@@ -134,26 +134,29 @@ function new_contact($uid,$url,$channel,$interactive = false, $confirm = false)
|
||||
$their_perms = 0;
|
||||
$xchan_hash = '';
|
||||
|
||||
|
||||
$r = q("select * from xchan where xchan_hash = '%s' or xchan_url = '%s' limit 1",
|
||||
dbesc($url),
|
||||
dbesc($url)
|
||||
);
|
||||
|
||||
|
||||
if(! $r) {
|
||||
// attempt network auto-discovery
|
||||
if(strpos($url,'@') && (! $is_http)) {
|
||||
$d = discover_by_webbie($url);
|
||||
}
|
||||
elseif($is_http) {
|
||||
if(get_config('system','feed_contacts'))
|
||||
|
||||
$d = discover_by_webbie($url);
|
||||
|
||||
if((! $d) && ($is_http)) {
|
||||
|
||||
// try RSS discovery
|
||||
|
||||
if(get_config('system','feed_contacts')) {
|
||||
$d = discover_by_url($url);
|
||||
}
|
||||
else {
|
||||
$result['message'] = t('Protocol disabled.');
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
if($d) {
|
||||
$r = q("select * from xchan where xchan_hash = '%s' or xchan_url = '%s' limit 1",
|
||||
dbesc($url),
|
||||
@@ -161,6 +164,9 @@ function new_contact($uid,$url,$channel,$interactive = false, $confirm = false)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// if discovery was a success we should have an xchan record in $r
|
||||
|
||||
if($r) {
|
||||
$xchan = $r[0];
|
||||
$xchan_hash = $r[0]['xchan_hash'];
|
||||
@@ -175,7 +181,9 @@ function new_contact($uid,$url,$channel,$interactive = false, $confirm = false)
|
||||
return $result;
|
||||
}
|
||||
|
||||
$x = array('channel_id' => $uid, 'follow_address' => $url, 'xchan' => $r[0], 'allowed' => 1, 'singleton' => 0);
|
||||
$allowed = (($is_red || $r[0]['xchan_network'] === 'rss') ? 1 : 0);
|
||||
|
||||
$x = array('channel_id' => $uid, 'follow_address' => $url, 'xchan' => $r[0], 'allowed' => $allowed, 'singleton' => 0);
|
||||
|
||||
call_hooks('follow_allow',$x);
|
||||
|
||||
@@ -185,28 +193,13 @@ function new_contact($uid,$url,$channel,$interactive = false, $confirm = false)
|
||||
}
|
||||
$singleton = intval($x['singleton']);
|
||||
|
||||
if((local_channel()) && $uid == local_channel()) {
|
||||
$aid = get_account_id();
|
||||
$hash = get_observer_hash();
|
||||
$ch = $a->get_channel();
|
||||
$default_group = $ch['channel_default_group'];
|
||||
}
|
||||
else {
|
||||
$r = q("select * from channel where channel_id = %d limit 1",
|
||||
intval($uid)
|
||||
);
|
||||
if(! $r) {
|
||||
$result['message'] = t('local account not found.');
|
||||
return $result;
|
||||
}
|
||||
$aid = $r[0]['channel_account_id'];
|
||||
$hash = $r[0]['channel_hash'];
|
||||
$default_group = $r[0]['channel_default_group'];
|
||||
}
|
||||
$aid = $channel['channel_account_id'];
|
||||
$hash = get_observer_hash();
|
||||
$default_group = $channel['channel_default_group'];
|
||||
|
||||
if($xchan['xchan_network'] === 'rss') {
|
||||
|
||||
if($is_http) {
|
||||
|
||||
// check service class feed limits
|
||||
|
||||
$r = q("select count(*) as total from abook where abook_account = %d and abook_feed = 1 ",
|
||||
intval($aid)
|
||||
@@ -230,7 +223,6 @@ function new_contact($uid,$url,$channel,$interactive = false, $confirm = false)
|
||||
intval($uid)
|
||||
);
|
||||
|
||||
|
||||
if($r) {
|
||||
$abook_instance = $r[0]['abook_instance'];
|
||||
|
||||
@@ -280,7 +272,7 @@ function new_contact($uid,$url,$channel,$interactive = false, $confirm = false)
|
||||
proc_run('php', 'include/notifier.php', 'permission_create', $result['abook']['abook_id']);
|
||||
}
|
||||
|
||||
$arr = array('channel_id' => $uid, 'abook' => $result['abook']);
|
||||
$arr = array('channel_id' => $uid, 'channel' => $channel, 'abook' => $result['abook']);
|
||||
|
||||
call_hooks('follow', $arr);
|
||||
|
||||
|
||||
@@ -200,7 +200,7 @@ function group_get_members($gid) {
|
||||
if(intval($gid)) {
|
||||
$r = q("SELECT * FROM `group_member`
|
||||
LEFT JOIN abook ON abook_xchan = `group_member`.`xchan` left join xchan on xchan_hash = abook_xchan
|
||||
WHERE `gid` = %d AND abook_channel = %d and `group_member`.`uid` = %d and xchan_deleted = 0 and abook_blocked = 0 and abook_pending = 0 ORDER BY xchan_name ASC ",
|
||||
WHERE `gid` = %d AND abook_channel = %d and `group_member`.`uid` = %d and xchan_deleted = 0 and abook_self = 0 and abook_blocked = 0 and abook_pending = 0 ORDER BY xchan_name ASC ",
|
||||
intval($gid),
|
||||
intval(local_channel()),
|
||||
intval(local_channel())
|
||||
@@ -211,6 +211,22 @@ function group_get_members($gid) {
|
||||
return $ret;
|
||||
}
|
||||
|
||||
function group_get_members_xchan($gid) {
|
||||
$ret = array();
|
||||
if(intval($gid)) {
|
||||
$r = q("SELECT xchan FROM group_member WHERE gid = %d AND uid = %d",
|
||||
intval($gid),
|
||||
intval(local_channel())
|
||||
);
|
||||
if(count($r)) {
|
||||
foreach($r as $rr) {
|
||||
$ret[] = $rr['xchan'];
|
||||
}
|
||||
}
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
function mini_group_select($uid,$group = '') {
|
||||
|
||||
$grps = array();
|
||||
|
||||
@@ -134,10 +134,17 @@ function hubloc_change_primary($hubloc) {
|
||||
$r = q("select channel_id, channel_primary from channel where channel_hash = '%s' limit 1",
|
||||
dbesc($hubloc['hubloc_hash'])
|
||||
);
|
||||
if(($r) && (! $r[0]['channel_primary'])) {
|
||||
q("update channel set channel_primary = 1 where channel_id = %d",
|
||||
intval($r[0]['channel_id'])
|
||||
);
|
||||
if($r) {
|
||||
if(! $r[0]['channel_primary']) {
|
||||
q("update channel set channel_primary = 1 where channel_id = %d",
|
||||
intval($r[0]['channel_id'])
|
||||
);
|
||||
}
|
||||
else {
|
||||
q("update channel set channel_primary = 0 where channel_id = %d",
|
||||
intval($r[0]['channel_id'])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// do we even have an xchan for this hubloc and if so is it already set as primary?
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user