forked from GNUsocial/gnu-social
Compare commits
3473 Commits
v1.1.3rele
...
experiment
| Author | SHA1 | Date | |
|---|---|---|---|
|
010f70e432
|
|||
|
fc310a0b4e
|
|||
|
d398456be8
|
|||
|
3288d48b8a
|
|||
|
94edde001c
|
|||
|
41d759428f
|
|||
|
469cd97b9b
|
|||
|
8a01224feb
|
|||
|
61d558b371
|
|||
|
8c5486ba13
|
|||
|
a7d4a56b14
|
|||
|
bef23f20bc
|
|||
|
22ad2bd5cc
|
|||
|
968a425459
|
|||
|
30975111d9
|
|||
|
7c85d312ed
|
|||
|
c50e3324ef
|
|||
|
aebc5358b5
|
|||
|
24b3e22f73
|
|||
|
6e9cde8a5c
|
|||
|
4089fc692d
|
|||
|
f25759d60b
|
|||
|
a383021992
|
|||
|
d6e6e56814
|
|||
|
9afa265c30
|
|||
|
027c9a9324
|
|||
|
2c10ce5cfc
|
|||
|
c03c6f1bb5
|
|||
|
be5328cdc5
|
|||
|
4a781d483a
|
|||
|
5bcabbb025
|
|||
|
b6cd58d501
|
|||
|
2ba6f66b7f
|
|||
|
152beb5798
|
|||
|
96612fcd43
|
|||
|
4cda3fc645
|
|||
|
b72fcd2a05
|
|||
|
9018b1301a
|
|||
|
20901d26df
|
|||
|
0b3ebf841d
|
|||
|
fd1bd9838d
|
|||
|
7320c6834f
|
|||
|
9c533a54a7
|
|||
|
5be4c6a22e
|
|||
|
61500c5223
|
|||
|
f7c426e81c
|
|||
|
40f2f5f977
|
|||
|
b7b54b8a07
|
|||
|
a6e41d3bd8
|
|||
|
d4ad0cc3d4
|
|||
|
3af33d1317
|
|||
| 2448d83ace | |||
|
923ff309fe
|
|||
|
f039c86578
|
|||
|
e76e3b710b
|
|||
| 022a9476cc | |||
|
4e5f9a51f0
|
|||
|
44593f2ab4
|
|||
|
2ae1198704
|
|||
|
9e52bd127f
|
|||
|
41b45435ff
|
|||
|
e9fa41c5a8
|
|||
|
48c11a3fda
|
|||
|
fa1585bd00
|
|||
|
f5918d8d5c
|
|||
|
ff4d31404b
|
|||
|
ac6f2bed5e
|
|||
|
5cb45fcd66
|
|||
|
dd22894f66
|
|||
|
11178289fa
|
|||
|
1e8beefb07
|
|||
|
f68a2ce481
|
|||
|
b0f5352a53
|
|||
|
69ff8c2750
|
|||
|
355b26221d
|
|||
|
d4c3e26f50
|
|||
|
5bd5c25dcf
|
|||
|
e30ae79eb7
|
|||
|
fb861ed41f
|
|||
|
33bf99cfda
|
|||
|
4d883d1011
|
|||
|
1d95080f9a
|
|||
|
bb57d7dc10
|
|||
|
f3972abb70
|
|||
|
2e3ab5bdfb
|
|||
|
d23312aff9
|
|||
|
a43f1a641a
|
|||
|
31c5fd6da7
|
|||
|
7b3ca428e9
|
|||
|
df5e7b139a
|
|||
|
4c1fc40c43
|
|||
|
c381e58d33
|
|||
|
333567c6a1
|
|||
|
632a54208d
|
|||
|
daaf7ea236
|
|||
|
3019048585
|
|||
|
9781ddc8e0
|
|||
|
c12eacc758
|
|||
|
d13da61d30
|
|||
|
f64436771c
|
|||
|
91666f7d61
|
|||
|
b20a4c89fb
|
|||
|
6453593b0d
|
|||
|
f72cfd1c2b
|
|||
|
c0a404c640
|
|||
|
aec8521e4b
|
|||
|
eb6ff68f7a
|
|||
|
c86cac2095
|
|||
|
c14718e8dd
|
|||
|
ae7516c893
|
|||
|
32ad5dbd74
|
|||
|
2ea739ef61
|
|||
|
420b3f4aeb
|
|||
|
6cea2b1d00
|
|||
|
9c99c11790
|
|||
|
ecbfba1b1a
|
|||
|
66b39d3607
|
|||
|
8e627f2c18
|
|||
|
7cace2051f
|
|||
|
a4cb90ba12
|
|||
|
cb0093bd4a
|
|||
|
c804892672
|
|||
|
e053ee451b
|
|||
|
9a6fddb004
|
|||
|
06b9bd9910
|
|||
|
47daf6169a
|
|||
|
71b1ee7796
|
|||
|
4266b361c0
|
|||
|
504c8f8935
|
|||
|
c38bbed7df
|
|||
|
7308e66981
|
|||
|
2590ea7b67
|
|||
|
6aa61abd81
|
|||
|
96abf53e22
|
|||
|
b7d205465f
|
|||
|
d19c990acf
|
|||
|
38abbc14b9
|
|||
|
0eb9575534
|
|||
|
a02093e848
|
|||
|
9343d00110
|
|||
|
67f5421691
|
|||
| bbaeaad052 | |||
| 5236278f45 | |||
|
289eef5cf7
|
|||
|
c155f4e30e
|
|||
|
5896f5bb82
|
|||
|
1556b3e019
|
|||
|
c58b9fb5b1
|
|||
|
97a3c067d9
|
|||
|
92db61a975
|
|||
|
05e10589c3
|
|||
|
a590ddd85e
|
|||
|
0bead1c58a
|
|||
|
0845224188
|
|||
|
1da1f0918e
|
|||
|
b075ab610b
|
|||
|
5b858a7bc1
|
|||
|
f760de43b0
|
|||
|
960675b459
|
|||
|
f9c1d14c7a
|
|||
|
ed21290ef4
|
|||
|
6b098a26f7
|
|||
|
19a966f1a9
|
|||
|
f5f11b6e54
|
|||
|
9077403f65
|
|||
|
bbdad515a2
|
|||
|
7034476cc7
|
|||
|
927472cf06
|
|||
|
b2456d8cd2
|
|||
|
d1e92a80e5
|
|||
|
af951685ed
|
|||
|
9c61e92257
|
|||
|
4297eb71a0
|
|||
|
b89368bf6a
|
|||
|
5fc5df68f5
|
|||
|
a83d506d6c
|
|||
|
56481c8289
|
|||
|
6d2f8daeae
|
|||
|
bdbd588de9
|
|||
|
176d604abb
|
|||
|
bff65afe5d
|
|||
|
6479b698f8
|
|||
|
a01914ddac
|
|||
|
2e3ec15827
|
|||
|
6deac21960
|
|||
|
c4de4cab32
|
|||
|
75af2232dc
|
|||
|
988d384654
|
|||
|
14db5d9864
|
|||
|
e0ebef594f
|
|||
|
63d26d1295
|
|||
|
ed850a7763
|
|||
|
e196a3577d
|
|||
|
c0e4dec674
|
|||
|
88ab76c480
|
|||
|
1f9acaf4ef
|
|||
|
55710aa33d
|
|||
|
8e743eabb9
|
|||
|
d34155c743
|
|||
|
0d6b4093fe
|
|||
|
400716c1b2
|
|||
|
75c9ffde31
|
|||
|
4258148a03
|
|||
|
6956e6907c
|
|||
|
7ee908f4dc
|
|||
|
b2d72673c7
|
|||
|
b51d43e6e2
|
|||
|
5777cdeaf9
|
|||
|
b0ef7599b2
|
|||
|
2c74bd7fb4
|
|||
|
b9fdaa1401
|
|||
|
88bb0c6b38
|
|||
|
df956a5f90
|
|||
|
aa66263b92
|
|||
|
ae27d95509
|
|||
|
2beda0dd44
|
|||
|
b79629b6d2
|
|||
|
4f6f4aa512
|
|||
|
3554a5c369
|
|||
|
5ca8842308
|
|||
| 5bf4a68454 | |||
| 903e6b33ff | |||
| 0a0ead3081 | |||
| efeb4b4ffe | |||
| 780d341939 | |||
| 5e012c39ab | |||
| 787afb9b41 | |||
| 0e7c657301 | |||
| 95f92d34db | |||
| 3cd33fb83a | |||
|
c2fc2300c7
|
|||
|
7fd4149695
|
|||
|
0273c8ca24
|
|||
|
477518abf7
|
|||
|
47171069c2
|
|||
|
e8f57e8380
|
|||
|
7f3a9bc880
|
|||
|
263a5f67f3
|
|||
|
df1f12470f
|
|||
|
0cf53a4163
|
|||
|
12f3e1f406
|
|||
|
15f2514aa2
|
|||
|
900d538e26
|
|||
|
8f8b66c938
|
|||
|
3c0f6b294f
|
|||
|
cfd771283a
|
|||
|
88eea554fc
|
|||
|
5c8735ebea
|
|||
|
d2a7281a4d
|
|||
|
0ce686d8bb
|
|||
|
b4bf720b06
|
|||
|
0d83bbff23
|
|||
|
a9d710f189
|
|||
|
4b095961d8
|
|||
|
14ecf913bf
|
|||
|
2b4bf6c31f
|
|||
|
6437e68132
|
|||
|
37a2db3706
|
|||
|
362be17aba
|
|||
|
3a5ba9b6c4
|
|||
|
dd7d412e83
|
|||
|
593d5bf96e
|
|||
|
d6cf812707
|
|||
|
2d7b201e71
|
|||
|
ac5df2f6b3
|
|||
|
375d0097f3
|
|||
|
a5eb231196
|
|||
|
aa6886a62a
|
|||
|
aa1fd8ea40
|
|||
|
f47fedcfd4
|
|||
|
f206b55869
|
|||
|
69f5c1e312
|
|||
|
8b4148a00d
|
|||
|
df44d92bb2
|
|||
|
021583ea05
|
|||
|
4afaa6858b
|
|||
|
ab7d1b0370
|
|||
|
38225dfa6e
|
|||
|
154025090c
|
|||
|
8ec17086a0
|
|||
|
18f2823e14
|
|||
|
7dd23f3f2c
|
|||
|
a34f0c2534
|
|||
|
7d15ec1620
|
|||
|
2d253ee5ad
|
|||
|
c18879b02f
|
|||
|
a48e699133
|
|||
|
77675ea8c4
|
|||
|
b7b69b549e
|
|||
|
681f001f4e
|
|||
|
c5e5708915
|
|||
|
86e92fedc2
|
|||
|
8ef6aceb6a
|
|||
|
bf01e97533
|
|||
| 835a3c6701 | |||
| cc0ef73799 | |||
| c3eda07521 | |||
| 832a5c0bd9 | |||
| 143ecea376 | |||
| 0eebcdbd51 | |||
| aada96beb7 | |||
| 218bec1826 | |||
| 4d2131808a | |||
| 4ef400f509 | |||
| 086754d95b | |||
| 5e9cd21db5 | |||
| 65c2c42790 | |||
| d6f31ad4b4 | |||
| 8f7e0f2131 | |||
| 3af3526b5c | |||
| a46140fc00 | |||
| eecef99372 | |||
| 5543f65ce9 | |||
| 818a31a690 | |||
| 9b862d6a26 | |||
| f8107c86c5 | |||
| ce98e80836 | |||
| 75adf2e59f | |||
| 31518f97ee | |||
| dab822037c | |||
| 79644d1e2b | |||
| 5f9b61f4bf | |||
| 3a6a1b71d6 | |||
| f25494cd83 | |||
| b79c0595d5 | |||
| 33cdea87ee | |||
| c532fdb4c8 | |||
| 5cc82785c6 | |||
| 05fbcdefa8 | |||
| dd218b04e9 | |||
| 059ed1fa76 | |||
| f946da6f29 | |||
| 9e2037e086 | |||
| 84399a76e3 | |||
| 4f0bdade45 | |||
| d5db350595 | |||
| f5fcfe628e | |||
| fde7b87c65 | |||
| f841e5e0dd | |||
| 39ac043d59 | |||
| 041d19a22d | |||
| b99fab00e9 | |||
| 88e84f2dc5 | |||
| 16055c7055 | |||
| 15c406a348 | |||
| eff703ca21 | |||
| 2e943293e6 | |||
| 6aea20db05 | |||
| a5a2032e75 | |||
| c948ca6178 | |||
| 676210f76a | |||
| af4b0113ba | |||
| 3f565442d2 | |||
| 4397d12fa4 | |||
| c58d7e470a | |||
| 5a40d1f3e3 | |||
| ced6e236ce | |||
| d5a7f2122a | |||
| d0d98a611d | |||
| 650bfec699 | |||
| 6d842d60c5 | |||
| e0e1dca0f0 | |||
| 6374e30475 | |||
| 0086d8dec4 | |||
| 6910620d59 | |||
| 0629c1434d | |||
| 120571fa42 | |||
| d9a3ecb116 | |||
| 1bf5e9d117 | |||
| aa28251c11 | |||
| c2f6665cce | |||
| b196af5f36 | |||
| ebfa0e2240 | |||
| 365a7b436f | |||
| 93e1e4b7a9 | |||
| e5ee31a2fe | |||
| e32d8711d6 | |||
| 78a17425f9 | |||
| 94b100dc06 | |||
| 75c494dca1 | |||
| f95b8ab226 | |||
| 6819dd9fb7 | |||
| c57a8481b1 | |||
| ec0c551bb3 | |||
| f17d4d2d92 | |||
| 255055d149 | |||
| 55c4ad40cd | |||
| 5fbc079c55 | |||
| 22c79db540 | |||
| bb56b24d8f | |||
| b2841cb5fc | |||
| f264cd6125 | |||
| d49de9d35e | |||
| 7f765c530e | |||
| e699824b1d | |||
| 6da8cf7f14 | |||
| e08767cec0 | |||
| 83415b7aa6 | |||
| 495e66f4ae | |||
| 17ea4ecce1 | |||
| 1d7375b9cb | |||
| 0a69f6de8c | |||
| 72cd2e7a30 | |||
| c6389c63b8 | |||
| f388554166 | |||
| b4ad396cd1 | |||
| c3473e45d2 | |||
| 075b495f5a | |||
| 9b3ccac246 | |||
| 82d9326343 | |||
| 464406cccc | |||
| 2782aa9924 | |||
| 1df7be7e8a | |||
| 792a9f097c | |||
| 4649ee9e71 | |||
| c1db9bd0a3 | |||
| cc47cda3d1 | |||
| 1503c98f26 | |||
| b82658e345 | |||
| 1bad2fa050 | |||
| 926d0af663 | |||
| 0a7496de1e | |||
| 9814baf192 | |||
| 5ec7717fa1 | |||
| d316f9dd6f | |||
| 529ec19801 | |||
| e105889a59 | |||
| c37a75cf7b | |||
| a33a25983e | |||
| 2f137f8b44 | |||
| 0f52638a80 | |||
| bbc2fe1b5a | |||
| 45a894c953 | |||
| c8915df31e | |||
| f6dea6e162 | |||
| ec8ad1888a | |||
| 8a280c349f | |||
| cbb36c9531 | |||
| acf5bd1ff5 | |||
| 6dd6491bee | |||
| 2f65311ae6 | |||
| cadd48922d | |||
| 2232f28283 | |||
| b639ce906c | |||
| d6414e51a2 | |||
| 1fda65bc3d | |||
| a5505bf848 | |||
| 678d62781b | |||
| b5ffe8a52b | |||
| 8e9da452c6 | |||
| 8fc2a83e3c | |||
| f4e40002a4 | |||
| 8c6881f526 | |||
| 0802f7a9e3 | |||
| d95e51a030 | |||
| 085a98cea3 | |||
| f7af76a1ba | |||
| c5b26bcffb | |||
| 244cc8dae1 | |||
| 520733888d | |||
| a1cac40f6a | |||
| 6bfea8a0df | |||
| ae29a9c00a | |||
| 5ddc551fd9 | |||
| 764ff60c34 | |||
| ae91f75aeb | |||
| 5d4f544a03 | |||
| efd2719481 | |||
| 66ed6fb658 | |||
| 6606a72e67 | |||
| fc019d6a6e | |||
| 6be1622fd0 | |||
| d0fd0e6c6c | |||
| 079d230959 | |||
| 637c25d5fe | |||
| 051720a686 | |||
| f3c2048c62 | |||
| 988c5af6d3 | |||
| aa58c3520c | |||
| cafd9a39a0 | |||
| 120011a2d0 | |||
| c8b2ce6694 | |||
| b855dd00ac | |||
| d082f4249c | |||
| f11f9040b1 | |||
| 27dbd5521a | |||
| 4f3b797c80 | |||
| f5df7edc6c | |||
| 99c4e8ded5 | |||
| a8b599d213 | |||
| ffaf5da984 | |||
| 49fa11ba07 | |||
| a1546a51cd | |||
| 0f0851dbf3 | |||
| ef617819e0 | |||
| 636f8d1be9 | |||
| b8c73d2d2a | |||
| b2aff4c75e | |||
| f912236114 | |||
| 349df02f78 | |||
| 0a15ccab9b | |||
| cfbb28f1ea | |||
| e008bf1863 | |||
| 297d30706f | |||
| 2f570fcc2a | |||
|
|
ea6623f029 | ||
|
|
ccf4480395 | ||
|
|
98f072bc12 | ||
|
|
03aa46cf4e | ||
|
|
4d0f87b91b | ||
|
|
a4fdb193bc | ||
|
|
9ea47c5385 | ||
|
|
79f0615441 | ||
|
|
7e215d9f9e | ||
|
|
04b9c736a6 | ||
|
|
5e26359783 | ||
|
|
493476f408 | ||
|
|
54fd7eda06 | ||
|
|
f838dbe5f3 | ||
|
|
793e1b0417 | ||
|
|
66875e93f8 | ||
|
|
08fe5fb23f | ||
|
|
d4038cd520 | ||
|
|
f29b15924c | ||
|
|
f621e521f9 | ||
|
|
b9622e4512 | ||
|
|
f67c41a7ac | ||
|
|
19be786da8 | ||
|
|
e14efe86a4 | ||
|
|
a19b51f91e | ||
|
|
35d2bdfd5e | ||
|
|
485607169f | ||
|
|
ee039ab2e9 | ||
|
|
e2df8aec10 | ||
|
|
0d18615fd8 | ||
|
|
4f69686968 | ||
|
|
777b8b55fd | ||
|
|
7688cc39a8 | ||
|
|
4fd33bf37f | ||
|
|
3d3c560516 | ||
|
|
1abc3e3e7d | ||
|
|
f1f4ad7ba7 | ||
|
|
66670ff220 | ||
|
|
a5eca9f110 | ||
|
|
f9b98f87a4 | ||
|
|
28b337f793 | ||
|
|
b02564e575 | ||
|
|
850f1b327e | ||
|
|
b98db96c27 | ||
|
|
49b0494f28 | ||
|
|
27137b4762 | ||
|
|
81109c88c7 | ||
|
|
748d86d6d3 | ||
|
|
dde68b1d22 | ||
|
|
a27e3593fa | ||
|
|
aaa6585a1e | ||
|
|
a3908a22ae | ||
|
|
0a5ac7cf7e | ||
|
|
7e99d5faa8 | ||
|
|
b43cc4f742 | ||
|
|
e99d8481b5 | ||
|
|
5950986a6f | ||
|
|
c37f5a59b3 | ||
|
|
92ffc5644f | ||
|
|
439ea2c182 | ||
|
|
27065e5ead | ||
|
|
12cfb5006a | ||
|
|
ac16b3eff1 | ||
|
|
696ebe60e0 | ||
|
|
168b7d313a | ||
|
|
3a51d3ef89 | ||
|
|
7c8dbccee2 | ||
|
|
7a925cd9a6 | ||
|
|
0a1ea8749b | ||
|
|
8543c8c68e | ||
|
|
8bbeb79233 | ||
|
|
4fcde940ff | ||
|
|
a98e3a32f9 | ||
|
|
a9c35def3f | ||
|
|
b860c6bbb0 | ||
|
|
03007194c8 | ||
|
|
b600dc0902 | ||
|
|
0868880d45 | ||
|
|
5ec7e2e092 | ||
|
|
b60185a97c | ||
|
|
cacd9a574d | ||
|
|
5a7b895476 | ||
|
|
630ef3e826 | ||
| bb4f5b88e7 | |||
| 23904f326d | |||
| 9b42f525e8 | |||
| 9d12dde7c1 | |||
| adb5cfbb72 | |||
| f8c47387c4 | |||
| b337d6b2eb | |||
| f486656756 | |||
| 2c9bd3575b | |||
| e1941b6612 | |||
| 256169a3c4 | |||
| f51a772826 | |||
| 0d2cf6eaa6 | |||
| 8a14222d51 | |||
| 9c2a911dab | |||
|
|
cfc8af675f | ||
|
|
b1cb923036 | ||
|
|
ff1d6d9df8 | ||
|
|
5c1b3b99f4 | ||
| 7e9ffbe033 | |||
|
|
38deea85e2 | ||
|
|
91eb3354e3 | ||
|
|
5cced1c9ed | ||
|
|
9cc7b6adf5 | ||
|
|
1f4f080bd2 | ||
|
|
8eb32add3a | ||
|
|
fdaa89e3c9 | ||
|
|
dd8fe29a98 | ||
|
|
ed9e4be6b2 | ||
|
|
69202ce7a0 | ||
|
|
88ce4cbf80 | ||
|
|
4c021a2838 | ||
|
|
4050222bc8 | ||
|
|
4b4da170f2 | ||
|
|
8ef85e90e9 | ||
|
|
06e92344cc | ||
|
|
a9944592c4 | ||
|
|
02c7bdf4f0 | ||
|
|
b34307b74c | ||
|
|
c43f25f4b8 | ||
|
|
8547c54103 | ||
|
|
db608ca3c1 | ||
|
|
abc32ecc0e | ||
|
|
d7ff38fe24 | ||
|
|
4b84ef5183 | ||
|
|
a7b7d487d7 | ||
|
|
7e7bfd1958 | ||
|
|
9f4a53dbbd | ||
|
|
96415f8523 | ||
|
|
e0672e559a | ||
|
|
c8b6db650a | ||
|
|
9ae31501cc | ||
|
|
1330c96681 | ||
|
|
774d7ffdf9 | ||
|
|
0492d71294 | ||
|
|
1c37eb7c72 | ||
|
|
34fab45b6b | ||
|
|
b1e49f67f4 | ||
|
|
6926d70543 | ||
|
|
09a1342588 | ||
|
|
ff96c2bb59 | ||
|
|
4ab7da32ce | ||
|
|
749bec5d52 | ||
|
|
7a68ba4f05 | ||
|
|
3affbc3c78 | ||
|
|
5663e5e58d | ||
|
|
922c435e28 | ||
|
|
5c4be9d29e | ||
|
|
13fb9b4698 | ||
|
|
8e17dd1829 | ||
|
|
3a4d3fc1e2 | ||
|
|
1f7e3a1d90 | ||
|
|
40aa4fa60e | ||
|
|
aa4418e71a | ||
|
|
76b8b29776 | ||
|
|
d862457623 | ||
|
|
f6a40390e0 | ||
|
|
1387eab434 | ||
|
|
ca576981a3 | ||
|
|
5cf7050008 | ||
|
|
af3ed18d48 | ||
|
|
54e8852fb7 | ||
|
|
109b17b1f9 | ||
|
|
a129a6e368 | ||
|
|
736fb672a5 | ||
|
|
7b467091d6 | ||
|
|
b364a51f80 | ||
|
|
8f68d7deb4 | ||
|
|
b5b39b5f68 | ||
|
|
49cd0af021 | ||
|
|
c423101c00 | ||
|
|
ebf6f8d735 | ||
|
|
ce94d50043 | ||
|
|
0ed0d0470c | ||
|
|
153c8d0d64 | ||
|
|
75bc71f473 | ||
|
|
29f30a6932 | ||
|
|
f4e52f5e11 | ||
|
|
902a57d10f | ||
|
|
928064c5ee | ||
|
|
492f32c555 | ||
|
|
b0566e7b8c | ||
|
|
6d3dba17d2 | ||
|
|
2d1200e2e6 | ||
|
|
a2c40163f5 | ||
|
|
a51c546f8c | ||
|
|
b2c2e6b6c6 | ||
|
|
fa0612c0d1 | ||
|
|
4d0028d95f | ||
|
|
54c54990a4 | ||
|
|
930a9a99f2 | ||
|
|
36aff803c6 | ||
|
|
b609932726 | ||
|
|
8f7790fa3c | ||
|
|
e13e763d5c | ||
|
|
c0caf520b8 | ||
|
|
1c1ef7a572 | ||
|
|
fefee324b4 | ||
|
|
07178e6ffa | ||
|
|
d96e4f9076 | ||
|
|
6445931493 | ||
|
|
11d6c19d65 | ||
|
|
b9355b49f3 | ||
|
|
be86a05ddb | ||
|
|
79be38992f | ||
|
|
6d92230c32 | ||
|
|
f5267a1975 | ||
|
|
5dbde32f01 | ||
|
|
655b5e36a4 | ||
|
|
a4c6fbbbd8 | ||
|
|
1f89f3298c | ||
|
|
f16fcb0200 | ||
|
|
253705f704 | ||
|
|
cf8c85f6ba | ||
|
|
dec35a6aa1 | ||
|
|
9442556c3e | ||
|
|
a761c4e11a | ||
|
|
fa40bfb8dc | ||
|
|
27d292affd | ||
|
|
dc5992bebd | ||
|
|
3c06a1e24f | ||
|
|
84cfa65bc6 | ||
|
|
43665749bb | ||
|
|
57297aba56 | ||
|
|
9204213dbc | ||
|
|
1b0cab6dc8 | ||
|
|
9a0c64c3d1 | ||
|
|
4b8e6bb198 | ||
|
|
624aef0a8e | ||
|
|
d66ec9d85c | ||
|
|
fc6bb1ddf6 | ||
|
|
475e78e13f | ||
|
|
8ceeb6be80 | ||
|
|
f76bfca921 | ||
|
|
0758b84d2c | ||
|
|
aab9212ffa | ||
|
|
b3c5fe9e96 | ||
|
|
8ca49478ab | ||
|
|
e142b90653 | ||
|
|
8276baecab | ||
|
|
b678ab2191 | ||
|
|
5ed2abaf64 | ||
|
|
513a1e58b8 | ||
|
|
d86636ebd4 | ||
|
|
6d1fa10965 | ||
|
|
86bd1dbbbf | ||
|
|
96aa98cbcf | ||
|
|
30deeaf4ef | ||
|
|
fe50909549 | ||
|
|
651af27674 | ||
|
|
75958fc9b4 | ||
|
|
036b4480f3 | ||
|
|
d4813b4ce9 | ||
|
|
21be5199cc | ||
|
|
8f43c12e22 | ||
|
|
a752a5a07c | ||
|
|
4945a1342f | ||
|
|
fd7e06bf18 | ||
|
|
e2960aebcb | ||
|
|
5b11c26e79 | ||
|
|
a60c79c35d | ||
|
|
0508886fc4 | ||
|
|
e0af29fd5e | ||
|
|
9fa363d9bf | ||
|
|
c3a0b08c40 | ||
|
|
b52d4faca7 | ||
|
|
7d593366c7 | ||
|
|
4d00a0f6dd | ||
|
|
648a911055 | ||
|
|
0d3a1cc14e | ||
|
|
c9b36b6030 | ||
|
|
52caf7cab1 | ||
|
|
46d946f381 | ||
|
|
4568578e16 | ||
|
|
c0b6d8807f | ||
|
|
c25d33e38a | ||
|
|
488247119a | ||
|
|
08c792fac7 | ||
|
|
e96c273351 | ||
|
|
a20e95fd38 | ||
|
|
37f21b516d | ||
|
|
690b8750c6 | ||
|
|
459a60d789 | ||
|
|
56c4309cb8 | ||
|
|
d21d4f5cb1 | ||
|
|
a498134b13 | ||
|
|
d91ab6f277 | ||
|
|
a5c97762e0 | ||
|
|
d5e41ec099 | ||
|
|
9e45641b7b | ||
|
|
b7300c6457 | ||
|
|
04258b6072 | ||
|
|
480904a4e3 | ||
|
|
7635f455ab | ||
|
|
c06346ef31 | ||
|
|
65d6204a01 | ||
|
|
bdacd638c7 | ||
|
|
b9a2badc31 | ||
|
|
be49bfa0c1 | ||
|
|
c1963438bc | ||
|
|
19e4f120c0 | ||
|
|
cc4a95fbd5 | ||
|
|
246bf30c41 | ||
|
|
a71f54c6bf | ||
|
|
e4db0eb9b9 | ||
|
|
e1ff2a0ef1 | ||
|
|
3f98f8fecf | ||
|
|
10010552e1 | ||
|
|
d38bf8ff4c | ||
|
|
caab08b017 | ||
|
|
85d8d9b268 | ||
|
|
a64a099d7d | ||
|
|
2a75237c70 | ||
|
|
d7801737f6 | ||
|
|
b2b0990bf6 | ||
|
|
ed84c1f8bf | ||
|
|
6567f10e69 | ||
|
|
b2dbf9bc20 | ||
|
|
78929629f0 | ||
|
|
7945a9c825 | ||
|
|
4c60aac8f8 | ||
|
|
d394f6fc9c | ||
|
|
605a8919a7 | ||
|
|
bfa3095137 | ||
|
|
0e401edac2 | ||
|
|
468d00d393 | ||
|
|
f5f10890b6 | ||
|
|
9b2db7608b | ||
|
|
0ca169aad2 | ||
|
|
9291bfbecb | ||
|
|
e620c20bb4 | ||
|
|
4b73024a57 | ||
|
|
b4e42d6562 | ||
|
|
3934d403ef | ||
|
|
e571c62319 | ||
|
|
9dffd1c93e | ||
|
|
34890aff90 | ||
|
|
503fa2e537 | ||
|
|
e10e6644e3 | ||
|
|
4d2770319e | ||
|
|
0cba00ebbb | ||
|
|
6e52fd4c95 | ||
|
|
9a2ac34ba3 | ||
|
|
e334ce9a55 | ||
|
|
b8a0d14fd5 | ||
|
|
7b0f5ab576 | ||
|
|
e7f541219d | ||
|
|
0bc59f1b9a | ||
|
|
8088b78a24 | ||
|
|
b98d01bd06 | ||
|
|
d0c999199b | ||
|
|
f907843d43 | ||
|
|
8aa1a3d05e | ||
|
|
c91c385dec | ||
|
|
2838aaad14 | ||
|
|
d6a7843240 | ||
|
|
51f65edb55 | ||
|
|
256d57adaa | ||
|
|
6d6b1447f8 | ||
|
|
801399218f | ||
|
|
c2e69a06b0 | ||
|
|
ae49f82580 | ||
|
|
879666fab7 | ||
|
|
81e45e3ace | ||
|
|
107351a6b5 | ||
|
|
292d98a33c | ||
|
|
72ee91a8da | ||
|
|
2eb61543d9 | ||
|
|
60002df680 | ||
|
|
f081d58e2b | ||
|
|
13244c1e37 | ||
|
|
71c9462d2e | ||
|
|
c410f9b67a | ||
|
|
b4fb1569ce | ||
|
|
fdcedb8295 | ||
|
|
39e3e8a04e | ||
|
|
7bb3717673 | ||
|
|
8dcf563674 | ||
|
|
a582cfe4f2 | ||
|
|
0af82054ff | ||
|
|
f812d9142f | ||
|
|
92ecb50cff | ||
|
|
1b2c308808 | ||
|
|
0c448ee83f | ||
|
|
a075d35c8c | ||
|
|
f26b488045 | ||
|
|
2fd81e218a | ||
|
|
fc4d8bcf65 | ||
|
|
0ef9223803 | ||
|
|
9bc186a072 | ||
|
|
70cb6d5d94 | ||
|
|
162a955f41 | ||
|
|
aadb4832bc | ||
|
|
0e96ffe287 | ||
|
|
958d5bfe22 | ||
|
|
c0ba6250aa | ||
|
|
0a6b134f23 | ||
|
|
a7715fc9c3 | ||
|
|
b508fbe3b1 | ||
|
|
9a9ac8b55f | ||
|
|
adda4caea4 | ||
|
|
a7ff0ef506 | ||
|
|
ee1c1bce80 | ||
|
|
7b00ab4699 | ||
|
|
df60e72fb3 | ||
|
|
d5b5d97bc1 | ||
|
|
640c4b2ca8 | ||
|
|
11822cbed0 | ||
|
|
9fb74c2f27 | ||
|
|
f361a64ab5 | ||
|
|
a4934a4ef3 | ||
|
|
46c63b3240 | ||
|
|
f77f56e1f2 | ||
|
|
2f05f05dc9 | ||
|
|
02b17049e3 | ||
|
|
ee6791fe97 | ||
|
|
de5554f1e2 | ||
|
|
e1f9143cf5 | ||
|
|
4fd69b684a | ||
|
|
c133565780 | ||
|
|
099be93420 | ||
|
|
43b7076ff8 | ||
|
|
49e33557e1 | ||
|
|
f16789f10e | ||
|
|
2b4540952e | ||
|
|
91ff4dbdec | ||
|
|
4cc196a69a | ||
|
|
7cedbcd63f | ||
|
|
ba7ad5fd28 | ||
|
|
7ca22ecc1d | ||
|
|
02a23a2aff | ||
|
|
47af6e85b8 | ||
|
|
04b0d63d43 | ||
|
|
62c9b56b3f | ||
|
|
155038a5c0 | ||
|
|
89ce298a3b | ||
|
|
9563fb0af3 | ||
|
|
2c4fcaaf07 | ||
|
|
3aaad123de | ||
|
|
7a07b95240 | ||
|
|
e5babcd36e | ||
|
|
1134fec173 | ||
|
|
d2b44f4400 | ||
|
|
aaba304ca8 | ||
|
|
288f8363ae | ||
|
|
b09e1525eb | ||
|
|
9fadb73ea5 | ||
|
|
cf1483e6b5 | ||
|
|
b579842eb6 | ||
|
|
47ab835549 | ||
|
|
69341880d3 | ||
|
|
e146ebc05b | ||
|
|
ceb5092b34 | ||
|
|
17da1f7fb5 | ||
|
|
43e56c08f7 | ||
|
|
6f9c70398b | ||
|
|
8b9a1dd535 | ||
|
|
c2d9d5b75b | ||
|
|
4fa6295fde | ||
|
|
bf4c06295a | ||
|
|
443a5438be | ||
|
|
9b88f93cad | ||
|
|
d6196a5e69 | ||
|
|
b39d43a700 | ||
|
|
20497bf905 | ||
|
|
fe20ed08d0 | ||
|
|
a87653860b | ||
|
|
9f2977bfd1 | ||
|
|
1e8efe180c | ||
|
|
29712edbd3 | ||
|
|
0211771d5f | ||
|
|
f100d33d94 | ||
|
|
9a05f11b65 | ||
|
|
b28f3ffa19 | ||
|
|
168d138481 | ||
|
|
3daa764d87 | ||
|
|
ff06671cd5 | ||
|
|
5736bd1408 | ||
|
|
999b31b615 | ||
|
|
e925c566ac | ||
|
|
8faf299a23 | ||
|
|
2985284f2b | ||
|
|
2d1d697498 | ||
|
|
57310dcb15 | ||
|
|
a574971f0b | ||
|
|
68a5551f36 | ||
|
|
3a6b4cca1e | ||
|
|
6fe35833e7 | ||
|
|
4b4f235481 | ||
|
|
6c0c84c284 | ||
|
|
26c966084a | ||
|
|
bf92c44d81 | ||
|
|
07422c4e1a | ||
|
|
6e6e50939b | ||
|
|
0ecb164e2e | ||
|
|
15cf498e75 | ||
|
|
377965d100 | ||
|
|
c9b0e994c1 | ||
|
|
daf4f0727d | ||
|
|
652c3b5d62 | ||
|
|
95764a0c48 | ||
|
|
97e9991d85 | ||
|
|
26be897578 | ||
|
|
b15fb50194 | ||
|
|
d7218535dd | ||
|
|
3108d82a4d | ||
|
|
d5fa31a6f5 | ||
|
|
a8cd9034ff | ||
|
|
d73840352b | ||
|
|
766eac8467 | ||
|
|
0fe5ae7675 | ||
|
|
66c4ab7e24 | ||
|
|
34f49edf2c | ||
|
|
27bb76706c | ||
|
|
ce00acdb39 | ||
|
|
e5a97611d0 | ||
|
|
d2f49e56bc | ||
|
|
520989bc59 | ||
|
|
2407853970 | ||
|
|
ccc0d7d401 | ||
|
|
ac68436b0b | ||
|
|
b0fece57ea | ||
|
|
7dda377a79 | ||
|
|
4a754553f7 | ||
|
|
074797384d | ||
|
|
7718b167c3 | ||
|
|
a2f5b77ff0 | ||
|
|
40ec37bd27 | ||
|
|
0d5f66e8b8 | ||
|
|
c67cf336d4 | ||
|
|
4efbf9361c | ||
|
|
87a768ac8d | ||
|
|
26ee98a224 | ||
|
|
5c1851028a | ||
|
|
f0b8f91a75 | ||
|
|
70fac546da | ||
|
|
80755fc6e2 | ||
|
|
feb3c16b3f | ||
|
|
cef20e1332 | ||
|
|
3b50815422 | ||
|
|
33270dabf3 | ||
|
|
a97c511c7a | ||
|
|
3b5789639b | ||
|
|
04a59d22a6 | ||
|
|
cb1944aca9 | ||
|
|
c2add5e1d1 | ||
|
|
a72e0a53e7 | ||
|
|
3ad81ab730 | ||
|
|
2afb15ee02 | ||
|
|
160b811669 | ||
|
|
fe603928e2 | ||
|
|
57298da60e | ||
|
|
d14ac1edf6 | ||
|
|
8ca49ab511 | ||
|
|
04202b59ef | ||
|
|
4bc3eabd29 | ||
|
|
36bc871c65 | ||
|
|
1589f6e26f | ||
|
|
b52f0c795e | ||
|
|
8f13d331ad | ||
|
|
b46e3d5bf4 | ||
|
|
8a8d0f1dcd | ||
|
|
e3ef58bd8e | ||
|
|
57f7f40fa9 | ||
|
|
7e4aacd342 | ||
|
|
1caab62200 | ||
|
|
6c8da48efa | ||
|
|
10a304ab83 | ||
|
|
a1d83bd2a8 | ||
|
|
df6da4d941 | ||
|
|
d8d2ad3e10 | ||
|
|
2f5bdeed62 | ||
|
|
40b0812d9b | ||
|
|
26ea268fed | ||
|
|
04a5d2bfef | ||
|
|
06d76a649f | ||
|
|
b0960c5345 | ||
|
|
6546c088d9 | ||
|
|
69550a1036 | ||
|
|
027726205d | ||
|
|
4d2b8c26fa | ||
|
|
cc47efe4b5 | ||
|
|
c0e53ae658 | ||
|
|
5ec23f2200 | ||
|
|
51d1ea4f8f | ||
|
|
fff0ecd1cd | ||
|
|
86b5bfe075 | ||
| f01331671c | |||
| b4b71f7626 | |||
| f088a3d54f | |||
| 5b23781e68 | |||
| edc9fd203d | |||
| 844ecbf71e | |||
| 8570ad2094 | |||
| bc3eb7bccc | |||
| 800c0daafe | |||
| 9b1ccdc320 | |||
| 6c8e826028 | |||
| d47bb3736e | |||
| ec1719e61d | |||
| a657a7809a | |||
| ef0f65720e | |||
| 22b5dd8567 | |||
| f9290705f8 | |||
| e51520bd63 | |||
| 6028175bfc | |||
| e9cd437668 | |||
| aa153f2ee7 | |||
| b1e6b00545 | |||
|
|
4f0ddc85d3 | ||
|
|
5d45702d5f | ||
|
|
d731a5cb09 | ||
|
|
06dfd91a82 | ||
|
|
c540466147 | ||
|
|
4d8b04cda9 | ||
|
|
aed2344bd4 | ||
|
|
c2508f8fa2 | ||
|
|
52d67b0f44 | ||
|
|
8079a476b6 | ||
|
|
2ef944d5c4 | ||
|
|
fde929b151 | ||
|
|
96f1cc1a5c | ||
|
|
647bf8c953 | ||
|
|
d2c7d70f49 | ||
|
|
001629b6dd | ||
|
|
b04469a252 | ||
|
|
54484e56e7 | ||
|
|
adc689cb15 | ||
|
|
d0f96a7023 | ||
|
|
08145f635f | ||
|
|
4884a97223 | ||
|
|
55136c1c6f | ||
|
|
fc300607e5 | ||
|
|
8c20ed0c89 | ||
|
|
c8e9cbdbb8 | ||
|
|
3f70ac5cde | ||
|
|
11a7182594 | ||
|
|
817074a787 | ||
|
|
c75bf1a19d | ||
|
|
11ebb98919 | ||
|
|
e4093343c2 | ||
|
|
101ea554ef | ||
|
|
ef6a986dc6 | ||
|
|
db593496a7 | ||
|
|
00c492891e | ||
|
|
0e81f9c726 | ||
|
|
b419c5cf7c | ||
|
|
20e5a6d1f3 | ||
|
|
99a9a5d850 | ||
|
|
a15d51c3d8 | ||
|
|
b01974b665 | ||
|
|
be5bec9887 | ||
|
|
27045f03f5 | ||
|
|
071baf04fd | ||
|
|
341e34b766 | ||
|
|
5c21816b22 | ||
|
|
afd18db381 | ||
|
|
6c8cd4c9f8 | ||
|
|
255d395f1d | ||
|
|
2f845e98e8 | ||
|
|
1371e3efb8 | ||
|
|
8a2c1658a8 | ||
|
|
b65c200922 | ||
|
|
33caf31237 | ||
|
|
cb7effca05 | ||
|
|
8745a3e824 | ||
|
|
ac6510d481 | ||
|
|
2109c7b830 | ||
|
|
629857d3ef | ||
|
|
60eed202dd | ||
|
|
14e2621a05 | ||
|
|
99da7963d1 | ||
|
|
2abe910ff5 | ||
|
|
15f7941daf | ||
|
|
535b87bb64 | ||
|
|
e63c0d1b03 | ||
|
|
8bc714a2b1 | ||
|
|
07b0aa8f52 | ||
|
|
ce665baa88 | ||
|
|
8c41663175 | ||
|
|
7cb10b71bb | ||
|
|
47cacf5f1a | ||
|
|
042e4b070c | ||
|
|
f84dbb369f | ||
|
|
34ec165bff | ||
|
|
b20c0bdec7 | ||
|
|
c527ad0803 | ||
|
|
0a6bb5190f | ||
|
|
cf353f8829 | ||
|
|
2bd7c021fd | ||
|
|
46f788d1eb | ||
|
|
5ea5d30075 | ||
|
|
22d650469b | ||
|
|
849ad494d8 | ||
|
|
7a2bb38331 | ||
|
|
1428ac2cb0 | ||
|
|
efdc7d9ba0 | ||
|
|
e4e41bb595 | ||
|
|
379fbb6e5d | ||
|
|
09c3236afc | ||
|
|
7d52440461 | ||
|
|
e206995268 | ||
|
|
ab4120721f | ||
|
|
a9c365a5eb | ||
|
|
8ad928d48d | ||
|
|
ebf5efe9f2 | ||
|
|
c7055341f9 | ||
|
|
34c5be5c42 | ||
|
|
1675916fda | ||
|
|
a38c608420 | ||
|
|
20be1d179a | ||
|
|
1870f38099 | ||
|
|
96eced9845 | ||
|
|
92e8c40c55 | ||
|
|
0bfa747382 | ||
|
|
be3c4263b3 | ||
|
|
f00852a619 | ||
|
|
83df8848c8 | ||
|
|
99183ce4e2 | ||
|
|
434ce56e33 | ||
|
|
ec86de2bc4 | ||
|
|
341f3d0ea5 | ||
|
|
579120df70 | ||
|
|
63eb323e8b | ||
|
|
2861ae2823 | ||
|
|
0b947ce2c7 | ||
|
|
2222d6d173 | ||
|
|
33e9b57b78 | ||
|
|
62f4dfdc7a | ||
|
|
7e01fd9c38 | ||
|
|
eefaf7a2b4 | ||
|
|
31dcf99e61 | ||
|
|
0def5f1dca | ||
|
|
ac94374f48 | ||
|
|
9f72b6e2c0 | ||
|
|
f9e38c1a8d | ||
|
|
6db56cc949 | ||
|
|
7081720ecb | ||
|
|
f7ded4d87b | ||
|
|
67780ca4a9 | ||
|
|
871f3c4bfe | ||
|
|
395fe8cb10 | ||
|
|
af936f6f8e | ||
|
|
5512e95e0a | ||
|
|
5e14f18c83 | ||
|
|
5adb971d9a | ||
|
|
f51e5ba19d | ||
|
|
488bddb02a | ||
|
|
3a2ec3ef9c | ||
|
|
08283f6c54 | ||
|
|
f7d3f58318 | ||
|
|
89e84e9b1b | ||
|
|
9226cce151 | ||
|
|
6526bdc824 | ||
|
|
1967f46a69 | ||
|
|
e504d13120 | ||
|
|
2f284f4274 | ||
|
|
4d171b27a4 | ||
|
|
fe4a9a6189 | ||
|
|
c862589dcf | ||
|
|
61765b0e33 | ||
|
|
78a111b57d | ||
|
|
9a515b9234 | ||
|
|
b924c180ae | ||
|
|
737f3eb553 | ||
|
|
6e3954f3bb | ||
|
|
4544f29832 | ||
|
|
477c357f11 | ||
|
|
7869a7c1b0 | ||
|
|
edc7159ef6 | ||
|
|
1db6943702 | ||
|
|
e8dff6c4a0 | ||
|
|
23ed816035 | ||
|
|
324b7f38a9 | ||
|
|
aa7aff3f6b | ||
|
|
236929a166 | ||
|
|
953e243639 | ||
|
|
338d53c982 | ||
|
|
37ebcc509b | ||
|
|
f9be6f9a85 | ||
|
|
2cc2b5b856 | ||
|
|
194976135f | ||
|
|
ef17f3ea7d | ||
|
|
0eec6fcfb6 | ||
|
|
09a772419a | ||
|
|
6c035d01d4 | ||
|
|
97bddc4537 | ||
|
|
684675bd84 | ||
|
|
b8c0fa9fa0 | ||
|
|
9e7794cd66 | ||
|
|
92ad44abf9 | ||
|
|
7e83ddf80e | ||
|
|
a9be720f09 | ||
|
|
d7906f113e | ||
|
|
01dcaefcfb | ||
|
|
cfba91ea43 | ||
|
|
134b6f6478 | ||
|
|
64104cb182 | ||
|
|
9aedcc7997 | ||
|
|
35547e28ea | ||
|
|
c6543e1f95 | ||
|
|
2183875e9e | ||
|
|
e5ee069f4a | ||
|
|
6c844315aa | ||
|
|
872bb1388d | ||
|
|
42aa255152 | ||
|
|
e58188d136 | ||
|
|
bb32c0af3b | ||
|
|
63fd2c7037 | ||
|
|
520a2ba202 | ||
|
|
13e8445083 | ||
|
|
d1c70cb13b | ||
|
|
6898cff623 | ||
|
|
f4558e3c41 | ||
|
|
d24075b1c5 | ||
|
|
a8c2a9da3a | ||
|
|
8041df7d41 | ||
|
|
073a181778 | ||
|
|
bec6fdc66a | ||
|
|
6833c9f1c2 | ||
|
|
18ade30185 | ||
|
|
e7ab305335 | ||
|
|
110d3a453a | ||
|
|
f5aeab39b4 | ||
|
|
e7738895ce | ||
|
|
60446dfc20 | ||
|
|
dc211c9c44 | ||
|
|
27babac6dc | ||
|
|
3e2b7cddc8 | ||
|
|
80ba2b3ccc | ||
|
|
b730582336 | ||
|
|
1b429dd2e5 | ||
|
|
448404e45c | ||
|
|
562d84c375 | ||
|
|
f09e3362aa | ||
|
|
51b5b1c08c | ||
|
|
ca2dde9a41 | ||
|
|
6674d1ed0f | ||
|
|
2a10dffff8 | ||
|
|
e0b17fc97d | ||
|
|
52800c3a65 | ||
|
|
9124617055 | ||
|
|
b312712d1b | ||
|
|
5bc1b8695e | ||
|
|
d921f3dadb | ||
|
|
c154712012 | ||
|
|
3634af3fdc | ||
|
|
1df9ec9f0f | ||
|
|
ae54a94d41 | ||
|
|
69add504e6 | ||
|
|
a0d30b6872 | ||
|
|
a06b33be66 | ||
|
|
fe3e33e702 | ||
|
|
3f56459734 | ||
|
|
4903241e4b | ||
|
|
85be003cf5 | ||
|
|
bddc1c0f9d | ||
|
|
01f6d83b86 | ||
|
|
aa994ee4fb | ||
|
|
d058a70557 | ||
|
|
7298468df7 | ||
|
|
63caa5044d | ||
|
|
2ae93dbec6 | ||
|
|
b434bead2c | ||
|
|
6284b155b8 | ||
|
|
b12c2d17d5 | ||
|
|
5fb1e26a4c | ||
|
|
6423750250 | ||
|
|
d9b5ef1cee | ||
|
|
f1717bde51 | ||
|
|
c6f4f40bba | ||
|
|
65f1b1e1e3 | ||
|
|
ad91ef66bd | ||
|
|
6bfa593988 | ||
|
|
3ea580b537 | ||
|
|
87b0b493eb | ||
|
|
4eb4a2de00 | ||
|
|
1f2f57b03b | ||
|
|
4afaad3df5 | ||
|
|
c3ba2e0f94 | ||
|
|
693c3168da | ||
|
|
8f309bc768 | ||
|
|
1a0d6a90c2 | ||
|
|
7f2019b4af | ||
|
|
ee7f0a2016 | ||
|
|
644b417f6c | ||
|
|
471576d6e8 | ||
|
|
7ee8aa7838 | ||
|
|
af63e9a7ad | ||
|
|
95c7344557 | ||
|
|
0c936e54ba | ||
|
|
62b90c29db | ||
|
|
6911b499d3 | ||
|
|
44f4c9374d | ||
|
|
11dabbe44d | ||
|
|
0a5a3845db | ||
|
|
5b797328f2 | ||
|
|
b89f1ad7d8 | ||
|
|
b0104d9992 | ||
|
|
9d8f4c774f | ||
|
|
8b7a22ecd9 | ||
|
|
a4e6db8d76 | ||
|
|
78506d5249 | ||
|
|
6747b18b75 | ||
|
|
544f13c52a | ||
|
|
4644f6e96b | ||
|
|
a3b228399b | ||
|
|
100a557c7c | ||
|
|
6acc75ccff | ||
|
|
b41f9620fa | ||
|
|
58bde08425 | ||
|
|
7d6c6edab3 | ||
|
|
d209964718 | ||
|
|
c03f659efb | ||
|
|
2e66cbeb60 | ||
|
|
19409cb999 | ||
|
|
c06182c38f | ||
|
|
f79cd8cee3 | ||
|
|
c130739de0 | ||
|
|
1a4a1583d5 | ||
|
|
3633ca04eb | ||
|
|
e61c0c45aa | ||
|
|
6d81848f25 | ||
|
|
10b3b343dd | ||
|
|
f6fd025be2 | ||
|
|
b5897687a6 | ||
|
|
ebeae261de | ||
|
|
9733f3c02c | ||
|
|
217c8a3933 | ||
|
|
7188d81ad4 | ||
|
|
48cacd6d9d | ||
|
|
1e378a514d | ||
|
|
92ab5e18ee | ||
|
|
b42af10905 | ||
|
|
afe8158cb7 | ||
|
|
a05bea0af5 | ||
|
|
e1514a151c | ||
|
|
2a82cfdb2a | ||
|
|
49da433879 | ||
|
|
92388e1734 | ||
|
|
3860c25dc0 | ||
|
|
25ee5ed1f9 | ||
|
|
566214ac62 | ||
|
|
1459f10803 | ||
|
|
0795a39459 | ||
|
|
e5831d6807 | ||
|
|
88bdb5114f | ||
|
|
90bd9088bb | ||
|
|
01cf8ab82c | ||
|
|
aee5506f00 | ||
|
|
b6183f2de1 | ||
|
|
452e0fe553 | ||
|
|
2f341a3369 | ||
|
|
66e55d1a1f | ||
|
|
63fac32bc0 | ||
|
|
aaeaeba57c | ||
|
|
d3c56897a3 | ||
|
|
0c2c3ec862 | ||
|
|
b6e7b18c7b | ||
|
|
55d049b1e8 | ||
|
|
8c0601816f | ||
|
|
350cde08d8 | ||
|
|
db5a29fd9a | ||
|
|
0716605e94 | ||
|
|
c802480d75 | ||
|
|
2519431f02 | ||
|
|
b38e71e544 | ||
|
|
c981afcf31 | ||
|
|
eccb8a4faf | ||
|
|
7fa5ddfc44 | ||
|
|
054f4e77f5 | ||
|
|
1398d6cc21 | ||
|
|
b902b019fb | ||
|
|
5e589aba3c | ||
|
|
c28cee88b7 | ||
|
|
14a45dc546 | ||
|
|
883621ba34 | ||
|
|
067cc81ebb | ||
|
|
b19ee7b894 | ||
|
|
1b356d3bf2 | ||
|
|
94a4059b4a | ||
|
|
735a0023cc | ||
|
|
2ad4fa99ed | ||
|
|
c0950c5fc6 | ||
|
|
afbbbbd4f2 | ||
|
|
32812c9482 | ||
|
|
c70e806d74 | ||
|
|
05be2e7386 | ||
|
|
e2e8885ce3 | ||
|
|
b214d8b6ee | ||
|
|
ba98bb9334 | ||
|
|
630a578e1d | ||
|
|
0bb35d7e7f | ||
|
|
357296baeb | ||
|
|
bff525d26f | ||
|
|
e4bdb21a54 | ||
|
|
c0ac7f0ac8 | ||
|
|
eba2fe1624 | ||
|
|
0030fe3aeb | ||
|
|
aaabf82eff | ||
|
|
de91d28f6f | ||
|
|
24d5d200b8 | ||
|
|
573ba2ee43 | ||
|
|
b4fced4bd7 | ||
|
|
52310a8ad8 | ||
|
|
11d203c54a | ||
|
|
723f12923c | ||
|
|
8b106dbc6c | ||
|
|
955d5a136f | ||
|
|
2db3825940 | ||
|
|
db3253e5d2 | ||
|
|
dbde8383c9 | ||
|
|
6d552f15b6 | ||
|
|
ba15724a62 | ||
|
|
938d286fb6 | ||
|
|
2e6c7b1bb8 | ||
|
|
5be705ca2a | ||
|
|
07b4cfaeae | ||
|
|
c9379b3608 | ||
|
|
22c8c96249 | ||
|
|
d66828c2bf | ||
|
|
a244f3ba4d | ||
|
|
0c20d35206 | ||
|
|
462ea26303 | ||
|
|
b25632ebc4 | ||
|
|
2a2b3f72fb | ||
|
|
52819d39d9 | ||
|
|
1d41ff16d6 | ||
|
|
36dd245ee3 | ||
|
|
e0bc35b975 | ||
|
|
893bafa14b | ||
|
|
7d262ad50b | ||
|
|
d9e7862cea | ||
|
|
9f30c299ee | ||
|
|
39845444cc | ||
|
|
ec32db2dd6 | ||
|
|
411e8ed79d | ||
|
|
c1c2a9f1a1 | ||
|
|
2850e56f30 | ||
|
|
9c0354bbf1 | ||
|
|
c09f1c2443 | ||
|
|
912f2c3567 | ||
|
|
ad51998d67 | ||
|
|
1049080df5 | ||
|
|
966b00617e | ||
|
|
b408208e4c | ||
|
|
a1edc2c6a9 | ||
|
|
2a06261f75 | ||
|
|
0b58465fb9 | ||
|
|
f67a93eddc | ||
|
|
7044f0e2cf | ||
|
|
ed7a88ce66 | ||
|
|
e392160435 | ||
|
|
5c0a3102ff | ||
|
|
2032c7c1f7 | ||
|
|
d295d8b43c | ||
|
|
ee8bac9ad7 | ||
|
|
4863bd30d7 | ||
|
|
7070a14480 | ||
|
|
a38f25f7cd | ||
|
|
a5259073df | ||
|
|
3e5ce46e98 | ||
|
|
f746866b65 | ||
|
|
8f31a1a820 | ||
|
|
4187568522 | ||
|
|
da82048d77 | ||
|
|
04d1caff78 | ||
|
|
bea06da531 | ||
|
|
7643f3cf7b | ||
|
|
aa5c6bbf08 | ||
|
|
9536f2a909 | ||
|
|
c7475d78b4 | ||
|
|
3c9a07677e | ||
|
|
b669f57068 | ||
|
|
ccebe536b3 | ||
|
|
b9a0733062 | ||
|
|
5961b45140 | ||
|
|
5f53738376 | ||
|
|
5eb4a7d711 | ||
|
|
f717081893 | ||
|
|
01b5118c6f | ||
|
|
d705bcbd98 | ||
|
|
f0f5ecb756 | ||
|
|
c0342b1482 | ||
|
|
d1fc7c0774 | ||
|
|
46be9b76ef | ||
|
|
6c8d2e159e | ||
|
|
db9bb6b5a1 | ||
|
|
5ea0d74a57 | ||
|
|
30a1a460b7 | ||
|
|
5eb61c17d4 | ||
|
|
0a4eeb89da | ||
|
|
11dc170ead | ||
|
|
98c0c1ed53 | ||
|
|
83a05724b8 | ||
|
|
44653d339d | ||
|
|
f2705180e0 | ||
|
|
306d80de94 | ||
|
|
2740ff8c4c | ||
|
|
74ad4038ac | ||
|
|
3f8593268e | ||
|
|
8ea83aac48 | ||
|
|
81d65afb28 | ||
|
|
c93547b080 | ||
|
|
54f75683c7 | ||
|
|
abfd691fda | ||
|
|
20c73f0596 | ||
|
|
b224d93098 | ||
|
|
719bf065ca | ||
|
|
a1041a53f7 | ||
|
|
711badb6b4 | ||
|
|
1e4063254b | ||
|
|
b8352e912f | ||
|
|
69a1d77480 | ||
|
|
54d7a7cccd | ||
|
|
c7afe2f86c | ||
|
|
5f4e3fe0eb | ||
|
|
fb95af1cf5 | ||
|
|
7b73d267d5 | ||
|
|
08b6cfde66 | ||
|
|
2110c20ecc | ||
|
|
9f51692f26 | ||
|
|
02c67fd114 | ||
|
|
b6be1a3659 | ||
|
|
00b4a084ad | ||
|
|
061e7891e9 | ||
|
|
a1af5562de | ||
|
|
df84ccd916 | ||
|
|
2f118fde9e | ||
|
|
46f98b3142 | ||
|
|
72ee098e0b | ||
|
|
43df2d201c | ||
|
|
691df04103 | ||
|
|
ab24f59660 | ||
|
|
3886db64bc | ||
|
|
e7a875755d | ||
|
|
7cf4e1bb09 | ||
|
|
eaea9d48c5 | ||
|
|
2e9fa8f4b7 | ||
|
|
d7d63e1464 | ||
|
|
bb175f3d4e | ||
|
|
4ca32628f7 | ||
|
|
6b4beb90e1 | ||
|
|
d7adc4e13f | ||
|
|
c13b935201 | ||
|
|
18fc39d2cf | ||
|
|
c083a8bcc2 | ||
|
|
e8783d46d0 | ||
|
|
d9a42550ff | ||
|
|
ceae66a30f | ||
|
|
031a491abd | ||
|
|
1536d3ef29 | ||
|
|
c03ed457a6 | ||
|
|
d2e6519bad | ||
|
|
688fa4839c | ||
|
|
fe411e8138 | ||
|
|
515682c0cd | ||
|
|
b17e0b4169 | ||
|
|
daa5f87fd4 | ||
|
|
d75b5d2f4a | ||
|
|
f6dbf66983 | ||
|
|
6cf674f8f8 | ||
|
|
7845a09b34 | ||
|
|
e4d432295d | ||
|
|
339204f1ee | ||
|
|
a4e679a118 | ||
|
|
195296846e | ||
|
|
7967db6ff5 | ||
|
|
c4f962a7d0 | ||
|
|
bc030da320 | ||
|
|
9cc7df51d6 | ||
|
|
bf7f17474d | ||
|
|
8a07edec5f | ||
|
|
0042971d74 | ||
|
|
6b5450b7e6 | ||
|
|
5dcc98d1c6 | ||
|
|
fc4aa470b2 | ||
|
|
586fb5a517 | ||
|
|
e186ad57d0 | ||
|
|
e6667db0cd | ||
|
|
e0887220b0 | ||
|
|
3290227b50 | ||
|
|
a59c439b46 | ||
|
|
7b6c887d76 | ||
|
|
25eb06ac46 | ||
|
|
0df8531834 | ||
|
|
496ab8c920 | ||
|
|
986030060b | ||
|
|
2d20656e22 | ||
|
|
98ebe1f63b | ||
|
|
1d529c021a | ||
|
|
f89c052cf8 | ||
|
|
38f2ecefac | ||
|
|
8305641b20 | ||
|
|
e473937cb9 | ||
|
|
8c9efff1ac | ||
|
|
37f8d3bef2 | ||
|
|
d1ba0dddec | ||
|
|
4a8f330ed2 | ||
|
|
63ab20d20b | ||
|
|
9a39ebe66f | ||
|
|
ddc3cecfc0 | ||
|
|
45479c90a3 | ||
|
|
b3c3af1ef6 | ||
|
|
2b43d484eb | ||
|
|
9688a55d56 | ||
|
|
e8e487187e | ||
|
|
4211206e3b | ||
|
|
ffe14fe5f3 | ||
|
|
c285f80b18 | ||
|
|
1e1543dd72 | ||
|
|
9c0c8a19dd | ||
|
|
ec98fd0c43 | ||
|
|
67a9c0415c | ||
|
|
a1ea335140 | ||
|
|
69bb81556f | ||
|
|
0b9a2fdf3a | ||
|
|
3b5fabbe97 | ||
|
|
fdd3d63098 | ||
|
|
5af96d3ec7 | ||
|
|
250221ff7f | ||
|
|
ec504ec4df | ||
|
|
96ce758c05 | ||
|
|
a45d9471ed | ||
|
|
a6e33bdd6a | ||
|
|
10f17efc4f | ||
|
|
d9fbc17f77 | ||
|
|
50f9f23ff1 | ||
|
|
34bd4e6441 | ||
|
|
0b75eaed92 | ||
|
|
e615032331 | ||
|
|
de8aed6a28 | ||
|
|
d61375cb7f | ||
|
|
4c8a8848ed | ||
|
|
00cbc852b0 | ||
|
|
8dd06cd8d8 | ||
|
|
20801a32f7 | ||
|
|
090f4a9474 | ||
|
|
0ef483fb4a | ||
|
|
945920f24d | ||
|
|
6938d26524 | ||
|
|
dea9f43d85 | ||
|
|
90e93b9656 | ||
|
|
586aaa596e | ||
|
|
457d32e273 | ||
|
|
dd8e17a387 | ||
|
|
93524c4be3 | ||
|
|
924bcd93e5 | ||
|
|
aa004d03aa | ||
|
|
7785219234 | ||
|
|
56e2b0007c | ||
|
|
a75b1df627 | ||
|
|
e3cafc011e | ||
|
|
3b363d626d | ||
|
|
d564e28f8e | ||
|
|
9b19688d65 | ||
|
|
e4d77cb9b2 | ||
|
|
05a9c11c47 | ||
|
|
9919ccb8b5 | ||
|
|
661930cbe6 | ||
|
|
6a2a54dcb5 | ||
|
|
c9cfda5ef2 | ||
|
|
4ba7c4a021 | ||
|
|
74a60ab963 | ||
|
|
3bc2454e91 | ||
|
|
a7df79ac07 | ||
|
|
31866be98b | ||
|
|
57e22d78e0 | ||
|
|
a4a6a8469e | ||
|
|
3158f9c33a | ||
|
|
711f220397 | ||
|
|
a223273544 | ||
|
|
61876ed232 | ||
|
|
f025671b8a | ||
|
|
489099ca91 | ||
|
|
08b4b73c67 | ||
|
|
fb492d4bb2 | ||
|
|
f0480c34d7 | ||
|
|
3395f6081c | ||
|
|
c9a9a8bc58 | ||
|
|
fa44e0c06e | ||
|
|
16e7b5af12 | ||
|
|
5265c48d04 | ||
|
|
b9a4053eec | ||
|
|
1517deeeb6 | ||
|
|
0dd68d11cb | ||
|
|
4f37c564a5 | ||
|
|
5ad2f2873e | ||
|
|
966971bd12 | ||
|
|
7767c57087 | ||
|
|
ba4a84602a | ||
|
|
d115f9dd1b | ||
|
|
1ccb934541 | ||
|
|
434956fc75 | ||
|
|
7da925ca70 | ||
|
|
3a7d8efc57 | ||
|
|
286b1e0ab7 | ||
|
|
2cbef2b10f | ||
|
|
d88e9ffd33 | ||
|
|
7c829852b8 | ||
|
|
709f1bbd75 | ||
|
|
8a4bec811b | ||
|
|
7889b21e7b | ||
|
|
000af6d9ee | ||
|
|
07458e5375 | ||
|
|
e8eb9f9614 | ||
|
|
e9ab06b59e | ||
|
|
979c525124 | ||
|
|
06b25f384a | ||
|
|
5af5bb2a32 | ||
|
|
caa5fb75b3 | ||
|
|
f4d6710a0f | ||
|
|
b3da5bdaa3 | ||
|
|
f6d4d00e02 | ||
|
|
37c97ac8fc | ||
|
|
5ac20a4d30 | ||
|
|
45203a4992 | ||
|
|
bb72229d6a | ||
|
|
16880de8f6 | ||
|
|
b20b9727cf | ||
|
|
e21043e81c | ||
|
|
1ecf709918 | ||
|
|
5288a6f9e2 | ||
|
|
c505652c15 | ||
|
|
2ebdac70da | ||
|
|
853b016a42 | ||
|
|
598b51eb7a | ||
|
|
985f3b44b7 | ||
|
|
ea6d8b8bde | ||
|
|
e1df763940 | ||
|
|
bb76af4f65 | ||
|
|
839b3e7392 | ||
|
|
adfd76f44b | ||
|
|
df7ff4ef1a | ||
|
|
c71600c144 | ||
|
|
5f24fc0986 | ||
|
|
a53284fe4f | ||
|
|
4ef05e35b8 | ||
|
|
956cfaf844 | ||
|
|
95f991cff3 | ||
|
|
c4541d8f5b | ||
|
|
ee29b23bd4 | ||
|
|
69e944e21a | ||
|
|
4827655632 | ||
|
|
5e7a7701b9 | ||
|
|
eefbfe746f | ||
|
|
45dfa9f215 | ||
|
|
64b72a3c9b | ||
|
|
51e5cc2ac8 | ||
|
|
2fc4b174c1 | ||
|
|
bd6c93a811 | ||
|
|
54971842f2 | ||
|
|
0fd83f0028 | ||
|
|
e98bceec10 | ||
|
|
f51cb6fca9 | ||
|
|
63f9af307d | ||
|
|
3453521c9c | ||
|
|
2744bdcdb7 | ||
|
|
e87115d462 | ||
|
|
548e59fc99 | ||
|
|
6ca5bb4d41 | ||
|
|
2a8ab1c6ca | ||
|
|
57f78dc61c | ||
|
|
388655d19b | ||
|
|
35b0a9e3ae | ||
|
|
25b4996145 | ||
|
|
75079320d1 | ||
|
|
aac6a21c4e | ||
|
|
d2c7c83615 | ||
|
|
1b3021d61c | ||
|
|
550606177b | ||
|
|
24910f2363 | ||
|
|
2ce2201496 | ||
|
|
9e89a177c7 | ||
|
|
bd24724560 | ||
|
|
bc1f8b5db6 | ||
|
|
6679ecb9d7 | ||
|
|
f85aa41adc | ||
|
|
f2d2f7ebe2 | ||
|
|
b54c7f720c | ||
|
|
1ef206467f | ||
|
|
85a407e7b0 | ||
|
|
8c7c6f3047 | ||
|
|
9fead39f36 | ||
|
|
948744538c | ||
|
|
dc7c64592b | ||
|
|
47cd054976 | ||
|
|
132b932ff3 | ||
|
|
8b8e2825e3 | ||
|
|
7dcb229ab3 | ||
|
|
63322989c2 | ||
|
|
f198d5d110 | ||
|
|
bdac23564a | ||
|
|
c741d1a52a | ||
|
|
8c6c6039a2 | ||
|
|
099dafc4c2 | ||
|
|
c5a4921176 | ||
|
|
6bfc97c95d | ||
|
|
6ebc5f0bff | ||
|
|
8614cd77eb | ||
|
|
1c5e364880 | ||
|
|
7d67eefdf5 | ||
|
|
3e5ae79c5a | ||
|
|
25e4b9a35e | ||
|
|
a1c7c0ab01 | ||
|
|
845a0f8e2d | ||
|
|
19df5c9b50 | ||
|
|
3b9b9331a8 | ||
|
|
500ff6be1a | ||
|
|
18670c69b2 | ||
|
|
a7043bf7cc | ||
|
|
15ab9ff9e3 | ||
|
|
59b93b23e2 | ||
|
|
e6b3924a5d | ||
|
|
160df2f2d1 | ||
|
|
af6a3aa456 | ||
|
|
cb5bcf4937 | ||
|
|
a32bfe7d87 | ||
|
|
5a008c3738 | ||
|
|
27022e7c39 | ||
|
|
3b046ee49d | ||
|
|
f7030b538f | ||
|
|
d13883ec86 | ||
|
|
6bc0030699 | ||
|
|
1d791f81fa | ||
|
|
4314a286e3 | ||
|
|
fc06c599bc | ||
|
|
1f866fcaed | ||
|
|
12cd0af111 | ||
|
|
1f5e306760 | ||
|
|
557e430c7d | ||
|
|
c946ddc275 | ||
|
|
563b3b1328 | ||
|
|
d84bf83419 | ||
|
|
1b3d583418 | ||
|
|
809e2f6d07 | ||
|
|
e52275e37f | ||
|
|
1981cb7662 | ||
|
|
d5c733919b | ||
|
|
d230d332cf | ||
|
|
13e1f0a561 | ||
|
|
e8e996182f | ||
|
|
fc440ba7e7 | ||
|
|
883ef2414f | ||
|
|
46c227bf3a | ||
|
|
36cfe9f857 | ||
|
|
1d53e7060a | ||
|
|
6332a4d800 | ||
|
|
f02d32b718 | ||
|
|
4a3ed7d0ae | ||
|
|
71afb5be75 | ||
|
|
4117118e23 | ||
|
|
b4a0bff740 | ||
|
|
14ac6e665c | ||
|
|
b0204023c0 | ||
|
|
c9afdae01c | ||
|
|
a62755182c | ||
|
|
3987cad9b7 | ||
|
|
cfd9aee57b | ||
|
|
d7a29be3ac | ||
|
|
a833eaa651 | ||
|
|
3166a04cef | ||
|
|
bf4acc21be | ||
|
|
ad7ebd1a8c | ||
|
|
d10ce6ac7c | ||
|
|
3d6e25ee5f | ||
|
|
d0c26fb1a4 | ||
|
|
f93f02f424 | ||
|
|
42a62da764 | ||
|
|
7978cd6d59 | ||
|
|
8470a55a41 | ||
|
|
d7a4098b56 | ||
|
|
af23c9f7cd | ||
|
|
1dfac3ad63 | ||
|
|
f1e3314bb7 | ||
|
|
0adb7af9a0 | ||
|
|
c19f87f867 | ||
|
|
da365be5a2 | ||
|
|
39e8c13afb | ||
|
|
a4051945fd | ||
|
|
6dcb293ba0 | ||
|
|
b83ff3f924 | ||
|
|
09412ac813 | ||
|
|
1d39c9d66a | ||
|
|
16f4583498 | ||
|
|
2726478467 | ||
|
|
bac95913e8 | ||
|
|
ed97b88b04 | ||
|
|
76114e2748 | ||
|
|
d00f19663b | ||
|
|
47aabf4fda | ||
|
|
d4216d09c6 | ||
|
|
5bfd9dbaa7 | ||
|
|
3a8ce99a9d | ||
|
|
1839082f95 | ||
|
|
d8af92bda2 | ||
|
|
09ef0c1f33 | ||
|
|
a1d064129a | ||
|
|
28ca5d90d9 | ||
|
|
a6390007b7 | ||
|
|
2e8a5aeb23 | ||
|
|
48efdc3593 | ||
|
|
005b4c8dd1 | ||
|
|
d66b495ba8 | ||
|
|
cb8bf360c4 | ||
|
|
d4295cfb25 | ||
|
|
5e131aed80 | ||
|
|
97243c8a91 | ||
|
|
274e394d8e | ||
|
|
1e9077f529 | ||
|
|
6861d2f3a1 | ||
|
|
624584f9df | ||
|
|
4f3a031786 | ||
|
|
e96d7d48f5 | ||
|
|
83e7ade714 | ||
|
|
47e541eaec | ||
|
|
c1537a1e82 | ||
|
|
c81322d51a | ||
|
|
d02c75d019 | ||
|
|
e98d5d0c0c | ||
|
|
9de79f0a36 | ||
|
|
ba2975aac8 | ||
|
|
3138fa0b40 | ||
|
|
9545219a23 | ||
|
|
bd306bdb9f | ||
|
|
bc70ec1263 | ||
|
|
3a6733dc98 | ||
|
|
6d6db77f06 | ||
|
|
a5a96dd857 | ||
|
|
87dd0fbdb6 | ||
|
|
6a95a0cecb | ||
|
|
60130633f0 | ||
|
|
7aa9a69c2f | ||
|
|
ede6dcd4ac | ||
|
|
e4f688fcfd | ||
|
|
3e9b0d6018 | ||
|
|
af28160679 | ||
|
|
58274c99d4 | ||
|
|
9b613029e6 | ||
|
|
844fe3924e | ||
|
|
0959efd7be | ||
|
|
ce65fe96ad | ||
|
|
5ccf3ed714 | ||
|
|
c48508d590 | ||
|
|
107f612384 | ||
|
|
4645033b98 | ||
|
|
6d33c003fc | ||
|
|
b1de90fe08 | ||
|
|
922b65d231 | ||
|
|
547f92de07 | ||
|
|
195285ac2f | ||
|
|
558cbe5b6d | ||
|
|
44ea8aa681 | ||
|
|
8de3469957 | ||
|
|
299949b156 | ||
|
|
df3bcbb6cb | ||
|
|
0177c8f1cf | ||
|
|
4ea79bc396 | ||
|
|
2f91cb0df7 | ||
|
|
cb212ba41c | ||
|
|
72cafe03e9 | ||
|
|
f8765c6166 | ||
|
|
dcffe5d992 | ||
|
|
4e2be07234 | ||
|
|
23bb45b845 | ||
|
|
d4041a4a1f | ||
|
|
16517f019a | ||
|
|
88e2f739a9 | ||
|
|
7bef2ad4cc | ||
|
|
a93c69d150 | ||
|
|
2e327dfcd7 | ||
|
|
f134a423f6 | ||
|
|
97f7e6632d | ||
|
|
327b8c863e | ||
|
|
97d177f42a | ||
|
|
2d0153195e | ||
|
|
7be4641040 | ||
|
|
4790db348d | ||
|
|
4d382a59d0 | ||
|
|
9fa18fa366 | ||
|
|
be22886be8 | ||
|
|
49a91885c9 | ||
|
|
f522c08438 | ||
|
|
6b4c331060 | ||
|
|
2759c3f0db | ||
|
|
e32f2b0a39 | ||
|
|
8c6d0759c7 | ||
|
|
0767bf487e | ||
|
|
f83b81b8c4 | ||
|
|
250d99d997 | ||
|
|
8933022edc | ||
|
|
dafe775ffa | ||
|
|
53c1750f0d | ||
|
|
f3f619cc41 | ||
|
|
51840a6693 | ||
|
|
55544845db | ||
|
|
86ce93b376 | ||
|
|
39ebb64b85 | ||
|
|
14cb2d5398 | ||
|
|
afdd6d39ec | ||
|
|
b4cbf620ab | ||
|
|
1ebd4f342e | ||
|
|
38f7deca78 | ||
|
|
51ef894a47 | ||
|
|
1e89369ef8 | ||
|
|
a2d8305e21 | ||
|
|
9f84f63471 | ||
|
|
241b965715 | ||
|
|
ae681b10e7 | ||
|
|
980085a8a3 | ||
|
|
43178dfe10 | ||
|
|
50a10cf161 | ||
|
|
cd24f7d30a | ||
|
|
78e23bd4ec | ||
|
|
b7c4c960e2 | ||
|
|
e64c3a1d87 | ||
|
|
cdcf6cdb25 | ||
|
|
aa3865c303 | ||
|
|
11c57e7aee | ||
|
|
2bb5c5806f | ||
|
|
365f3d2aa5 | ||
|
|
102f7ab059 | ||
|
|
99a2230fdb | ||
|
|
bf7c035f99 | ||
|
|
5f5e53a8d5 | ||
|
|
b2cfbded2e | ||
|
|
f4833c6c91 | ||
|
|
f32414dd93 | ||
|
|
349e842078 | ||
|
|
ca8f0f84c4 | ||
|
|
0f5ebb6827 | ||
|
|
5ca2a28246 | ||
|
|
566977c136 | ||
|
|
15c16ac54e | ||
|
|
bd75305560 | ||
|
|
c769924505 | ||
|
|
a24c6fdb39 | ||
|
|
d179afa303 | ||
|
|
723b49a22a | ||
|
|
e2c6f2f96f | ||
|
|
e4310a57cd | ||
|
|
4c7436e328 | ||
|
|
4360c65ed9 | ||
|
|
3b1181dae6 | ||
|
|
e43fe85454 | ||
|
|
cfc82591da | ||
|
|
4e5c0e70a6 | ||
|
|
265fa12917 | ||
|
|
a3b265a477 | ||
|
|
41b64cb8a3 | ||
|
|
a0336ce48b | ||
|
|
d9538183bd | ||
|
|
158b323767 | ||
|
|
6ec72b2978 | ||
|
|
47ae21c08e | ||
|
|
e9516ea4dd | ||
|
|
0785e2910f | ||
|
|
97ac722b24 | ||
|
|
7ca0ff9a19 | ||
|
|
1db02d7f36 | ||
|
|
204a8f1fcc | ||
|
|
57d57b8d8f | ||
|
|
bf34f730dd | ||
|
|
952f68fed5 | ||
|
|
7d4658643d | ||
|
|
a9bdf761e8 | ||
|
|
30e70c4697 | ||
|
|
43754c7f17 | ||
|
|
feb97cfc22 | ||
|
|
a262c16f06 | ||
|
|
175b7e8541 | ||
|
|
867cb225b6 | ||
|
|
346a73c36f | ||
|
|
97d8e4571f | ||
|
|
dc1ceca86e | ||
|
|
6529fdd28d | ||
|
|
e4e0a39dad | ||
|
|
53772ba305 | ||
|
|
d6598e790c | ||
|
|
9534969c05 | ||
|
|
a3b2118906 | ||
|
|
b4271a3533 | ||
|
|
79d68a52d0 | ||
|
|
9a89990293 | ||
|
|
7ec69e4215 | ||
|
|
99fbb181c1 | ||
|
|
4abb3f19bf | ||
|
|
ddd60e7142 | ||
|
|
47f408ca7c | ||
|
|
e3431a2c91 | ||
|
|
e41809af89 | ||
|
|
a112e7f9a4 | ||
|
|
63c087a255 | ||
|
|
7862b853bf | ||
|
|
da34491c59 | ||
|
|
d1b294e1ac | ||
|
|
b9a11f8c21 | ||
|
|
b8643f73b7 | ||
|
|
23651c6142 | ||
|
|
2696e13b19 | ||
|
|
446c930823 | ||
|
|
781209a23b | ||
|
|
065f707bd7 | ||
|
|
6c43e9c2e0 | ||
|
|
747c91210f | ||
|
|
cd978fa153 | ||
|
|
12ad588a9b | ||
|
|
6a0007c410 | ||
|
|
9dc4f13579 | ||
|
|
12f1707a74 | ||
|
|
b4dc060d75 | ||
|
|
ba51a696d2 | ||
|
|
52a3764ae4 | ||
|
|
1e6520fddd | ||
|
|
6a4470912f | ||
|
|
8356c2495c | ||
|
|
722ff4d9c0 | ||
|
|
a3c5ef59d6 | ||
|
|
5227483855 | ||
|
|
21778d057e | ||
|
|
826503766e | ||
|
|
1414abfe95 | ||
|
|
dc51354316 | ||
|
|
fae9e27365 | ||
|
|
d500fb8598 | ||
|
|
c58228195b | ||
|
|
519e3308ab | ||
|
|
29662eef5e | ||
|
|
2730510393 | ||
|
|
2669c51265 | ||
|
|
aeb2e282db | ||
|
|
4d17d95335 | ||
|
|
bac37d1714 | ||
|
|
e6e1705852 | ||
|
|
28d9f82ab1 | ||
|
|
6336248d71 | ||
|
|
67aff528f5 | ||
|
|
93f5043230 | ||
|
|
80f7a5f025 | ||
|
|
4239c952d2 | ||
|
|
e69f878241 | ||
|
|
6d3aa3276a | ||
|
|
e3e3a91734 | ||
|
|
54da2526ed | ||
|
|
99f2aba6e1 | ||
|
|
128a00c4ab | ||
|
|
1d0a448e07 | ||
|
|
731fd01139 | ||
|
|
3ef573f67c | ||
|
|
e6f07d8554 | ||
|
|
31c9b2c1d8 | ||
|
|
9319033ff0 | ||
|
|
0eb5122817 | ||
|
|
6bcfc73175 | ||
|
|
d672547112 | ||
|
|
e16f7d04a8 | ||
|
|
b59dacb806 | ||
|
|
5f7032dfee | ||
|
|
c67b89e56b | ||
|
|
ce803f6d06 | ||
|
|
1edb1bbc17 | ||
|
|
893d117309 | ||
|
|
0c17c32267 | ||
|
|
23e66bef64 | ||
|
|
d16a883e17 | ||
|
|
b23cc7465f | ||
|
|
afbdcf8938 | ||
|
|
a838c90951 | ||
|
|
f68d1ade3f | ||
|
|
543d968b81 | ||
|
|
a361fdbd77 | ||
|
|
73dbc5ca1b | ||
|
|
d9b649642d | ||
|
|
d2c11925bf | ||
|
|
5fbb01130a | ||
|
|
47dc15c9f6 | ||
|
|
d6bf90cfb7 | ||
|
|
ade4518ae4 | ||
|
|
422d475e44 | ||
|
|
501d081d3b | ||
|
|
d2507a6266 | ||
|
|
46829c6d3c | ||
|
|
2d1b70c94d | ||
|
|
2301862ae6 | ||
|
|
dcb7ce36d8 | ||
|
|
e2a090c9cc | ||
|
|
c23c3a4f53 | ||
|
|
4bf26eff4c | ||
|
|
be14e15dac | ||
|
|
fbcca62ae1 | ||
|
|
8ef2abf30b | ||
|
|
799c2e47fe | ||
|
|
be35975b12 | ||
|
|
557ad2d1fd | ||
|
|
c7c34ec05a | ||
|
|
83f679fb57 | ||
|
|
3cef75bcac | ||
|
|
e5ad98e601 | ||
|
|
5dce08d068 | ||
|
|
f10625f8bc | ||
|
|
338df7e35b | ||
|
|
c8753353ed | ||
|
|
913595780f | ||
|
|
1471defff3 | ||
|
|
05fea4cdc6 | ||
|
|
2198f39597 | ||
|
|
6f2fbd448d | ||
|
|
38a187b93e | ||
|
|
7fdcbd56d5 | ||
|
|
70d85c58e2 | ||
|
|
67dfc0a046 | ||
|
|
b9d35659c8 | ||
|
|
733debd9b3 | ||
|
|
8806cce735 | ||
|
|
dd229e855a | ||
|
|
893d888152 | ||
|
|
49b7648fea | ||
|
|
d0b2d86ca1 | ||
|
|
9f961597c6 | ||
|
|
a61235086b | ||
|
|
ec257d940a | ||
|
|
dcf29c2a07 | ||
|
|
eaa394ed7d | ||
|
|
a614205663 | ||
|
|
2c5cba28b6 | ||
|
|
7c90d7022b | ||
|
|
ef5ed10eb9 | ||
|
|
cd71188d3a | ||
|
|
a30d34be7f | ||
|
|
d98784e059 | ||
|
|
3dea259f52 | ||
|
|
2938b3e960 | ||
|
|
13cf744fb3 | ||
|
|
2686635f60 | ||
|
|
1126f70786 | ||
|
|
7c7f2f890f | ||
|
|
d6664f5735 | ||
|
|
58e852f7f7 | ||
|
|
6bec22ea4e | ||
|
|
25f623565a | ||
|
|
098c8b1df4 | ||
|
|
55546a5aab | ||
|
|
7aca4e7463 | ||
|
|
41e36e1f28 | ||
|
|
1f01356076 | ||
|
|
60804d1902 | ||
|
|
d5ecbd05a1 | ||
|
|
9960714896 | ||
|
|
90045d66ea | ||
|
|
2c83614170 | ||
|
|
349dba8be0 | ||
|
|
e903bd0bc3 | ||
|
|
b1ed1f48ea | ||
|
|
25c15119bc | ||
|
|
84930f89f9 | ||
|
|
19b743a9f5 | ||
|
|
9fcfb7cb1d | ||
|
|
6a4aa34b0c | ||
|
|
40cffb9463 | ||
|
|
a2b914ce60 | ||
|
|
43abfe659b | ||
|
|
367fc054dc | ||
|
|
771f08b3c7 | ||
|
|
5167b1fa40 | ||
|
|
c6ae883ad2 | ||
|
|
a5c1b063fd | ||
|
|
689e277c62 | ||
|
|
36f099958c | ||
|
|
cb40f72c7e | ||
|
|
f708a5b016 | ||
|
|
efd2326a29 | ||
|
|
5b11238010 | ||
|
|
6b31feb70f | ||
|
|
a6898b033d | ||
|
|
c0851d59f5 | ||
|
|
fb7f572eed | ||
|
|
7e6783bb8f | ||
|
|
daea5647b6 | ||
|
|
9b3cbb373e | ||
|
|
efe23ed404 | ||
|
|
05439831e7 | ||
|
|
06e325d61b | ||
|
|
d94f9031ff | ||
|
|
10f16e4f32 | ||
|
|
c459bded53 | ||
|
|
fb15dc5080 | ||
|
|
bf38fb7bef | ||
|
|
7c80c9a1f9 | ||
|
|
dfc11f99ad | ||
|
|
bb0cb9b3f6 | ||
|
|
d73c264e25 | ||
|
|
34093388a7 | ||
|
|
a47563cf3d | ||
|
|
03d2b680f8 | ||
|
|
52778e1882 | ||
|
|
42545c6625 | ||
|
|
e69715005d | ||
|
|
c01982c917 | ||
|
|
aa76e5863f | ||
|
|
b8d1e1f4a6 | ||
|
|
884aeb4d2e | ||
|
|
473f893d04 | ||
|
|
76c8139054 | ||
|
|
a48055a3cc | ||
|
|
c0b0f8e2f9 | ||
|
|
e447964639 | ||
|
|
b1b6a0a69c | ||
|
|
a888294135 | ||
|
|
ca0c792ed3 | ||
|
|
48e1a2431b | ||
|
|
b15434375c | ||
|
|
9614aba0e1 | ||
|
|
fef52d7b51 | ||
|
|
a9d18a077e | ||
|
|
1cec627d72 | ||
|
|
4e50717e12 | ||
|
|
ef005987a1 | ||
|
|
1121b38eb1 | ||
|
|
89dd44bf3e | ||
|
|
81f9a59f25 | ||
|
|
d0e2f8745d | ||
|
|
3f9c1c142a | ||
|
|
45446f17ad | ||
|
|
be1759f112 | ||
|
|
d3a4a2225f | ||
|
|
81bf0fd261 | ||
|
|
f74d2d555c | ||
|
|
d13454fb84 | ||
|
|
5999171c11 | ||
|
|
45b523bada | ||
|
|
21cc737f5c | ||
|
|
9accd953e4 | ||
|
|
64e74d527f | ||
|
|
c393bc9563 | ||
|
|
912d65c767 | ||
|
|
fa8e02b832 | ||
|
|
de047f9727 | ||
|
|
80dc2788dd | ||
|
|
477d71c0bf | ||
|
|
84dda697d6 | ||
|
|
73992a1ed8 | ||
|
|
9eea255c79 | ||
|
|
358684a5ed | ||
|
|
385705c65b | ||
|
|
15d12b209d | ||
|
|
7715ea993b | ||
|
|
f768de4b46 | ||
|
|
cae344b67b | ||
|
|
6c46a93a81 | ||
|
|
486a02d60d | ||
|
|
11b925c4ca | ||
|
|
c1655c2c0f | ||
|
|
b0416ae592 | ||
|
|
78346af572 | ||
|
|
bdc38a7204 | ||
|
|
6dc0477c00 | ||
|
|
deda83fdef | ||
|
|
4678546d33 | ||
|
|
a85a08ff35 | ||
|
|
0797ee0871 | ||
|
|
3019f8f23f | ||
|
|
fdfa71a033 | ||
|
|
c559b8ce2a | ||
|
|
f53ebdeadb | ||
|
|
1f76c1e4a9 | ||
|
|
2b67b53112 | ||
|
|
44c10bb2aa | ||
|
|
a1530b0e68 | ||
|
|
8df38df5cb | ||
|
|
16088d9439 | ||
|
|
bc0a903bd4 | ||
|
|
818fb05cfe | ||
|
|
e5019c3858 | ||
|
|
b570f0d3cb | ||
|
|
2af9de4f23 | ||
|
|
b530d385bc | ||
|
|
0caf0612d0 | ||
|
|
6e49281adb | ||
|
|
2f1bfe126b | ||
|
|
c173c4faa5 | ||
|
|
59e75ef966 | ||
|
|
f092026541 | ||
|
|
df00a88cb4 | ||
|
|
bacd49a6a8 | ||
|
|
0781c2a7b9 | ||
|
|
b7c849b5b0 | ||
|
|
83cb1dfa68 | ||
|
|
6834f355f2 | ||
|
|
99261e0781 | ||
|
|
53339ff463 | ||
|
|
331abf173b | ||
|
|
f699ffeb8a | ||
|
|
cf7d2f4d0f | ||
|
|
0ddaa6ff75 | ||
|
|
0482b7de8e | ||
|
|
24d9d76644 | ||
|
|
1e5770bbcf | ||
|
|
adba38ce20 | ||
|
|
45dd343126 | ||
|
|
29b45bb87a | ||
|
|
8ab98b72ac | ||
|
|
377947c57f | ||
|
|
1d26fedf12 | ||
|
|
494746e665 | ||
|
|
a5fd4fde25 | ||
|
|
b38a789005 | ||
|
|
818aaa0578 | ||
|
|
961725205d | ||
|
|
ee305891c4 | ||
|
|
3e7e3de554 | ||
|
|
5c262a788d | ||
|
|
3720e37f06 | ||
|
|
99da1ebe41 | ||
|
|
3ed632decf | ||
|
|
e75472f460 | ||
|
|
eceafb84de | ||
|
|
14bd6daab1 | ||
|
|
e49e113140 | ||
|
|
3658774429 | ||
|
|
f4feef477b | ||
|
|
b696fb4eb1 | ||
|
|
8c28e54ccc | ||
|
|
dbe5d72e4c | ||
|
|
d07640caba | ||
|
|
e4a1dff98d | ||
|
|
e94017a552 | ||
|
|
a1b509bb0b | ||
|
|
8d331b0f35 | ||
|
|
543a7e421e | ||
|
|
c826fe0af4 | ||
|
|
bd6efa0e45 | ||
|
|
f24cdf4a80 | ||
|
|
1a46d86ca6 | ||
|
|
93c614c184 | ||
|
|
c1f22f106b | ||
|
|
5b2b969a77 | ||
|
|
8acf930c45 | ||
|
|
b13f8df79b | ||
|
|
63fff7ef47 | ||
|
|
87ae5292b8 | ||
|
|
e498bc6b7b | ||
|
|
7fbf72f9c1 | ||
|
|
42dff2742a | ||
|
|
67801a5566 | ||
|
|
5ef10a14ef | ||
|
|
c3c5a9974d | ||
|
|
55aa68b941 | ||
|
|
fbec7c4e75 | ||
|
|
d1e609a886 | ||
|
|
f143925931 | ||
|
|
d13483ca20 | ||
|
|
33194b3cff | ||
|
|
28cd5640c1 | ||
|
|
0463d96392 | ||
|
|
4e0ed61f7c | ||
|
|
e6f2676c5c | ||
|
|
c48871cf1b | ||
|
|
6255e1dca3 | ||
|
|
801ca3531b | ||
|
|
3eebf2a353 | ||
|
|
cd2695190d | ||
|
|
1f02dc639e | ||
|
|
be58fd64f5 | ||
|
|
6505504411 | ||
|
|
d4be5349b3 | ||
|
|
9e5c71e701 | ||
|
|
c02f23e63f | ||
|
|
5d4b1d0b88 | ||
|
|
839ae571d8 | ||
|
|
e7308b0ecb | ||
|
|
94392ab00c | ||
|
|
05d3622939 | ||
|
|
6924bb1d29 | ||
|
|
a9b5519293 | ||
|
|
4d179c6b0c | ||
|
|
47c7e1b875 | ||
|
|
f1c4c64cd9 | ||
|
|
346e34e543 | ||
|
|
4352d1739d | ||
|
|
1a1e44cdfd | ||
|
|
7b2036a4b5 | ||
|
|
b596391fcd | ||
|
|
d6ac002639 | ||
|
|
4a8e936e19 | ||
|
|
0fd2ad649e | ||
|
|
4b22b0c42a | ||
|
|
6d9f390ba8 | ||
|
|
da2f179ae9 | ||
|
|
e577e883f4 | ||
|
|
59d3bbe037 | ||
|
|
d45457e4a9 | ||
|
|
1946197a1c | ||
|
|
32549cfd8c | ||
|
|
2c5460eb0e | ||
|
|
31c8416a8f | ||
|
|
956e053da6 | ||
|
|
792b62874e | ||
|
|
0b4b0de412 | ||
|
|
1c25cffbd8 | ||
|
|
3d66d960a1 | ||
|
|
8b78e01d4c | ||
|
|
64f2f3d976 | ||
|
|
8ad6b8809a | ||
|
|
e10691abea | ||
|
|
9a75778b29 | ||
|
|
3471213d1c | ||
|
|
ab93bb009c | ||
|
|
df8c14d66a | ||
|
|
701f6ff608 | ||
|
|
6a16939830 | ||
|
|
bf0df016e5 | ||
|
|
de7e8c59e8 | ||
|
|
fb537fb7f4 | ||
|
|
065e23b1c4 | ||
|
|
00ace6c2df | ||
|
|
f7a1c8a94c | ||
|
|
34b25e6afc | ||
|
|
b4b57bba54 | ||
|
|
bda30a92bc | ||
|
|
7266a968f9 | ||
|
|
f467b89f40 | ||
|
|
3bddf01350 | ||
|
|
c19964094b | ||
|
|
b374e5f08b | ||
|
|
df0f9547b5 | ||
|
|
7df8a6b731 | ||
|
|
aa3028e5d9 | ||
|
|
3251ef3b51 | ||
|
|
95d415257a | ||
|
|
0dc7fcce5b | ||
|
|
336f099241 | ||
|
|
fe328ae5e4 | ||
|
|
cf6e06a5dd | ||
|
|
0dfafe2567 | ||
|
|
26a6eca94e | ||
|
|
f4309ed715 | ||
|
|
e02c10a589 | ||
|
|
54325e266f | ||
|
|
ad4beb9091 | ||
|
|
10973dcf69 | ||
|
|
86106b890a | ||
|
|
4fc2b2584b | ||
|
|
34ce2f6cfa | ||
|
|
f6df44ea85 | ||
|
|
7adf1c99fc | ||
|
|
7f1ce07e9f | ||
|
|
fab745c6d6 | ||
|
|
6606781916 | ||
|
|
5ba6be1a87 | ||
|
|
df19791a8f | ||
|
|
8b0fdfb4a0 | ||
|
|
7cf6aaecd0 | ||
|
|
66289d3e76 | ||
|
|
6772d991ae | ||
|
|
f61187a210 | ||
|
|
bceece3bb9 | ||
|
|
b0bf620c61 | ||
|
|
29847f172f | ||
|
|
d7a8ee99af | ||
|
|
998db39b1a | ||
|
|
ad5d5f8054 | ||
|
|
08be0e5c67 | ||
|
|
c0ef167514 | ||
|
|
2f836e2a59 | ||
|
|
17a65ff873 | ||
|
|
7f4b51e246 | ||
|
|
4bc0b374bc | ||
|
|
bd00ef839d | ||
|
|
556d6e198f | ||
|
|
cf916141d0 | ||
|
|
feb6b636f4 | ||
|
|
12d77ac3e4 | ||
|
|
4a31e4992d | ||
|
|
6026dcaed1 | ||
|
|
62c4ffe889 | ||
|
|
b76461fc78 | ||
|
|
0ac71c2b7b | ||
|
|
83c112e24b | ||
|
|
306df3dc3b | ||
|
|
ace47a4512 | ||
|
|
48f31928e9 | ||
|
|
4904c2bc10 | ||
|
|
cc26c4cb1a | ||
|
|
90945e548b | ||
|
|
71119e4980 | ||
|
|
3e830dad37 | ||
|
|
d8092207c0 | ||
|
|
bb0faaea56 | ||
|
|
f5ed66280b | ||
|
|
2b4a6c7dd7 | ||
|
|
ef4c11d262 | ||
|
|
0d39337683 | ||
|
|
67c0c1b6c5 | ||
|
|
0baa9debbc | ||
|
|
1644608376 | ||
|
|
0e91a38c9c | ||
|
|
0f938ff234 | ||
|
|
c2ea85a5e2 | ||
|
|
1be376cf87 | ||
|
|
1eff108561 | ||
|
|
2addf8e456 | ||
|
|
ef4e61c91b | ||
|
|
4ea396f871 | ||
|
|
edd62e58fd | ||
|
|
8d26d83d7a | ||
|
|
2dd968f94e | ||
|
|
d5d8068632 | ||
|
|
5f0412b9ee | ||
|
|
289116cb64 | ||
|
|
20592f184d | ||
|
|
42c653a9d0 | ||
|
|
c114c6bbad | ||
|
|
129bd1bf03 | ||
|
|
d659e0aaf9 | ||
|
|
8d1105fe73 | ||
|
|
441e2c8d34 | ||
|
|
4fecda58ff | ||
|
|
376d545082 | ||
|
|
c498db147a | ||
|
|
10bb4cb659 | ||
|
|
b537696370 | ||
|
|
6d9ea620a3 | ||
|
|
a06dc57621 | ||
|
|
3e16e31080 | ||
|
|
831e9db7ec | ||
|
|
4479d780e5 | ||
|
|
334a0d56e7 | ||
|
|
8bab642cc7 | ||
|
|
b7edac2610 | ||
|
|
c95f74018d | ||
|
|
fbe0e68617 | ||
|
|
5b847eff12 | ||
|
|
bca4bb8373 | ||
|
|
b01484a0a3 | ||
|
|
5c4a7a1052 | ||
|
|
1eba33590b | ||
|
|
70695a1463 | ||
|
|
1630424797 | ||
|
|
b33b40db45 | ||
|
|
38c84a92c7 | ||
|
|
5d548d157f | ||
|
|
abb8d1273e | ||
|
|
4f0fae9e90 | ||
|
|
11810bbf54 | ||
|
|
47db1ab063 | ||
|
|
f09a82268f | ||
|
|
b95b318052 | ||
|
|
6aba21fcd8 | ||
|
|
fa1e4620cf | ||
|
|
aa4d880148 | ||
|
|
96e0819f00 | ||
|
|
c5bdf6924d | ||
|
|
64ac344efa | ||
|
|
b9971e8a80 | ||
|
|
1e3cf08d82 | ||
|
|
dbfb698859 | ||
|
|
96fb18da3f | ||
|
|
d0e7203d88 | ||
|
|
acd4980ab4 | ||
|
|
844670f88d | ||
|
|
65184782aa | ||
|
|
f29daa22b6 | ||
|
|
dbdac9cfbe | ||
|
|
e40014b4de | ||
|
|
c83deecba2 | ||
|
|
5f999e84d8 | ||
|
|
507f9a28c0 | ||
|
|
7ccd36849e | ||
|
|
f345f1d605 | ||
|
|
deb5275c7a | ||
|
|
959f971a65 | ||
|
|
9f83e60f25 | ||
|
|
0e32729e59 | ||
|
|
c950f18546 | ||
|
|
96e0867d4c | ||
|
|
45b24286e5 | ||
|
|
f513ceac7d | ||
|
|
5c768d7ef7 | ||
|
|
4b7c904fe0 | ||
|
|
a3ddc4ec0c | ||
|
|
3ca4af6868 | ||
|
|
ba623d2b4e | ||
|
|
a9b1b60a97 | ||
|
|
d7b58491ce | ||
|
|
a74572b469 | ||
|
|
6ac8b845bf | ||
|
|
fe4c8a771b | ||
|
|
0aa759fab7 | ||
|
|
2edf535ecd | ||
|
|
85d5cfede5 | ||
|
|
e58c529c53 | ||
|
|
2207eacc92 | ||
|
|
fed0895d98 | ||
|
|
1b81131c51 | ||
|
|
e1de6e0aa9 | ||
|
|
ebbb9a8990 | ||
|
|
54e87dd2c3 | ||
|
|
3ae81f095c | ||
|
|
03c68d283d | ||
|
|
4c2bc465a0 | ||
|
|
fae7bc0bc0 | ||
|
|
dc36621dc2 | ||
|
|
21979bb7d7 | ||
|
|
033ed7e4aa | ||
|
|
cd22be3374 | ||
|
|
ddfb56d920 | ||
|
|
983fd75ec9 | ||
|
|
2030ddfc79 | ||
|
|
439b466979 | ||
|
|
d1f1063900 | ||
|
|
123bb445db | ||
|
|
8649591626 | ||
|
|
3e1a6a65e6 | ||
|
|
4b31bc3fd2 | ||
|
|
df21c3c95d | ||
|
|
df46f123dd | ||
|
|
fc3f1f6942 | ||
|
|
677f0ac479 | ||
|
|
303fa91720 | ||
|
|
c7e08195e4 | ||
|
|
d9d74ca96c | ||
|
|
aa5bbdf6e5 | ||
|
|
3b1792c8b5 | ||
|
|
e4892d21b1 | ||
|
|
8edc5148d9 | ||
|
|
63fd35dffa | ||
|
|
b43294ec6f | ||
|
|
a4a37d6fc9 | ||
|
|
626333a59e | ||
|
|
2c8536dbf0 | ||
|
|
401b774c2f | ||
|
|
d260808cd3 | ||
|
|
79c40bc73b | ||
|
|
b6aeff89c4 | ||
|
|
236bf0b0f5 | ||
|
|
005c108118 | ||
|
|
5b307c0417 | ||
|
|
65adefe170 | ||
|
|
4b69ef41e2 | ||
|
|
e379c49d49 | ||
|
|
c8a907c828 | ||
|
|
3f4d4cb7a0 | ||
|
|
67e7bc55ea | ||
|
|
7834e67583 | ||
|
|
297d68f36c | ||
|
|
0e588bdeca | ||
|
|
1dac0e709a | ||
|
|
b209276e72 | ||
|
|
5726459629 | ||
|
|
0926316a76 | ||
|
|
3255e2e1b8 | ||
|
|
32f77dbf05 | ||
|
|
89d3d9b2ce | ||
|
|
77951647ce | ||
|
|
238d2a3876 | ||
|
|
fe9457daea | ||
|
|
174586bd51 | ||
|
|
cae43344ec | ||
|
|
18f07a48e8 | ||
|
|
37f2da03e1 | ||
|
|
45bc192625 | ||
|
|
a793d211d2 | ||
|
|
b4c51b2d39 | ||
|
|
9728270acd | ||
|
|
5d91c9a820 | ||
|
|
2ad7c4313d | ||
|
|
6376b78a80 | ||
|
|
a9f879c2ba | ||
|
|
b24191f9f9 | ||
|
|
3154302b53 | ||
|
|
61ed36e446 | ||
|
|
dd149a76f3 | ||
|
|
2dfd34b12d | ||
|
|
55655ba319 | ||
|
|
827dffb94c | ||
|
|
2d3f1ef520 | ||
|
|
0bdbb32f3b | ||
|
|
5dc718c54d | ||
|
|
5a2d760177 | ||
|
|
499d4aadbc | ||
|
|
216a04df86 | ||
|
|
3013b84e98 | ||
|
|
2d81df4760 | ||
|
|
180958185f | ||
|
|
ee6096cca8 | ||
|
|
3902dc963a | ||
|
|
0ba53edd96 | ||
|
|
ec19661312 | ||
|
|
d7fd6bac72 | ||
|
|
af1b0915f4 | ||
|
|
6afa091dca | ||
|
|
f4ed171397 | ||
|
|
2970333adb | ||
|
|
57f26a97fb | ||
|
|
4238875ebe | ||
|
|
684b9419a0 | ||
|
|
2aed59a02a | ||
|
|
9b461db4da | ||
|
|
184293c634 | ||
|
|
bc9e3b1843 | ||
|
|
30a4393afa | ||
|
|
aab7667cd5 | ||
|
|
833abbb191 | ||
|
|
e6d7534a88 | ||
|
|
db726ca294 | ||
|
|
7c68537b06 | ||
|
|
db9f68e651 | ||
|
|
66a1d63dd0 | ||
|
|
aba38d5586 | ||
|
|
1244e8d929 | ||
|
|
2e77a83816 | ||
|
|
dac617d95a | ||
|
|
88f7bb1ed5 | ||
|
|
ae73baf4ee | ||
|
|
0c6fe78a73 | ||
|
|
b8f52965a9 | ||
|
|
d52b7e3124 | ||
|
|
80bc7f0e25 | ||
|
|
5b7deee0cc | ||
|
|
3a6c98ff16 | ||
|
|
a09cf51b99 | ||
|
|
21a12a2f60 | ||
|
|
118a4f56ab | ||
|
|
34b6d37266 | ||
|
|
d6e56924fe | ||
|
|
ad3b62cf2f | ||
|
|
0e24709989 | ||
|
|
edb73ec480 | ||
|
|
02418cffd8 | ||
|
|
0bd0c65b87 | ||
|
|
b209dcf8a7 | ||
|
|
96a7bf2b90 | ||
|
|
604ed1fd9a | ||
|
|
9ad9b91efb | ||
|
|
404d5781fc | ||
|
|
52de57e2f6 | ||
|
|
4b83d62750 | ||
|
|
a541533e04 | ||
|
|
917a547f91 | ||
|
|
d448275713 | ||
|
|
4354ce21d1 | ||
|
|
dc5dd69f2e | ||
|
|
ea75e1c29c | ||
|
|
7f30e61402 | ||
|
|
3c86542a40 | ||
|
|
476197569f | ||
|
|
1e07f8c045 | ||
|
|
57c87088d4 | ||
|
|
f4b0756e70 | ||
|
|
a597b28001 | ||
|
|
5f74ec6782 | ||
|
|
e06553b15b | ||
|
|
84a65c7189 | ||
|
|
91c1ab6017 | ||
|
|
c77bce12e5 | ||
|
|
76004660e9 | ||
|
|
c1e6e4e65b | ||
|
|
b434243416 | ||
|
|
60e7dc1e39 | ||
|
|
de1d49865c | ||
|
|
cd6ad8571f | ||
|
|
86ed4ac603 | ||
|
|
8056aec93e | ||
|
|
dc9342f184 | ||
|
|
31bcf8cfa2 | ||
|
|
a416abb940 | ||
|
|
7b04ee6a9b | ||
|
|
a04b1cda45 | ||
|
|
b0abce9bc8 | ||
|
|
c6f58d432c | ||
|
|
abde7a2682 | ||
|
|
05b814ce68 | ||
|
|
ad49158fb5 | ||
|
|
266b032b17 | ||
|
|
7ce32619cc | ||
|
|
5b09a150bc | ||
|
|
e0084a6fdf | ||
|
|
b609a3610f | ||
|
|
6f62adedfc | ||
|
|
9fdf6474f8 | ||
|
|
beba2a25d0 | ||
|
|
e10d081a56 | ||
|
|
6cd7a4a400 | ||
|
|
5933056a5b | ||
|
|
d6d06c8cbb | ||
|
|
712a6d49d0 | ||
|
|
da168674f9 | ||
|
|
8d2504a809 | ||
|
|
be0c10e8f6 | ||
|
|
992fe6896f | ||
|
|
8d516d7f08 | ||
|
|
2dd979d3f8 | ||
|
|
a093dea38c | ||
|
|
9045575e62 | ||
|
|
9f82da07f1 | ||
|
|
53e820b466 | ||
|
|
cfaaf3c13c | ||
|
|
47ef917f62 | ||
|
|
a6e299a2fc | ||
|
|
ba5a43f2f9 | ||
|
|
f1d9d8a6ed | ||
|
|
647171e089 | ||
|
|
fd2efbc6f8 | ||
|
|
2d44400cfc | ||
|
|
673bef2fda | ||
|
|
94d54ebc29 | ||
|
|
44dc00a58c | ||
|
|
cd23c78800 | ||
|
|
01a4ab30dc | ||
|
|
c10a4cf6d2 | ||
|
|
e868ac41cd | ||
|
|
c5a5eaf288 | ||
|
|
ac98600640 | ||
|
|
7d524307d2 | ||
|
|
9101a1db3d | ||
|
|
2a1be57470 | ||
|
|
e439ace944 | ||
|
|
fae79b5812 | ||
|
|
bb29d18017 | ||
|
|
5929b629e5 | ||
|
|
76396041e2 | ||
|
|
64fbc93217 | ||
|
|
24b1e26406 | ||
|
|
961031bc28 | ||
|
|
ad453785f0 | ||
|
|
08bd4fa6a8 | ||
|
|
3900a739b9 | ||
|
|
55b2d124bc | ||
|
|
a964ea61cd | ||
|
|
c037f04d17 | ||
|
|
7c4e550e31 | ||
|
|
204f6bb503 | ||
|
|
6c4985476e | ||
|
|
9a92b58057 | ||
|
|
f8877e015b | ||
|
|
50c297bcbe | ||
|
|
6a36121a56 | ||
|
|
f9d82a6ac5 | ||
|
|
e567406c9f | ||
|
|
1ab4c9998a | ||
|
|
d6924f7680 | ||
|
|
76432b958b | ||
|
|
e46b2803a7 | ||
|
|
1cbf2510e7 | ||
|
|
8cc85f684b | ||
|
|
b5b7a27f9b | ||
|
|
06f60b57c1 | ||
|
|
37e8b027f9 | ||
|
|
ed248f7f5a | ||
|
|
90565cc44d | ||
|
|
9fb3ea3ce6 | ||
|
|
d63bca9d3c | ||
|
|
9b8ac2d404 | ||
|
|
65f1f74f2b | ||
|
|
43cec8eaac | ||
|
|
2103075ffa | ||
|
|
f939485b52 | ||
|
|
77957372ab | ||
|
|
33dc06ae21 | ||
|
|
d0458b824a | ||
|
|
45ee2060fa | ||
|
|
6919dda958 | ||
|
|
acdcb2ad8d | ||
|
|
edef6f929a | ||
|
|
62c6ed58ba | ||
|
|
ed3022adc1 | ||
|
|
3b6a424c9f | ||
|
|
9054bb69e9 | ||
|
|
5424c82423 | ||
|
|
3f3482f017 | ||
|
|
d5a24da167 | ||
|
|
030b570051 | ||
|
|
3a74f49182 | ||
|
|
748bd825e7 | ||
|
|
e6507a0f18 | ||
|
|
1864a9de38 | ||
|
|
a25d952ef9 | ||
|
|
9e1d4bfbf0 | ||
|
|
fde3b99e8e | ||
|
|
29620619b5 | ||
|
|
46cf5aa2a4 | ||
|
|
ee9176f20d | ||
|
|
1d11153396 | ||
|
|
7c373edf4d | ||
|
|
41fe435553 | ||
|
|
01cbe744b6 | ||
|
|
e32cd2dd15 | ||
|
|
39462c3a2e | ||
|
|
e9a6d5be51 | ||
|
|
fca53a56b4 | ||
|
|
a03249dd99 | ||
|
|
437dc3d713 | ||
|
|
ea076a8783 | ||
|
|
965cd92a72 | ||
|
|
204ebe607d | ||
|
|
267a49103e | ||
|
|
a42d74a238 | ||
|
|
f9c51c2478 | ||
|
|
776b82e6e8 | ||
|
|
8a002e98bc | ||
|
|
4fc62a8bf5 | ||
|
|
3bdcdfd114 | ||
|
|
f7769c17b5 | ||
|
|
76c9971c31 | ||
|
|
e46dcc0cc4 | ||
|
|
9dc8250956 | ||
|
|
3a910d8c8c | ||
|
|
e203271d95 | ||
|
|
6267e7a930 | ||
|
|
d76d37340a | ||
|
|
871912a00a | ||
|
|
628e7fa583 | ||
|
|
15643c802b | ||
|
|
814696c202 | ||
|
|
50070c9b0a | ||
|
|
06503cc11b | ||
|
|
daaafd86e2 | ||
|
|
9e52b6f2d1 | ||
|
|
fae8e38616 | ||
|
|
4cba7a4002 | ||
|
|
9712a92853 | ||
|
|
28eb441812 | ||
|
|
3c2a720b21 | ||
|
|
6478034e92 | ||
|
|
faf14197cd | ||
|
|
b63054cb1d | ||
|
|
4de125dd84 | ||
|
|
268b901048 | ||
|
|
136c3140c2 | ||
|
|
7e90103f21 | ||
|
|
d4fc064e44 | ||
|
|
623a7eee57 | ||
|
|
57943cad99 | ||
|
|
c5f79fd2f3 | ||
|
|
e212f2ae77 | ||
|
|
a39f51c044 | ||
|
|
8abf96cfd8 | ||
|
|
b0a598ba7b | ||
|
|
e269a3fad9 | ||
|
|
47c83f4c49 | ||
|
|
1635d459ec | ||
|
|
77db161aca | ||
|
|
b3667c72c7 | ||
|
|
e3b1d401fd | ||
|
|
ad7cd155fb | ||
|
|
882ce56cf4 | ||
|
|
29e1203609 | ||
|
|
a3011febdf | ||
|
|
6e28524647 | ||
|
|
c26e08d6a6 | ||
|
|
9376a6d75a | ||
|
|
8ad81a6aa3 | ||
|
|
c00b2ecc4b | ||
|
|
dd2fb27316 | ||
|
|
bc7eb792f4 | ||
|
|
abfa052861 | ||
|
|
dbfc8092d7 | ||
|
|
6137d301be | ||
|
|
af87552e04 | ||
|
|
94f5247f91 | ||
|
|
dee4ca37ab | ||
|
|
b24d711f55 | ||
|
|
50f0235654 | ||
|
|
cafab14f2b | ||
|
|
63251fb9d0 | ||
|
|
fc9de94cbd | ||
|
|
f9698598c6 | ||
|
|
d1afc78124 | ||
|
|
ebdd792b6f | ||
|
|
ca19a5cd6d | ||
|
|
20145092ce | ||
|
|
5718f812d9 | ||
|
|
fe6498e7c8 | ||
|
|
5358fb3cce | ||
|
|
9449235765 | ||
|
|
a4739b0107 | ||
|
|
bdd15cfe63 | ||
|
|
26631bf9e6 | ||
|
|
551c69ed56 | ||
|
|
2b2ebfc254 | ||
|
|
fd121f371a | ||
|
|
c5da7306bd | ||
|
|
2bf0ec719d | ||
|
|
7e388e697d | ||
|
|
0726dcd06c | ||
|
|
c84b21008e | ||
|
|
6b9a8b7b19 | ||
|
|
e728e2aa81 | ||
|
|
2096c18e57 | ||
|
|
2cebbead75 | ||
|
|
a2ddcc124f | ||
|
|
82f9b6908c | ||
|
|
731d283159 | ||
|
|
1d85fd35a2 | ||
|
|
b4b8cb57b3 | ||
|
|
3294d704a4 | ||
|
|
f926e27a65 | ||
|
|
c31d6608a8 | ||
|
|
cd0b70dbc1 | ||
|
|
0e6b80ded3 | ||
|
|
19e7cf5f4a | ||
|
|
0200b1d784 | ||
|
|
6b717a6a69 | ||
|
|
925aacec1a | ||
|
|
bb8d377b91 | ||
|
|
f7176e7aef | ||
|
|
ef0385a25c | ||
|
|
5675f328b6 | ||
|
|
63ca11fc7d | ||
|
|
4a6f509aa5 | ||
|
|
d010c5a581 | ||
|
|
e1822c2b66 | ||
|
|
cd42ee7e85 | ||
|
|
6d72800098 | ||
|
|
2b58d6b774 | ||
|
|
7e2caa0bb1 | ||
|
|
51ecd6be15 | ||
|
|
7601e10b6a | ||
|
|
4210096a6f | ||
|
|
f642da201d | ||
|
|
0a0455b8d2 | ||
|
|
529b2f6613 | ||
|
|
f9f7c46751 | ||
|
|
8a119dc970 | ||
|
|
b75e88f65f | ||
|
|
1194c47c5d | ||
|
|
a55d1df585 | ||
|
|
0337a7b866 | ||
|
|
5f1e9e80c2 | ||
|
|
c5715bc756 | ||
|
|
e4a17fedc6 | ||
|
|
ee96a08700 | ||
|
|
4526c3f712 | ||
|
|
eefef44378 | ||
|
|
d7d96806a4 | ||
|
|
5e834e8119 | ||
|
|
cbabab273f | ||
|
|
0bd16b521c | ||
|
|
07d92acfd0 | ||
|
|
ef1f17fc2a | ||
|
|
5081477e95 | ||
|
|
f094918cf6 | ||
|
|
c94d9994d8 | ||
|
|
f6432fdf48 | ||
|
|
4fc4f91b9e | ||
|
|
9ab996d9e6 | ||
|
|
3cf5fe8795 | ||
|
|
94d3f50aee | ||
|
|
3dc30b6b8f | ||
|
|
8439efe77d | ||
|
|
a1098fa153 | ||
|
|
0b81fbd590 | ||
|
|
f92fe73d03 | ||
|
|
4f2095ea00 | ||
|
|
d9ed2a0fae | ||
|
|
4d6b5e70df | ||
|
|
a647a4f6b3 | ||
|
|
2821be2bce | ||
|
|
0ff11ac978 | ||
|
|
5a235ffbf9 | ||
|
|
642f7f850d | ||
|
|
1adf5f2863 | ||
|
|
3ee673ac91 | ||
|
|
20f8dd6565 | ||
|
|
940737a958 | ||
|
|
1350987e2e | ||
|
|
dc31a3d7d6 | ||
|
|
dcfcceb6f2 | ||
|
|
d24c4f349f | ||
|
|
c85e78ac3c | ||
|
|
7ddf586da7 | ||
|
|
4e9e3cf0d5 | ||
|
|
5bea746fa8 | ||
|
|
5c8e56e8d2 | ||
|
|
6f0f8cd6c7 | ||
|
|
2a32af084f | ||
|
|
6f76c8b59d | ||
|
|
88411fb1ca | ||
|
|
3302067aad | ||
|
|
0a2c51510c | ||
|
|
c79b9a2289 | ||
|
|
8cfe72c683 | ||
|
|
9ef224fceb | ||
|
|
af67f15cf2 | ||
|
|
e338931ffa | ||
|
|
502f26299b | ||
|
|
8a273eef20 | ||
|
|
fa080328cf | ||
|
|
fa3457f391 | ||
|
|
aa27c45230 | ||
|
|
f321c3c2ea | ||
|
|
9bb648739b | ||
|
|
3287ecc8d3 | ||
|
|
1e89540c3f | ||
|
|
5a3a3420e3 | ||
|
|
8ae1328e71 | ||
|
|
6f61b4488e | ||
|
|
474c8bef0a | ||
|
|
7aa1e02d06 | ||
|
|
b41c6824c5 | ||
|
|
05006f687a | ||
|
|
1ea876296d | ||
|
|
55894f02c7 | ||
|
|
32dacb9369 | ||
|
|
d6423bbbc8 | ||
|
|
1442ca16b4 | ||
|
|
1a1b992858 | ||
|
|
a452a3b1a0 | ||
|
|
3c5383b11c | ||
|
|
77190c9a87 | ||
|
|
75d45dace9 | ||
|
|
b604630a74 | ||
|
|
9deff7afaf | ||
|
|
4e682f3d88 | ||
|
|
196df7d8a4 | ||
|
|
98b65763b0 | ||
|
|
aefaef3ead | ||
|
|
be15ab47dc | ||
|
|
bc1d667784 | ||
|
|
395c2cc075 | ||
|
|
a6c03e3127 | ||
|
|
6080f6673e | ||
|
|
fab08278ea | ||
|
|
6b147175bb | ||
|
|
503c05b749 | ||
|
|
1303943424 | ||
|
|
8cf0628f28 | ||
|
|
c48a9191c8 | ||
|
|
38f977d2f3 | ||
|
|
45861c6d9c | ||
|
|
8abc2d3b8d | ||
|
|
0da7512597 | ||
|
|
13c331fa81 | ||
|
|
62596d462b | ||
|
|
f35ea45e09 | ||
|
|
72015d499f | ||
|
|
3755faf558 | ||
|
|
ff6969302b | ||
|
|
d7fd507d99 | ||
|
|
4c2bbf2354 | ||
|
|
22dbeaef29 | ||
|
|
9720fd8250 | ||
|
|
f6df1f1dd3 | ||
|
|
286b54e527 | ||
|
|
a4af51b5ba | ||
|
|
dcfb813066 | ||
|
|
fe9dc8e901 | ||
|
|
284705eeb8 | ||
|
|
ec4e432d55 | ||
|
|
8c933a6c06 | ||
|
|
325199b5e6 | ||
|
|
80bf185ad5 | ||
|
|
19bf975e56 | ||
|
|
1227d2d710 | ||
|
|
bece816ec7 | ||
|
|
7fdf2f50f4 | ||
|
|
746e658f3e | ||
|
|
caa0dd549e | ||
|
|
49cf19ccfe | ||
|
|
6abcc24834 | ||
|
|
fd53bb404f | ||
|
|
dceb67c247 | ||
|
|
b3e299b931 | ||
|
|
818e895af1 | ||
|
|
7e65f4f6ea | ||
|
|
8fac7a9f6c | ||
|
|
f25e5e3860 | ||
|
|
1cc96cd334 | ||
|
|
4e26527447 | ||
|
|
c214aa5149 | ||
|
|
48f8f3f5cf | ||
|
|
0b09e4bfcb | ||
|
|
4eab52ee75 | ||
|
|
b8e4f41987 | ||
|
|
f7553d73a2 | ||
|
|
b0e767eaf1 | ||
|
|
82ef687730 | ||
|
|
7e6ba94241 | ||
|
|
46a41f48ca | ||
|
|
86a8f4c5c7 | ||
|
|
afbb3ec37a | ||
|
|
d0ef37a487 | ||
|
|
611e5ab421 | ||
|
|
38729133e2 | ||
|
|
ce0b221573 | ||
|
|
95b61a5e12 | ||
|
|
3bbb748a08 | ||
|
|
9a843548c0 | ||
|
|
220a13b87f | ||
|
|
4b8301d39e | ||
|
|
0854a84eb9 | ||
|
|
ce91f1c0e6 | ||
|
|
060dbe1b56 | ||
|
|
b9d4a9c9f9 | ||
|
|
325e784ccd | ||
|
|
0d577584c3 | ||
|
|
27bc654b5b | ||
|
|
c1e3cfe7a7 | ||
|
|
96099807e1 | ||
|
|
b639a25856 | ||
|
|
0e6c83e521 | ||
|
|
987232a0a6 | ||
|
|
b54710950f | ||
|
|
d061e1065e | ||
|
|
0590f2975e | ||
|
|
5471c65c9a | ||
|
|
e299583eee | ||
|
|
8ac8e2e734 | ||
|
|
5b940f255f | ||
|
|
c05e9b118c | ||
|
|
45dc76de26 | ||
|
|
0dfe39ac87 | ||
|
|
27480d8e8e | ||
|
|
176bde269f | ||
|
|
df2cc09362 | ||
|
|
042cb1604a | ||
|
|
0acf3e0e30 | ||
|
|
4ad7e8f459 | ||
|
|
d445e0c877 | ||
|
|
e64ac4c418 | ||
|
|
94e19e1ac6 | ||
|
|
a254f38a23 | ||
|
|
52e0ce8b06 | ||
|
|
b039d960f5 | ||
|
|
66df043c19 | ||
|
|
8fbdb4b9ac | ||
|
|
0deaf6c50c | ||
|
|
3dce6d9f6a | ||
|
|
9aa59c7f62 | ||
|
|
7ba7f43199 | ||
|
|
c31c2d10b9 | ||
|
|
5a8f24eb46 | ||
|
|
59763ceecb | ||
|
|
282f4d6a89 | ||
|
|
6cdedf6049 | ||
|
|
61aa71ed34 | ||
|
|
901a825b61 | ||
|
|
75f35bcfe7 | ||
|
|
406b6148f5 | ||
|
|
f7b41625e5 | ||
|
|
0168fddae5 | ||
|
|
ef780d5034 | ||
|
|
6862184956 | ||
|
|
2b181b40f7 | ||
|
|
4c457c82ef | ||
|
|
3f8a519980 | ||
|
|
fb03fc073a | ||
|
|
2b93643277 | ||
|
|
396f1e92ca | ||
|
|
c60b6bdb38 | ||
|
|
9c83ddc122 | ||
|
|
b6b9036821 | ||
|
|
dc0b62f636 | ||
|
|
9102429a13 | ||
|
|
1fcb7afd3a | ||
|
|
fe14c64e5e | ||
|
|
107ca92458 | ||
|
|
9a8ccbaef2 | ||
|
|
d0347bb98f | ||
|
|
3fcb79bc1e | ||
|
|
41da1d6403 | ||
|
|
41baba9ed3 | ||
|
|
2f86cd8602 | ||
|
|
a1061c7145 | ||
|
|
2a0a0287d4 |
43
.env
Normal file
43
.env
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
# In all environments, the following files are loaded if they exist,
|
||||||
|
# the latter taking precedence over the former:
|
||||||
|
#
|
||||||
|
# * .env contains default values for the environment variables needed by the app
|
||||||
|
# * .env.local uncommitted file with local overrides
|
||||||
|
# * .env.$APP_ENV committed environment-specific defaults
|
||||||
|
# * .env.$APP_ENV.local uncommitted environment-specific overrides
|
||||||
|
#
|
||||||
|
# Real environment variables win over .env files.
|
||||||
|
#
|
||||||
|
# DO NOT DEFINE PRODUCTION SECRETS IN THIS FILE NOR IN ANY OTHER COMMITTED FILES.
|
||||||
|
#
|
||||||
|
# Run "composer dump-env prod" to compile .env files for production use (requires symfony/flex >=1.2).
|
||||||
|
# https://symfony.com/doc/current/best_practices.html#use-environment-variables-for-infrastructure-configuration
|
||||||
|
|
||||||
|
###> symfony/framework-bundle ###
|
||||||
|
APP_ENV=dev
|
||||||
|
APP_SECRET=6a9ac3a09c73230107373e8e0b71e0a3
|
||||||
|
#TRUSTED_PROXIES=127.0.0.0/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16
|
||||||
|
#TRUSTED_HOSTS='^(localhost|example\.com)$'
|
||||||
|
###< symfony/framework-bundle ###
|
||||||
|
|
||||||
|
###> symfony/mailer ###
|
||||||
|
# MAILER_DSN=smtp://localhost
|
||||||
|
###< symfony/mailer ###
|
||||||
|
|
||||||
|
###> doctrine/doctrine-bundle ###
|
||||||
|
# Format described at https://www.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#connecting-using-a-url
|
||||||
|
# For an SQLite database, use: "sqlite:///%kernel.project_dir%/var/data.db"
|
||||||
|
# For a PostgreSQL database, use: "postgresql://db_user:db_password@127.0.0.1:5432/db_name?serverVersion=11&charset=utf8"
|
||||||
|
# IMPORTANT: You MUST configure your server version, either here or in config/packages/doctrine.yaml
|
||||||
|
DATABASE_URL=postgresql://postgres:foobar@postgres:5432/social
|
||||||
|
#?serverVersion=11&charset=utf8
|
||||||
|
###< doctrine/doctrine-bundle ###
|
||||||
|
|
||||||
|
SHELL_VERBOSITY=3
|
||||||
|
###> symfony/messenger ###
|
||||||
|
# Choose one of the transports below
|
||||||
|
# MESSENGER_TRANSPORT_DSN=amqp://guest:guest@localhost:5672/%2f/messages
|
||||||
|
MESSENGER_TRANSPORT_DSN_HIGH=doctrine://default?queue_name=high
|
||||||
|
MESSENGER_TRANSPORT_DSN_LOW=doctrine://default?queue_name=low
|
||||||
|
# MESSENGER_TRANSPORT_DSN=redis://localhost:6379/messages
|
||||||
|
###< symfony/messenger ###
|
||||||
6
.env.test
Normal file
6
.env.test
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
# define your env variables for the test env here
|
||||||
|
KERNEL_CLASS='App\Kernel'
|
||||||
|
APP_SECRET='$ecretf0rt3st'
|
||||||
|
SYMFONY_DEPRECATIONS_HELPER=999999
|
||||||
|
PANTHER_APP_ENV=panther
|
||||||
|
DATABASE_URL=postgresql://postgres:password@db:5432/social
|
||||||
93
.gitignore
vendored
93
.gitignore
vendored
@@ -1,32 +1,63 @@
|
|||||||
avatar/*
|
|
||||||
background/*
|
|
||||||
files/*
|
|
||||||
file/*
|
|
||||||
local/*
|
|
||||||
_darcs/*
|
|
||||||
logs/*
|
|
||||||
log/*
|
|
||||||
run/*
|
|
||||||
config.php
|
|
||||||
.htaccess
|
|
||||||
httpd.conf
|
|
||||||
*.tmproj
|
|
||||||
dataobject.ini
|
|
||||||
*~
|
|
||||||
*.bak
|
|
||||||
*.orig
|
|
||||||
*.rej
|
|
||||||
.#*
|
|
||||||
*.swp
|
|
||||||
.buildpath
|
|
||||||
.project
|
|
||||||
.settings
|
|
||||||
TODO.rym
|
|
||||||
config-*.php
|
|
||||||
good-config.php
|
|
||||||
lac08.log
|
|
||||||
php.log
|
|
||||||
.DS_Store
|
|
||||||
nbproject
|
|
||||||
*.mo
|
|
||||||
|
|
||||||
|
###> symfony/framework-bundle ###
|
||||||
|
/.env.local
|
||||||
|
/.env.local.php
|
||||||
|
/.env.*.local
|
||||||
|
/config/secrets/prod/prod.decrypt.private.php
|
||||||
|
/public/bundles/
|
||||||
|
/var/
|
||||||
|
/vendor/
|
||||||
|
###< symfony/framework-bundle ###
|
||||||
|
|
||||||
|
###> symfony/phpunit-bridge ###
|
||||||
|
.phpunit
|
||||||
|
.phpunit.result.cache
|
||||||
|
/phpunit.xml
|
||||||
|
###< symfony/phpunit-bridge ###
|
||||||
|
|
||||||
|
###> friendsofphp/php-cs-fixer ###
|
||||||
|
!.php_cs
|
||||||
|
/.php_cs.cache
|
||||||
|
###< friendsofphp/php-cs-fixer ###
|
||||||
|
|
||||||
|
###> phpunit/phpunit ###
|
||||||
|
/phpunit.xml
|
||||||
|
.phpunit.result.cache
|
||||||
|
###< phpunit/phpunit ###
|
||||||
|
|
||||||
|
|
||||||
|
DOCUMENTATION/database/*
|
||||||
|
!DOCUMENTATION/database/database.pdf
|
||||||
|
|
||||||
|
docker/certbot/.files
|
||||||
|
docker/certbot/www
|
||||||
|
docker/*/*.env
|
||||||
|
|
||||||
|
docker/mail/etc/hostname
|
||||||
|
docker/mail/etc/hosts
|
||||||
|
docker/mail/etc/resolv.conf
|
||||||
|
docker/mail/config/aliases.db
|
||||||
|
docker/mail/config/domains.db
|
||||||
|
docker/mail/config/mailboxes.db
|
||||||
|
docker/mail/config/passwd.db
|
||||||
|
docker/mail/etc/service/*
|
||||||
|
!docker/mail/etc/service/*/run
|
||||||
|
|
||||||
|
!docker/testing/*
|
||||||
|
!docker/testing/docker-compose.yaml
|
||||||
|
docker/testing/*~
|
||||||
|
|
||||||
|
docker-compose.yaml
|
||||||
|
composer.local.json
|
||||||
|
|
||||||
|
social.local.yaml
|
||||||
|
|
||||||
|
# V2
|
||||||
|
config.php
|
||||||
|
/file
|
||||||
|
|
||||||
|
notes
|
||||||
|
|
||||||
|
|
||||||
|
.test_coverage_report
|
||||||
|
.phpunit_cache
|
||||||
278
.php_cs
Normal file
278
.php_cs
Normal file
@@ -0,0 +1,278 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This document has been generated with
|
||||||
|
* https://mlocati.github.io/php-cs-fixer-configurator/#version:2.16.1|configurator
|
||||||
|
* you can change this configuration by importing this file.
|
||||||
|
*/
|
||||||
|
return PhpCsFixer\Config::create()
|
||||||
|
->setRiskyAllowed(true)
|
||||||
|
->setRules([
|
||||||
|
// Each line of multi-line DocComments must have an asterisk [PSR-5] and must be aligned with the first one.
|
||||||
|
'align_multiline_comment' => ['comment_type' => 'phpdocs_like'],
|
||||||
|
// PHP arrays should be declared using the configured syntax.
|
||||||
|
'array_syntax' => ['syntax' => 'short'],
|
||||||
|
// Binary operators should be surrounded by space as configured.
|
||||||
|
'binary_operator_spaces' => [
|
||||||
|
'default' => 'align_single_space_minimal',
|
||||||
|
'operators' => ['??' => 'align'],
|
||||||
|
],
|
||||||
|
// There MUST be one blank line after the namespace declaration.
|
||||||
|
'blank_line_after_namespace' => true,
|
||||||
|
// Each element of an array must be indented exactly once.
|
||||||
|
'array_indentation' => true,
|
||||||
|
// Ensure there is no code on the same line as the PHP open tag and it is followed by a blank line.
|
||||||
|
'blank_line_after_opening_tag' => false,
|
||||||
|
// The body of each structure MUST be enclosed by braces. Braces should be properly placed. Body of braces should be properly indented.
|
||||||
|
'braces' => ['allow_single_line_closure' => true, 'position_after_functions_and_oop_constructs' => 'next',
|
||||||
|
// 'allow_single_line_functions' => true, // Awaiting PR merge...
|
||||||
|
],
|
||||||
|
// A single space or none should be between cast and variable.
|
||||||
|
'cast_spaces' => true,
|
||||||
|
// Class, trait and interface elements must be separated with one blank line.
|
||||||
|
'class_attributes_separation' => false,
|
||||||
|
// Whitespace around the keywords of a class, trait or interfaces definition should be one space.
|
||||||
|
'class_definition' => ['single_item_single_line' => true, 'single_line' => true],
|
||||||
|
// Using `isset($var) &&` multiple times should be done in one call.
|
||||||
|
'combine_consecutive_issets' => true,
|
||||||
|
// Calling `unset` on multiple items should be done in one call.
|
||||||
|
'combine_consecutive_unsets' => true,
|
||||||
|
// Remove extra spaces in a nullable typehint.
|
||||||
|
'compact_nullable_typehint' => true,
|
||||||
|
// Concatenation should be spaced according configuration.
|
||||||
|
'concat_space' => ['spacing' => 'one'],
|
||||||
|
// The PHP constants `true`, `false`, and `null` MUST be written using the correct casing.
|
||||||
|
'constant_case' => true,
|
||||||
|
// Equal sign in declare statement should be surrounded by spaces or not following configuration.
|
||||||
|
'declare_equal_normalize' => ['space' => 'single'],
|
||||||
|
// Replaces `dirname(__FILE__)` expression with equivalent `__DIR__` constant.
|
||||||
|
'dir_constant' => true,
|
||||||
|
// PHP code MUST use only UTF-8 without BOM (remove BOM).
|
||||||
|
'encoding' => true,
|
||||||
|
// Replace deprecated `ereg` regular expression functions with `preg`.
|
||||||
|
'ereg_to_preg' => true,
|
||||||
|
// Escape implicit backslashes in strings and heredocs to ease the understanding of which are special chars interpreted by PHP and which not.
|
||||||
|
'escape_implicit_backslashes' => true,
|
||||||
|
// Add curly braces to indirect variables to make them clear to understand. Requires PHP >= 7.0.
|
||||||
|
'explicit_indirect_variable' => true,
|
||||||
|
// Converts implicit variables into explicit ones in double-quoted strings or heredoc syntax.
|
||||||
|
'explicit_string_variable' => true,
|
||||||
|
// PHP code must use the long `<?php` tags or short-echo `<?=` tags and not other tag variations.
|
||||||
|
'full_opening_tag' => true,
|
||||||
|
// Transforms imported FQCN parameters and return types in function arguments to short version.
|
||||||
|
'fully_qualified_strict_types' => true,
|
||||||
|
// Spaces should be properly placed in a function declaration.
|
||||||
|
'function_declaration' => ['closure_function_spacing' => 'one'],
|
||||||
|
// Ensure single space between function's argument and its typehint.
|
||||||
|
'function_typehint_space' => true,
|
||||||
|
// Pre- or post-increment and decrement operators should be used if possible.
|
||||||
|
'increment_style' => true,
|
||||||
|
// Code MUST use configured indentation type.
|
||||||
|
'indentation_type' => true,
|
||||||
|
// All PHP files must use same line ending.
|
||||||
|
'line_ending' => true,
|
||||||
|
// Use `&&` and `||` logical operators instead of `and` and `or`.
|
||||||
|
'logical_operators' => true,
|
||||||
|
// PHP keywords MUST be in lower case.
|
||||||
|
'lowercase_keywords' => true,
|
||||||
|
// Class static references `self`, `static` and `parent` MUST be in lower case.
|
||||||
|
'lowercase_static_reference' => true,
|
||||||
|
// Magic constants should be referred to using the correct casing.
|
||||||
|
'magic_constant_casing' => true,
|
||||||
|
// Magic method definitions and calls must be using the correct casing.
|
||||||
|
'magic_method_casing' => true,
|
||||||
|
// Replaces `intval`, `floatval`, `doubleval`, `strval` and `boolval` function calls with according type casting operator.
|
||||||
|
'modernize_types_casting' => true,
|
||||||
|
// DocBlocks must start with two asterisks, multiline comments must start with a single asterisk, after the opening slash. Both must end with a single asterisk before the closing slash.
|
||||||
|
'multiline_comment_opening_closing' => true,
|
||||||
|
// Forbid multi-line whitespace before the closing semicolon or move the semicolon to the new line for chained calls.
|
||||||
|
'multiline_whitespace_before_semicolons' => true,
|
||||||
|
// Add leading `\` before constant invocation of internal constant to speed up resolving. Constant name match is case-sensitive, except for `null`, `false` and `true`.
|
||||||
|
'native_constant_invocation' => false,
|
||||||
|
// Function defined by PHP should be called using the correct casing.
|
||||||
|
'native_function_casing' => true,
|
||||||
|
// Add leading `\` before function invocation to speed up resolving.
|
||||||
|
'native_function_invocation' => false,
|
||||||
|
// Native type hints for functions should use the correct case.
|
||||||
|
'native_function_type_declaration_casing' => true,
|
||||||
|
// There should be no empty lines after class opening brace.
|
||||||
|
'no_blank_lines_after_class_opening' => true,
|
||||||
|
// There should not be blank lines between docblock and the documented element.
|
||||||
|
'no_blank_lines_after_phpdoc' => true,
|
||||||
|
// There must be a comment when fall-through is intentional in a non-empty case body.
|
||||||
|
'no_break_comment' => true,
|
||||||
|
// The closing `? >` tag MUST be omitted from files containing only PHP.
|
||||||
|
'no_closing_tag' => true,
|
||||||
|
// There should not be any empty comments.
|
||||||
|
'no_empty_comment' => true,
|
||||||
|
// There should not be empty PHPDoc blocks.
|
||||||
|
'no_empty_phpdoc' => true,
|
||||||
|
// Remove useless semicolon statements.
|
||||||
|
'no_empty_statement' => true,
|
||||||
|
// Removes extra blank lines and/or blank lines following configuration.
|
||||||
|
'no_extra_blank_lines' => true,
|
||||||
|
// Remove leading slashes in `use` clauses.
|
||||||
|
'no_leading_import_slash' => true,
|
||||||
|
// The namespace declaration line shouldn't contain leading whitespace.
|
||||||
|
'no_leading_namespace_whitespace' => true,
|
||||||
|
// Either language construct `print` or `echo` should be used.
|
||||||
|
'no_mixed_echo_print' => true,
|
||||||
|
// Operator `=>` should not be surrounded by multi-line whitespaces.
|
||||||
|
'no_multiline_whitespace_around_double_arrow' => true,
|
||||||
|
// Properties MUST not be explicitly initialized with `null` except when they have a type declaration (PHP 7.4).
|
||||||
|
'no_null_property_initialization' => true,
|
||||||
|
// Short cast `bool` using double exclamation mark should not be used.
|
||||||
|
'no_short_bool_cast' => true,
|
||||||
|
// Replace short-echo `<?=` with long format `<?php echo` syntax.
|
||||||
|
'no_short_echo_tag' => true,
|
||||||
|
// Single-line whitespace before closing semicolon are prohibited.
|
||||||
|
'no_singleline_whitespace_before_semicolons' => true,
|
||||||
|
// When making a method or function call, there MUST NOT be a space between the method or function name and the opening parenthesis.
|
||||||
|
'no_spaces_after_function_name' => true,
|
||||||
|
// There MUST NOT be spaces around offset braces.
|
||||||
|
'no_spaces_around_offset' => true,
|
||||||
|
// There MUST NOT be a space after the opening parenthesis. There MUST NOT be a space before the closing parenthesis.
|
||||||
|
'no_spaces_inside_parenthesis' => true,
|
||||||
|
// Replaces superfluous `elseif` with `if`.
|
||||||
|
'no_superfluous_elseif' => false,
|
||||||
|
// Remove trailing commas in list function calls.
|
||||||
|
'no_trailing_comma_in_list_call' => true,
|
||||||
|
// PHP single-line arrays should not have trailing comma.
|
||||||
|
'no_trailing_comma_in_singleline_array' => true,
|
||||||
|
// Remove trailing whitespace at the end of non-blank lines.
|
||||||
|
'no_trailing_whitespace' => true,
|
||||||
|
// There MUST be no trailing spaces inside comment or PHPDoc.
|
||||||
|
'no_trailing_whitespace_in_comment' => true,
|
||||||
|
// Removes unneeded parentheses around control statements.
|
||||||
|
'no_unneeded_control_parentheses' => true,
|
||||||
|
// Removes unneeded curly braces that are superfluous and aren't part of a control structure's body.
|
||||||
|
'no_unneeded_curly_braces' => true,
|
||||||
|
// In function arguments there must not be arguments with default values before non-default ones.
|
||||||
|
'no_unreachable_default_argument_value' => true,
|
||||||
|
// Variables must be set `null` instead of using `(unset)` casting.
|
||||||
|
'no_unset_cast' => false,
|
||||||
|
// Properties should be set to `null` instead of using `unset`.
|
||||||
|
'no_unset_on_property' => true,
|
||||||
|
// Unused `use` statements must be removed.
|
||||||
|
'no_unused_imports' => true,
|
||||||
|
// There should not be useless `else` cases.
|
||||||
|
'no_useless_else' => false,
|
||||||
|
// There should not be an empty `return` statement at the end of a function.
|
||||||
|
'no_useless_return' => true,
|
||||||
|
// In array declaration, there MUST NOT be a whitespace before each comma.
|
||||||
|
'no_whitespace_before_comma_in_array' => true,
|
||||||
|
// Remove trailing whitespace at the end of blank lines.
|
||||||
|
'no_whitespace_in_blank_line' => true,
|
||||||
|
// Remove Zero-width space (ZWSP), Non-breaking space (NBSP) and other invisible unicode symbols.
|
||||||
|
'non_printable_character' => true,
|
||||||
|
// Array index should always be written by using square braces.
|
||||||
|
'normalize_index_brace' => true,
|
||||||
|
// There should not be space before or after object `T_OBJECT_OPERATOR` `->`.
|
||||||
|
'object_operator_without_whitespace' => true,
|
||||||
|
// Ordering `use` statements.
|
||||||
|
'ordered_imports' => true,
|
||||||
|
// Orders the elements of classes/interfaces/traits.
|
||||||
|
'ordered_class_elements' => false,
|
||||||
|
// PHPUnit assertion method calls like `->assertSame(true, $foo)` should be written with dedicated method like `->assertTrue($foo)`.
|
||||||
|
'php_unit_construct' => true,
|
||||||
|
// PHPUnit annotations should be a FQCNs including a root namespace.
|
||||||
|
'php_unit_fqcn_annotation' => true,
|
||||||
|
// Enforce camel (or snake) case for PHPUnit test methods, following configuration.
|
||||||
|
'php_unit_method_casing' => true,
|
||||||
|
// Usage of PHPUnit's mock e.g. `->will($this->returnValue(..))` must be replaced by its shorter equivalent such as `->willReturn(...)`.
|
||||||
|
'php_unit_mock_short_will_return' => true,
|
||||||
|
// Order `@covers` annotation of PHPUnit tests.
|
||||||
|
'php_unit_ordered_covers' => true,
|
||||||
|
// Changes the visibility of the `setUp()` and `tearDown()` functions of PHPUnit to `protected`, to match the PHPUnit TestCase.
|
||||||
|
'php_unit_set_up_tear_down_visibility' => true,
|
||||||
|
// PHPUnit methods like `assertSame` should be used instead of `assertEquals`.
|
||||||
|
'php_unit_strict' => true,
|
||||||
|
// Calls to `PHPUnit\Framework\TestCase` static methods must all be of the same type, either `$this->`, `self::` or `static::`.
|
||||||
|
'php_unit_test_case_static_method_calls' => true,
|
||||||
|
// PHPDoc should contain `@param` for all params.
|
||||||
|
'phpdoc_add_missing_param_annotation' => true,
|
||||||
|
// All items of the given phpdoc tags must be either left-aligned or (by default) aligned vertically.
|
||||||
|
'phpdoc_align' => true,
|
||||||
|
// Docblocks should have the same indentation as the documented subject.
|
||||||
|
'phpdoc_indent' => true,
|
||||||
|
// Fix PHPDoc inline tags, make `@inheritdoc` always inline.
|
||||||
|
'phpdoc_inline_tag' => true,
|
||||||
|
// `@access` annotations should be omitted from PHPDoc.
|
||||||
|
'phpdoc_no_access' => true,
|
||||||
|
// No alias PHPDoc tags should be used.
|
||||||
|
'phpdoc_no_alias_tag' => true,
|
||||||
|
// Annotations in PHPDoc should be ordered so that `@param` annotations come first, then `@throws` annotations, then `@return` annotations.
|
||||||
|
'phpdoc_order' => true,
|
||||||
|
// The type of `@return` annotations of methods returning a reference to itself must the configured one.
|
||||||
|
'phpdoc_return_self_reference' => true,
|
||||||
|
// Scalar types should always be written in the same form. `int` not `integer`, `bool` not `boolean`, `float` not `real` or `double`.
|
||||||
|
'phpdoc_scalar' => true,
|
||||||
|
// Annotations in PHPDoc should be grouped together so that annotations of the same type immediately follow each other, and annotations of a different type are separated by a single blank line.
|
||||||
|
'phpdoc_separation' => true,
|
||||||
|
// Single line `@var` PHPDoc should have proper spacing.
|
||||||
|
'phpdoc_single_line_var_spacing' => false,
|
||||||
|
// Removes extra blank lines after summary and after description in PHPDoc.
|
||||||
|
'phpdoc_trim_consecutive_blank_line_separation' => true,
|
||||||
|
// The correct case must be used for standard PHP types in PHPDoc.
|
||||||
|
'phpdoc_types' => true,
|
||||||
|
// Sorts PHPDoc types.
|
||||||
|
'phpdoc_types_order' => true,
|
||||||
|
// `@var` and `@type` annotations must have type and name in the correct order.
|
||||||
|
'phpdoc_var_annotation_correct_order' => true,
|
||||||
|
// Class names should match the file name.
|
||||||
|
'psr4' => true,
|
||||||
|
// There should be one or no space before colon, and one space after it in return type declarations, according to configuration.
|
||||||
|
'return_type_declaration' => true,
|
||||||
|
// Inside class or interface element `self` should be preferred to the class name itself.
|
||||||
|
'self_accessor' => true,
|
||||||
|
// Instructions must be terminated with a semicolon.
|
||||||
|
'semicolon_after_instruction' => true,
|
||||||
|
// Cast shall be used, not `settype`.
|
||||||
|
'set_type_to_cast' => true,
|
||||||
|
// Cast `(boolean)` and `(integer)` should be written as `(bool)` and `(int)`, `(double)` and `(real)` as `(float)`, `(binary)` as `(string)`.
|
||||||
|
'short_scalar_cast' => true,
|
||||||
|
// Converts explicit variables in double-quoted strings and heredoc syntax from simple to complex format (`${` to `{$`).
|
||||||
|
'simple_to_complex_string_variable' => true,
|
||||||
|
// There should be exactly one blank line before a namespace declaration.
|
||||||
|
'single_blank_line_before_namespace' => true,
|
||||||
|
// There MUST be one use keyword per declaration.
|
||||||
|
'single_import_per_statement' => true,
|
||||||
|
// There MUST NOT be more than one property or constant declared per statement.
|
||||||
|
'single_class_element_per_statement' => true,
|
||||||
|
// Each namespace use MUST go on its own line and there MUST be one blank line after the use statements block.
|
||||||
|
'single_line_after_imports' => true,
|
||||||
|
// Single-line comments and multi-line comments with only one line of actual content should use the `//` syntax.
|
||||||
|
'single_line_comment_style' => true,
|
||||||
|
// Convert double quotes to single quotes for simple strings.
|
||||||
|
'single_quote' => true,
|
||||||
|
// Each trait `use` must be done as single statement.
|
||||||
|
'single_trait_insert_per_statement' => true,
|
||||||
|
// Fix whitespace after a semicolon.
|
||||||
|
'space_after_semicolon' => true,
|
||||||
|
// Increment and decrement operators should be used if possible.
|
||||||
|
'standardize_increment' => true,
|
||||||
|
// Replace all `<>` with `!=`.
|
||||||
|
'standardize_not_equals' => true,
|
||||||
|
// A case should be followed by a colon and not a semicolon.
|
||||||
|
'switch_case_semicolon_to_colon' => true,
|
||||||
|
// Removes extra spaces between colon and case value.
|
||||||
|
'switch_case_space' => true,
|
||||||
|
// Standardize spaces around ternary operator.
|
||||||
|
'ternary_operator_spaces' => true,
|
||||||
|
// PHP multi-line arrays should have a trailing comma.
|
||||||
|
'trailing_comma_in_multiline_array' => true,
|
||||||
|
// Unary operators should be placed adjacent to their operands.
|
||||||
|
'unary_operator_spaces' => true,
|
||||||
|
// Visibility MUST be declared on all properties and methods; `abstract` and `final` MUST be declared before the visibility; `static` MUST be declared after the visibility.
|
||||||
|
'visibility_required' => true,
|
||||||
|
// In array declaration, there MUST be a whitespace after each comma.
|
||||||
|
'whitespace_after_comma_in_array' => true,
|
||||||
|
])
|
||||||
|
->setFinder(PhpCsFixer\Finder::create()
|
||||||
|
->exclude('vendor')
|
||||||
|
->exclude('var')
|
||||||
|
->exclude('docker')
|
||||||
|
->exclude('src/Entity')
|
||||||
|
->notPath('src/Core/DB/DefaultSettings.php')
|
||||||
|
->in(__DIR__)
|
||||||
|
);
|
||||||
806
CONFIGURE
806
CONFIGURE
@@ -1,806 +0,0 @@
|
|||||||
Configuration options
|
|
||||||
=====================
|
|
||||||
|
|
||||||
The main configuration file for StatusNet (excepting configurations for
|
|
||||||
dependency software) is config.php in your StatusNet directory. If you
|
|
||||||
edit any other file in the directory, like lib/default.php (where most
|
|
||||||
of the defaults are defined), you will lose your configuration options
|
|
||||||
in any upgrade, and you will wish that you had been more careful.
|
|
||||||
|
|
||||||
Starting with version 0.9.0, a Web based configuration panel has been
|
|
||||||
added to StatusNet. The preferred method for changing config options is
|
|
||||||
to use this panel.
|
|
||||||
|
|
||||||
A command-line script, setconfig.php, can be used to set individual
|
|
||||||
configuration options. It's in the scripts/ directory.
|
|
||||||
|
|
||||||
Starting with version 0.7.1, you can put config files in the
|
|
||||||
/etc/statusnet/ directory on your server, if it exists. Config files
|
|
||||||
will be included in this order:
|
|
||||||
|
|
||||||
* /etc/statusnet/statusnet.php - server-wide config
|
|
||||||
* /etc/statusnet/<servername>.php - for a virtual host
|
|
||||||
* /etc/statusnet/<servername>_<pathname>.php - for a path
|
|
||||||
* INSTALLDIR/config.php - for a particular implementation
|
|
||||||
|
|
||||||
Almost all configuration options are made through a two-dimensional
|
|
||||||
associative array, cleverly named $config. A typical configuration
|
|
||||||
line will be:
|
|
||||||
|
|
||||||
$config['section']['option'] = value;
|
|
||||||
|
|
||||||
For brevity, the following documentation describes each section and
|
|
||||||
option.
|
|
||||||
|
|
||||||
site
|
|
||||||
----
|
|
||||||
|
|
||||||
This section is a catch-all for site-wide variables.
|
|
||||||
|
|
||||||
name: the name of your site, like 'YourCompany Microblog'.
|
|
||||||
server: the server part of your site's URLs, like 'example.net'.
|
|
||||||
path: The path part of your site's URLs, like 'statusnet' or ''
|
|
||||||
(installed in root).
|
|
||||||
fancy: whether or not your site uses fancy URLs (see Fancy URLs
|
|
||||||
section above). Default is false.
|
|
||||||
logfile: full path to a file for StatusNet to save logging
|
|
||||||
information to. You may want to use this if you don't have
|
|
||||||
access to syslog.
|
|
||||||
logdebug: whether to log additional debug info like backtraces on
|
|
||||||
hard errors. Default false.
|
|
||||||
locale_path: full path to the directory for locale data. Unless you
|
|
||||||
store all your locale data in one place, you probably
|
|
||||||
don't need to use this.
|
|
||||||
language: default language for your site. Defaults to US English.
|
|
||||||
Note that this is overridden if a user is logged in and has
|
|
||||||
selected a different language. It is also overridden if the
|
|
||||||
user is NOT logged in, but their browser requests a different
|
|
||||||
langauge. Since pretty much everybody's browser requests a
|
|
||||||
language, that means that changing this setting has little or
|
|
||||||
no effect in practice.
|
|
||||||
languages: A list of languages supported on your site. Typically you'd
|
|
||||||
only change this if you wanted to disable support for one
|
|
||||||
or another language:
|
|
||||||
"unset($config['site']['languages']['de'])" will disable
|
|
||||||
support for German.
|
|
||||||
theme: Theme for your site (see Theme section). Two themes are
|
|
||||||
provided by default: 'default' and 'stoica' (the one used by
|
|
||||||
Identi.ca). It's appreciated if you don't use the 'stoica' theme
|
|
||||||
except as the basis for your own.
|
|
||||||
email: contact email address for your site. By default, it's extracted
|
|
||||||
from your Web server environment; you may want to customize it.
|
|
||||||
broughtbyurl: name of an organization or individual who provides the
|
|
||||||
service. Each page will include a link to this name in the
|
|
||||||
footer. A good way to link to the blog, forum, wiki,
|
|
||||||
corporate portal, or whoever is making the service available.
|
|
||||||
broughtby: text used for the "brought by" link.
|
|
||||||
timezone: default timezone for message display. Users can set their
|
|
||||||
own time zone. Defaults to 'UTC', which is a pretty good default.
|
|
||||||
closed: If set to 'true', will disallow registration on your site.
|
|
||||||
This is a cheap way to restrict accounts to only one
|
|
||||||
individual or group; just register the accounts you want on
|
|
||||||
the service, *then* set this variable to 'true'.
|
|
||||||
inviteonly: If set to 'true', will only allow registration if the user
|
|
||||||
was invited by an existing user.
|
|
||||||
private: If set to 'true', anonymous users will be redirected to the
|
|
||||||
'login' page. Also, API methods that normally require no
|
|
||||||
authentication will require it. Note that this does not turn
|
|
||||||
off registration; use 'closed' or 'inviteonly' for the
|
|
||||||
behaviour you want.
|
|
||||||
notice: A plain string that will appear on every page. A good place
|
|
||||||
to put introductory information about your service, or info about
|
|
||||||
upgrades and outages, or other community info. Any HTML will
|
|
||||||
be escaped.
|
|
||||||
logo: URL of an image file to use as the logo for the site. Overrides
|
|
||||||
the logo in the theme, if any.
|
|
||||||
ssllogo: URL of an image file to use as the logo on SSL pages. If unset,
|
|
||||||
theme logo is used instead.
|
|
||||||
ssl: Whether to use SSL and https:// URLs for some or all pages.
|
|
||||||
Possible values are 'always' (use it for all pages), 'never'
|
|
||||||
(don't use it for any pages), or 'sometimes' (use it for
|
|
||||||
sensitive pages that include passwords like login and registration,
|
|
||||||
but not for regular pages). Default to 'never'.
|
|
||||||
sslserver: use an alternate server name for SSL URLs, like
|
|
||||||
'secure.example.org'. You should be careful to set cookie
|
|
||||||
parameters correctly so that both the SSL server and the
|
|
||||||
"normal" server can access the session cookie and
|
|
||||||
preferably other cookies as well.
|
|
||||||
shorturllength: ignored. See 'url' section below.
|
|
||||||
dupelimit: minimum time allowed for one person to say the same thing
|
|
||||||
twice. Default 60s. Anything lower is considered a user
|
|
||||||
or UI error.
|
|
||||||
textlimit: default max size for texts in the site. Defaults to 0 (no limit).
|
|
||||||
Can be fine-tuned for notices, messages, profile bios and group descriptions.
|
|
||||||
|
|
||||||
db
|
|
||||||
--
|
|
||||||
|
|
||||||
This section is a reference to the configuration options for
|
|
||||||
DB_DataObject (see <http://ur1.ca/7xp>). The ones that you may want to
|
|
||||||
set are listed below for clarity.
|
|
||||||
|
|
||||||
database: a DSN (Data Source Name) for your StatusNet database. This is
|
|
||||||
in the format 'protocol://username:password@hostname/databasename',
|
|
||||||
where 'protocol' is 'mysql' or 'mysqli' (or possibly 'postgresql', if you
|
|
||||||
really know what you're doing), 'username' is the username,
|
|
||||||
'password' is the password, and etc.
|
|
||||||
ini_yourdbname: if your database is not named 'statusnet', you'll need
|
|
||||||
to set this to point to the location of the
|
|
||||||
statusnet.ini file. Note that the real name of your database
|
|
||||||
should go in there, not literally 'yourdbname'.
|
|
||||||
db_driver: You can try changing this to 'MDB2' to use the other driver
|
|
||||||
type for DB_DataObject, but note that it breaks the OpenID
|
|
||||||
libraries, which only support PEAR::DB.
|
|
||||||
debug: On a database error, you may get a message saying to set this
|
|
||||||
value to 5 to see debug messages in the browser. This breaks
|
|
||||||
just about all pages, and will also expose the username and
|
|
||||||
password
|
|
||||||
quote_identifiers: Set this to true if you're using postgresql.
|
|
||||||
type: either 'mysql' or 'postgresql' (used for some bits of
|
|
||||||
database-type-specific SQL in the code). Defaults to mysql.
|
|
||||||
mirror: you can set this to an array of DSNs, like the above
|
|
||||||
'database' value. If it's set, certain read-only actions will
|
|
||||||
use a random value out of this array for the database, rather
|
|
||||||
than the one in 'database' (actually, 'database' is overwritten).
|
|
||||||
You can offload a busy DB server by setting up MySQL replication
|
|
||||||
and adding the slaves to this array. Note that if you want some
|
|
||||||
requests to go to the 'database' (master) server, you'll need
|
|
||||||
to include it in this array, too.
|
|
||||||
utf8: whether to talk to the database in UTF-8 mode. This is the default
|
|
||||||
with new installations, but older sites may want to turn it off
|
|
||||||
until they get their databases fixed up. See "UTF-8 database"
|
|
||||||
above for details.
|
|
||||||
schemacheck: when to let plugins check the database schema to add
|
|
||||||
tables or update them. Values can be 'runtime' (default)
|
|
||||||
or 'script'. 'runtime' can be costly (plugins check the
|
|
||||||
schema on every hit, adding potentially several db
|
|
||||||
queries, some quite long), but not everyone knows how to
|
|
||||||
run a script. If you can, set this to 'script' and run
|
|
||||||
scripts/checkschema.php whenever you install or upgrade a
|
|
||||||
plugin.
|
|
||||||
|
|
||||||
syslog
|
|
||||||
------
|
|
||||||
|
|
||||||
By default, StatusNet sites log error messages to the syslog facility.
|
|
||||||
(You can override this using the 'logfile' parameter described above).
|
|
||||||
|
|
||||||
appname: The name that StatusNet uses to log messages. By default it's
|
|
||||||
"statusnet", but if you have more than one installation on the
|
|
||||||
server, you may want to change the name for each instance so
|
|
||||||
you can track log messages more easily.
|
|
||||||
priority: level to log at. Currently ignored.
|
|
||||||
facility: what syslog facility to used. Defaults to LOG_USER, only
|
|
||||||
reset if you know what syslog is and have a good reason
|
|
||||||
to change it.
|
|
||||||
|
|
||||||
queue
|
|
||||||
-----
|
|
||||||
|
|
||||||
You can configure the software to queue time-consuming tasks, like
|
|
||||||
sending out SMS email or XMPP messages, for off-line processing. See
|
|
||||||
'Queues and daemons' above for how to set this up.
|
|
||||||
|
|
||||||
enabled: Whether to uses queues. Defaults to false.
|
|
||||||
daemon: Wather to use queuedaemon. Defaults to false, which means
|
|
||||||
you'll use OpportunisticQM plugin.
|
|
||||||
subsystem: Which kind of queueserver to use. Values include "db" for
|
|
||||||
our hacked-together database queuing (no other server
|
|
||||||
required) and "stomp" for a stomp server.
|
|
||||||
stomp_server: "broker URI" for stomp server. Something like
|
|
||||||
"tcp://hostname:61613". More complicated ones are
|
|
||||||
possible; see your stomp server's documentation for
|
|
||||||
details.
|
|
||||||
queue_basename: a root name to use for queues (stomp only). Typically
|
|
||||||
something like '/queue/sitename/' makes sense. If running
|
|
||||||
multiple instances on the same server, make sure that
|
|
||||||
either this setting or $config['site']['nickname'] are
|
|
||||||
unique for each site to keep them separate.
|
|
||||||
|
|
||||||
stomp_username: username for connecting to the stomp server; defaults
|
|
||||||
to null.
|
|
||||||
stomp_password: password for connecting to the stomp server; defaults
|
|
||||||
to null.
|
|
||||||
|
|
||||||
stomp_persistent: keep items across queue server restart, if enabled.
|
|
||||||
Under ActiveMQ, the server configuration determines if and how
|
|
||||||
persistent storage is actually saved.
|
|
||||||
|
|
||||||
If using a message queue server other than ActiveMQ, you may
|
|
||||||
need to disable this if it does not support persistence.
|
|
||||||
|
|
||||||
stomp_transactions: use transactions to aid in error detection.
|
|
||||||
A broken transaction will be seen quickly, allowing a message
|
|
||||||
to be redelivered immediately if a daemon crashes.
|
|
||||||
|
|
||||||
If using a message queue server other than ActiveMQ, you may
|
|
||||||
need to disable this if it does not support transactions.
|
|
||||||
|
|
||||||
stomp_acks: send acknowledgements to aid in flow control.
|
|
||||||
An acknowledgement of successful processing tells the server
|
|
||||||
we're ready for more and can help keep things moving smoothly.
|
|
||||||
|
|
||||||
This should *not* be turned off when running with ActiveMQ, but
|
|
||||||
if using another message queue server that does not support
|
|
||||||
acknowledgements you might need to disable this.
|
|
||||||
|
|
||||||
softlimit: an absolute or relative "soft memory limit"; daemons will
|
|
||||||
restart themselves gracefully when they find they've hit
|
|
||||||
this amount of memory usage. Defaults to 90% of PHP's global
|
|
||||||
memory_limit setting.
|
|
||||||
|
|
||||||
inboxes: delivery of messages to receiver's inboxes can be delayed to
|
|
||||||
queue time for best interactive performance on the sender.
|
|
||||||
This may however be annoyingly slow when using the DB queues,
|
|
||||||
so you can set this to false if it's causing trouble.
|
|
||||||
|
|
||||||
breakout: for stomp, individual queues are by default grouped up for
|
|
||||||
best scalability. If some need to be run by separate daemons,
|
|
||||||
etc they can be manually adjusted here.
|
|
||||||
|
|
||||||
Default will share all queues for all sites within each group.
|
|
||||||
Specify as <group>/<queue> or <group>/<queue>/<site>,
|
|
||||||
using nickname identifier as site.
|
|
||||||
|
|
||||||
'main/distrib' separate "distrib" queue covering all sites
|
|
||||||
'xmpp/xmppout/mysite' separate "xmppout" queue covering just 'mysite'
|
|
||||||
|
|
||||||
max_retries: for stomp, drop messages after N failed attempts to process.
|
|
||||||
Defaults to 10.
|
|
||||||
|
|
||||||
dead_letter_dir: for stomp, optional directory to dump data on failed
|
|
||||||
queue processing events after discarding them.
|
|
||||||
|
|
||||||
stomp_no_transactions: for stomp, the server does not support transactions,
|
|
||||||
so do not try to user them. This is needed for http://www.morbidq.com/.
|
|
||||||
|
|
||||||
stomp_no_acks: for stomp, the server does not support acknowledgements.
|
|
||||||
so do not try to user them. This is needed for http://www.morbidq.com/.
|
|
||||||
|
|
||||||
license
|
|
||||||
-------
|
|
||||||
|
|
||||||
The default license to use for your users notices. The default is the
|
|
||||||
Creative Commons Attribution 3.0 license, which is probably the right
|
|
||||||
choice for any public site. Note that some other servers will not
|
|
||||||
accept notices if you apply a stricter license than this.
|
|
||||||
|
|
||||||
type: one of 'cc' (for Creative Commons licenses), 'allrightsreserved'
|
|
||||||
(default copyright), or 'private' (for private and confidential
|
|
||||||
information).
|
|
||||||
owner: for 'allrightsreserved' or 'private', an assigned copyright
|
|
||||||
holder (for example, an employer for a private site). If
|
|
||||||
not specified, will be attributed to 'contributors'.
|
|
||||||
url: URL of the license, used for links.
|
|
||||||
title: Title for the license, like 'Creative Commons Attribution 3.0'.
|
|
||||||
image: A button shown on each page for the license.
|
|
||||||
|
|
||||||
mail
|
|
||||||
----
|
|
||||||
|
|
||||||
This is for configuring out-going email. We use PEAR's Mail module,
|
|
||||||
see: http://pear.php.net/manual/en/package.mail.mail.factory.php
|
|
||||||
|
|
||||||
backend: the backend to use for mail, one of 'mail', 'sendmail', and
|
|
||||||
'smtp'. Defaults to PEAR's default, 'mail'.
|
|
||||||
params: if the mail backend requires any parameters, you can provide
|
|
||||||
them in an associative array.
|
|
||||||
|
|
||||||
nickname
|
|
||||||
--------
|
|
||||||
|
|
||||||
This is for configuring nicknames in the service.
|
|
||||||
|
|
||||||
blacklist: an array of strings for usernames that may not be
|
|
||||||
registered. A default array exists for strings that are
|
|
||||||
used by StatusNet (e.g. 'doc', 'main', 'avatar', 'theme')
|
|
||||||
but you may want to add others if you have other software
|
|
||||||
installed in a subdirectory of StatusNet or if you just
|
|
||||||
don't want certain words used as usernames.
|
|
||||||
featured: an array of nicknames of 'featured' users of the site.
|
|
||||||
Can be useful to draw attention to well-known users, or
|
|
||||||
interesting people, or whatever.
|
|
||||||
|
|
||||||
avatar
|
|
||||||
------
|
|
||||||
|
|
||||||
For configuring avatar access.
|
|
||||||
|
|
||||||
dir: Directory to look for avatar files and to put them into.
|
|
||||||
Defaults to avatar subdirectory of install directory; if
|
|
||||||
you change it, make sure to change path, too.
|
|
||||||
path: Path to avatars. Defaults to path for avatar subdirectory,
|
|
||||||
but you can change it if you wish. Note that this will
|
|
||||||
be included with the avatar server, too.
|
|
||||||
server: If set, defines another server where avatars are stored in the
|
|
||||||
root directory. Note that the 'avatar' subdir still has to be
|
|
||||||
writeable. You'd typically use this to split HTTP requests on
|
|
||||||
the client to speed up page loading, either with another
|
|
||||||
virtual server or with an NFS or SAMBA share. Clients
|
|
||||||
typically only make 2 connections to a single server at a
|
|
||||||
time <http://ur1.ca/6ih>, so this can parallelize the job.
|
|
||||||
Defaults to null.
|
|
||||||
ssl: Whether to access avatars using HTTPS. Defaults to null, meaning
|
|
||||||
to guess based on site-wide SSL settings.
|
|
||||||
|
|
||||||
public
|
|
||||||
------
|
|
||||||
|
|
||||||
For configuring the public stream.
|
|
||||||
|
|
||||||
localonly: If set to true, only messages posted by users of this
|
|
||||||
service (rather than other services, filtered through OStatus)
|
|
||||||
are shown in the public stream. Default true.
|
|
||||||
blacklist: An array of IDs of users to hide from the public stream.
|
|
||||||
Useful if you have someone making excessive Twitterfeed posts
|
|
||||||
to the site, other kinds of automated posts, testing bots, etc.
|
|
||||||
autosource: Sources of notices that are from automatic posters, and thus
|
|
||||||
should be kept off the public timeline. Default empty.
|
|
||||||
|
|
||||||
theme
|
|
||||||
-----
|
|
||||||
|
|
||||||
server: Like avatars, you can speed up page loading by pointing the
|
|
||||||
theme file lookup to another server (virtual or real).
|
|
||||||
Defaults to NULL, meaning to use the site server.
|
|
||||||
dir: Directory where theme files are stored. Used to determine
|
|
||||||
whether to show parts of a theme file. Defaults to the theme
|
|
||||||
subdirectory of the install directory.
|
|
||||||
path: Path part of theme URLs, before the theme name. Relative to the
|
|
||||||
theme server. It may make sense to change this path when upgrading,
|
|
||||||
(using version numbers as the path) to make sure that all files are
|
|
||||||
reloaded by caching clients or proxies. Defaults to null,
|
|
||||||
which means to use the site path + '/theme'.
|
|
||||||
ssl: Whether to use SSL for theme elements. Default is null, which means
|
|
||||||
guess based on site SSL settings.
|
|
||||||
sslserver: SSL server to use when page is HTTPS-encrypted. If
|
|
||||||
unspecified, site ssl server and so on will be used.
|
|
||||||
sslpath: If sslserver if defined, path to use when page is HTTPS-encrypted.
|
|
||||||
|
|
||||||
javascript
|
|
||||||
----------
|
|
||||||
|
|
||||||
server: You can speed up page loading by pointing the
|
|
||||||
theme file lookup to another server (virtual or real).
|
|
||||||
Defaults to NULL, meaning to use the site server.
|
|
||||||
path: Path part of Javascript URLs. Defaults to null,
|
|
||||||
which means to use the site path + '/js/'.
|
|
||||||
ssl: Whether to use SSL for JavaScript files. Default is null, which means
|
|
||||||
guess based on site SSL settings.
|
|
||||||
sslserver: SSL server to use when page is HTTPS-encrypted. If
|
|
||||||
unspecified, site ssl server and so on will be used.
|
|
||||||
sslpath: If sslserver if defined, path to use when page is HTTPS-encrypted.
|
|
||||||
bustframes: If true, all web pages will break out of framesets. If false,
|
|
||||||
can comfortably live in a frame or iframe... probably. Default
|
|
||||||
to true.
|
|
||||||
|
|
||||||
xmpp
|
|
||||||
----
|
|
||||||
|
|
||||||
For configuring the XMPP sub-system.
|
|
||||||
|
|
||||||
enabled: Whether to accept and send messages by XMPP. Default false.
|
|
||||||
server: server part of XMPP ID for update user.
|
|
||||||
port: connection port for clients. Default 5222, which you probably
|
|
||||||
shouldn't need to change.
|
|
||||||
user: username for the client connection. Users will receive messages
|
|
||||||
from 'user'@'server'.
|
|
||||||
resource: a unique identifier for the connection to the server. This
|
|
||||||
is actually used as a prefix for each XMPP component in the system.
|
|
||||||
password: password for the user account.
|
|
||||||
host: some XMPP domains are served by machines with a different
|
|
||||||
hostname. (For example, @gmail.com GTalk users connect to
|
|
||||||
talk.google.com). Set this to the correct hostname if that's the
|
|
||||||
case with your server.
|
|
||||||
encryption: Whether to encrypt the connection between StatusNet and the
|
|
||||||
XMPP server. Defaults to true, but you can get
|
|
||||||
considerably better performance turning it off if you're
|
|
||||||
connecting to a server on the same machine or on a
|
|
||||||
protected network.
|
|
||||||
debug: if turned on, this will make the XMPP library blurt out all of
|
|
||||||
the incoming and outgoing messages as XML stanzas. Use as a
|
|
||||||
last resort, and never turn it on if you don't have queues
|
|
||||||
enabled, since it will spit out sensitive data to the browser.
|
|
||||||
public: an array of JIDs to send _all_ notices to. This is useful for
|
|
||||||
participating in third-party search and archiving services.
|
|
||||||
|
|
||||||
invite
|
|
||||||
------
|
|
||||||
|
|
||||||
For configuring invites.
|
|
||||||
|
|
||||||
enabled: Whether to allow users to send invites. Default true.
|
|
||||||
|
|
||||||
tag
|
|
||||||
---
|
|
||||||
|
|
||||||
Miscellaneous tagging stuff.
|
|
||||||
|
|
||||||
dropoff: Decay factor for tag listing, in seconds.
|
|
||||||
Defaults to exponential decay over ten days; you can twiddle
|
|
||||||
with it to try and get better results for your site.
|
|
||||||
|
|
||||||
popular
|
|
||||||
-------
|
|
||||||
|
|
||||||
Settings for the "popular" section of the site.
|
|
||||||
|
|
||||||
dropoff: Decay factor for popularity listing, in seconds.
|
|
||||||
Defaults to exponential decay over ten days; you can twiddle
|
|
||||||
with it to try and get better results for your site.
|
|
||||||
|
|
||||||
daemon
|
|
||||||
------
|
|
||||||
|
|
||||||
For daemon processes.
|
|
||||||
|
|
||||||
piddir: directory that daemon processes should write their PID file
|
|
||||||
(process ID) to. Defaults to /var/run/, which is where this
|
|
||||||
stuff should usually go on Unix-ish systems.
|
|
||||||
user: If set, the daemons will try to change their effective user ID
|
|
||||||
to this user before running. Probably a good idea, especially if
|
|
||||||
you start the daemons as root. Note: user name, like 'daemon',
|
|
||||||
not 1001.
|
|
||||||
group: If set, the daemons will try to change their effective group ID
|
|
||||||
to this named group. Again, a name, not a numerical ID.
|
|
||||||
|
|
||||||
emailpost
|
|
||||||
---------
|
|
||||||
|
|
||||||
For post-by-email.
|
|
||||||
|
|
||||||
enabled: Whether to enable post-by-email. Defaults to true. You will
|
|
||||||
also need to set up maildaemon.php.
|
|
||||||
|
|
||||||
sms
|
|
||||||
---
|
|
||||||
|
|
||||||
For SMS integration.
|
|
||||||
|
|
||||||
enabled: Whether to enable SMS integration. Defaults to true. Queues
|
|
||||||
should also be enabled.
|
|
||||||
|
|
||||||
integration
|
|
||||||
-----------
|
|
||||||
|
|
||||||
A catch-all for integration with other systems.
|
|
||||||
|
|
||||||
taguri: base for tag:// URIs. Defaults to site-server + ',2009'.
|
|
||||||
|
|
||||||
inboxes
|
|
||||||
-------
|
|
||||||
|
|
||||||
For notice inboxes.
|
|
||||||
|
|
||||||
enabled: No longer used. If you set this to something other than true,
|
|
||||||
StatusNet will no longer run.
|
|
||||||
|
|
||||||
throttle
|
|
||||||
--------
|
|
||||||
|
|
||||||
For notice-posting throttles.
|
|
||||||
|
|
||||||
enabled: Whether to throttle posting. Defaults to false.
|
|
||||||
count: Each user can make this many posts in 'timespan' seconds. So, if count
|
|
||||||
is 100 and timespan is 3600, then there can be only 100 posts
|
|
||||||
from a user every hour.
|
|
||||||
timespan: see 'count'.
|
|
||||||
|
|
||||||
profile
|
|
||||||
-------
|
|
||||||
|
|
||||||
Profile management.
|
|
||||||
|
|
||||||
biolimit: max character length of bio; 0 means no limit; null means to use
|
|
||||||
the site text limit default.
|
|
||||||
backup: whether users can backup their own profiles. Defaults to true.
|
|
||||||
restore: whether users can restore their profiles from backup files. Defaults
|
|
||||||
to true.
|
|
||||||
delete: whether users can delete their own accounts. Defaults to false.
|
|
||||||
move: whether users can move their accounts to another server. Defaults
|
|
||||||
to true.
|
|
||||||
|
|
||||||
newuser
|
|
||||||
-------
|
|
||||||
|
|
||||||
Options with new users.
|
|
||||||
|
|
||||||
default: nickname of a user account to automatically subscribe new
|
|
||||||
users to. Typically this would be system account for e.g.
|
|
||||||
service updates or announcements. Users are able to unsub
|
|
||||||
if they want. Default is null; no auto subscribe.
|
|
||||||
welcome: nickname of a user account that sends welcome messages to new
|
|
||||||
users. Can be the same as 'default' account, although on
|
|
||||||
busy servers it may be a good idea to keep that one just for
|
|
||||||
'urgent' messages. Default is null; no message.
|
|
||||||
|
|
||||||
If either of these special user accounts are specified, the users should
|
|
||||||
be created before the configuration is updated.
|
|
||||||
|
|
||||||
attachments
|
|
||||||
-----------
|
|
||||||
|
|
||||||
The software lets users upload files with their notices. You can configure
|
|
||||||
the types of accepted files by mime types and a trio of quota options:
|
|
||||||
per file, per user (total), per user per month.
|
|
||||||
|
|
||||||
We suggest the use of the pecl file_info extension to handle mime type
|
|
||||||
detection.
|
|
||||||
|
|
||||||
supported: an array of mime types you accept to store and distribute,
|
|
||||||
like 'image/gif', 'video/mpeg', 'audio/mpeg', etc. Make sure you
|
|
||||||
setup your server to properly recognize the types you want to
|
|
||||||
support.
|
|
||||||
uploads: false to disable uploading files with notices (true by default).
|
|
||||||
|
|
||||||
For quotas, be sure you've set the upload_max_filesize and post_max_size
|
|
||||||
in php.ini to be large enough to handle your upload. In httpd.conf
|
|
||||||
(if you're using apache), check that the LimitRequestBody directive isn't
|
|
||||||
set too low (it's optional, so it may not be there at all).
|
|
||||||
|
|
||||||
process_links: follow redirects and save all available file information
|
|
||||||
(mimetype, date, size, oembed, etc.). Defaults to true.
|
|
||||||
file_quota: maximum size for a single file upload in bytes. A user can send
|
|
||||||
any amount of notices with attachments as long as each attachment
|
|
||||||
is smaller than file_quota.
|
|
||||||
user_quota: total size in bytes a user can store on this server. Each user
|
|
||||||
can store any number of files as long as their total size does
|
|
||||||
not exceed the user_quota.
|
|
||||||
monthly_quota: total size permitted in the current month. This is the total
|
|
||||||
size in bytes that a user can upload each month.
|
|
||||||
dir: directory accessible to the Web process where uploads should go.
|
|
||||||
Defaults to the 'file' subdirectory of the install directory, which
|
|
||||||
should be writeable by the Web user.
|
|
||||||
server: server name to use when creating URLs for uploaded files.
|
|
||||||
Defaults to null, meaning to use the default Web server. Using
|
|
||||||
a virtual server here can speed up Web performance.
|
|
||||||
path: URL path, relative to the server, to find files. Defaults to
|
|
||||||
main path + '/file/'.
|
|
||||||
ssl: whether to use HTTPS for file URLs. Defaults to null, meaning to
|
|
||||||
guess based on other SSL settings.
|
|
||||||
sslserver: if specified, this server will be used when creating HTTPS
|
|
||||||
URLs. Otherwise, the site SSL server will be used, with /file/ path.
|
|
||||||
sslpath: if this and the sslserver are specified, this path will be used
|
|
||||||
when creating HTTPS URLs. Otherwise, the attachments|path value
|
|
||||||
will be used.
|
|
||||||
|
|
||||||
group
|
|
||||||
-----
|
|
||||||
|
|
||||||
Options for group functionality.
|
|
||||||
|
|
||||||
maxaliases: maximum number of aliases a group can have. Default 3. Set
|
|
||||||
to 0 or less to prevent aliases in a group.
|
|
||||||
desclimit: maximum number of characters to allow in group descriptions.
|
|
||||||
null (default) means to use the site-wide text limits. 0
|
|
||||||
means no limit.
|
|
||||||
addtag: Whether to add a tag for the group nickname for every group post
|
|
||||||
(pre-1.0.x behaviour). Defaults to false.
|
|
||||||
|
|
||||||
search
|
|
||||||
------
|
|
||||||
|
|
||||||
Some stuff for search.
|
|
||||||
|
|
||||||
type: type of search. Ignored if PostgreSQL or Sphinx are enabled. Can either
|
|
||||||
be 'fulltext' or 'like' (default). The former is faster and more efficient
|
|
||||||
but requires the lame old MyISAM engine for MySQL. The latter
|
|
||||||
will work with InnoDB but could be miserably slow on large
|
|
||||||
systems. We'll probably add another type sometime in the future,
|
|
||||||
with our own indexing system (maybe like MediaWiki's).
|
|
||||||
|
|
||||||
sessions
|
|
||||||
--------
|
|
||||||
|
|
||||||
Session handling.
|
|
||||||
|
|
||||||
handle: boolean. Whether we should register our own PHP session-handling
|
|
||||||
code (using the database and cache layers if enabled). Defaults to false.
|
|
||||||
Setting this to true makes some sense on large or multi-server
|
|
||||||
sites, but it probably won't hurt for smaller ones, either.
|
|
||||||
debug: whether to output debugging info for session storage. Can help
|
|
||||||
with weird session bugs, sometimes. Default false.
|
|
||||||
|
|
||||||
background
|
|
||||||
----------
|
|
||||||
|
|
||||||
Users can upload backgrounds for their pages; this section defines
|
|
||||||
their use.
|
|
||||||
|
|
||||||
server: the server to use for background. Using a separate (even
|
|
||||||
virtual) server for this can speed up load times. Default is
|
|
||||||
null; same as site server.
|
|
||||||
dir: directory to write backgrounds too. Default is '/background/'
|
|
||||||
subdir of install dir.
|
|
||||||
path: path to backgrounds. Default is sub-path of install path; note
|
|
||||||
that you may need to change this if you change site-path too.
|
|
||||||
sslserver: SSL server to use when page is HTTPS-encrypted. If
|
|
||||||
unspecified, site ssl server and so on will be used.
|
|
||||||
sslpath: If sslserver if defined, path to use when page is HTTPS-encrypted.
|
|
||||||
|
|
||||||
ping
|
|
||||||
----
|
|
||||||
|
|
||||||
Using the "XML-RPC Ping" method initiated by weblogs.com, the site can
|
|
||||||
notify third-party servers of updates.
|
|
||||||
|
|
||||||
notify: an array of URLs for ping endpoints. Default is the empty
|
|
||||||
array (no notification).
|
|
||||||
|
|
||||||
design
|
|
||||||
------
|
|
||||||
|
|
||||||
Default design (colors and background) for the site. Actual appearance
|
|
||||||
depends on the theme. Null values mean to use the theme defaults.
|
|
||||||
|
|
||||||
backgroundcolor: Hex color of the site background.
|
|
||||||
contentcolor: Hex color of the content area background.
|
|
||||||
sidebarcolor: Hex color of the sidebar background.
|
|
||||||
textcolor: Hex color of all non-link text.
|
|
||||||
linkcolor: Hex color of all links.
|
|
||||||
backgroundimage: Image to use for the background.
|
|
||||||
disposition: Flags for whether or not to tile the background image.
|
|
||||||
|
|
||||||
notice
|
|
||||||
------
|
|
||||||
|
|
||||||
Configuration options specific to notices.
|
|
||||||
|
|
||||||
contentlimit: max length of the plain-text content of a notice.
|
|
||||||
Default is null, meaning to use the site-wide text limit.
|
|
||||||
0 means no limit.
|
|
||||||
defaultscope: default scope for notices. If null, the default
|
|
||||||
scope depends on site/private. It's 1 if the site is private,
|
|
||||||
0 otherwise. Set this value to override.
|
|
||||||
|
|
||||||
message
|
|
||||||
-------
|
|
||||||
|
|
||||||
Configuration options specific to messages.
|
|
||||||
|
|
||||||
contentlimit: max length of the plain-text content of a message.
|
|
||||||
Default is null, meaning to use the site-wide text limit.
|
|
||||||
0 means no limit.
|
|
||||||
|
|
||||||
logincommand
|
|
||||||
------------
|
|
||||||
|
|
||||||
Configuration options for the login command.
|
|
||||||
|
|
||||||
disabled: whether to enable this command. If enabled, users who send
|
|
||||||
the text 'login' to the site through any channel will
|
|
||||||
receive a link to login to the site automatically in return.
|
|
||||||
Possibly useful for users who primarily use an XMPP or SMS
|
|
||||||
interface and can't be bothered to remember their site
|
|
||||||
password. Note that the security implications of this are
|
|
||||||
pretty serious and have not been thoroughly tested. You
|
|
||||||
should enable it only after you've convinced yourself that
|
|
||||||
it is safe. Default is 'false'.
|
|
||||||
|
|
||||||
singleuser
|
|
||||||
----------
|
|
||||||
|
|
||||||
If an installation has only one user, this can simplify a lot of the
|
|
||||||
interface. It also makes the user's profile the root URL.
|
|
||||||
|
|
||||||
enabled: Whether to run in "single user mode". Default false.
|
|
||||||
nickname: nickname of the single user. If no nickname is specified,
|
|
||||||
the site owner account will be used (if present).
|
|
||||||
|
|
||||||
robotstxt
|
|
||||||
---------
|
|
||||||
|
|
||||||
We put out a default robots.txt file to guide the processing of
|
|
||||||
Web crawlers. See http://www.robotstxt.org/ for more information
|
|
||||||
on the format of this file.
|
|
||||||
|
|
||||||
crawldelay: if non-empty, this value is provided as the Crawl-Delay:
|
|
||||||
for the robots.txt file. see http://ur1.ca/l5a0
|
|
||||||
for more information. Default is zero, no explicit delay.
|
|
||||||
disallow: Array of (virtual) directories to disallow. Default is 'main',
|
|
||||||
'search', 'message', 'settings', 'admin'. Ignored when site
|
|
||||||
is private, in which case the entire site ('/') is disallowed.
|
|
||||||
|
|
||||||
api
|
|
||||||
---
|
|
||||||
|
|
||||||
Options for the Twitter-like API.
|
|
||||||
|
|
||||||
realm: HTTP Basic Auth realm (see http://tools.ietf.org/html/rfc2617
|
|
||||||
for details). Some third-party tools like ping.fm want this to be
|
|
||||||
'Identi.ca API', so set it to that if you want to. default = null,
|
|
||||||
meaning 'something based on the site name'.
|
|
||||||
|
|
||||||
nofollow
|
|
||||||
--------
|
|
||||||
|
|
||||||
We optionally put 'rel="nofollow"' on some links in some pages. The
|
|
||||||
following configuration settings let you fine-tune how or when things
|
|
||||||
are nofollowed. See http://en.wikipedia.org/wiki/Nofollow for more
|
|
||||||
information on what 'nofollow' means.
|
|
||||||
|
|
||||||
subscribers: whether to nofollow links to subscribers on the profile
|
|
||||||
and personal pages. Default is true.
|
|
||||||
members: links to members on the group page. Default true.
|
|
||||||
peopletag: links to people listed in the peopletag page. Default true.
|
|
||||||
external: external links in notices. One of three values: 'sometimes',
|
|
||||||
'always', 'never'. If 'sometimes', then external links are not
|
|
||||||
nofollowed on profile, notice, and favorites page. Default is
|
|
||||||
'sometimes'.
|
|
||||||
|
|
||||||
url
|
|
||||||
---
|
|
||||||
|
|
||||||
These are some options for fine-tuning how and when the server will
|
|
||||||
shorten URLs.
|
|
||||||
|
|
||||||
shortener: URL shortening service to use by default. Users can override
|
|
||||||
individually. 'internal' by default.
|
|
||||||
maxurllength: If an URL is strictly longer than this limit, it will be
|
|
||||||
shortened. Note that the URL shortener service may return an
|
|
||||||
URL longer than this limit. Defaults to 100. Users can
|
|
||||||
override. If set to 0, all URLs will be shortened.
|
|
||||||
maxnoticelength: If a notice is strictly longer than this limit, all
|
|
||||||
URLs in the notice will be shortened. Users can override.
|
|
||||||
-1 means the text limit for notices.
|
|
||||||
|
|
||||||
router
|
|
||||||
------
|
|
||||||
|
|
||||||
We use a router class for mapping URLs to code. This section controls
|
|
||||||
how that router works.
|
|
||||||
|
|
||||||
cache: whether to cache the router in cache layers. Defaults to true,
|
|
||||||
but may be set to false for developers (who might be actively
|
|
||||||
adding pages, so won't want the router cached) or others who see
|
|
||||||
strange behavior. You're unlikely to need this unless developing..
|
|
||||||
|
|
||||||
http
|
|
||||||
----
|
|
||||||
|
|
||||||
Settings for the HTTP client.
|
|
||||||
|
|
||||||
ssl_cafile: location of the CA file for SSL. If not set, won't verify
|
|
||||||
SSL peers. Default unset.
|
|
||||||
curl: Use cURL <http://curl.haxx.se/> for doing HTTP calls. You must
|
|
||||||
have the PHP curl extension installed for this to work.
|
|
||||||
proxy_host: Host to use for proxying HTTP requests. If unset, doesn't
|
|
||||||
do any HTTP proxy stuff. Default unset.
|
|
||||||
proxy_port: Port to use to connect to HTTP proxy host. Default null.
|
|
||||||
proxy_user: Username to use for authenticating to the HTTP proxy. Default null.
|
|
||||||
proxy_password: Password to use for authenticating to the HTTP proxy. Default null.
|
|
||||||
proxy_auth_scheme: Scheme to use for authenticating to the HTTP proxy. Default null.
|
|
||||||
|
|
||||||
plugins
|
|
||||||
-------
|
|
||||||
|
|
||||||
default: associative array mapping plugin name to array of arguments. To disable
|
|
||||||
a default plugin, unset its value in this array.
|
|
||||||
locale_path: path for finding plugin locale files. In the plugin's directory
|
|
||||||
by default.
|
|
||||||
server: Server to find static files for a plugin when the page is plain old HTTP.
|
|
||||||
Defaults to site/server (same as pages). Use this to move plugin CSS and
|
|
||||||
JS files to a CDN.
|
|
||||||
sslserver: Server to find static files for a plugin when the page is HTTPS. Defaults
|
|
||||||
to site/server (same as pages). Use this to move plugin CSS and JS files
|
|
||||||
to a CDN.
|
|
||||||
path: Path to the plugin files. defaults to site/path + '/plugins/'. Expects that
|
|
||||||
each plugin will have a subdirectory at plugins/NameOfPlugin. Change this
|
|
||||||
if you're using a CDN.
|
|
||||||
sslpath: Path to use on the SSL server. Same as plugins/path.
|
|
||||||
|
|
||||||
performance
|
|
||||||
-----------
|
|
||||||
|
|
||||||
high: if you need high performance, or if you're seeing bad
|
|
||||||
performance, set this to true. It will turn off some high-intensity code from
|
|
||||||
the site.
|
|
||||||
|
|
||||||
oldschool
|
|
||||||
---------
|
|
||||||
|
|
||||||
enabled: enable certain old-style user settings options, like stream-only mode,
|
|
||||||
conversation trees, and nicknames in streams. Off by default, and
|
|
||||||
may not be well supported in future versions.
|
|
||||||
|
|
||||||
|
|
||||||
661
COPYING
661
COPYING
@@ -1,661 +0,0 @@
|
|||||||
GNU AFFERO GENERAL PUBLIC LICENSE
|
|
||||||
Version 3, 19 November 2007
|
|
||||||
|
|
||||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
|
||||||
Everyone is permitted to copy and distribute verbatim copies
|
|
||||||
of this license document, but changing it is not allowed.
|
|
||||||
|
|
||||||
Preamble
|
|
||||||
|
|
||||||
The GNU Affero General Public License is a free, copyleft license for
|
|
||||||
software and other kinds of works, specifically designed to ensure
|
|
||||||
cooperation with the community in the case of network server software.
|
|
||||||
|
|
||||||
The licenses for most software and other practical works are designed
|
|
||||||
to take away your freedom to share and change the works. By contrast,
|
|
||||||
our General Public Licenses are intended to guarantee your freedom to
|
|
||||||
share and change all versions of a program--to make sure it remains free
|
|
||||||
software for all its users.
|
|
||||||
|
|
||||||
When we speak of free software, we are referring to freedom, not
|
|
||||||
price. Our General Public Licenses are designed to make sure that you
|
|
||||||
have the freedom to distribute copies of free software (and charge for
|
|
||||||
them if you wish), that you receive source code or can get it if you
|
|
||||||
want it, that you can change the software or use pieces of it in new
|
|
||||||
free programs, and that you know you can do these things.
|
|
||||||
|
|
||||||
Developers that use our General Public Licenses protect your rights
|
|
||||||
with two steps: (1) assert copyright on the software, and (2) offer
|
|
||||||
you this License which gives you legal permission to copy, distribute
|
|
||||||
and/or modify the software.
|
|
||||||
|
|
||||||
A secondary benefit of defending all users' freedom is that
|
|
||||||
improvements made in alternate versions of the program, if they
|
|
||||||
receive widespread use, become available for other developers to
|
|
||||||
incorporate. Many developers of free software are heartened and
|
|
||||||
encouraged by the resulting cooperation. However, in the case of
|
|
||||||
software used on network servers, this result may fail to come about.
|
|
||||||
The GNU General Public License permits making a modified version and
|
|
||||||
letting the public access it on a server without ever releasing its
|
|
||||||
source code to the public.
|
|
||||||
|
|
||||||
The GNU Affero General Public License is designed specifically to
|
|
||||||
ensure that, in such cases, the modified source code becomes available
|
|
||||||
to the community. It requires the operator of a network server to
|
|
||||||
provide the source code of the modified version running there to the
|
|
||||||
users of that server. Therefore, public use of a modified version, on
|
|
||||||
a publicly accessible server, gives the public access to the source
|
|
||||||
code of the modified version.
|
|
||||||
|
|
||||||
An older license, called the Affero General Public License and
|
|
||||||
published by Affero, was designed to accomplish similar goals. This is
|
|
||||||
a different license, not a version of the Affero GPL, but Affero has
|
|
||||||
released a new version of the Affero GPL which permits relicensing under
|
|
||||||
this license.
|
|
||||||
|
|
||||||
The precise terms and conditions for copying, distribution and
|
|
||||||
modification follow.
|
|
||||||
|
|
||||||
TERMS AND CONDITIONS
|
|
||||||
|
|
||||||
0. Definitions.
|
|
||||||
|
|
||||||
"This License" refers to version 3 of the GNU Affero General Public License.
|
|
||||||
|
|
||||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
|
||||||
works, such as semiconductor masks.
|
|
||||||
|
|
||||||
"The Program" refers to any copyrightable work licensed under this
|
|
||||||
License. Each licensee is addressed as "you". "Licensees" and
|
|
||||||
"recipients" may be individuals or organizations.
|
|
||||||
|
|
||||||
To "modify" a work means to copy from or adapt all or part of the work
|
|
||||||
in a fashion requiring copyright permission, other than the making of an
|
|
||||||
exact copy. The resulting work is called a "modified version" of the
|
|
||||||
earlier work or a work "based on" the earlier work.
|
|
||||||
|
|
||||||
A "covered work" means either the unmodified Program or a work based
|
|
||||||
on the Program.
|
|
||||||
|
|
||||||
To "propagate" a work means to do anything with it that, without
|
|
||||||
permission, would make you directly or secondarily liable for
|
|
||||||
infringement under applicable copyright law, except executing it on a
|
|
||||||
computer or modifying a private copy. Propagation includes copying,
|
|
||||||
distribution (with or without modification), making available to the
|
|
||||||
public, and in some countries other activities as well.
|
|
||||||
|
|
||||||
To "convey" a work means any kind of propagation that enables other
|
|
||||||
parties to make or receive copies. Mere interaction with a user through
|
|
||||||
a computer network, with no transfer of a copy, is not conveying.
|
|
||||||
|
|
||||||
An interactive user interface displays "Appropriate Legal Notices"
|
|
||||||
to the extent that it includes a convenient and prominently visible
|
|
||||||
feature that (1) displays an appropriate copyright notice, and (2)
|
|
||||||
tells the user that there is no warranty for the work (except to the
|
|
||||||
extent that warranties are provided), that licensees may convey the
|
|
||||||
work under this License, and how to view a copy of this License. If
|
|
||||||
the interface presents a list of user commands or options, such as a
|
|
||||||
menu, a prominent item in the list meets this criterion.
|
|
||||||
|
|
||||||
1. Source Code.
|
|
||||||
|
|
||||||
The "source code" for a work means the preferred form of the work
|
|
||||||
for making modifications to it. "Object code" means any non-source
|
|
||||||
form of a work.
|
|
||||||
|
|
||||||
A "Standard Interface" means an interface that either is an official
|
|
||||||
standard defined by a recognized standards body, or, in the case of
|
|
||||||
interfaces specified for a particular programming language, one that
|
|
||||||
is widely used among developers working in that language.
|
|
||||||
|
|
||||||
The "System Libraries" of an executable work include anything, other
|
|
||||||
than the work as a whole, that (a) is included in the normal form of
|
|
||||||
packaging a Major Component, but which is not part of that Major
|
|
||||||
Component, and (b) serves only to enable use of the work with that
|
|
||||||
Major Component, or to implement a Standard Interface for which an
|
|
||||||
implementation is available to the public in source code form. A
|
|
||||||
"Major Component", in this context, means a major essential component
|
|
||||||
(kernel, window system, and so on) of the specific operating system
|
|
||||||
(if any) on which the executable work runs, or a compiler used to
|
|
||||||
produce the work, or an object code interpreter used to run it.
|
|
||||||
|
|
||||||
The "Corresponding Source" for a work in object code form means all
|
|
||||||
the source code needed to generate, install, and (for an executable
|
|
||||||
work) run the object code and to modify the work, including scripts to
|
|
||||||
control those activities. However, it does not include the work's
|
|
||||||
System Libraries, or general-purpose tools or generally available free
|
|
||||||
programs which are used unmodified in performing those activities but
|
|
||||||
which are not part of the work. For example, Corresponding Source
|
|
||||||
includes interface definition files associated with source files for
|
|
||||||
the work, and the source code for shared libraries and dynamically
|
|
||||||
linked subprograms that the work is specifically designed to require,
|
|
||||||
such as by intimate data communication or control flow between those
|
|
||||||
subprograms and other parts of the work.
|
|
||||||
|
|
||||||
The Corresponding Source need not include anything that users
|
|
||||||
can regenerate automatically from other parts of the Corresponding
|
|
||||||
Source.
|
|
||||||
|
|
||||||
The Corresponding Source for a work in source code form is that
|
|
||||||
same work.
|
|
||||||
|
|
||||||
2. Basic Permissions.
|
|
||||||
|
|
||||||
All rights granted under this License are granted for the term of
|
|
||||||
copyright on the Program, and are irrevocable provided the stated
|
|
||||||
conditions are met. This License explicitly affirms your unlimited
|
|
||||||
permission to run the unmodified Program. The output from running a
|
|
||||||
covered work is covered by this License only if the output, given its
|
|
||||||
content, constitutes a covered work. This License acknowledges your
|
|
||||||
rights of fair use or other equivalent, as provided by copyright law.
|
|
||||||
|
|
||||||
You may make, run and propagate covered works that you do not
|
|
||||||
convey, without conditions so long as your license otherwise remains
|
|
||||||
in force. You may convey covered works to others for the sole purpose
|
|
||||||
of having them make modifications exclusively for you, or provide you
|
|
||||||
with facilities for running those works, provided that you comply with
|
|
||||||
the terms of this License in conveying all material for which you do
|
|
||||||
not control copyright. Those thus making or running the covered works
|
|
||||||
for you must do so exclusively on your behalf, under your direction
|
|
||||||
and control, on terms that prohibit them from making any copies of
|
|
||||||
your copyrighted material outside their relationship with you.
|
|
||||||
|
|
||||||
Conveying under any other circumstances is permitted solely under
|
|
||||||
the conditions stated below. Sublicensing is not allowed; section 10
|
|
||||||
makes it unnecessary.
|
|
||||||
|
|
||||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
|
||||||
|
|
||||||
No covered work shall be deemed part of an effective technological
|
|
||||||
measure under any applicable law fulfilling obligations under article
|
|
||||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
|
||||||
similar laws prohibiting or restricting circumvention of such
|
|
||||||
measures.
|
|
||||||
|
|
||||||
When you convey a covered work, you waive any legal power to forbid
|
|
||||||
circumvention of technological measures to the extent such circumvention
|
|
||||||
is effected by exercising rights under this License with respect to
|
|
||||||
the covered work, and you disclaim any intention to limit operation or
|
|
||||||
modification of the work as a means of enforcing, against the work's
|
|
||||||
users, your or third parties' legal rights to forbid circumvention of
|
|
||||||
technological measures.
|
|
||||||
|
|
||||||
4. Conveying Verbatim Copies.
|
|
||||||
|
|
||||||
You may convey verbatim copies of the Program's source code as you
|
|
||||||
receive it, in any medium, provided that you conspicuously and
|
|
||||||
appropriately publish on each copy an appropriate copyright notice;
|
|
||||||
keep intact all notices stating that this License and any
|
|
||||||
non-permissive terms added in accord with section 7 apply to the code;
|
|
||||||
keep intact all notices of the absence of any warranty; and give all
|
|
||||||
recipients a copy of this License along with the Program.
|
|
||||||
|
|
||||||
You may charge any price or no price for each copy that you convey,
|
|
||||||
and you may offer support or warranty protection for a fee.
|
|
||||||
|
|
||||||
5. Conveying Modified Source Versions.
|
|
||||||
|
|
||||||
You may convey a work based on the Program, or the modifications to
|
|
||||||
produce it from the Program, in the form of source code under the
|
|
||||||
terms of section 4, provided that you also meet all of these conditions:
|
|
||||||
|
|
||||||
a) The work must carry prominent notices stating that you modified
|
|
||||||
it, and giving a relevant date.
|
|
||||||
|
|
||||||
b) The work must carry prominent notices stating that it is
|
|
||||||
released under this License and any conditions added under section
|
|
||||||
7. This requirement modifies the requirement in section 4 to
|
|
||||||
"keep intact all notices".
|
|
||||||
|
|
||||||
c) You must license the entire work, as a whole, under this
|
|
||||||
License to anyone who comes into possession of a copy. This
|
|
||||||
License will therefore apply, along with any applicable section 7
|
|
||||||
additional terms, to the whole of the work, and all its parts,
|
|
||||||
regardless of how they are packaged. This License gives no
|
|
||||||
permission to license the work in any other way, but it does not
|
|
||||||
invalidate such permission if you have separately received it.
|
|
||||||
|
|
||||||
d) If the work has interactive user interfaces, each must display
|
|
||||||
Appropriate Legal Notices; however, if the Program has interactive
|
|
||||||
interfaces that do not display Appropriate Legal Notices, your
|
|
||||||
work need not make them do so.
|
|
||||||
|
|
||||||
A compilation of a covered work with other separate and independent
|
|
||||||
works, which are not by their nature extensions of the covered work,
|
|
||||||
and which are not combined with it such as to form a larger program,
|
|
||||||
in or on a volume of a storage or distribution medium, is called an
|
|
||||||
"aggregate" if the compilation and its resulting copyright are not
|
|
||||||
used to limit the access or legal rights of the compilation's users
|
|
||||||
beyond what the individual works permit. Inclusion of a covered work
|
|
||||||
in an aggregate does not cause this License to apply to the other
|
|
||||||
parts of the aggregate.
|
|
||||||
|
|
||||||
6. Conveying Non-Source Forms.
|
|
||||||
|
|
||||||
You may convey a covered work in object code form under the terms
|
|
||||||
of sections 4 and 5, provided that you also convey the
|
|
||||||
machine-readable Corresponding Source under the terms of this License,
|
|
||||||
in one of these ways:
|
|
||||||
|
|
||||||
a) Convey the object code in, or embodied in, a physical product
|
|
||||||
(including a physical distribution medium), accompanied by the
|
|
||||||
Corresponding Source fixed on a durable physical medium
|
|
||||||
customarily used for software interchange.
|
|
||||||
|
|
||||||
b) Convey the object code in, or embodied in, a physical product
|
|
||||||
(including a physical distribution medium), accompanied by a
|
|
||||||
written offer, valid for at least three years and valid for as
|
|
||||||
long as you offer spare parts or customer support for that product
|
|
||||||
model, to give anyone who possesses the object code either (1) a
|
|
||||||
copy of the Corresponding Source for all the software in the
|
|
||||||
product that is covered by this License, on a durable physical
|
|
||||||
medium customarily used for software interchange, for a price no
|
|
||||||
more than your reasonable cost of physically performing this
|
|
||||||
conveying of source, or (2) access to copy the
|
|
||||||
Corresponding Source from a network server at no charge.
|
|
||||||
|
|
||||||
c) Convey individual copies of the object code with a copy of the
|
|
||||||
written offer to provide the Corresponding Source. This
|
|
||||||
alternative is allowed only occasionally and noncommercially, and
|
|
||||||
only if you received the object code with such an offer, in accord
|
|
||||||
with subsection 6b.
|
|
||||||
|
|
||||||
d) Convey the object code by offering access from a designated
|
|
||||||
place (gratis or for a charge), and offer equivalent access to the
|
|
||||||
Corresponding Source in the same way through the same place at no
|
|
||||||
further charge. You need not require recipients to copy the
|
|
||||||
Corresponding Source along with the object code. If the place to
|
|
||||||
copy the object code is a network server, the Corresponding Source
|
|
||||||
may be on a different server (operated by you or a third party)
|
|
||||||
that supports equivalent copying facilities, provided you maintain
|
|
||||||
clear directions next to the object code saying where to find the
|
|
||||||
Corresponding Source. Regardless of what server hosts the
|
|
||||||
Corresponding Source, you remain obligated to ensure that it is
|
|
||||||
available for as long as needed to satisfy these requirements.
|
|
||||||
|
|
||||||
e) Convey the object code using peer-to-peer transmission, provided
|
|
||||||
you inform other peers where the object code and Corresponding
|
|
||||||
Source of the work are being offered to the general public at no
|
|
||||||
charge under subsection 6d.
|
|
||||||
|
|
||||||
A separable portion of the object code, whose source code is excluded
|
|
||||||
from the Corresponding Source as a System Library, need not be
|
|
||||||
included in conveying the object code work.
|
|
||||||
|
|
||||||
A "User Product" is either (1) a "consumer product", which means any
|
|
||||||
tangible personal property which is normally used for personal, family,
|
|
||||||
or household purposes, or (2) anything designed or sold for incorporation
|
|
||||||
into a dwelling. In determining whether a product is a consumer product,
|
|
||||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
|
||||||
product received by a particular user, "normally used" refers to a
|
|
||||||
typical or common use of that class of product, regardless of the status
|
|
||||||
of the particular user or of the way in which the particular user
|
|
||||||
actually uses, or expects or is expected to use, the product. A product
|
|
||||||
is a consumer product regardless of whether the product has substantial
|
|
||||||
commercial, industrial or non-consumer uses, unless such uses represent
|
|
||||||
the only significant mode of use of the product.
|
|
||||||
|
|
||||||
"Installation Information" for a User Product means any methods,
|
|
||||||
procedures, authorization keys, or other information required to install
|
|
||||||
and execute modified versions of a covered work in that User Product from
|
|
||||||
a modified version of its Corresponding Source. The information must
|
|
||||||
suffice to ensure that the continued functioning of the modified object
|
|
||||||
code is in no case prevented or interfered with solely because
|
|
||||||
modification has been made.
|
|
||||||
|
|
||||||
If you convey an object code work under this section in, or with, or
|
|
||||||
specifically for use in, a User Product, and the conveying occurs as
|
|
||||||
part of a transaction in which the right of possession and use of the
|
|
||||||
User Product is transferred to the recipient in perpetuity or for a
|
|
||||||
fixed term (regardless of how the transaction is characterized), the
|
|
||||||
Corresponding Source conveyed under this section must be accompanied
|
|
||||||
by the Installation Information. But this requirement does not apply
|
|
||||||
if neither you nor any third party retains the ability to install
|
|
||||||
modified object code on the User Product (for example, the work has
|
|
||||||
been installed in ROM).
|
|
||||||
|
|
||||||
The requirement to provide Installation Information does not include a
|
|
||||||
requirement to continue to provide support service, warranty, or updates
|
|
||||||
for a work that has been modified or installed by the recipient, or for
|
|
||||||
the User Product in which it has been modified or installed. Access to a
|
|
||||||
network may be denied when the modification itself materially and
|
|
||||||
adversely affects the operation of the network or violates the rules and
|
|
||||||
protocols for communication across the network.
|
|
||||||
|
|
||||||
Corresponding Source conveyed, and Installation Information provided,
|
|
||||||
in accord with this section must be in a format that is publicly
|
|
||||||
documented (and with an implementation available to the public in
|
|
||||||
source code form), and must require no special password or key for
|
|
||||||
unpacking, reading or copying.
|
|
||||||
|
|
||||||
7. Additional Terms.
|
|
||||||
|
|
||||||
"Additional permissions" are terms that supplement the terms of this
|
|
||||||
License by making exceptions from one or more of its conditions.
|
|
||||||
Additional permissions that are applicable to the entire Program shall
|
|
||||||
be treated as though they were included in this License, to the extent
|
|
||||||
that they are valid under applicable law. If additional permissions
|
|
||||||
apply only to part of the Program, that part may be used separately
|
|
||||||
under those permissions, but the entire Program remains governed by
|
|
||||||
this License without regard to the additional permissions.
|
|
||||||
|
|
||||||
When you convey a copy of a covered work, you may at your option
|
|
||||||
remove any additional permissions from that copy, or from any part of
|
|
||||||
it. (Additional permissions may be written to require their own
|
|
||||||
removal in certain cases when you modify the work.) You may place
|
|
||||||
additional permissions on material, added by you to a covered work,
|
|
||||||
for which you have or can give appropriate copyright permission.
|
|
||||||
|
|
||||||
Notwithstanding any other provision of this License, for material you
|
|
||||||
add to a covered work, you may (if authorized by the copyright holders of
|
|
||||||
that material) supplement the terms of this License with terms:
|
|
||||||
|
|
||||||
a) Disclaiming warranty or limiting liability differently from the
|
|
||||||
terms of sections 15 and 16 of this License; or
|
|
||||||
|
|
||||||
b) Requiring preservation of specified reasonable legal notices or
|
|
||||||
author attributions in that material or in the Appropriate Legal
|
|
||||||
Notices displayed by works containing it; or
|
|
||||||
|
|
||||||
c) Prohibiting misrepresentation of the origin of that material, or
|
|
||||||
requiring that modified versions of such material be marked in
|
|
||||||
reasonable ways as different from the original version; or
|
|
||||||
|
|
||||||
d) Limiting the use for publicity purposes of names of licensors or
|
|
||||||
authors of the material; or
|
|
||||||
|
|
||||||
e) Declining to grant rights under trademark law for use of some
|
|
||||||
trade names, trademarks, or service marks; or
|
|
||||||
|
|
||||||
f) Requiring indemnification of licensors and authors of that
|
|
||||||
material by anyone who conveys the material (or modified versions of
|
|
||||||
it) with contractual assumptions of liability to the recipient, for
|
|
||||||
any liability that these contractual assumptions directly impose on
|
|
||||||
those licensors and authors.
|
|
||||||
|
|
||||||
All other non-permissive additional terms are considered "further
|
|
||||||
restrictions" within the meaning of section 10. If the Program as you
|
|
||||||
received it, or any part of it, contains a notice stating that it is
|
|
||||||
governed by this License along with a term that is a further
|
|
||||||
restriction, you may remove that term. If a license document contains
|
|
||||||
a further restriction but permits relicensing or conveying under this
|
|
||||||
License, you may add to a covered work material governed by the terms
|
|
||||||
of that license document, provided that the further restriction does
|
|
||||||
not survive such relicensing or conveying.
|
|
||||||
|
|
||||||
If you add terms to a covered work in accord with this section, you
|
|
||||||
must place, in the relevant source files, a statement of the
|
|
||||||
additional terms that apply to those files, or a notice indicating
|
|
||||||
where to find the applicable terms.
|
|
||||||
|
|
||||||
Additional terms, permissive or non-permissive, may be stated in the
|
|
||||||
form of a separately written license, or stated as exceptions;
|
|
||||||
the above requirements apply either way.
|
|
||||||
|
|
||||||
8. Termination.
|
|
||||||
|
|
||||||
You may not propagate or modify a covered work except as expressly
|
|
||||||
provided under this License. Any attempt otherwise to propagate or
|
|
||||||
modify it is void, and will automatically terminate your rights under
|
|
||||||
this License (including any patent licenses granted under the third
|
|
||||||
paragraph of section 11).
|
|
||||||
|
|
||||||
However, if you cease all violation of this License, then your
|
|
||||||
license from a particular copyright holder is reinstated (a)
|
|
||||||
provisionally, unless and until the copyright holder explicitly and
|
|
||||||
finally terminates your license, and (b) permanently, if the copyright
|
|
||||||
holder fails to notify you of the violation by some reasonable means
|
|
||||||
prior to 60 days after the cessation.
|
|
||||||
|
|
||||||
Moreover, your license from a particular copyright holder is
|
|
||||||
reinstated permanently if the copyright holder notifies you of the
|
|
||||||
violation by some reasonable means, this is the first time you have
|
|
||||||
received notice of violation of this License (for any work) from that
|
|
||||||
copyright holder, and you cure the violation prior to 30 days after
|
|
||||||
your receipt of the notice.
|
|
||||||
|
|
||||||
Termination of your rights under this section does not terminate the
|
|
||||||
licenses of parties who have received copies or rights from you under
|
|
||||||
this License. If your rights have been terminated and not permanently
|
|
||||||
reinstated, you do not qualify to receive new licenses for the same
|
|
||||||
material under section 10.
|
|
||||||
|
|
||||||
9. Acceptance Not Required for Having Copies.
|
|
||||||
|
|
||||||
You are not required to accept this License in order to receive or
|
|
||||||
run a copy of the Program. Ancillary propagation of a covered work
|
|
||||||
occurring solely as a consequence of using peer-to-peer transmission
|
|
||||||
to receive a copy likewise does not require acceptance. However,
|
|
||||||
nothing other than this License grants you permission to propagate or
|
|
||||||
modify any covered work. These actions infringe copyright if you do
|
|
||||||
not accept this License. Therefore, by modifying or propagating a
|
|
||||||
covered work, you indicate your acceptance of this License to do so.
|
|
||||||
|
|
||||||
10. Automatic Licensing of Downstream Recipients.
|
|
||||||
|
|
||||||
Each time you convey a covered work, the recipient automatically
|
|
||||||
receives a license from the original licensors, to run, modify and
|
|
||||||
propagate that work, subject to this License. You are not responsible
|
|
||||||
for enforcing compliance by third parties with this License.
|
|
||||||
|
|
||||||
An "entity transaction" is a transaction transferring control of an
|
|
||||||
organization, or substantially all assets of one, or subdividing an
|
|
||||||
organization, or merging organizations. If propagation of a covered
|
|
||||||
work results from an entity transaction, each party to that
|
|
||||||
transaction who receives a copy of the work also receives whatever
|
|
||||||
licenses to the work the party's predecessor in interest had or could
|
|
||||||
give under the previous paragraph, plus a right to possession of the
|
|
||||||
Corresponding Source of the work from the predecessor in interest, if
|
|
||||||
the predecessor has it or can get it with reasonable efforts.
|
|
||||||
|
|
||||||
You may not impose any further restrictions on the exercise of the
|
|
||||||
rights granted or affirmed under this License. For example, you may
|
|
||||||
not impose a license fee, royalty, or other charge for exercise of
|
|
||||||
rights granted under this License, and you may not initiate litigation
|
|
||||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
|
||||||
any patent claim is infringed by making, using, selling, offering for
|
|
||||||
sale, or importing the Program or any portion of it.
|
|
||||||
|
|
||||||
11. Patents.
|
|
||||||
|
|
||||||
A "contributor" is a copyright holder who authorizes use under this
|
|
||||||
License of the Program or a work on which the Program is based. The
|
|
||||||
work thus licensed is called the contributor's "contributor version".
|
|
||||||
|
|
||||||
A contributor's "essential patent claims" are all patent claims
|
|
||||||
owned or controlled by the contributor, whether already acquired or
|
|
||||||
hereafter acquired, that would be infringed by some manner, permitted
|
|
||||||
by this License, of making, using, or selling its contributor version,
|
|
||||||
but do not include claims that would be infringed only as a
|
|
||||||
consequence of further modification of the contributor version. For
|
|
||||||
purposes of this definition, "control" includes the right to grant
|
|
||||||
patent sublicenses in a manner consistent with the requirements of
|
|
||||||
this License.
|
|
||||||
|
|
||||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
|
||||||
patent license under the contributor's essential patent claims, to
|
|
||||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
|
||||||
propagate the contents of its contributor version.
|
|
||||||
|
|
||||||
In the following three paragraphs, a "patent license" is any express
|
|
||||||
agreement or commitment, however denominated, not to enforce a patent
|
|
||||||
(such as an express permission to practice a patent or covenant not to
|
|
||||||
sue for patent infringement). To "grant" such a patent license to a
|
|
||||||
party means to make such an agreement or commitment not to enforce a
|
|
||||||
patent against the party.
|
|
||||||
|
|
||||||
If you convey a covered work, knowingly relying on a patent license,
|
|
||||||
and the Corresponding Source of the work is not available for anyone
|
|
||||||
to copy, free of charge and under the terms of this License, through a
|
|
||||||
publicly available network server or other readily accessible means,
|
|
||||||
then you must either (1) cause the Corresponding Source to be so
|
|
||||||
available, or (2) arrange to deprive yourself of the benefit of the
|
|
||||||
patent license for this particular work, or (3) arrange, in a manner
|
|
||||||
consistent with the requirements of this License, to extend the patent
|
|
||||||
license to downstream recipients. "Knowingly relying" means you have
|
|
||||||
actual knowledge that, but for the patent license, your conveying the
|
|
||||||
covered work in a country, or your recipient's use of the covered work
|
|
||||||
in a country, would infringe one or more identifiable patents in that
|
|
||||||
country that you have reason to believe are valid.
|
|
||||||
|
|
||||||
If, pursuant to or in connection with a single transaction or
|
|
||||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
|
||||||
covered work, and grant a patent license to some of the parties
|
|
||||||
receiving the covered work authorizing them to use, propagate, modify
|
|
||||||
or convey a specific copy of the covered work, then the patent license
|
|
||||||
you grant is automatically extended to all recipients of the covered
|
|
||||||
work and works based on it.
|
|
||||||
|
|
||||||
A patent license is "discriminatory" if it does not include within
|
|
||||||
the scope of its coverage, prohibits the exercise of, or is
|
|
||||||
conditioned on the non-exercise of one or more of the rights that are
|
|
||||||
specifically granted under this License. You may not convey a covered
|
|
||||||
work if you are a party to an arrangement with a third party that is
|
|
||||||
in the business of distributing software, under which you make payment
|
|
||||||
to the third party based on the extent of your activity of conveying
|
|
||||||
the work, and under which the third party grants, to any of the
|
|
||||||
parties who would receive the covered work from you, a discriminatory
|
|
||||||
patent license (a) in connection with copies of the covered work
|
|
||||||
conveyed by you (or copies made from those copies), or (b) primarily
|
|
||||||
for and in connection with specific products or compilations that
|
|
||||||
contain the covered work, unless you entered into that arrangement,
|
|
||||||
or that patent license was granted, prior to 28 March 2007.
|
|
||||||
|
|
||||||
Nothing in this License shall be construed as excluding or limiting
|
|
||||||
any implied license or other defenses to infringement that may
|
|
||||||
otherwise be available to you under applicable patent law.
|
|
||||||
|
|
||||||
12. No Surrender of Others' Freedom.
|
|
||||||
|
|
||||||
If conditions are imposed on you (whether by court order, agreement or
|
|
||||||
otherwise) that contradict the conditions of this License, they do not
|
|
||||||
excuse you from the conditions of this License. If you cannot convey a
|
|
||||||
covered work so as to satisfy simultaneously your obligations under this
|
|
||||||
License and any other pertinent obligations, then as a consequence you may
|
|
||||||
not convey it at all. For example, if you agree to terms that obligate you
|
|
||||||
to collect a royalty for further conveying from those to whom you convey
|
|
||||||
the Program, the only way you could satisfy both those terms and this
|
|
||||||
License would be to refrain entirely from conveying the Program.
|
|
||||||
|
|
||||||
13. Remote Network Interaction; Use with the GNU General Public License.
|
|
||||||
|
|
||||||
Notwithstanding any other provision of this License, if you modify the
|
|
||||||
Program, your modified version must prominently offer all users
|
|
||||||
interacting with it remotely through a computer network (if your version
|
|
||||||
supports such interaction) an opportunity to receive the Corresponding
|
|
||||||
Source of your version by providing access to the Corresponding Source
|
|
||||||
from a network server at no charge, through some standard or customary
|
|
||||||
means of facilitating copying of software. This Corresponding Source
|
|
||||||
shall include the Corresponding Source for any work covered by version 3
|
|
||||||
of the GNU General Public License that is incorporated pursuant to the
|
|
||||||
following paragraph.
|
|
||||||
|
|
||||||
Notwithstanding any other provision of this License, you have
|
|
||||||
permission to link or combine any covered work with a work licensed
|
|
||||||
under version 3 of the GNU General Public License into a single
|
|
||||||
combined work, and to convey the resulting work. The terms of this
|
|
||||||
License will continue to apply to the part which is the covered work,
|
|
||||||
but the work with which it is combined will remain governed by version
|
|
||||||
3 of the GNU General Public License.
|
|
||||||
|
|
||||||
14. Revised Versions of this License.
|
|
||||||
|
|
||||||
The Free Software Foundation may publish revised and/or new versions of
|
|
||||||
the GNU Affero General Public License from time to time. Such new versions
|
|
||||||
will be similar in spirit to the present version, but may differ in detail to
|
|
||||||
address new problems or concerns.
|
|
||||||
|
|
||||||
Each version is given a distinguishing version number. If the
|
|
||||||
Program specifies that a certain numbered version of the GNU Affero General
|
|
||||||
Public License "or any later version" applies to it, you have the
|
|
||||||
option of following the terms and conditions either of that numbered
|
|
||||||
version or of any later version published by the Free Software
|
|
||||||
Foundation. If the Program does not specify a version number of the
|
|
||||||
GNU Affero General Public License, you may choose any version ever published
|
|
||||||
by the Free Software Foundation.
|
|
||||||
|
|
||||||
If the Program specifies that a proxy can decide which future
|
|
||||||
versions of the GNU Affero General Public License can be used, that proxy's
|
|
||||||
public statement of acceptance of a version permanently authorizes you
|
|
||||||
to choose that version for the Program.
|
|
||||||
|
|
||||||
Later license versions may give you additional or different
|
|
||||||
permissions. However, no additional obligations are imposed on any
|
|
||||||
author or copyright holder as a result of your choosing to follow a
|
|
||||||
later version.
|
|
||||||
|
|
||||||
15. Disclaimer of Warranty.
|
|
||||||
|
|
||||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
|
||||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
|
||||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
|
||||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
|
||||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
||||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
|
||||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
|
||||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
|
||||||
|
|
||||||
16. Limitation of Liability.
|
|
||||||
|
|
||||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
|
||||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
|
||||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
|
||||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
|
||||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
|
||||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
|
||||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
|
||||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
|
||||||
SUCH DAMAGES.
|
|
||||||
|
|
||||||
17. Interpretation of Sections 15 and 16.
|
|
||||||
|
|
||||||
If the disclaimer of warranty and limitation of liability provided
|
|
||||||
above cannot be given local legal effect according to their terms,
|
|
||||||
reviewing courts shall apply local law that most closely approximates
|
|
||||||
an absolute waiver of all civil liability in connection with the
|
|
||||||
Program, unless a warranty or assumption of liability accompanies a
|
|
||||||
copy of the Program in return for a fee.
|
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
|
||||||
|
|
||||||
How to Apply These Terms to Your New Programs
|
|
||||||
|
|
||||||
If you develop a new program, and you want it to be of the greatest
|
|
||||||
possible use to the public, the best way to achieve this is to make it
|
|
||||||
free software which everyone can redistribute and change under these terms.
|
|
||||||
|
|
||||||
To do so, attach the following notices to the program. It is safest
|
|
||||||
to attach them to the start of each source file to most effectively
|
|
||||||
state the exclusion of warranty; and each file should have at least
|
|
||||||
the "copyright" line and a pointer to where the full notice is found.
|
|
||||||
|
|
||||||
<one line to give the program's name and a brief idea of what it does.>
|
|
||||||
Copyright (C) <year> <name of author>
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Affero General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Affero General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
Also add information on how to contact you by electronic and paper mail.
|
|
||||||
|
|
||||||
If your software can interact with users remotely through a computer
|
|
||||||
network, you should also make sure that it provides a way for users to
|
|
||||||
get its source. For example, if your program is a web application, its
|
|
||||||
interface could display a "Source" link that leads users to an archive
|
|
||||||
of the code. There are many ways you could offer source, and different
|
|
||||||
solutions will be better for different programs; see section 13 for the
|
|
||||||
specific requirements.
|
|
||||||
|
|
||||||
You should also get your employer (if you work as a programmer) or school,
|
|
||||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
|
||||||
For more information on this, and how to apply and follow the GNU AGPL, see
|
|
||||||
<http://www.gnu.org/licenses/>.
|
|
||||||
99
CREDITS.md
Normal file
99
CREDITS.md
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
Credits for GNU social
|
||||||
|
======================
|
||||||
|
The following is an incomplete list of developers
|
||||||
|
who've worked on GNU social, or its predecessors
|
||||||
|
StatusNet and Free Social. Apologies for any
|
||||||
|
oversight; please let mattl@gnu.org know if
|
||||||
|
anyone's been overlooked in error.
|
||||||
|
|
||||||
|
Current team
|
||||||
|
------------
|
||||||
|
* Alexei Sorokin
|
||||||
|
* Bruno Casteleiro
|
||||||
|
* Diogo Cordeiro
|
||||||
|
* Hugo Sales
|
||||||
|
|
||||||
|
Additional Contributors
|
||||||
|
-----------------------
|
||||||
|
* Akio
|
||||||
|
* Blaine Cook
|
||||||
|
* Bob Mottram
|
||||||
|
* Brenda Wallace
|
||||||
|
* Brett Taylor
|
||||||
|
* Brian Hendrickson
|
||||||
|
* Brigitte Schuster
|
||||||
|
* Ciaran Gultnieks
|
||||||
|
* Craig Andrews
|
||||||
|
* Daniel Supernault
|
||||||
|
* Dan Moore
|
||||||
|
* David Yip
|
||||||
|
* Deb Nicholson
|
||||||
|
* Donald Robertson
|
||||||
|
* Eric Helgeson
|
||||||
|
* Federico Marani
|
||||||
|
* Fil
|
||||||
|
* Garret Buell
|
||||||
|
* Henry Story
|
||||||
|
* Ian Denhart
|
||||||
|
* Jeffery To
|
||||||
|
* Jeff Mitchell
|
||||||
|
* Ken Sedgwick
|
||||||
|
* Leslie Michael Orchard
|
||||||
|
* Maiyannah Bishop
|
||||||
|
* Matthew Gregg
|
||||||
|
* Matt Lee
|
||||||
|
* mEDI
|
||||||
|
* Melvin Carvalho
|
||||||
|
* Michael Landers
|
||||||
|
* Miguel Dantas
|
||||||
|
* Mikael Nordfeldth
|
||||||
|
* Mike Cochrane
|
||||||
|
* Moonman
|
||||||
|
* Neil E Hodges
|
||||||
|
* Normandy
|
||||||
|
* Ori Avtalion
|
||||||
|
* Sean Murphy
|
||||||
|
* Stéphane Bérubé
|
||||||
|
* Steven DuBois
|
||||||
|
* Tobias Diekershoff
|
||||||
|
* Verius
|
||||||
|
|
||||||
|
Credits for StatusNet
|
||||||
|
--------------
|
||||||
|
Leads
|
||||||
|
* Evan Prodromou
|
||||||
|
* Zach Copley
|
||||||
|
|
||||||
|
Team
|
||||||
|
* Adrian Lang
|
||||||
|
* Brion Vibber
|
||||||
|
* 'drry'
|
||||||
|
* Earle Martin
|
||||||
|
* Erik Stambaugh
|
||||||
|
* Florian Biree
|
||||||
|
* Gina Haeussge
|
||||||
|
* James Walker
|
||||||
|
* Joshua Judson Rosen (rozzin)
|
||||||
|
* Ken Sheppardson
|
||||||
|
* Marie-Claude Doyon
|
||||||
|
* Meitar Moscovitz
|
||||||
|
* Ori Avtalion
|
||||||
|
* Robin Millette
|
||||||
|
* Samantha Doherty
|
||||||
|
* Sarven Capadisli
|
||||||
|
* Simon Waters, Surevine
|
||||||
|
* Tryggvi Björgvinsson
|
||||||
|
|
||||||
|
Translators
|
||||||
|
-----------
|
||||||
|
* Siebrand Mazeland
|
||||||
|
* Tiago 'gouki' Faria
|
||||||
|
* TranslateWiki.net
|
||||||
|
|
||||||
|
A special thanks to the thousands of people who
|
||||||
|
have tried out GNU social, told their friends, and
|
||||||
|
built the fediverse network to what it is today.
|
||||||
|
|
||||||
|
License help from
|
||||||
|
-----------------
|
||||||
|
* Bradley M. Kuhn
|
||||||
3
DOCUMENTATION/DEVELOPERS/defaults.md
Normal file
3
DOCUMENTATION/DEVELOPERS/defaults.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
In the `dev` environment, the default values for the config table are reloaded on each HTTP request
|
||||||
|
|
||||||
|
In case you want to override this, add `SOCIAL_NO_RELOAD_DEFAULTS=1` to your .env.local file
|
||||||
1
DOCUMENTATION/DEVELOPERS/install.md
Symbolic link
1
DOCUMENTATION/DEVELOPERS/install.md
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../../INSTALL.md
|
||||||
762
DOCUMENTATION/SYSTEM_ADMINISTRATORS/CONFIGURE.md
Normal file
762
DOCUMENTATION/SYSTEM_ADMINISTRATORS/CONFIGURE.md
Normal file
@@ -0,0 +1,762 @@
|
|||||||
|
Configuration options
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
The configuration for GNU social is stored in the database table
|
||||||
|
`config`.
|
||||||
|
|
||||||
|
A Web based configuration panel exists so the site admin can configure
|
||||||
|
GNU social. The preferred method for changing config options is to use this
|
||||||
|
panel.
|
||||||
|
|
||||||
|
A command-line script, `set_config.php`, can be used to set individual
|
||||||
|
configuration options. It's in the `bin/` directory.
|
||||||
|
|
||||||
|
Almost all configuration options are made through a two-dimensional
|
||||||
|
associative array, cleverly named `$config`. A typical configuration
|
||||||
|
line will be:
|
||||||
|
|
||||||
|
$config['section']['setting] = value;
|
||||||
|
|
||||||
|
The following documentation describes each section and setting.
|
||||||
|
|
||||||
|
|
||||||
|
site
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
This section is a catch-all for site-wide variables.
|
||||||
|
|
||||||
|
* `name` (string, required, defaults to the value provided in the configre script,
|
||||||
|
sitename): the name of your site, like 'YourCompany Microblog'.
|
||||||
|
|
||||||
|
* `server` (string, required, defaults to the value provided in the configre script,
|
||||||
|
sitename): the server domain, like 'example.net'.
|
||||||
|
|
||||||
|
* `notice` (string, default null): A plain string that will appear on every page. A good
|
||||||
|
place to put introductory information about your service, or info about upgrades and
|
||||||
|
outages, or other community info. Any HTML will be escaped.
|
||||||
|
|
||||||
|
* `theme` (string, default 'default'): Theme for your site (see Theme section).
|
||||||
|
|
||||||
|
* `logo` (string, default null): URL of an image file to use as the logo for the site.
|
||||||
|
Overrides the logo in the theme, if any.
|
||||||
|
|
||||||
|
* `language` (string, default "en"): default language for your site. Defaults to English.
|
||||||
|
Note that this is overridden, if enabled in the following setting, if a user is logged
|
||||||
|
in and has selected a different language or if the user is NOT logged in, but their
|
||||||
|
browser requests a different langauge. Since pretty much everybody's browser requests
|
||||||
|
a language, that means that changing this setting has little or no effect in practice.
|
||||||
|
|
||||||
|
* `detect_language` (boolean, default true): whether to use the most appropriate language
|
||||||
|
depending on the requester's browser preferences.
|
||||||
|
|
||||||
|
* `languages` (array, default null): A list of languages supported on your site. Typically
|
||||||
|
you'd only change this if you wanted to disable support for one or more languages:
|
||||||
|
|
||||||
|
`unset($config['site']['languages']['de'])` will disable support for German.
|
||||||
|
|
||||||
|
* `email` (string, required): contact email address for your site. By default, it's
|
||||||
|
extracted from your Web server environment or the value provided in the configure
|
||||||
|
script; you may want to customize it.
|
||||||
|
|
||||||
|
* `recovery_disclose` (boolean, default false): whether to confirm if the email exists
|
||||||
|
when attempting to login. Recommended to keep it false, for some privacy.
|
||||||
|
|
||||||
|
* `timezone` (string, default 'UTC'): default timezone for message display. Users
|
||||||
|
can set their own time zone. Defaults to 'UTC', which is a pretty good
|
||||||
|
default.
|
||||||
|
|
||||||
|
* `brought_by` (string, default null): text used for the "brought by" link.
|
||||||
|
|
||||||
|
* `brought_by_url` (string, default null): name of an organization or individual who
|
||||||
|
provides the service. Each page will include a link to this name in the footer or
|
||||||
|
sidebar. A good way to link to the blog, forum, wiki, corporate portal, or whoever is
|
||||||
|
making the service available.
|
||||||
|
|
||||||
|
* `closed` (boolean, default false): If set to 'true', will disallow registration on your
|
||||||
|
site. This is a easy way to restrict accounts to only one individual or group; just
|
||||||
|
register the accounts you want on the service, *then* set this variable to 'true'.
|
||||||
|
|
||||||
|
* `invite_only` (boolean, default false): If set to 'true', will only allow registration
|
||||||
|
if the user was invited by an existing user.
|
||||||
|
|
||||||
|
* `private` (boolean, default false): If set to 'true', anonymous users will be redirected
|
||||||
|
to the 'login' page. Also, API methods that normally require no authentication will
|
||||||
|
require it. Note that this does not turn off registration; use 'closed' or
|
||||||
|
'invite_only' for that behaviour.
|
||||||
|
|
||||||
|
* `ssl` (enum['always', 'sometimes', 'never'], default always'): Whether to use SSL and
|
||||||
|
https:// URLs for some or all pages.
|
||||||
|
|
||||||
|
Possible values are 'always' (use it for all pages), 'never' (don't use it for any
|
||||||
|
pages), or 'sometimes' (use it for sensitive pages that include passwords like login
|
||||||
|
and registration, but not for regular pages).
|
||||||
|
|
||||||
|
* `ssl_proxy` (string|boolean, default false): Whether to force GNUsocial to think it is
|
||||||
|
HTTPS when the server gives no such information. I.e. when you're using a reverse
|
||||||
|
proxy that adds the encryption layer but the webserver that runs PHP isn't configured
|
||||||
|
with a key and certificate. If a string is given, it will be used as the URL of the
|
||||||
|
proxy server.
|
||||||
|
|
||||||
|
* `duplicate_time_limit` (integer, default 60): minimum time allowed for one person to say
|
||||||
|
the same thing twice. Default 60s. If it happens faster than this, it's considered a
|
||||||
|
user or UI error.
|
||||||
|
|
||||||
|
* `text_limit` (integer, default 1000): default max size for texts in the site. Can be
|
||||||
|
fine-tuned for notices, messages, profile bios and group descriptions. Zero indicates
|
||||||
|
no limit.
|
||||||
|
|
||||||
|
* `x-static-delivery` (string, default null): when a string, use this as the header with
|
||||||
|
which to serve static files. Possible values are 'X-Sendfile' (for Apache and others)
|
||||||
|
and 'X-Accel-Redirect' (for nginx).
|
||||||
|
|
||||||
|
|
||||||
|
security
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
* `hash_algos` (array, default ['sha1', 'sha256', 'sha512']): set to null for anything
|
||||||
|
that `hash_hmac()` can handle; can be any combination of the result of `hash_algos()`
|
||||||
|
|
||||||
|
|
||||||
|
db
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
* `mirror` (array, default null): you can set this to an array of database connection
|
||||||
|
URIs. If it's set, load will be split among these, and replication will be enabled.
|
||||||
|
|
||||||
|
|
||||||
|
fix
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
* `fancy_urls` (boolean, default true): fix any non-facy url to the correct form, when
|
||||||
|
possible.
|
||||||
|
|
||||||
|
* `http` (boolean, default true): fixe any http links to https.
|
||||||
|
|
||||||
|
|
||||||
|
queue
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
You can configure the software to queue time-consuming tasks, like
|
||||||
|
sending out SMS, email or XMPP messages, for off-line processing.
|
||||||
|
|
||||||
|
* `enabled` (boolean, default true): Whether to uses queues.
|
||||||
|
|
||||||
|
* `daemon` (boolean, default false): Whether to use queuedaemon. False means
|
||||||
|
you'll use OpportunisticQM plugin.
|
||||||
|
|
||||||
|
* `threads` (int): How many queue processes to run. Defaults to number of cpu cores in
|
||||||
|
unix-like systems or 1 on other OSes.
|
||||||
|
|
||||||
|
* `subsystem` (enum["db", "stomp", "redis"], default 'db'): Which kind of
|
||||||
|
queueserver to use. Values include "db" for our database queuing (no other server
|
||||||
|
required), "stomp" for a stomp server amd "redis" for a Redis server.
|
||||||
|
|
||||||
|
* `basename` (string, default '/queue/gnusocial/'): a root name to use for queues (stomp
|
||||||
|
and redis only). Typically something like '/queue/sitename/' makes sense. If running
|
||||||
|
multiple instances on the same server, make sure that either this setting or
|
||||||
|
`$config['site']['nickname']` are unique for each site to keep them separate.
|
||||||
|
|
||||||
|
* `control_channel` (string, default '/topic/gnusocial/control'): the control channel used
|
||||||
|
for different queue processes to communicate.
|
||||||
|
|
||||||
|
* `monitor` (string, default null): URL endpoint to monitor queue status
|
||||||
|
|
||||||
|
* `soft_limit` (string, default '90%'): an absolute or relative "soft memory limit";
|
||||||
|
daemons will restart themselves gracefully when they find they've hit this amount of
|
||||||
|
memory usage. Relative means a percentage of PHP's global `memory_limit` setting.
|
||||||
|
|
||||||
|
* `spawn_delay` (integer, default 1): seconds to wait between deamon restarts.
|
||||||
|
|
||||||
|
* `debug_memory` (boolean, default false): log daemon's memory usage.
|
||||||
|
|
||||||
|
* `stomp_server` (string, default null): URI for stomp server. Something like
|
||||||
|
"tcp://hostname:61613". More complicated ones are possible; see your stomp server's
|
||||||
|
documentation for details.
|
||||||
|
|
||||||
|
* `stomp_username` (string, default null): username for connecting to the stomp server.
|
||||||
|
|
||||||
|
* `stomp_password` (string, default null): password for connecting to the stomp server.
|
||||||
|
|
||||||
|
* `stomp_persistent` (boolean, default true): Keep items across queue server restart, if
|
||||||
|
enabled. Note: Under ActiveMQ, the server configuration determines if and how
|
||||||
|
persistent storage is actually saved. Not all stomp servers support persistence.
|
||||||
|
|
||||||
|
* `stomp_transactions` (boolean, default true): use transactions to aid in error
|
||||||
|
detection. A broken transaction will be seen quickly, allowing a message to be
|
||||||
|
redelivered immediately if a daemon crashes. Not all stop servers support
|
||||||
|
transactions.
|
||||||
|
|
||||||
|
* `stomp_acks` (boolean, default true): send acknowledgements to aid in flow control. An
|
||||||
|
acknowledgement of successful processing tells the server we're ready for more and can
|
||||||
|
help keep things moving smoothly. This should *not* be turned off when running with
|
||||||
|
ActiveMQ, (it breaks if you do), but if using another message queue server that does
|
||||||
|
not support acknowledgements you might need to disable this.
|
||||||
|
|
||||||
|
* `stomp_manual_failover` (boolean, default true): if multiple servers are listed, treat
|
||||||
|
them as separate (enqueue on one randomly, listen on all).
|
||||||
|
|
||||||
|
* `max_retries` (integer, default 10): for stomp, drop messages after N failed
|
||||||
|
attempts to process.
|
||||||
|
|
||||||
|
* `dead_letter_dir` (string, default null): for stomp, optional directory to dump
|
||||||
|
data on failed queue processing events after discarding them.
|
||||||
|
|
||||||
|
|
||||||
|
avatar
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
* `server` (string, default null): If set, defines another server where avatars are
|
||||||
|
stored. Note that the `dir` still has to be writeable. You'd typically use this to
|
||||||
|
split HTTP requests on the client to speed up page loading, either with another
|
||||||
|
virtual server or with an NFS or SAMBA share. Clients typically only make 2
|
||||||
|
connections to a single server at a time
|
||||||
|
<https://www.w3.org/Protocols/rfc2616/rfc2616-sec8.html#sec8.1.4>, so this can
|
||||||
|
parallelize the job.
|
||||||
|
|
||||||
|
* `url_base` (string, 'default '/avatar/'): URL where avatars can be found.
|
||||||
|
|
||||||
|
* `ssl` (boolean, default null): Whether to access avatars using HTTPS. Defaults
|
||||||
|
to null, meaning to guess based on site-wide SSL settings.
|
||||||
|
|
||||||
|
* `dir` (string, default 'file/avatar/'): Directory to save avatar files to.
|
||||||
|
|
||||||
|
* `max_size_px` (integer, default 300): Maximum width or height for user avatars, in pixels
|
||||||
|
|
||||||
|
|
||||||
|
javascript
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
* `server` (string, default null): You can speed up page loading by pointing the
|
||||||
|
javascript file lookup to another server (virtual or real). Defaults to NULL, meaning
|
||||||
|
to use the site server.
|
||||||
|
|
||||||
|
* `url_base` (string default '/js/'): URL part for JavaScript files.
|
||||||
|
|
||||||
|
* `ssl` (boolean, default null): Whether to use SSL for JavaScript files. Default is null,
|
||||||
|
which means guess based on site SSL settings.
|
||||||
|
|
||||||
|
* `bust_frames` (boolean, default true): If true, all web pages will break out of
|
||||||
|
framesets. If false, can comfortably live in a frame or iframe... probably.
|
||||||
|
|
||||||
|
|
||||||
|
attachments
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
* `server` (string, default null): Server name to use when creating URLs for uploaded
|
||||||
|
files. Defaults to null, meaning to use the default Web server. Using a virtual server
|
||||||
|
here can speed up Web performance.
|
||||||
|
|
||||||
|
* `url_base` (string, default '/file/'): URL path, relative to the server, to find
|
||||||
|
files. Defaults to main path + '/file/'.
|
||||||
|
|
||||||
|
* `ssl` (boolean, default null): Whether to use HTTPS for file URLs. Defaults to null,
|
||||||
|
meaning to use other SSL settings.
|
||||||
|
|
||||||
|
* `dir` (string, default '/file/uploads/'): Directory accessible to the Web process where
|
||||||
|
uploads should go.
|
||||||
|
|
||||||
|
* `supported` (array): An associative array of mime types you accept to store and
|
||||||
|
distribute, like 'image/gif', 'video/mpeg', 'audio/mpeg', to the corresponding file
|
||||||
|
extension. Make sure you setup your server to properly recognize the types you want to
|
||||||
|
support. It's important to use the result of calling `image_type_to_extension` for the
|
||||||
|
appropriate image type, in the case of images. This is so all parts of the code see
|
||||||
|
the same file extension for each image type (jpg vs jpeg). For example, to enable BMP
|
||||||
|
uploads, add this to the config.php file:
|
||||||
|
`image_type_to_mime_type(IMAGETYPE_BMP) => image_type_to_extension(IMAGETYPE_BMP);` See
|
||||||
|
https://www.php.net/manual/en/function.image-type-to-mime-type.php for a list of such
|
||||||
|
constants. If a filetype is not listed there, it's possible to add the mimetype and
|
||||||
|
the extension by hand, but they need to match those returned by the file command.
|
||||||
|
|
||||||
|
For quotas, be sure you've set the `upload_max_filesize` and `post_max_size` in php.ini to
|
||||||
|
be large enough to handle your upload. In httpd.conf (if you're using apache), check that
|
||||||
|
the LimitRequestBody directive isn't set too low (it's optional, so it may not be there at
|
||||||
|
all).
|
||||||
|
|
||||||
|
* `file_quota` (integer, defaults to minimum of `'post_max_size', 'upload_max_filesize',
|
||||||
|
'memory_limit'`): Maximum size for a single file upload, in bytes. A user can send any
|
||||||
|
amount of notices with attachments as long as each attachment is smaller than
|
||||||
|
file_quota.
|
||||||
|
|
||||||
|
* `user_quota` (integer, default 200M): Total size, in bytes, a user can store on this
|
||||||
|
server. Each user can store any number of files as long as their total size does not
|
||||||
|
exceed the user_quota.
|
||||||
|
|
||||||
|
* `monthly_quota` (integer, default 20M): Total size in bytes that a user can upload each
|
||||||
|
month.
|
||||||
|
|
||||||
|
* `uploads` (boolean, default true): Whether to allow uploading files with notices.
|
||||||
|
|
||||||
|
* `show_html` (boolean, default true): Whether to show (filtered) text/html attachments
|
||||||
|
(and oEmbed HTML etc.). Doesn't affect AJAX calls.
|
||||||
|
|
||||||
|
* `show_thumbs` (boolean, default true): Whether to show thumbnails in notice lists for
|
||||||
|
uploaded images, and photos and videos linked remotely that provide oEmbed info.
|
||||||
|
|
||||||
|
* `process_links` (boolean, default true): Whether to follow redirects and save all
|
||||||
|
available file information (mimetype, date, size, oembed, etc.).
|
||||||
|
|
||||||
|
* `ext_blacklist` (array, default []): associative array to either deny certain extensions or
|
||||||
|
change them to a different one. For example:
|
||||||
|
|
||||||
|
$config['attachments']['extblacklist']['php'] = 'phps'; // this turns .php into .phps
|
||||||
|
$config['attachments']['extblacklist']['exe'] = false; // this would deny any uploads
|
||||||
|
// of files with the "exe" extension
|
||||||
|
|
||||||
|
* `filename` (string, default hash): Name for new files, one of: 'upload', 'hash'.
|
||||||
|
|
||||||
|
* `memory_limit` (string, default '1024M'): PHP memory limit to use temporarily when
|
||||||
|
handling images
|
||||||
|
|
||||||
|
|
||||||
|
thumbnail
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
* `server` (string, default null): Server name from which to serve thumbnails. Defaults to
|
||||||
|
null, meaning to use the default Web server. Using a virtual server here can speed up
|
||||||
|
Web performance.
|
||||||
|
|
||||||
|
* `url_base` (string, default '/thumb/'): URL path, relative to the server, to find
|
||||||
|
files.
|
||||||
|
|
||||||
|
* `ssl` (boolean, default null): Whether to use HTTPS for thumbnail URLs. Defaults to null,
|
||||||
|
meaning to use other SSL settings.
|
||||||
|
|
||||||
|
* `dir` (string, default '/file/thumbnails/'): Path where to store thumbnails.
|
||||||
|
|
||||||
|
* `crop` (boolean, default false): Whether to crop thumbnails (or scale them down)
|
||||||
|
|
||||||
|
* `max_size_px` (integer, default 1000): Thumbnails with an edge greater than this will
|
||||||
|
not be generated.
|
||||||
|
|
||||||
|
* `width` (integer, default 450): Width for generated thumbnails.
|
||||||
|
|
||||||
|
* `height` (integer, default 600): Heigth for generated thumbnails.
|
||||||
|
|
||||||
|
* `upscale` (boolean, default false): Whether to generate thumbnails bigger than the original.
|
||||||
|
|
||||||
|
* `animated` (boolean, default false): Whether to allow animated thumbnails.
|
||||||
|
|
||||||
|
|
||||||
|
theme
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
* `server` (string, default null): Like avatars, you can speed up page loading
|
||||||
|
by pointing the theme file lookup to another server (virtual or real).
|
||||||
|
The default of null will use the same server as PA.
|
||||||
|
|
||||||
|
* `url_base` (string, default '/theme'): Path part of theme URLs, before the theme name.
|
||||||
|
Relative to the theme server. It may make sense to change this path when upgrading,
|
||||||
|
(using version numbers as the path) to make sure that all files are reloaded by
|
||||||
|
caching clients or proxies.
|
||||||
|
|
||||||
|
* `ssl` (boolean, default null): Whether to use SSL for theme elements. Default
|
||||||
|
is null, which means guess based on site SSL settings.
|
||||||
|
|
||||||
|
* `dir` (string, default "./themes"): Directory where theme files are stored.
|
||||||
|
Used to determine whether to show parts of a theme file. Defaults to the
|
||||||
|
theme subdirectory of the install directory.
|
||||||
|
|
||||||
|
|
||||||
|
plugins
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
* `server` (string, default null): Server to find static files for a plugin when the page
|
||||||
|
is plain old HTTP. Defaults to site/server (same as pages). You can use this to move
|
||||||
|
plugin CSS and JS files to a CDN.
|
||||||
|
|
||||||
|
* `url_base` (string, default '/plugins/'): Path to the plugin files. Expects that each
|
||||||
|
plugin will have a subdirectory at plugins/NameOfPlugin. Change this if you're using
|
||||||
|
a CDN.
|
||||||
|
|
||||||
|
* `ssl` (boolean, default null) Whether to use ssl for files served by plugins.
|
||||||
|
|
||||||
|
* `core` (associative array, default TODO): Core GNU social modules, cannot be disabled.
|
||||||
|
|
||||||
|
* `default`: (associative array, default TODO): Mapping from plugin name to array of
|
||||||
|
plugin arguments.
|
||||||
|
|
||||||
|
* `locale_path` (string, default null): Path for finding plugin locale files. In the
|
||||||
|
plugin's directory by default.
|
||||||
|
|
||||||
|
|
||||||
|
license
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
The default license to use for your users' notices. The default is the Creative Commons
|
||||||
|
Attribution 4.0 license, which is probably the right choice for any public site. Note that
|
||||||
|
some other servers will not accept notices if you apply a stricter license than this.
|
||||||
|
|
||||||
|
* `type` (enum["cc", "allrightsreserved", "private"], default 'cc'): One of 'cc' (for
|
||||||
|
Creative Commons licenses), 'allrightsreserved' (default copyright), or 'private' (for
|
||||||
|
private and confidential information).
|
||||||
|
|
||||||
|
* `owner` (string|boolean, default null): For 'allrightsreserved' or 'private', an
|
||||||
|
assigned copyright holder (for example, an employer for a private site). Use true to
|
||||||
|
attribute it to the poster.
|
||||||
|
|
||||||
|
* `url` (string, default 'https://creativecommons.org/licenses/by/4.0/'): URL of the
|
||||||
|
license, used for links.
|
||||||
|
|
||||||
|
* `title` (string, default 'Creative Commons Attribution 4.0'): Title for the license.
|
||||||
|
|
||||||
|
* `image` (string, default '/theme/licenses/cc_by_4.0.png'): URL path for the license image.
|
||||||
|
|
||||||
|
|
||||||
|
mail
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
This is for configuring out-going email.
|
||||||
|
|
||||||
|
* `backend` (enum["mail", "sendmail", "smtp"], default 'mail'): The backend to use for
|
||||||
|
mail. We recommend SMTP where your setup supports it as it is of the three the more
|
||||||
|
difficult one for script exploits to abuse (relatively speaking - they all have
|
||||||
|
potential problems.).
|
||||||
|
|
||||||
|
* `params` (array, default null): If the mail backend requires any parameters, you can
|
||||||
|
provide them in this array.
|
||||||
|
|
||||||
|
* `domain_check` (boolean, default true): Check email origin is valid.
|
||||||
|
|
||||||
|
|
||||||
|
nickname
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
* `blacklist` (array, default ['doc', 'main', 'avatar', 'theme']): an array of strings for
|
||||||
|
usernames that may not be registered. You may want to add others if you have other
|
||||||
|
software installed in a subdirectory of GNU social or if you just don't want certain
|
||||||
|
words used as usernames.
|
||||||
|
|
||||||
|
* `featured` (array, default null): an array of nicknames of 'featured' users of the site.
|
||||||
|
Can be useful to draw attention to well-known users, or interesting people, or
|
||||||
|
whatever.
|
||||||
|
|
||||||
|
|
||||||
|
profile
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
* `banned` (array, defualt []): array of users to hell-ban
|
||||||
|
|
||||||
|
* `bio_text_limit` (integer, default null): Max character length of bio; 0 means no
|
||||||
|
limit; null means to use the site text limit default.
|
||||||
|
|
||||||
|
* `allow_nick_change` (boolean, default false): Whether to allow users to change their
|
||||||
|
nickname.
|
||||||
|
|
||||||
|
* `allow_private_stream` (boolean, default true): Whether users can set their streams to
|
||||||
|
private, so only followers can see it.
|
||||||
|
|
||||||
|
* `backup` (boolean, default false): Whether users can backup their own profiles. Can
|
||||||
|
cause DoS.
|
||||||
|
|
||||||
|
* `restore` (boolean, default false): Whether users can restore their profiles from backup
|
||||||
|
files. Can cause DoS.
|
||||||
|
|
||||||
|
* `delete` (boolean, default false): Whether users can delete their own accounts.
|
||||||
|
|
||||||
|
* `move` (boolean, default false): Whether users can move their accounts to another
|
||||||
|
server.
|
||||||
|
|
||||||
|
|
||||||
|
image
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
* `jpegquality` {integer, default 85}: default quality to use when reencoding images as
|
||||||
|
jpeg.
|
||||||
|
|
||||||
|
|
||||||
|
theme_upload
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
* `enabled` (boolean, default true): Whether to allow users to upload themes
|
||||||
|
|
||||||
|
* `formats` (array, default ['zip', 'tar', 'gz', 'tar.gz']): Formats to allow
|
||||||
|
|
||||||
|
foaf
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
* `mbox_sha1sum` (boolean, default false): whether to include this box in the FOAF
|
||||||
|
protocol page
|
||||||
|
|
||||||
|
|
||||||
|
public
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
For configuring the public stream.
|
||||||
|
|
||||||
|
* `local_only` (boolean, default false): If set to true, only messages posted by users of
|
||||||
|
this instance (rather than remote instances) are shown in the public stream.
|
||||||
|
|
||||||
|
* `blacklist` (array, default []): An array of IDs of users to hide from the public
|
||||||
|
stream. Useful if you have someone making an excessive amount of posts to the site or
|
||||||
|
some kind of automated poster, testing bots, etc.
|
||||||
|
|
||||||
|
* `exclude_sources` (array, default []): Sources of notices that should be kept off of
|
||||||
|
the public timeline (because they're from automatic posters, for instance).
|
||||||
|
|
||||||
|
|
||||||
|
throttle
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
For notice-posting throttles.
|
||||||
|
|
||||||
|
* `enabled` (boolean, default true): Whether to throttle posting.
|
||||||
|
|
||||||
|
* `count` (integer, default 20): Each user can make this many posts in 'timespan' seconds.
|
||||||
|
So, if count is 100 and timespan is 3600, then there can be only 100 posts from a user
|
||||||
|
every hour.
|
||||||
|
|
||||||
|
* `timespan` (integer, default 600): See 'count'.
|
||||||
|
|
||||||
|
|
||||||
|
invite
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
* `enabled` (boolean, default true): Whether to allow users to send invites.
|
||||||
|
|
||||||
|
|
||||||
|
tag
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
* `dropoff` (integer, default 86400 * 10): Exponential decay factor for tag listing, in
|
||||||
|
seconds. You can twiddle with this to try to get better results for your site.
|
||||||
|
|
||||||
|
* `cutoff` (integer, default 86400 * 90): Cutoff, in seconds, before which to not look for
|
||||||
|
notices.
|
||||||
|
|
||||||
|
|
||||||
|
popular
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
* `dropoff` (integer, default 86400 * 10): Exponential decay factor for popular notices, in
|
||||||
|
seconds. You can twiddle with this to try to get better results for your site.
|
||||||
|
|
||||||
|
* `cutoff` (integer, default 86400 * 90): Cutoff, in seconds, before which to not look for
|
||||||
|
notices.
|
||||||
|
|
||||||
|
|
||||||
|
daemon
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
* `piddir` (string, default `sys_get_temp_dir()`): Directory that daemon processes should
|
||||||
|
write their PID file (process ID) to.
|
||||||
|
|
||||||
|
* `user` (string|integer, default false): If set, the daemons will try to change their
|
||||||
|
effective user ID to this user before running. Probably a good idea, especially if you
|
||||||
|
start the daemons as root.
|
||||||
|
|
||||||
|
* `group` (string|integer, default false): If set, the daemons will try to change their
|
||||||
|
effective group ID to this named group.
|
||||||
|
|
||||||
|
|
||||||
|
ping
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Using the "XML-RPC Ping" method initiated by weblogs.com, the site can
|
||||||
|
notify third-party servers of updates.
|
||||||
|
|
||||||
|
* `notify` (array, default []): An array of URLs for ping endpoints.
|
||||||
|
|
||||||
|
* `timeout` (integer, default 2): Interval in seconds between notifications.
|
||||||
|
|
||||||
|
|
||||||
|
new_users
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
* `default_subscriptions` (array, default null): Nickname of user accounts to
|
||||||
|
automatically subscribe new users to. Typically this would be a system account for e.g.
|
||||||
|
service updates or announcements. Users are able to unsub if they want.
|
||||||
|
|
||||||
|
* `welcome_user` (string, default null): Nickname of a user account that sends welcome
|
||||||
|
messages to new users.
|
||||||
|
|
||||||
|
N.B. If either of these special user accounts are specified, the users should be created
|
||||||
|
before the configuration is updated.
|
||||||
|
|
||||||
|
|
||||||
|
linkify
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
* `bare_domain` (boolean, default false): Prepend schema to any linked domains (a href,
|
||||||
|
not display text).
|
||||||
|
|
||||||
|
* `linkify_ipv4` (boolean, default false): Convert IPv4 addresses into hyperlinks.
|
||||||
|
|
||||||
|
* `linkify_ipv6` (boolean, default false): Convert IPv6 addresses into hyperlinks.
|
||||||
|
|
||||||
|
|
||||||
|
group
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
* `max_aliases` (integer, default 3): Maximum number of aliases a group can have.
|
||||||
|
Set to 0 or less to prevent aliases in a group.
|
||||||
|
|
||||||
|
* `description_limit` (integer, default null): Maximum number of characters to allow in
|
||||||
|
group descriptions. null means to use the site-wide text limits. 0 means no limit.
|
||||||
|
|
||||||
|
|
||||||
|
people_tag
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
* `max_tags` (integer, default 100): Maximum number of people tags a user can create.
|
||||||
|
|
||||||
|
* `max_people` (integer, default 500): Maximum number of people with the same user people tag.
|
||||||
|
|
||||||
|
* `allow_tagging` (associative array, default ['local' => true, 'remote' => true])>: Which
|
||||||
|
kind of user to allow tagging.
|
||||||
|
|
||||||
|
* `description_limit` (integer, default null): Maximum tag description lenght.
|
||||||
|
|
||||||
|
|
||||||
|
search
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
* `type` (enum('fulltext', 'like'), default 'like'): type of search. Ignored if PostgreSQL
|
||||||
|
is enabled. Can either be 'fulltext' or 'like'. The former is faster and more
|
||||||
|
efficient but requires the lame old MyISAM engine for MySQL. The latter will work with
|
||||||
|
InnoDB but could be miserably slow on large systems.
|
||||||
|
|
||||||
|
|
||||||
|
html_filter
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
* `tags` (array, default ['img', 'video', 'audio', 'script']): Remove tags from
|
||||||
|
user/remotely generated HTML.
|
||||||
|
|
||||||
|
|
||||||
|
notice
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
* `content_limit` (integer, default null): Max length of the plain-text content of a
|
||||||
|
notice. Null means to use the site-wide text limit. 0 means no limit.
|
||||||
|
|
||||||
|
* `allow_private` (boolean, default false): Whether to allow users to post notices visible
|
||||||
|
only to their subscribers.
|
||||||
|
|
||||||
|
* `hide_banned` (boolean, default true): Whether to hide hell-banned users' notices.
|
||||||
|
|
||||||
|
|
||||||
|
message
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
* `content_limit` (integer, default null): Max length of the plain-text content of a
|
||||||
|
message. Null means to use the site-wide text limit. 0 means no limit.
|
||||||
|
|
||||||
|
|
||||||
|
location
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
* `share` (enum('always', 'user', 'never'), default 'user'): Whether to share user
|
||||||
|
location. 'user' means each user can choose.
|
||||||
|
|
||||||
|
|
||||||
|
admin
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
* `panels` (array, default ['site', 'user', 'paths', 'access', 'sessions', 'sitenotice',
|
||||||
|
'license', 'plugins']): Which panels to include in the admin tab.
|
||||||
|
|
||||||
|
|
||||||
|
single_user
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
If an installation has only one user, this can simplify a lot of the
|
||||||
|
interface. It also makes the user's profile the root URL.
|
||||||
|
|
||||||
|
* `enabled` (boolean, default value provided in configure): Whether to run in "single user mode".
|
||||||
|
|
||||||
|
* `nickname` (string, default null): nickname of the single user. If no nickname is
|
||||||
|
specified, the site owner account will be used (if present).
|
||||||
|
|
||||||
|
|
||||||
|
robots_txt
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
* `crawl_delay` (integer, default 0): if non-zero, this value is provided as the
|
||||||
|
'Crawl-Delay:' for the robots.txt file. see
|
||||||
|
<https://en.wikipedia.org/wiki/Robots_exclusion_standard#Crawl-delay_directive> for
|
||||||
|
more information. Default is zero, no explicit delay.
|
||||||
|
|
||||||
|
* `disallow`(array, default ['main', 'settings', 'admin', 'search', 'message']): Array of
|
||||||
|
paths to disallow. Ignored when site is private, in which case the entire site ('/')
|
||||||
|
is disallowed.
|
||||||
|
|
||||||
|
|
||||||
|
nofollow
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
We optionally put 'rel="nofollow"' on some links in some pages. The following
|
||||||
|
configuration settings let you fine-tune how or when things are nofollowed. See
|
||||||
|
http://en.wikipedia.org/wiki/Nofollow for more information on what 'nofollow' means.
|
||||||
|
|
||||||
|
* `subscribers` (boolean, default true): Whether to nofollow links to subscribers on the
|
||||||
|
profile and personal pages.
|
||||||
|
|
||||||
|
* `members` (boolean, default true): Whether to nofollow links to members on the group
|
||||||
|
page. Default true.
|
||||||
|
|
||||||
|
* `peopletag` (boolean, default true): Whether to nofollow links to people listed in the
|
||||||
|
peopletag page. Default true.
|
||||||
|
|
||||||
|
* `external` (enum('always', 'sometimes', 'never'), default 'sometimes'): External links
|
||||||
|
in notices. One of three values: 'always', 'sometimes', 'never'. If 'sometimes', then
|
||||||
|
external links are not nofollowed on profile, notice, and favorites page. Default is
|
||||||
|
'sometimes'.
|
||||||
|
|
||||||
|
|
||||||
|
url_shortener
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
* `service` (string, default 'internal'): URL shortening service to use by default. Users
|
||||||
|
can override individually.
|
||||||
|
|
||||||
|
* `max_url_length` (integer, default 100): If an URL is strictly longer than this limit,
|
||||||
|
it will be shortened. Note that the URL shortener service may return an URL longer
|
||||||
|
than this limit. Users can override. If set to 0, all URLs will be shortened.
|
||||||
|
|
||||||
|
* `max_notice_length` (integer, default null): If a notice is strictly longer than this
|
||||||
|
limit, all URLs in the notice will be shortened. Users can override this.
|
||||||
|
|
||||||
|
|
||||||
|
http
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
* `ssl_cafile` (string, default '/docker/certbot/files/live/'): location of the CA file
|
||||||
|
for SSL connections. If not set, peers won't be able to verify our identity.
|
||||||
|
|
||||||
|
* `timeout` (integer, default `ini_get('default_socket_timeout')`): Timeout in seconds
|
||||||
|
when to close a connection.
|
||||||
|
|
||||||
|
* `proxy_host` (string, default null): Host to use for proxying HTTP requests. If null,
|
||||||
|
doesn't use an HTTP proxy.
|
||||||
|
|
||||||
|
* `proxy_port` (integer, default null): Port to use to connect to HTTP proxy host.
|
||||||
|
|
||||||
|
* `proxy_user` (string, default null): Username to use for authenticating to the HTTP proxy.
|
||||||
|
|
||||||
|
* `proxy_password` (string, default null): Password to use for authenticating to the HTTP proxy.
|
||||||
|
|
||||||
|
* `proxy_auth_scheme` (TODO): Scheme to use for authenticating to the HTTP proxy.
|
||||||
|
|
||||||
|
|
||||||
|
discovery
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
* `CORS` (boolean, default false): Whether to allow Cross-Origin Resource Sharing for
|
||||||
|
service discovery (host-meta, XRD, etc.)
|
||||||
|
|
||||||
|
|
||||||
|
performance
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
* `high` (boolean, default fakse): Disables some high-performance-intensity components.
|
||||||
|
|
||||||
|
|
||||||
|
login_command
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
* `enabled` (boolean, default false): Whether to enable users to send the text 'login' to
|
||||||
|
the site through any channel and receive a link to login to the site automatically in
|
||||||
|
return. Possibly useful for users who primarily use an XMPP or SMS interface. Note
|
||||||
|
that the security implications of this are pretty serious. You should enable it only
|
||||||
|
after you've convinced yourself that it is safe.
|
||||||
|
|
||||||
1
DOCUMENTATION/SYSTEM_ADMINISTRATORS/install.md
Symbolic link
1
DOCUMENTATION/SYSTEM_ADMINISTRATORS/install.md
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../../INSTALL.md
|
||||||
1465
EVENTS.txt
1465
EVENTS.txt
File diff suppressed because it is too large
Load Diff
468
INSTALL
468
INSTALL
@@ -1,468 +0,0 @@
|
|||||||
TABLE OF CONTENTS
|
|
||||||
=================
|
|
||||||
* Prerequisites
|
|
||||||
- PHP modules
|
|
||||||
- Better performance
|
|
||||||
* Installation
|
|
||||||
- Getting it up and running
|
|
||||||
- Fancy URLs
|
|
||||||
- Sphinx
|
|
||||||
- SMS
|
|
||||||
- Queues and daemons
|
|
||||||
- Themes
|
|
||||||
- Translation
|
|
||||||
- Backups
|
|
||||||
- Private
|
|
||||||
|
|
||||||
Prerequisites
|
|
||||||
=============
|
|
||||||
|
|
||||||
PHP modules
|
|
||||||
-----------
|
|
||||||
|
|
||||||
The following software packages are *required* for this software to
|
|
||||||
run correctly.
|
|
||||||
|
|
||||||
- PHP 5.4+ For newer versions, some functions that are used may be
|
|
||||||
disabled by default, such as the pcntl_* family. See the
|
|
||||||
section on 'Queues and daemons' for more information.
|
|
||||||
- MariaDB 5+ GNU Social uses, by default, a MariaDB server for data
|
|
||||||
storage. Versions 5.x and 10.x have both reportedly
|
|
||||||
worked well. It is also possible to run MySQL 5.5+.
|
|
||||||
- Web server Apache, lighttpd and nginx will all work. CGI mode is
|
|
||||||
recommended and also some variant of 'suexec' (or a
|
|
||||||
proper setup php-fpm pool)
|
|
||||||
NOTE: mod_rewrite or its equivalent is extremely useful.
|
|
||||||
|
|
||||||
Your PHP installation must include the following PHP extensions for a
|
|
||||||
functional setup of GNU Social:
|
|
||||||
|
|
||||||
- openssl (compiled in for Debian, enabled manually in Arch Linux)
|
|
||||||
- php5-curl Fetching files by HTTP.
|
|
||||||
- php5-gd Image manipulation (scaling).
|
|
||||||
- php5-gmp For Salmon signatures (part of OStatus).
|
|
||||||
- php5-json For WebFinger lookups and more.
|
|
||||||
- php5-mysqlnd The native driver for PHP5 MariaDB connections. If you
|
|
||||||
use MySQL, 'mysql' or 'mysqli' may work.
|
|
||||||
|
|
||||||
The above package names are for Debian based systems. In the case of
|
|
||||||
Arch Linux, PHP is compiled with support for most extensions but they
|
|
||||||
require manual enabling in the relevant php.ini file (mostly php5-gmp).
|
|
||||||
|
|
||||||
Better performance
|
|
||||||
------------------
|
|
||||||
|
|
||||||
For some functionality, you will also need the following extensions:
|
|
||||||
|
|
||||||
- opcache Improves performance a _lot_. Included in PHP, must be
|
|
||||||
enabled manually in php.ini for most distributions. Find
|
|
||||||
and set at least: opcache.enable=1
|
|
||||||
- mailparse Efficient parsing of email requires this extension.
|
|
||||||
Submission by email or SMS-over-email uses this.
|
|
||||||
- sphinx A client for the sphinx server, an alternative to MySQL
|
|
||||||
or Postgresql fulltext search. You will also need a
|
|
||||||
Sphinx server to serve the search queries.
|
|
||||||
- gettext For multiple languages. Default on many PHP installs;
|
|
||||||
will be emulated if not present.
|
|
||||||
- exif For thumbnails to be properly oriented.
|
|
||||||
|
|
||||||
You may also experience better performance from your site if you configure
|
|
||||||
a PHP cache/accelerator. Most distributions come with "opcache" support.
|
|
||||||
Enable it in your php.ini, it is documented there together with its settings.
|
|
||||||
|
|
||||||
Installation
|
|
||||||
============
|
|
||||||
|
|
||||||
Getting it up and running
|
|
||||||
-------------------------
|
|
||||||
|
|
||||||
Installing the basic GNU Social web component is relatively easy,
|
|
||||||
especially if you've previously installed PHP/MariaDB packages.
|
|
||||||
|
|
||||||
1. Unpack the tarball you downloaded on your Web server. Usually a
|
|
||||||
command like this will work:
|
|
||||||
|
|
||||||
tar zxf gnusocial-*.tar.gz
|
|
||||||
|
|
||||||
...which will make a gnusocial-x.y.z subdirectory in your current
|
|
||||||
directory. (If you don't have shell access on your Web server, you
|
|
||||||
may have to unpack the tarball on your local computer and FTP the
|
|
||||||
files to the server.)
|
|
||||||
|
|
||||||
2. Move the tarball to a directory of your choosing in your Web root
|
|
||||||
directory. Usually something like this will work:
|
|
||||||
|
|
||||||
mv gnusocial-x.y.z /var/www/gnusocial
|
|
||||||
|
|
||||||
This will often make your GNU Social instance available in the gnusocial
|
|
||||||
path of your server, like "http://example.net/gnusocial". "social" or
|
|
||||||
"blog" might also be good path names. If you know how to configure
|
|
||||||
virtual hosts on your web server, you can try setting up
|
|
||||||
"http://social.example.net/" or the like.
|
|
||||||
|
|
||||||
If you have "rewrite" support on your webserver, and you should,
|
|
||||||
then please enable this in order to make full use of your site. This
|
|
||||||
will enable "Fancy URL" support, which you can read more about if you
|
|
||||||
scroll down a bit in this document.
|
|
||||||
|
|
||||||
3. Make your target directory writeable by the Web server.
|
|
||||||
|
|
||||||
chmod a+w /var/www/gnusocial/
|
|
||||||
|
|
||||||
On some systems, this will probably work:
|
|
||||||
|
|
||||||
chgrp www-data /var/www/gnusocial/
|
|
||||||
chmod g+w /var/www/gnusocial/
|
|
||||||
|
|
||||||
If your Web server runs as another user besides "www-data", try
|
|
||||||
that user's default group instead. As a last resort, you can create
|
|
||||||
a new group like "gnusocial" and add the Web server's user to the group.
|
|
||||||
|
|
||||||
4. You should also take this moment to make your avatar, background, and
|
|
||||||
file subdirectories writeable by the Web server. An insecure way to do
|
|
||||||
this is:
|
|
||||||
|
|
||||||
chmod a+w /var/www/gnusocial/avatar
|
|
||||||
chmod a+w /var/www/gnusocial/background
|
|
||||||
chmod a+w /var/www/gnusocial/file
|
|
||||||
|
|
||||||
You can also make the avatar, background, and file directories
|
|
||||||
writeable by the Web server group, as noted above.
|
|
||||||
|
|
||||||
5. Create a database to hold your site data. Something like this
|
|
||||||
should work:
|
|
||||||
|
|
||||||
mysqladmin -u "root" --password="rootpassword" create gnusocial
|
|
||||||
|
|
||||||
Note that GNU Social should have its own database; you should not share
|
|
||||||
the database with another program. You can name it whatever you want,
|
|
||||||
though.
|
|
||||||
|
|
||||||
(If you don't have shell access to your server, you may need to use
|
|
||||||
a tool like phpMyAdmin to create a database. Check your hosting
|
|
||||||
service's documentation for how to create a new MariaDB database.)
|
|
||||||
|
|
||||||
6. Create a new database account that GNU Social will use to access the
|
|
||||||
database. If you have shell access, this will probably work from the
|
|
||||||
MariaDB shell:
|
|
||||||
|
|
||||||
GRANT ALL on gnusocial.*
|
|
||||||
TO 'gnusocial'@'localhost'
|
|
||||||
IDENTIFIED BY 'agoodpassword';
|
|
||||||
|
|
||||||
You should change the user identifier 'gnusocial' and 'agoodpassword'
|
|
||||||
to your preferred new database username and password. You may want to
|
|
||||||
test logging in to MariaDB as this new user.
|
|
||||||
|
|
||||||
7. In a browser, navigate to the GNU Social install script; something like:
|
|
||||||
|
|
||||||
http://social.example.net/install.php
|
|
||||||
|
|
||||||
Enter the database connection information and your site name. The
|
|
||||||
install program will configure your site and install the initial,
|
|
||||||
almost-empty database.
|
|
||||||
|
|
||||||
8. You should now be able to navigate to your social site's main directory
|
|
||||||
and see the "Public Timeline", which will probably be empty. You can
|
|
||||||
now register new user, post some notices, edit your profile, etc.
|
|
||||||
|
|
||||||
Fancy URLs
|
|
||||||
----------
|
|
||||||
|
|
||||||
By default, GNU Social will use URLs that include the main PHP program's
|
|
||||||
name in them. For example, a user's home profile might be found at:
|
|
||||||
|
|
||||||
http://example.net/gnusocial/index.php/gnusocial/fred
|
|
||||||
|
|
||||||
On certain systems that don't support this kind of syntax, they'll
|
|
||||||
look like this:
|
|
||||||
|
|
||||||
http://example.net/gnusocial/index.php?p=gnusocial/fred
|
|
||||||
|
|
||||||
It's possible to configure the software so it looks like this instead:
|
|
||||||
|
|
||||||
http://example.net/gnusocial/fred
|
|
||||||
|
|
||||||
These "fancy URLs" are more readable and memorable for users. To use
|
|
||||||
fancy URLs, you must either have Apache 2.x with .htaccess enabled and
|
|
||||||
mod_rewrite enabled, -OR- know how to configure "url redirection" in
|
|
||||||
your server (like lighttpd or nginx).
|
|
||||||
|
|
||||||
1. Copy the htaccess.sample file to .htaccess in your StatusNet
|
|
||||||
directory.
|
|
||||||
|
|
||||||
2. Change the "RewriteBase" in the new .htaccess file to be the URL path
|
|
||||||
to your GNU Social installation on your server. Typically this will
|
|
||||||
be the path to your GNU Social directory relative to your Web root.
|
|
||||||
If you are installing it in the root directory, leave it as '/'.
|
|
||||||
|
|
||||||
3. Add, uncomment or change a line in your config.php file so it says:
|
|
||||||
|
|
||||||
$config['site']['fancy'] = true;
|
|
||||||
|
|
||||||
You should now be able to navigate to a "fancy" URL on your server,
|
|
||||||
like:
|
|
||||||
|
|
||||||
http://example.net/gnusocial/main/register
|
|
||||||
|
|
||||||
If you changed your HTTP server configuration, you may need to restart
|
|
||||||
the server first.
|
|
||||||
|
|
||||||
If it doesn't work, double-check that AllowOverride for the GNU Social
|
|
||||||
directory is 'All' in your Apache configuration file. This is usually
|
|
||||||
/etc/httpd.conf, /etc/apache/httpd.conf, or (on Debian and Ubuntu)
|
|
||||||
/etc/apache2/sites-available/default. See the Apache documentation for
|
|
||||||
.htaccess files for more details:
|
|
||||||
|
|
||||||
http://httpd.apache.org/docs/2.2/howto/htaccess.html
|
|
||||||
|
|
||||||
Also, check that mod_rewrite is installed and enabled:
|
|
||||||
|
|
||||||
http://httpd.apache.org/docs/2.2/mod/mod_rewrite.html
|
|
||||||
|
|
||||||
Sphinx
|
|
||||||
------
|
|
||||||
|
|
||||||
To use a Sphinx server to search users and notices, you'll need to
|
|
||||||
enable the SphinxSearch plugin. Add to your config.php:
|
|
||||||
|
|
||||||
addPlugin('SphinxSearch');
|
|
||||||
$config['sphinx']['server'] = 'searchhost.local';
|
|
||||||
|
|
||||||
You also need to install, compile and enable the sphinx pecl extension for
|
|
||||||
php on the client side, which itself depends on the sphinx development files.
|
|
||||||
|
|
||||||
See plugins/SphinxSearch/README for more details and server setup.
|
|
||||||
|
|
||||||
SMS
|
|
||||||
---
|
|
||||||
|
|
||||||
StatusNet supports a cheap-and-dirty system for sending update messages
|
|
||||||
to mobile phones and for receiving updates from the mobile. Instead of
|
|
||||||
sending through the SMS network itself, which is costly and requires
|
|
||||||
buy-in from the wireless carriers, it simply piggybacks on the email
|
|
||||||
gateways that many carriers provide to their customers. So, SMS
|
|
||||||
configuration is essentially email configuration.
|
|
||||||
|
|
||||||
Each user sends to a made-up email address, which they keep a secret.
|
|
||||||
Incoming email that is "From" the user's SMS email address, and "To"
|
|
||||||
the users' secret email address on the site's domain, will be
|
|
||||||
converted to a notice and stored in the DB.
|
|
||||||
|
|
||||||
For this to work, there *must* be a domain or sub-domain for which all
|
|
||||||
(or most) incoming email can pass through the incoming mail filter.
|
|
||||||
|
|
||||||
1. Run the SQL script carrier.sql in your StatusNet database. This will
|
|
||||||
usually work:
|
|
||||||
|
|
||||||
mysql -u "statusnetuser" --password="statusnetpassword" statusnet < db/carrier.sql
|
|
||||||
|
|
||||||
This will populate your database with a list of wireless carriers
|
|
||||||
that support email SMS gateways.
|
|
||||||
|
|
||||||
2. Make sure the maildaemon.php file is executable:
|
|
||||||
|
|
||||||
chmod +x scripts/maildaemon.php
|
|
||||||
|
|
||||||
Note that "daemon" is kind of a misnomer here; the script is more
|
|
||||||
of a filter than a daemon.
|
|
||||||
|
|
||||||
2. Edit /etc/aliases on your mail server and add the following line:
|
|
||||||
|
|
||||||
*: /path/to/statusnet/scripts/maildaemon.php
|
|
||||||
|
|
||||||
3. Run whatever code you need to to update your aliases database. For
|
|
||||||
many mail servers (Postfix, Exim, Sendmail), this should work:
|
|
||||||
|
|
||||||
newaliases
|
|
||||||
|
|
||||||
You may need to restart your mail server for the new database to
|
|
||||||
take effect.
|
|
||||||
|
|
||||||
4. Set the following in your config.php file:
|
|
||||||
|
|
||||||
$config['mail']['domain'] = 'yourdomain.example.net';
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Queues and daemons
|
|
||||||
------------------
|
|
||||||
|
|
||||||
Some activities that StatusNet needs to do, like broadcast OStatus, SMS,
|
|
||||||
XMPP messages and TwitterBridge operations, can be 'queued' and done by
|
|
||||||
off-line bots instead.
|
|
||||||
|
|
||||||
Two mechanisms are available to achieve offline operations:
|
|
||||||
|
|
||||||
* New embedded OpportunisticQM plugin, which is enabled by default
|
|
||||||
* Legacy queuedaemon script, which can be enabled via config file.
|
|
||||||
|
|
||||||
### OpportunisticQM plugin
|
|
||||||
|
|
||||||
This plugin is enabled by default. It tries its best to do background
|
|
||||||
job during regular HTTP requests, like API or HTML pages calls.
|
|
||||||
|
|
||||||
Since queueing system is enabled by default, notices to be broadcasted
|
|
||||||
will be stored, by default, into DB (table queue_item).
|
|
||||||
|
|
||||||
Each time it can, OpportunisticQM will try to handle some of them.
|
|
||||||
|
|
||||||
This is a good solution whether you:
|
|
||||||
|
|
||||||
* have no access to command line (shared hosting)
|
|
||||||
* do not want to deal with long-running PHP processes
|
|
||||||
* run a low traffic GNU social instance
|
|
||||||
|
|
||||||
In other case, you really should consider enabling the queuedaemon for
|
|
||||||
performance reasons. Background daemons are necessary anyway if you wish
|
|
||||||
to use the Instant Messaging features such as communicating via XMPP.
|
|
||||||
|
|
||||||
### queuedaemon
|
|
||||||
|
|
||||||
If you want to use legacy queuedaemon, you must be able to run
|
|
||||||
long-running offline processes, either on your main Web server or on
|
|
||||||
another server you control. (Your other server will still need all the
|
|
||||||
above prerequisites, with the exception of Apache.) Installing on a
|
|
||||||
separate server is probably a good idea for high-volume sites.
|
|
||||||
|
|
||||||
1. You'll need the "CLI" (command-line interface) version of PHP
|
|
||||||
installed on whatever server you use.
|
|
||||||
|
|
||||||
Modern PHP versions in some operating systems have disabled functions
|
|
||||||
related to forking, which is required for daemons to operate. To make
|
|
||||||
this work, make sure that your php-cli config (/etc/php5/cli/php.ini)
|
|
||||||
does NOT have these functions listed under 'disable_functions':
|
|
||||||
|
|
||||||
* pcntl_fork, pcntl_wait, pcntl_wifexited, pcntl_wexitstatus,
|
|
||||||
pcntl_wifsignaled, pcntl_wtermsig
|
|
||||||
|
|
||||||
Other recommended settings for optimal performance are:
|
|
||||||
* mysqli.allow_persistent = On
|
|
||||||
* mysqli.reconnect = On
|
|
||||||
|
|
||||||
2. If you're using a separate server for queues, install StatusNet
|
|
||||||
somewhere on the server. You don't need to worry about the
|
|
||||||
.htaccess file, but make sure that your config.php file is close
|
|
||||||
to, or identical to, your Web server's version.
|
|
||||||
|
|
||||||
3. In your config.php files (both the Web server and the queues
|
|
||||||
server!), set the following variable:
|
|
||||||
|
|
||||||
$config['queue']['enabled'] = true;
|
|
||||||
$config['queue']['daemon'] = true;
|
|
||||||
|
|
||||||
You may also want to look at the 'daemon' section of this file for
|
|
||||||
more daemon options. Note that if you set the 'user' and/or 'group'
|
|
||||||
options, you'll need to create that user and/or group by hand.
|
|
||||||
They're not created automatically.
|
|
||||||
|
|
||||||
4. On the queues server, run the command scripts/startdaemons.sh.
|
|
||||||
|
|
||||||
This will run the queue handlers:
|
|
||||||
|
|
||||||
* queuedaemon.php - polls for queued items for inbox processing and
|
|
||||||
pushing out to OStatus, SMS, XMPP, etc.
|
|
||||||
* imdaemon.php - if an IM plugin is enabled (like XMPP)
|
|
||||||
* other daemons, like TwitterBridge ones, that you may have enabled
|
|
||||||
|
|
||||||
These daemons will automatically restart in most cases of failure
|
|
||||||
including memory leaks (if a memory_limit is set), but may still die
|
|
||||||
or behave oddly if they lose connections to the XMPP or queue servers.
|
|
||||||
|
|
||||||
It may be a good idea to use a daemon-monitoring service, like 'monit',
|
|
||||||
to check their status and keep them running.
|
|
||||||
|
|
||||||
All the daemons write their process IDs (pids) to /var/run/ by
|
|
||||||
default. This can be useful for starting, stopping, and monitoring the
|
|
||||||
daemons. If you are running multiple sites on the same machine, it will
|
|
||||||
be necessary to avoid collisions of these PID files by setting a site-
|
|
||||||
specific directory in config.php:
|
|
||||||
|
|
||||||
$config['daemon']['piddir'] = __DIR__ . '/../run/';
|
|
||||||
|
|
||||||
It is also possible to use a STOMP server instead of our kind of hacky
|
|
||||||
home-grown DB-based queue solution. This is strongly recommended for
|
|
||||||
best response time, especially when using XMPP.
|
|
||||||
|
|
||||||
Themes
|
|
||||||
------
|
|
||||||
|
|
||||||
Older themes (version 0.9.x and below) no longer work with StatusNet
|
|
||||||
1.0.x, due to major changes in the site layout. We ship with three new
|
|
||||||
themes for this version, 'neo', 'neo-blue' and 'neo-light'.
|
|
||||||
|
|
||||||
As of right now, your ability to change the theme is site-wide; users
|
|
||||||
can't choose their own theme. Additionally, the only thing you can
|
|
||||||
change in the theme is CSS stylesheets and some image files; you can't
|
|
||||||
change the HTML output, like adding or removing menu items.
|
|
||||||
|
|
||||||
You can choose a theme using the $config['site']['theme'] element in
|
|
||||||
the config.php file. See below for details.
|
|
||||||
|
|
||||||
You can add your own theme by making a sub-directory of the 'theme'
|
|
||||||
subdirectory with the name of your theme. Each theme can have the
|
|
||||||
following files:
|
|
||||||
|
|
||||||
display.css: a CSS2 file for "default" styling for all browsers.
|
|
||||||
logo.png: a logo image for the site.
|
|
||||||
default-avatar-profile.png: a 96x96 pixel image to use as the avatar for
|
|
||||||
users who don't upload their own.
|
|
||||||
default-avatar-stream.png: Ditto, but 48x48. For streams of notices.
|
|
||||||
default-avatar-mini.png: Ditto ditto, but 24x24. For subscriptions
|
|
||||||
listing on profile pages.
|
|
||||||
|
|
||||||
You may want to start by copying the files from the default theme to
|
|
||||||
your own directory.
|
|
||||||
|
|
||||||
Translation
|
|
||||||
-----------
|
|
||||||
|
|
||||||
Translations in StatusNet use the gettext system <http://www.gnu.org/software/gettext/>.
|
|
||||||
Theoretically, you can add your own sub-directory to the locale/
|
|
||||||
subdirectory to add a new language to your system. You'll need to
|
|
||||||
compile the ".po" files into ".mo" files, however.
|
|
||||||
|
|
||||||
Contributions of translation information to StatusNet are very easy:
|
|
||||||
you can use the Web interface at translatewiki.net to add one
|
|
||||||
or a few or lots of new translations -- or even new languages. You can
|
|
||||||
also download more up-to-date .po files there, if you so desire.
|
|
||||||
|
|
||||||
For info on helping with translations, see http://status.net/wiki/Translations
|
|
||||||
|
|
||||||
Backups
|
|
||||||
-------
|
|
||||||
|
|
||||||
There is no built-in system for doing backups in StatusNet. You can make
|
|
||||||
backups of a working StatusNet system by backing up the database and
|
|
||||||
the Web directory. To backup the database use mysqldump <http://ur1.ca/7xo>
|
|
||||||
and to backup the Web directory, try tar.
|
|
||||||
|
|
||||||
Private
|
|
||||||
-------
|
|
||||||
|
|
||||||
The administrator can set the "private" flag for a site so that it's
|
|
||||||
not visible to non-logged-in users. (This is the default for new installs of version 1.0!)
|
|
||||||
|
|
||||||
This might be useful for workgroups who want to share a social
|
|
||||||
networking site for project management, but host it on a public
|
|
||||||
server.
|
|
||||||
|
|
||||||
Total privacy is attempted but not guaranteed or ensured. Private sites
|
|
||||||
currently don't work well with OStatus federation.
|
|
||||||
|
|
||||||
Access to file attachments can also be restricted to logged-in users only.
|
|
||||||
|
|
||||||
1. Add a directory outside the web root where your file uploads will be
|
|
||||||
stored. Usually a command like this will work:
|
|
||||||
|
|
||||||
mkdir /var/www/statusnet-files
|
|
||||||
|
|
||||||
2. Make the file uploads directory writeable by the web server. An
|
|
||||||
insecure way to do this is:
|
|
||||||
|
|
||||||
chmod a+x /var/www/statusnet-files
|
|
||||||
|
|
||||||
3. Tell StatusNet to use this directory for file uploads. Add a line
|
|
||||||
like this to your config.php:
|
|
||||||
|
|
||||||
$config['attachments']['dir'] = '/var/www/statusnet-files';
|
|
||||||
5
INSTALL.md
Normal file
5
INSTALL.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
GNU social
|
||||||
|
=====
|
||||||
|
|
||||||
|
GNU social is a federated social network. For documentation, visit
|
||||||
|
https://docs.gnusocial.rocks/ or view the files under docs/
|
||||||
35
Makefile
35
Makefile
@@ -1,18 +1,31 @@
|
|||||||
# Warning: do not transform tabs to spaces in this file.
|
DIR=$(strip $(notdir $(CURDIR))) # Seems a bit hack-ish, but `basename` works differently
|
||||||
|
|
||||||
all : translations
|
.PHONY:
|
||||||
|
@if ! docker info > /dev/null; then echo "Docker does not seem to be running"; exit 1; fi
|
||||||
|
|
||||||
core_mo = $(patsubst %.po,%.mo,$(wildcard locale/*/LC_MESSAGES/statusnet.po))
|
up: .PHONY
|
||||||
plugin_mo = $(patsubst %.po,%.mo,$(wildcard plugins/*/locale/*/LC_MESSAGES/*.po))
|
docker-compose up -d
|
||||||
|
|
||||||
translations : $(core_mo) $(plugin_mo)
|
down: .PHONY
|
||||||
|
docker-compose down
|
||||||
|
|
||||||
clean :
|
redis-shell:
|
||||||
rm -f $(core_mo) $(plugin_mo)
|
docker exec -it $(strip $(DIR))_redis_1 sh -c 'redis-cli'
|
||||||
|
|
||||||
updatepo :
|
php-repl: .PHONY
|
||||||
php scripts/update_po_templates.php --all
|
docker exec -it $(strip $(DIR))_php_1 sh -c '/var/www/social/bin/console psysh'
|
||||||
|
|
||||||
%.mo : %.po
|
php-shell: .PHONY
|
||||||
msgfmt -o $@ $<
|
docker exec -it $(strip $(DIR))_php_1 sh -c 'cd /var/www/social; sh'
|
||||||
|
|
||||||
|
psql-shell: .PHONY
|
||||||
|
docker exec -it $(strip $(DIR))_db_1 sh -c "psql -U postgres social"
|
||||||
|
|
||||||
|
database-force-schema-update:
|
||||||
|
docker exec -it $(strip $(DIR))_php_1 sh -c "/var/www/social/bin/console doctrine:schema:update --dump-sql --force"
|
||||||
|
|
||||||
|
test: .PHONY
|
||||||
|
cd docker/testing && docker-compose run php; docker-compose down
|
||||||
|
|
||||||
|
stop-test: .PHONY
|
||||||
|
cd docker/testing && docker-compose down
|
||||||
|
|||||||
44
PLUGINS.txt
44
PLUGINS.txt
@@ -1,44 +0,0 @@
|
|||||||
Plugins
|
|
||||||
=======
|
|
||||||
|
|
||||||
Beginning with the 0.7.x branch, StatusNet has supported a simple but
|
|
||||||
powerful plugin architecture. Important events in the code are named,
|
|
||||||
like 'StartNoticeSave', and other software can register interest
|
|
||||||
in those events. When the events happen, the other software is called
|
|
||||||
and has a choice of accepting or rejecting the events.
|
|
||||||
|
|
||||||
In the simplest case, you can add a function to config.php and use the
|
|
||||||
Event::addHandler() function to hook an event:
|
|
||||||
|
|
||||||
function AddGoogleLink($action)
|
|
||||||
{
|
|
||||||
$action->menuItem('http://www.google.com/', _('Google'), _('Search engine'));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
Event::addHandler('EndPrimaryNav', 'AddGoogleLink');
|
|
||||||
|
|
||||||
This adds a menu item to the end of the main navigation menu. You can
|
|
||||||
see the list of existing events, and parameters that handlers must
|
|
||||||
implement, in EVENTS.txt.
|
|
||||||
|
|
||||||
The Plugin class in lib/plugin.php makes it easier to write more
|
|
||||||
complex plugins. Sub-classes can just create methods named
|
|
||||||
'onEventName', where 'EventName' is the name of the event (case
|
|
||||||
matters!). These methods will be automatically registered as event
|
|
||||||
handlers by the Plugin constructor (which you must call from your own
|
|
||||||
class's constructor).
|
|
||||||
|
|
||||||
Several example plugins are included in the plugins/ directory. You
|
|
||||||
can enable a plugin with the following line in config.php:
|
|
||||||
|
|
||||||
addPlugin('Example', array('param1' => 'value1',
|
|
||||||
'param2' => 'value2'));
|
|
||||||
|
|
||||||
This will look for and load files named 'ExamplePlugin.php' or
|
|
||||||
'Example/ExamplePlugin.php' either in the plugins/ directory (for
|
|
||||||
plugins that ship with StatusNet) or in the local/ directory (for
|
|
||||||
plugins you write yourself or that you get from somewhere else) or
|
|
||||||
local/plugins/.
|
|
||||||
|
|
||||||
Plugins are documented in their own directories.
|
|
||||||
247
README.md
247
README.md
@@ -1,247 +0,0 @@
|
|||||||
# GNU social 1.1.3
|
|
||||||
February 2015-02-27
|
|
||||||
|
|
||||||
(c) Free Software Foundation, Inc
|
|
||||||
(c) StatusNet, Inc
|
|
||||||
|
|
||||||
This is the README file for GNU social, the free
|
|
||||||
software social networking platform. It includes
|
|
||||||
general information about the software and the
|
|
||||||
project.
|
|
||||||
|
|
||||||
Some other files to review:
|
|
||||||
|
|
||||||
- INSTALL: instructions on how to install the software.
|
|
||||||
- UPGRADE: upgrading from earlier versions
|
|
||||||
- CONFIGURE: configuration options in gruesome detail.
|
|
||||||
- PLUGINS.txt: how to install and configure plugins.
|
|
||||||
- EVENTS.txt: events supported by the plugin system
|
|
||||||
- COPYING: full text of the software license
|
|
||||||
|
|
||||||
Information on using GNU social can be found in
|
|
||||||
the "doc" subdirectory or in the "help" section
|
|
||||||
on-line, or you can catch us on IRC in #social on
|
|
||||||
the freenode network.
|
|
||||||
|
|
||||||
## About
|
|
||||||
|
|
||||||
GNU social is a free social networking
|
|
||||||
platform. It helps people in a community, company
|
|
||||||
or group to exchange short status updates, do
|
|
||||||
polls, announce events, or other social activities
|
|
||||||
(and you can add more!). Users can choose which
|
|
||||||
people to "follow" and receive only their friends'
|
|
||||||
or colleagues' status messages. It provides a
|
|
||||||
similar service to sites like Twitter, Google+ or
|
|
||||||
Facebook, but is much more awesome.
|
|
||||||
|
|
||||||
With a little work, status messages can be sent to
|
|
||||||
mobile phones, instant messenger programs (using
|
|
||||||
XMPP), and specially-designed desktop clients that
|
|
||||||
support the Twitter API.
|
|
||||||
|
|
||||||
GNU social supports an open standard called
|
|
||||||
OStatus <https://www.w3.org/community/ostatus/> that lets users in
|
|
||||||
different networks follow each other. It enables a
|
|
||||||
distributed social network spread all across the
|
|
||||||
Web.
|
|
||||||
|
|
||||||
GNU social was originally developed as "StatusNet" by
|
|
||||||
StatusNet, Inc. with Evan Prodromou as lead developer.
|
|
||||||
|
|
||||||
It is shared with you in hope that you too make an
|
|
||||||
service available to your users. To learn more,
|
|
||||||
please see the Open Software Service Definition
|
|
||||||
1.1: <http://www.opendefinition.org/ossd>
|
|
||||||
|
|
||||||
### License
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Affero General Public License as
|
|
||||||
published by the Free Software Foundation, either version 3 of the
|
|
||||||
License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful, but
|
|
||||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
Affero General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public
|
|
||||||
License along with this program, in the file "COPYING". If not, see
|
|
||||||
<http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
IMPORTANT NOTE: The GNU Affero General Public License (AGPL) has
|
|
||||||
*different requirements* from the "regular" GPL. In particular, if
|
|
||||||
you make modifications to the GNU social source code on your server,
|
|
||||||
you *MUST MAKE AVAILABLE* the modified version of the source code
|
|
||||||
to your users under the same license. This is a legal requirement
|
|
||||||
of using the software, and if you do not wish to share your
|
|
||||||
modifications, *YOU MAY NOT INSTALL GNU SOCIAL*.
|
|
||||||
|
|
||||||
Documentation in the /doc-src/ directory is available under the
|
|
||||||
Creative Commons Attribution 3.0 Unported license, with attribution to
|
|
||||||
"GNU social". See <http://creativecommons.org/licenses/by/3.0/> for details.
|
|
||||||
|
|
||||||
CSS and images in the /theme/ directory are available under the
|
|
||||||
Creative Commons Attribution 3.0 Unported license, with attribution to
|
|
||||||
"GNU social". See <http://creativecommons.org/licenses/by/3.0/> for details.
|
|
||||||
|
|
||||||
Our understanding and intention is that if you add your own theme that
|
|
||||||
uses only CSS and images, those files are not subject to the copyleft
|
|
||||||
requirements of the Affero General Public License 3.0. See
|
|
||||||
<http://wordpress.org/news/2009/07/themes-are-gpl-too/>. This is not
|
|
||||||
legal advice; consult your lawyer.
|
|
||||||
|
|
||||||
Additional library software has been made available in the 'extlib'
|
|
||||||
directory. All of it is Free Software and can be distributed under
|
|
||||||
liberal terms, but those terms may differ in detail from the AGPL's
|
|
||||||
particulars. See each package's license file in the extlib directory
|
|
||||||
for additional terms.
|
|
||||||
|
|
||||||
## New this version
|
|
||||||
|
|
||||||
This is a security fix and bug fix release since 1.1.3-beta2.
|
|
||||||
All 1.1.x sites should upgrade to this version.
|
|
||||||
|
|
||||||
So far it includes the following changes:
|
|
||||||
|
|
||||||
- XSS security fix (thanks Simon Waters, <https://www.surevine.com/>)
|
|
||||||
- Many improvements to ease adoption of the Qvitter front-end <https://github.com/hannesmannerheim/qvitter>
|
|
||||||
- Protocol adaptions for improved performance and stability
|
|
||||||
- Backing up a user's account now appears to work as it should
|
|
||||||
|
|
||||||
Upgrades from _StatusNet_ 1.1.1 will also experience these improvements:
|
|
||||||
|
|
||||||
- Fixes for SQL injection errors in profile lists.
|
|
||||||
- Improved ActivityStreams JSON representation of activities and objects.
|
|
||||||
- Upgrade to the Twitter 1.1 API.
|
|
||||||
- More robust handling of errors in distribution.
|
|
||||||
- Fix error in OStatus subscription for remote groups.
|
|
||||||
- Fix error in XMPP distribution.
|
|
||||||
- Tracking of conversation URI metadata (more coherent convos)
|
|
||||||
|
|
||||||
### Troubleshooting
|
|
||||||
|
|
||||||
The primary output for GNU social is syslog,
|
|
||||||
unless you configured a separate logfile. This is
|
|
||||||
probably the first place to look if you're getting
|
|
||||||
weird behaviour from GNU social.
|
|
||||||
|
|
||||||
If you're tracking the unstable version of
|
|
||||||
GNU social in the git repository (see below), and you
|
|
||||||
get a compilation error ("unexpected T_STRING") in
|
|
||||||
the browser, check to see that you don't have any
|
|
||||||
conflicts in your code.
|
|
||||||
|
|
||||||
### Unstable version
|
|
||||||
|
|
||||||
If you're adventurous or impatient, you may want
|
|
||||||
to install the development version of GNU social.
|
|
||||||
To get it, use the git version control tool
|
|
||||||
<http://git-scm.com/> like so:
|
|
||||||
|
|
||||||
git clone git@gitorious.org:social/mainline.git
|
|
||||||
|
|
||||||
In the current phase of development it is probably
|
|
||||||
recommended to use git as a means to stay up to date
|
|
||||||
with the source code. You can choose between these
|
|
||||||
branches:
|
|
||||||
- 1.1.x "stable", few updates, well tested code
|
|
||||||
- master "testing", more updates, usually working well
|
|
||||||
- nightly "unstable", most updates, not always working
|
|
||||||
|
|
||||||
To keep it up-to-date, use 'git pull'. Watch for conflicts!
|
|
||||||
|
|
||||||
## Further information
|
|
||||||
|
|
||||||
There are several ways to get more information about GNU social.
|
|
||||||
|
|
||||||
* The #social IRC channel on freenode.net <https://www.freenode.net/>.
|
|
||||||
* The unofficial XMPP room linked to IRC on <xmpp:gnusocial@conference.bka.li>
|
|
||||||
* The GNU social website <https://gnu.io/social/>
|
|
||||||
* Following us on GNU social -- <https://quitter.se/gnusocial>
|
|
||||||
|
|
||||||
* GNU social has a bug tracker for any defects you may find, or ideas for
|
|
||||||
making things better. <https://bugz.foocorp.net/>
|
|
||||||
* Patches are welcome, preferrably to our repository on Gitorious. <https://gitorious.org/social/mainline>
|
|
||||||
|
|
||||||
Credits
|
|
||||||
=======
|
|
||||||
|
|
||||||
The following is an incomplete list of developers
|
|
||||||
who've worked on GNU social, or its predecessors
|
|
||||||
StatusNet and Free Social. Apologies for any
|
|
||||||
oversight; please let mattl@gnu.org know if
|
|
||||||
anyone's been overlooked in error.
|
|
||||||
|
|
||||||
## Project Founders
|
|
||||||
|
|
||||||
* Matt Lee (GNU social)
|
|
||||||
* Evan Prodromou (StatusNet)
|
|
||||||
* Mikael Nordfeldth (Free Social)
|
|
||||||
|
|
||||||
Thanks to all of the StatusNet developers:
|
|
||||||
|
|
||||||
* Zach Copley, StatusNet, Inc.
|
|
||||||
* Earle Martin, StatusNet, Inc.
|
|
||||||
* Marie-Claude Doyon, designer, StatusNet, Inc.
|
|
||||||
* Sarven Capadisli, StatusNet, Inc.
|
|
||||||
* Robin Millette, StatusNet, Inc.
|
|
||||||
* Ciaran Gultnieks
|
|
||||||
* Michael Landers
|
|
||||||
* Ori Avtalion
|
|
||||||
* Garret Buell
|
|
||||||
* Mike Cochrane
|
|
||||||
* Matthew Gregg
|
|
||||||
* Florian Biree
|
|
||||||
* Erik Stambaugh
|
|
||||||
* 'drry'
|
|
||||||
* Gina Haeussge
|
|
||||||
* Tryggvi Björgvinsson
|
|
||||||
* Adrian Lang
|
|
||||||
* Ori Avtalion
|
|
||||||
* Meitar Moscovitz
|
|
||||||
* Ken Sheppardson (Trac server, man-about-town)
|
|
||||||
* Tiago 'gouki' Faria (i18n manager)
|
|
||||||
* Sean Murphy
|
|
||||||
* Leslie Michael Orchard
|
|
||||||
* Eric Helgeson
|
|
||||||
* Ken Sedgwick
|
|
||||||
* Brian Hendrickson
|
|
||||||
* Tobias Diekershoff
|
|
||||||
* Dan Moore
|
|
||||||
* Fil
|
|
||||||
* Jeff Mitchell
|
|
||||||
* Brenda Wallace
|
|
||||||
* Jeffery To
|
|
||||||
* Federico Marani
|
|
||||||
* mEDI
|
|
||||||
* Brett Taylor
|
|
||||||
* Brigitte Schuster
|
|
||||||
* Siebrand Mazeland and the amazing volunteer translators at translatewiki.net
|
|
||||||
* Brion Vibber, StatusNet, Inc.
|
|
||||||
* James Walker, StatusNet, Inc.
|
|
||||||
* Samantha Doherty, designer, StatusNet, Inc.
|
|
||||||
* Simon Waters, Surevine
|
|
||||||
* Joshua Judson Rosen (rozzin)
|
|
||||||
|
|
||||||
### Extra special thanks to the GNU socialites
|
|
||||||
|
|
||||||
* Craig Andrews
|
|
||||||
* Donald Robertson
|
|
||||||
* Deb Nicholson
|
|
||||||
* Ian Denhart
|
|
||||||
* Steven DuBois
|
|
||||||
* Blaine Cook
|
|
||||||
* Henry Story
|
|
||||||
* Melvin Carvalho
|
|
||||||
|
|
||||||
Thanks also to the developers of our upstream
|
|
||||||
library code and to the thousands of people who
|
|
||||||
have tried out GNU social, told their friends, and
|
|
||||||
built the fediverse network to what it is today.
|
|
||||||
|
|
||||||
### License help from
|
|
||||||
|
|
||||||
* Bradley M. Kuhn
|
|
||||||
|
|
||||||
12
TODO.SOCIAL
12
TODO.SOCIAL
@@ -1,12 +0,0 @@
|
|||||||
Things to be done
|
|
||||||
=================
|
|
||||||
|
|
||||||
* Create a theme for GNU social
|
|
||||||
|
|
||||||
* Create a set of plugins to give StatusNet a more social-network UI
|
|
||||||
|
|
||||||
* Work on improvements for annoying things in StatusNet (ie. no
|
|
||||||
redirect to login page when you need to be logged in, etc)
|
|
||||||
|
|
||||||
* Work on adding further Activities, such as sharing photos/video,
|
|
||||||
events, UI for managing relationships.
|
|
||||||
99
UPGRADE
99
UPGRADE
@@ -1,99 +0,0 @@
|
|||||||
Upgrading
|
|
||||||
=========
|
|
||||||
|
|
||||||
StatusNet 1.1.1 to GNU social
|
|
||||||
-----------------------------
|
|
||||||
|
|
||||||
We cannot support migrating from any other version of StatusNet than
|
|
||||||
1.1.1. If you are running a StatusNet version lower than this, please
|
|
||||||
follow the upgrade procedures for each respective StatusNet version.
|
|
||||||
|
|
||||||
You are now running StatusNet 1.1.1 and want to migrate to GNU social.
|
|
||||||
Beware there may be changes in minimum required version of PHP and the
|
|
||||||
modules used, so double-check the INSTALL file's requirements list.
|
|
||||||
|
|
||||||
Before you begin: Make backups. Always make backups. Of your entire
|
|
||||||
directory structure and the database too. All tables. All data. Alles.
|
|
||||||
|
|
||||||
0. Stop your queue daemons 'php scripts/stopdaemon.php' should do it.
|
|
||||||
Not everyone runs queue daemons, but the above command won't hurt.
|
|
||||||
|
|
||||||
1. Unpack your GNU social code to a fresh directory.
|
|
||||||
|
|
||||||
2. Synchronize your local files to the GNU social directory. These
|
|
||||||
will be the local files such as avatars, config and files:
|
|
||||||
|
|
||||||
avatar/*
|
|
||||||
background/*
|
|
||||||
file/*
|
|
||||||
local/*
|
|
||||||
.htaccess
|
|
||||||
config.php
|
|
||||||
|
|
||||||
3. Replace your old StatusNet directory with the new GNU social
|
|
||||||
directory in your webserver root.
|
|
||||||
|
|
||||||
4. Run the upgrade script: 'php scripts/upgrade.php'
|
|
||||||
|
|
||||||
5. Start your queue daemons: 'php scripts/startdaemons.php'
|
|
||||||
|
|
||||||
6. Report any issues at https://bugz.foocorp.net/ (tag GNU social)
|
|
||||||
|
|
||||||
|
|
||||||
Legacy StatusNet instructions
|
|
||||||
-----------------------------
|
|
||||||
|
|
||||||
These instructions are here for historical and perhaps informational
|
|
||||||
purposes.
|
|
||||||
|
|
||||||
If you've been using StatusNet 1.0 or lower, or if you've
|
|
||||||
been tracking the "git" version of the software, you will probably
|
|
||||||
want to upgrade and keep your existing data. Try these step-by-step
|
|
||||||
instructions; read to the end first before trying them.
|
|
||||||
|
|
||||||
0. Download StatusNet and set up all the prerequisites as if you were
|
|
||||||
doing a new install.
|
|
||||||
1. Make backups of both your database and your Web directory. UNDER NO
|
|
||||||
CIRCUMSTANCES should you try to do an upgrade without a known-good
|
|
||||||
backup. You have been warned.
|
|
||||||
2. Shut down Web access to your site, either by turning off your Web
|
|
||||||
server or by redirecting all pages to a "sorry, under maintenance"
|
|
||||||
page.
|
|
||||||
3. Shut down XMPP access to your site, typically by shutting down the
|
|
||||||
xmppdaemon.php process and all other daemons that you're running.
|
|
||||||
If you've got "monit" or "cron" automatically restarting your
|
|
||||||
daemons, make sure to turn that off, too.
|
|
||||||
4. Shut down SMS and email access to your site. The easy way to do
|
|
||||||
this is to comment out the line piping incoming email to your
|
|
||||||
maildaemon.php file, and running something like "newaliases".
|
|
||||||
5. Once all writing processes to your site are turned off, make a
|
|
||||||
final backup of the Web directory and database.
|
|
||||||
6. Move your StatusNet directory to a backup spot, like "statusnet.bak".
|
|
||||||
7. Unpack your StatusNet 1.1.1 tarball and move it to "statusnet" or
|
|
||||||
wherever your code used to be.
|
|
||||||
8. Copy the config.php file and the contents of the avatar/, background/,
|
|
||||||
file/, and local/ subdirectories from your old directory to your new
|
|
||||||
directory.
|
|
||||||
9. Copy htaccess.sample to .htaccess in the new directory. Change the
|
|
||||||
RewriteBase to use the correct path.
|
|
||||||
10. Upgrade the database.
|
|
||||||
|
|
||||||
NOTE: this step is destructive and cannot be
|
|
||||||
reversed. YOU CAN EASILY DESTROY YOUR SITE WITH THIS STEP. Don't
|
|
||||||
do it without a known-good backup!
|
|
||||||
|
|
||||||
In your new StatusNet 1.1.1 directory and AFTER YOU MAKE A
|
|
||||||
BACKUP run the upgrade.php script like this:
|
|
||||||
|
|
||||||
php ./scripts/upgrade.php
|
|
||||||
|
|
||||||
11. Use mysql or psql client to log into your database and make sure that
|
|
||||||
the notice, user, profile, subscription etc. tables are non-empty.
|
|
||||||
12. Turn back on the Web server, and check that things still work.
|
|
||||||
13. Turn back on XMPP bots and email maildaemon.
|
|
||||||
|
|
||||||
NOTE: the 1.0.0 version of StatusNet changed the URLs for all admin
|
|
||||||
panels from /admin/* to /panel/*. This now allows the (popular)
|
|
||||||
username 'admin', but blocks the considerably less popular username
|
|
||||||
'panel'. If you have an existing user named 'panel', you should rename
|
|
||||||
them before upgrading.
|
|
||||||
@@ -1,214 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StatusNet, the distributed open-source microblogging tool
|
|
||||||
*
|
|
||||||
* Site access administration panel
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category Settings
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @copyright 2010 StatusNet, Inc.
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('GNUSOCIAL')) { exit(1); }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Administer site access settings
|
|
||||||
*
|
|
||||||
* @category Admin
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
class AccessadminpanelAction extends AdminPanelAction
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Returns the page title
|
|
||||||
*
|
|
||||||
* @return string page title
|
|
||||||
*/
|
|
||||||
function title()
|
|
||||||
{
|
|
||||||
// TRANS: Page title for Access admin panel that allows configuring site access.
|
|
||||||
return _('Access');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Instructions for using this form.
|
|
||||||
*
|
|
||||||
* @return string instructions
|
|
||||||
*/
|
|
||||||
function getInstructions()
|
|
||||||
{
|
|
||||||
// TRANS: Page notice.
|
|
||||||
return _('Site access settings');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show the site admin panel form
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function showForm()
|
|
||||||
{
|
|
||||||
$form = new AccessAdminPanelForm($this);
|
|
||||||
$form->show();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Save settings from the form
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function saveSettings()
|
|
||||||
{
|
|
||||||
static $booleans = array('site' => array('private', 'inviteonly', 'closed'),
|
|
||||||
'public' => array('localonly'));
|
|
||||||
|
|
||||||
foreach ($booleans as $section => $parts) {
|
|
||||||
foreach ($parts as $setting) {
|
|
||||||
$values[$section][$setting] = ($this->boolean($setting)) ? 1 : 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$config = new Config();
|
|
||||||
|
|
||||||
$config->query('BEGIN');
|
|
||||||
|
|
||||||
foreach ($booleans as $section => $parts) {
|
|
||||||
foreach ($parts as $setting) {
|
|
||||||
Config::save($section, $setting, $values[$section][$setting]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$config->query('COMMIT');
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class AccessAdminPanelForm extends AdminForm
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* ID of the form
|
|
||||||
*
|
|
||||||
* @return int ID of the form
|
|
||||||
*/
|
|
||||||
function id()
|
|
||||||
{
|
|
||||||
return 'form_site_admin_panel';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* class of the form
|
|
||||||
*
|
|
||||||
* @return string class of the form
|
|
||||||
*/
|
|
||||||
function formClass()
|
|
||||||
{
|
|
||||||
return 'form_settings';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Action of the form
|
|
||||||
*
|
|
||||||
* @return string URL of the action
|
|
||||||
*/
|
|
||||||
function action()
|
|
||||||
{
|
|
||||||
return common_local_url('accessadminpanel');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Data elements of the form
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function formData()
|
|
||||||
{
|
|
||||||
$this->out->elementStart('fieldset', array('id' => 'settings_admin_account_access'));
|
|
||||||
// TRANS: Form legend for registration form.
|
|
||||||
$this->out->element('legend', null, _('Registration'));
|
|
||||||
$this->out->elementStart('ul', 'form_data');
|
|
||||||
|
|
||||||
$this->li();
|
|
||||||
// TRANS: Checkbox instructions for admin setting "Invite only".
|
|
||||||
$instructions = _('Make registration invitation only.');
|
|
||||||
// TRANS: Checkbox label for configuring site as invite only.
|
|
||||||
$this->out->checkbox('inviteonly', _('Invite only'),
|
|
||||||
(bool) $this->value('inviteonly'),
|
|
||||||
$instructions);
|
|
||||||
$this->unli();
|
|
||||||
|
|
||||||
$this->li();
|
|
||||||
// TRANS: Checkbox instructions for admin setting "Closed" (no new registrations).
|
|
||||||
$instructions = _('Disable new registrations.');
|
|
||||||
// TRANS: Checkbox label for disabling new user registrations.
|
|
||||||
$this->out->checkbox('closed', _('Closed'),
|
|
||||||
(bool) $this->value('closed'),
|
|
||||||
$instructions);
|
|
||||||
$this->unli();
|
|
||||||
|
|
||||||
$this->out->elementEnd('ul');
|
|
||||||
$this->out->elementEnd('fieldset');
|
|
||||||
|
|
||||||
|
|
||||||
// Public access settings (login requirements for feeds etc.)
|
|
||||||
$this->out->elementStart('fieldset', array('id' => 'settings_admin_public_access'));
|
|
||||||
// TRANS: Form legend for registration form.
|
|
||||||
$this->out->element('legend', null, _('Feed access'));
|
|
||||||
$this->out->elementStart('ul', 'form_data');
|
|
||||||
$this->li();
|
|
||||||
// TRANS: Checkbox instructions for admin setting "Private".
|
|
||||||
$instructions = _('Prohibit anonymous users (not logged in) from viewing site?');
|
|
||||||
// TRANS: Checkbox label for prohibiting anonymous users from viewing site.
|
|
||||||
$this->out->checkbox('private', _m('LABEL', 'Private'),
|
|
||||||
(bool) $this->value('private'),
|
|
||||||
$instructions);
|
|
||||||
$this->unli();
|
|
||||||
|
|
||||||
$this->li();
|
|
||||||
// TRANS: Description of the full network notice stream views..
|
|
||||||
$instructions = _('The full network view includes (public) remote notices which may be unrelated to local conversations.');
|
|
||||||
// TRANS: Checkbox label for hiding remote network posts if they have not been interacted with locally.
|
|
||||||
$this->out->checkbox('localonly', _('Restrict full network view to accounts'),
|
|
||||||
(bool) $this->value('localonly', 'public'),
|
|
||||||
$instructions);
|
|
||||||
$this->unli();
|
|
||||||
|
|
||||||
$this->out->elementEnd('ul');
|
|
||||||
$this->out->elementEnd('fieldset');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Action elements
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function formActions()
|
|
||||||
{
|
|
||||||
// TRANS: Button title to save access settings in site admin panel.
|
|
||||||
$title = _('Save access settings.');
|
|
||||||
// TRANS: Button text to save access settings in site admin panel.
|
|
||||||
$this->out->submit('submit', _m('BUTTON', 'Save'), 'submit', null, $title);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,161 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StatusNet - the distributed open-source microblogging tool
|
|
||||||
* Copyright (C) 2008-2010, StatusNet, Inc.
|
|
||||||
*
|
|
||||||
* Action to add a people tag to a user.
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* @category Action
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Shashi Gowda <connect2shashi@gmail.com>
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPLv3
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('STATUSNET')) {
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
require_once INSTALLDIR . '/lib/togglepeopletag.php';
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Action to tag a profile with a single tag.
|
|
||||||
*
|
|
||||||
* Takes parameters:
|
|
||||||
*
|
|
||||||
* - tagged: the ID of the profile being tagged
|
|
||||||
* - token: session token to prevent CSRF attacks
|
|
||||||
* - ajax: boolean; whether to return Ajax or full-browser results
|
|
||||||
* - peopletag_id: the ID of the tag being used
|
|
||||||
*
|
|
||||||
* Only works if the current user is logged in.
|
|
||||||
*
|
|
||||||
* @category Action
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Shashi Gowda <connect2shashi@gmail.com>
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPLv3
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
class AddpeopletagAction extends Action
|
|
||||||
{
|
|
||||||
var $user;
|
|
||||||
var $tagged;
|
|
||||||
var $peopletag;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check pre-requisites and instantiate attributes
|
|
||||||
*
|
|
||||||
* @param Array $args array of arguments (URL, GET, POST)
|
|
||||||
*
|
|
||||||
* @return boolean success flag
|
|
||||||
*/
|
|
||||||
function prepare($args)
|
|
||||||
{
|
|
||||||
parent::prepare($args);
|
|
||||||
|
|
||||||
// CSRF protection
|
|
||||||
|
|
||||||
$token = $this->trimmed('token');
|
|
||||||
|
|
||||||
if (!$token || $token != common_session_token()) {
|
|
||||||
// TRANS: Client error displayed when the session token does not match or is not given.
|
|
||||||
$this->clientError(_('There was a problem with your session token.'.
|
|
||||||
' Try again, please.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only for logged-in users
|
|
||||||
|
|
||||||
$this->user = common_current_user();
|
|
||||||
|
|
||||||
if (empty($this->user)) {
|
|
||||||
// TRANS: Error message displayed when trying to perform an action that requires a logged in user.
|
|
||||||
$this->clientError(_('Not logged in.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Profile to subscribe to
|
|
||||||
|
|
||||||
$tagged_id = $this->arg('tagged');
|
|
||||||
|
|
||||||
$this->tagged = Profile::getKV('id', $tagged_id);
|
|
||||||
|
|
||||||
if (empty($this->tagged)) {
|
|
||||||
// TRANS: Client error displayed trying to perform an action related to a non-existing profile.
|
|
||||||
$this->clientError(_('No such profile.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$id = $this->arg('peopletag_id');
|
|
||||||
$this->peopletag = Profile_list::getKV('id', $id);
|
|
||||||
|
|
||||||
if (empty($this->peopletag)) {
|
|
||||||
// TRANS: Client error displayed trying to reference a non-existing list.
|
|
||||||
$this->clientError(_('No such list.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle request
|
|
||||||
*
|
|
||||||
* Does the tagging and returns results.
|
|
||||||
*
|
|
||||||
* @param Array $args unused.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function handle($args)
|
|
||||||
{
|
|
||||||
// Throws exception on error
|
|
||||||
$ptag = Profile_tag::setTag($this->user->id, $this->tagged->id,
|
|
||||||
$this->peopletag->tag);
|
|
||||||
|
|
||||||
if (!$ptag) {
|
|
||||||
$user = User::getKV('id', $id);
|
|
||||||
if ($user) {
|
|
||||||
$this->clientError(
|
|
||||||
// TRANS: Client error displayed when an unknown error occurs when adding a user to a list.
|
|
||||||
// TRANS: %s is a username.
|
|
||||||
sprintf(_('There was an unexpected error while listing %s.'),
|
|
||||||
$user->nickname));
|
|
||||||
} else {
|
|
||||||
// TRANS: Client error displayed when an unknown error occurs when adding a user to a list.
|
|
||||||
// TRANS: %s is a profile URL.
|
|
||||||
$this->clientError(sprintf(_('There was a problem listing %s. ' .
|
|
||||||
'The remote server is probably not responding correctly. ' .
|
|
||||||
'Please try retrying later.'), $this->profile->profileurl));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ($this->boolean('ajax')) {
|
|
||||||
$this->startHTML('text/xml;charset=utf-8');
|
|
||||||
$this->elementStart('head');
|
|
||||||
// TRANS: Title after adding a user to a list.
|
|
||||||
$this->element('title', null, _m('TITLE','Listed'));
|
|
||||||
$this->elementEnd('head');
|
|
||||||
$this->elementStart('body');
|
|
||||||
$unsubscribe = new UntagButton($this, $this->tagged, $this->peopletag);
|
|
||||||
$unsubscribe->show();
|
|
||||||
$this->elementEnd('body');
|
|
||||||
$this->endHTML();
|
|
||||||
} else {
|
|
||||||
$url = common_local_url('subscriptions',
|
|
||||||
array('nickname' => $this->user->nickname));
|
|
||||||
common_redirect($url, 303);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
211
actions/all.php
211
actions/all.php
@@ -1,211 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StatusNet - the distributed open-source microblogging tool
|
|
||||||
* Copyright (C) 2008-2011, StatusNet, Inc.
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category Actions
|
|
||||||
* @package Actions
|
|
||||||
* @author Adrian Lang <mail@adrianlang.de>
|
|
||||||
* @author Brenda Wallace <shiny@cpan.org>
|
|
||||||
* @author Brion Vibber <brion@pobox.com>
|
|
||||||
* @author Craig Andrews <candrews@integralblue.com>
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @author Jeffery To <jeffery.to@gmail.com>
|
|
||||||
* @author Meitar Moscovitz <meitarm@gmail.com>
|
|
||||||
* @author Mike Cochrane <mikec@mikenz.geek.nz>
|
|
||||||
* @author Robin Millette <millette@status.net>
|
|
||||||
* @author Sarven Capadisli <csarven@status.net>
|
|
||||||
* @author Siebrand Mazeland <s.mazeland@xs4all.nl>
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @copyright 2009-2014 Free Software Foundation, Inc http://www.fsf.org
|
|
||||||
* @license GNU Affero General Public License http://www.gnu.org/licenses/
|
|
||||||
* @link http://status.net
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('GNUSOCIAL') && !defined('STATUSNET')) { exit(1); }
|
|
||||||
|
|
||||||
class AllAction extends ProfileAction
|
|
||||||
{
|
|
||||||
var $notice;
|
|
||||||
|
|
||||||
protected function prepare(array $args=array())
|
|
||||||
{
|
|
||||||
parent::prepare($args);
|
|
||||||
|
|
||||||
$user = common_current_user();
|
|
||||||
|
|
||||||
if (!empty($user) && $user->streamModeOnly()) {
|
|
||||||
$stream = new InboxNoticeStream($this->target, $this->scoped);
|
|
||||||
} else {
|
|
||||||
$stream = new ThreadingInboxNoticeStream($this->target, $this->scoped);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->notice = $stream->getNotices(($this->page-1)*NOTICES_PER_PAGE,
|
|
||||||
NOTICES_PER_PAGE + 1);
|
|
||||||
|
|
||||||
if ($this->page > 1 && $this->notice->N == 0) {
|
|
||||||
// TRANS: Client error when page not found (404).
|
|
||||||
$this->clientError(_('No such page.'), 404);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function title()
|
|
||||||
{
|
|
||||||
if (!empty($this->scoped) && $this->scoped->id == $this->target->id) {
|
|
||||||
// TRANS: Title of a user's own start page.
|
|
||||||
return _('Home timeline');
|
|
||||||
} else {
|
|
||||||
// TRANS: Title of another user's start page.
|
|
||||||
// TRANS: %s is the other user's name.
|
|
||||||
return sprintf(_("%s's home timeline"), $this->target->getBestName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getFeeds()
|
|
||||||
{
|
|
||||||
return array(
|
|
||||||
new Feed(Feed::JSON,
|
|
||||||
common_local_url(
|
|
||||||
'ApiTimelineFriends', array(
|
|
||||||
'format' => 'as',
|
|
||||||
'id' => $this->target->nickname
|
|
||||||
)
|
|
||||||
),
|
|
||||||
// TRANS: %s is user nickname.
|
|
||||||
sprintf(_('Feed for friends of %s (Activity Streams JSON)'), $this->target->nickname)),
|
|
||||||
new Feed(Feed::RSS1,
|
|
||||||
common_local_url(
|
|
||||||
'allrss', array(
|
|
||||||
'nickname' =>
|
|
||||||
$this->target->nickname)
|
|
||||||
),
|
|
||||||
// TRANS: %s is user nickname.
|
|
||||||
sprintf(_('Feed for friends of %s (RSS 1.0)'), $this->target->nickname)),
|
|
||||||
new Feed(Feed::RSS2,
|
|
||||||
common_local_url(
|
|
||||||
'ApiTimelineFriends', array(
|
|
||||||
'format' => 'rss',
|
|
||||||
'id' => $this->target->nickname
|
|
||||||
)
|
|
||||||
),
|
|
||||||
// TRANS: %s is user nickname.
|
|
||||||
sprintf(_('Feed for friends of %s (RSS 2.0)'), $this->target->nickname)),
|
|
||||||
new Feed(Feed::ATOM,
|
|
||||||
common_local_url(
|
|
||||||
'ApiTimelineFriends', array(
|
|
||||||
'format' => 'atom',
|
|
||||||
'id' => $this->target->nickname
|
|
||||||
)
|
|
||||||
),
|
|
||||||
// TRANS: %s is user nickname.
|
|
||||||
sprintf(_('Feed for friends of %s (Atom)'), $this->target->nickname))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function showEmptyListMessage()
|
|
||||||
{
|
|
||||||
// TRANS: Empty list message. %s is a user nickname.
|
|
||||||
$message = sprintf(_('This is the timeline for %s and friends but no one has posted anything yet.'), $this->target->nickname) . ' ';
|
|
||||||
|
|
||||||
if (common_logged_in()) {
|
|
||||||
if ($this->target->id === $this->scoped->id) {
|
|
||||||
// TRANS: Encouragement displayed on logged in user's empty timeline.
|
|
||||||
// TRANS: This message contains Markdown links. Keep "](" together.
|
|
||||||
$message .= _('Try subscribing to more people, [join a group](%%action.groups%%) or post something yourself.');
|
|
||||||
} else {
|
|
||||||
// TRANS: %1$s is user nickname, %2$s is user nickname, %2$s is user nickname prefixed with "@".
|
|
||||||
// TRANS: This message contains Markdown links. Keep "](" together.
|
|
||||||
$message .= sprintf(_('You can try to [nudge %1$s](../%2$s) from their profile or [post something to them](%%%%action.newnotice%%%%?status_textarea=%3$s).'), $this->target->nickname, $this->target->nickname, '@' . $this->target->nickname);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// TRANS: Encouragement displayed on empty timeline user pages for anonymous users.
|
|
||||||
// TRANS: %s is a user nickname. This message contains Markdown links. Keep "](" together.
|
|
||||||
$message .= sprintf(_('Why not [register an account](%%%%action.register%%%%) and then nudge %s or post a notice to them.'), $this->target->nickname);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->elementStart('div', 'guide');
|
|
||||||
$this->raw(common_markup_to_html($message));
|
|
||||||
$this->elementEnd('div');
|
|
||||||
}
|
|
||||||
|
|
||||||
function showContent()
|
|
||||||
{
|
|
||||||
if (Event::handle('StartShowAllContent', array($this))) {
|
|
||||||
|
|
||||||
$profile = null;
|
|
||||||
|
|
||||||
$current_user = common_current_user();
|
|
||||||
|
|
||||||
if (!empty($current_user)) {
|
|
||||||
$profile = $current_user->getProfile();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($current_user) && $current_user->streamModeOnly()) {
|
|
||||||
$nl = new PrimaryNoticeList($this->notice, $this, array('show_n'=>NOTICES_PER_PAGE));
|
|
||||||
} else {
|
|
||||||
$nl = new ThreadedNoticeList($this->notice, $this, $profile);
|
|
||||||
}
|
|
||||||
|
|
||||||
$cnt = $nl->show();
|
|
||||||
|
|
||||||
if (0 == $cnt) {
|
|
||||||
$this->showEmptyListMessage();
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->pagination(
|
|
||||||
$this->page > 1, $cnt > NOTICES_PER_PAGE,
|
|
||||||
$this->page, 'all', array('nickname' => $this->target->nickname)
|
|
||||||
);
|
|
||||||
|
|
||||||
Event::handle('EndShowAllContent', array($this));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function showSections()
|
|
||||||
{
|
|
||||||
// Show invite button, as long as site isn't closed, and
|
|
||||||
// we have a logged in user.
|
|
||||||
if (common_config('invite', 'enabled') && !common_config('site', 'closed') && common_logged_in()) {
|
|
||||||
if (!common_config('site', 'private')) {
|
|
||||||
$ibs = new InviteButtonSection(
|
|
||||||
$this,
|
|
||||||
// TRANS: Button text for inviting more users to the StatusNet instance.
|
|
||||||
// TRANS: Less business/enterprise-oriented language for public sites.
|
|
||||||
_m('BUTTON', 'Send invite')
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
$ibs = new InviteButtonSection($this);
|
|
||||||
}
|
|
||||||
$ibs->show();
|
|
||||||
}
|
|
||||||
// XXX: make this a little more convenient
|
|
||||||
|
|
||||||
if (!common_config('performance', 'high')) {
|
|
||||||
$pop = new InboxTagCloudSection($this, $this->target);
|
|
||||||
$pop->show();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class ThreadingInboxNoticeStream extends ThreadingNoticeStream
|
|
||||||
{
|
|
||||||
function __construct(Profile $target, Profile $scoped=null)
|
|
||||||
{
|
|
||||||
parent::__construct(new InboxNoticeStream($target, $scoped));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,133 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* RSS feed for user and friends timeline action class.
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* @category Action
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @author Robin Millette <millette@status.net>
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
|
|
||||||
* @link http://status.net/
|
|
||||||
*
|
|
||||||
* StatusNet - the distributed open-source microblogging tool
|
|
||||||
* Copyright (C) 2008, 2009, StatusNet, Inc.
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('STATUSNET') && !defined('LACONICA')) {
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
require_once INSTALLDIR.'/lib/rssaction.php';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* RSS feed for user and friends timeline.
|
|
||||||
*
|
|
||||||
* Formatting of RSS handled by Rss10Action
|
|
||||||
*
|
|
||||||
* @category Action
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @author Robin Millette <millette@status.net>
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
class AllrssAction extends Rss10Action
|
|
||||||
{
|
|
||||||
var $user = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialization.
|
|
||||||
*
|
|
||||||
* @param array $args Web and URL arguments
|
|
||||||
*
|
|
||||||
* @return boolean false if user doesn't exist
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
function prepare($args)
|
|
||||||
{
|
|
||||||
parent::prepare($args);
|
|
||||||
$nickname = $this->trimmed('nickname');
|
|
||||||
$this->user = User::getKV('nickname', $nickname);
|
|
||||||
|
|
||||||
if (!$this->user) {
|
|
||||||
// TRANS: Client error when user not found for an rss related action.
|
|
||||||
$this->clientError(_('No such user.'));
|
|
||||||
} else {
|
|
||||||
$this->notices = $this->getNotices($this->limit);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get notices
|
|
||||||
*
|
|
||||||
* @param integer $limit max number of notices to return
|
|
||||||
*
|
|
||||||
* @return array notices
|
|
||||||
*/
|
|
||||||
function getNotices($limit=0)
|
|
||||||
{
|
|
||||||
$stream = new InboxNoticeStream($this->user->getProfile());
|
|
||||||
$notice = $stream->getNotices(0, $limit, null, null);
|
|
||||||
|
|
||||||
$notices = array();
|
|
||||||
|
|
||||||
while ($notice->fetch()) {
|
|
||||||
$notices[] = clone($notice);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $notices;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get channel.
|
|
||||||
*
|
|
||||||
* @return array associative array on channel information
|
|
||||||
*/
|
|
||||||
function getChannel()
|
|
||||||
{
|
|
||||||
$user = $this->user;
|
|
||||||
$c = array('url' => common_local_url('allrss',
|
|
||||||
array('nickname' =>
|
|
||||||
$user->nickname)),
|
|
||||||
// TRANS: Message is used as link title. %s is a user nickname.
|
|
||||||
'title' => sprintf(_('%s and friends'), $user->nickname),
|
|
||||||
'link' => common_local_url('all',
|
|
||||||
array('nickname' =>
|
|
||||||
$user->nickname)),
|
|
||||||
// TRANS: Message is used as link description. %1$s is a username, %2$s is a site name.
|
|
||||||
'description' => sprintf(_('Updates from %1$s and friends on %2$s!'),
|
|
||||||
$user->nickname, common_config('site', 'name')));
|
|
||||||
return $c;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get image.
|
|
||||||
*
|
|
||||||
* @return string user avatar URL or null
|
|
||||||
*/
|
|
||||||
function getImage()
|
|
||||||
{
|
|
||||||
$user = $this->user;
|
|
||||||
$profile = $user->getProfile();
|
|
||||||
if (!$profile) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return $profile->avatarUrl(AVATAR_PROFILE_SIZE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,122 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StatusNet, the distributed open-source microblogging tool
|
|
||||||
*
|
|
||||||
* Dummy action that emulates Twitter's rate limit status API resource
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Brion Vibber <brion@pobox.com>
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @author Robin Millette <robin@millette.info>
|
|
||||||
* @author Siebrand Mazeland <s.mazeland@xs4all.nl>
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @copyright 2009 StatusNet, Inc.
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('STATUSNET')) {
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* We don't have a rate limit, but some clients check this method.
|
|
||||||
* It always returns the same thing: 150 hits left.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @author Robin Millette <robin@millette.info>
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
class ApiAccountRateLimitStatusAction extends ApiBareAuthAction
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Handle the request
|
|
||||||
*
|
|
||||||
* Return some Twitter-ish data about API limits
|
|
||||||
*
|
|
||||||
* @param array $args $_REQUEST data (unused)
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function handle($args)
|
|
||||||
{
|
|
||||||
parent::handle($args);
|
|
||||||
|
|
||||||
if (!in_array($this->format, array('xml', 'json'))) {
|
|
||||||
$this->clientError(
|
|
||||||
// TRANS: Client error displayed when coming across a non-supported API method.
|
|
||||||
_('API method not found.'),
|
|
||||||
404,
|
|
||||||
$this->format
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$reset = new DateTime();
|
|
||||||
$reset->modify('+1 hour');
|
|
||||||
|
|
||||||
$this->initDocument($this->format);
|
|
||||||
|
|
||||||
if ($this->format == 'xml') {
|
|
||||||
$this->elementStart('hash');
|
|
||||||
$this->element('remaining-hits', array('type' => 'integer'), 150);
|
|
||||||
$this->element('hourly-limit', array('type' => 'integer'), 150);
|
|
||||||
$this->element(
|
|
||||||
'reset-time', array('type' => 'datetime'),
|
|
||||||
common_date_iso8601($reset->format('r'))
|
|
||||||
);
|
|
||||||
$this->element(
|
|
||||||
'reset_time_in_seconds',
|
|
||||||
array('type' => 'integer'),
|
|
||||||
strtotime('+1 hour')
|
|
||||||
);
|
|
||||||
$this->elementEnd('hash');
|
|
||||||
} elseif ($this->format == 'json') {
|
|
||||||
$out = array(
|
|
||||||
'reset_time_in_seconds' => strtotime('+1 hour'),
|
|
||||||
'remaining_hits' => 150,
|
|
||||||
'hourly_limit' => 150,
|
|
||||||
'reset_time' => common_date_rfc2822(
|
|
||||||
$reset->format('r')
|
|
||||||
)
|
|
||||||
);
|
|
||||||
print json_encode($out);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->endDocument($this->format);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return true if read only.
|
|
||||||
*
|
|
||||||
* MAY override
|
|
||||||
*
|
|
||||||
* @param array $args other arguments
|
|
||||||
*
|
|
||||||
* @return boolean is read only action?
|
|
||||||
*/
|
|
||||||
function isReadOnly($args)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,204 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* StatusNet, the distributed open-source microblogging tool
|
|
||||||
*
|
|
||||||
* Register account
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package GNUsocial
|
|
||||||
* @author Hannes Mannerheim <h@nnesmannerhe.im>
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://www.gnu.org/software/social/
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('GNUSOCIAL')) { exit(1); }
|
|
||||||
|
|
||||||
class ApiAccountRegisterAction extends ApiAction
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Has there been an error?
|
|
||||||
*/
|
|
||||||
var $error = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Have we registered?
|
|
||||||
*/
|
|
||||||
var $registered = false;
|
|
||||||
|
|
||||||
protected $needPost = true;
|
|
||||||
|
|
||||||
protected $code = null; // invite code
|
|
||||||
protected $invite = null; // invite to-be-stored
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Take arguments for running
|
|
||||||
*
|
|
||||||
* @param array $args $_REQUEST args
|
|
||||||
*
|
|
||||||
* @return boolean success flag
|
|
||||||
*/
|
|
||||||
protected function prepare(array $args=array())
|
|
||||||
{
|
|
||||||
parent::prepare($args);
|
|
||||||
|
|
||||||
if ($this->format !== 'json') {
|
|
||||||
$this->clientError('This method currently only serves JSON.', 415);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->code = $this->trimmed('code');
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle the request
|
|
||||||
*
|
|
||||||
* @param array $args $_REQUEST data (unused)
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
protected function handle()
|
|
||||||
{
|
|
||||||
parent::handle();
|
|
||||||
|
|
||||||
$nickname = $this->trimmed('nickname');
|
|
||||||
$email = $this->trimmed('email');
|
|
||||||
$fullname = $this->trimmed('fullname');
|
|
||||||
$homepage = $this->trimmed('homepage');
|
|
||||||
$bio = $this->trimmed('bio');
|
|
||||||
$location = $this->trimmed('location');
|
|
||||||
|
|
||||||
// We don't trim these... whitespace is OK in a password!
|
|
||||||
$password = $this->arg('password');
|
|
||||||
$confirm = $this->arg('confirm');
|
|
||||||
|
|
||||||
if (empty($this->code)) {
|
|
||||||
common_ensure_session();
|
|
||||||
if (array_key_exists('invitecode', $_SESSION)) {
|
|
||||||
$this->code = $_SESSION['invitecode'];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (common_config('site', 'inviteonly') && empty($this->code)) {
|
|
||||||
// TRANS: Client error displayed when trying to register to an invite-only site without an invitation.
|
|
||||||
$this->clientError(_('Sorry, only invited people can register.'), 401);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($this->code)) {
|
|
||||||
$this->invite = Invitation::getKV('code', $this->code);
|
|
||||||
if (empty($this->invite)) {
|
|
||||||
// TRANS: Client error displayed when trying to register to an invite-only site without a valid invitation.
|
|
||||||
$this->clientError(_('Sorry, invalid invitation code.'), 401);
|
|
||||||
}
|
|
||||||
// Store this in case we need it
|
|
||||||
common_ensure_session();
|
|
||||||
$_SESSION['invitecode'] = $this->code;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Input scrubbing
|
|
||||||
try {
|
|
||||||
$nickname = Nickname::normalize($nickname, true);
|
|
||||||
} catch (NicknameException $e) {
|
|
||||||
// clientError handles Api exceptions with various formats and stuff
|
|
||||||
$this->clientError($e->getMessage(), $e->getCode());
|
|
||||||
}
|
|
||||||
|
|
||||||
$email = common_canonical_email($email);
|
|
||||||
|
|
||||||
if ($email && !Validate::email($email, common_config('email', 'check_domain'))) {
|
|
||||||
// TRANS: Form validation error displayed when trying to register without a valid e-mail address.
|
|
||||||
$this->clientError(_('Not a valid email address.'), 400);
|
|
||||||
} else if ($this->emailExists($email)) {
|
|
||||||
// TRANS: Form validation error displayed when trying to register with an already registered e-mail address.
|
|
||||||
$this->clientError(_('Email address already exists.'), 400);
|
|
||||||
} else if (!is_null($homepage) && (strlen($homepage) > 0) &&
|
|
||||||
!common_valid_http_url($homepage)) {
|
|
||||||
// TRANS: Form validation error displayed when trying to register with an invalid homepage URL.
|
|
||||||
$this->clientError(_('Homepage is not a valid URL.'), 400);
|
|
||||||
} else if (!is_null($fullname) && mb_strlen($fullname) > 255) {
|
|
||||||
// TRANS: Form validation error displayed when trying to register with a too long full name.
|
|
||||||
$this->clientError(_('Full name is too long (maximum 255 characters).'), 400);
|
|
||||||
} else if (Profile::bioTooLong($bio)) {
|
|
||||||
// TRANS: Form validation error on registration page when providing too long a bio text.
|
|
||||||
// TRANS: %d is the maximum number of characters for bio; used for plural.
|
|
||||||
$this->clientError(sprintf(_m('Bio is too long (maximum %d character).',
|
|
||||||
'Bio is too long (maximum %d characters).',
|
|
||||||
Profile::maxBio()),
|
|
||||||
Profile::maxBio()), 400);
|
|
||||||
} else if (!is_null($location) && mb_strlen($location) > 255) {
|
|
||||||
// TRANS: Form validation error displayed when trying to register with a too long location.
|
|
||||||
$this->clientError(_('Location is too long (maximum 255 characters).'), 400);
|
|
||||||
} else if (strlen($password) < 6) {
|
|
||||||
// TRANS: Form validation error displayed when trying to register with too short a password.
|
|
||||||
$this->clientError(_('Password must be 6 or more characters.'), 400);
|
|
||||||
} else if ($password != $confirm) {
|
|
||||||
// TRANS: Form validation error displayed when trying to register with non-matching passwords.
|
|
||||||
$this->clientError(_('Passwords do not match.'), 400);
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// annoy spammers
|
|
||||||
sleep(7);
|
|
||||||
|
|
||||||
if ($user = User::register(array('nickname' => $nickname,
|
|
||||||
'password' => $password,
|
|
||||||
'email' => $email,
|
|
||||||
'fullname' => $fullname,
|
|
||||||
'homepage' => $homepage,
|
|
||||||
'bio' => $bio,
|
|
||||||
'location' => $location,
|
|
||||||
'code' => $this->code))) {
|
|
||||||
if (!$user instanceof User) {
|
|
||||||
// TRANS: Form validation error displayed when trying to register with an invalid username or password.
|
|
||||||
$this->clientError(_('Invalid username or password.'), 400);
|
|
||||||
}
|
|
||||||
|
|
||||||
Event::handle('EndRegistrationTry', array($this));
|
|
||||||
|
|
||||||
$this->initDocument('json');
|
|
||||||
$this->showJsonObjects($this->twitterUserArray($user->getProfile()));
|
|
||||||
$this->endDocument('json');
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// TRANS: Form validation error displayed when trying to register with an invalid username or password.
|
|
||||||
$this->clientError(_('Invalid username or password.'), 400);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Does the given email address already exist?
|
|
||||||
*
|
|
||||||
* Checks a canonical email address against the database.
|
|
||||||
*
|
|
||||||
* @param string $email email address to check
|
|
||||||
*
|
|
||||||
* @return boolean true if the address already exists
|
|
||||||
*/
|
|
||||||
function emailExists($email)
|
|
||||||
{
|
|
||||||
$email = common_canonical_email($email);
|
|
||||||
if (!$email || strlen($email) == 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
$user = User::getKV('email', $email);
|
|
||||||
return is_object($user);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,90 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StatusNet, the distributed open-source microblogging tool
|
|
||||||
*
|
|
||||||
* Update a user's background color
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package GNUsocial
|
|
||||||
* @author Hannes Mannerheim <h@nnesmannerhe.im>
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://www.gnu.org/software/social/
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('GNUSOCIAL')) { exit(1); }
|
|
||||||
|
|
||||||
class ApiAccountUpdateBackgroundColorAction extends ApiAuthAction
|
|
||||||
{
|
|
||||||
var $backgroundcolor = null;
|
|
||||||
|
|
||||||
protected $needPost = true;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Take arguments for running
|
|
||||||
*
|
|
||||||
* @param array $args $_REQUEST args
|
|
||||||
*
|
|
||||||
* @return boolean success flag
|
|
||||||
*/
|
|
||||||
protected function prepare(array $args=array())
|
|
||||||
{
|
|
||||||
parent::prepare($args);
|
|
||||||
|
|
||||||
if ($this->format !== 'json') {
|
|
||||||
$this->clientError('This method currently only serves JSON.', 415);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->backgroundcolor = $this->trimmed('backgroundcolor');
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle the request
|
|
||||||
*
|
|
||||||
* Try to save the user's colors in her design. Create a new design
|
|
||||||
* if the user doesn't already have one.
|
|
||||||
*
|
|
||||||
* @param array $args $_REQUEST data (unused)
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
protected function handle()
|
|
||||||
{
|
|
||||||
parent::handle();
|
|
||||||
|
|
||||||
$validhex = preg_match('/^[a-f0-9]{6}$/i',$this->backgroundcolor);
|
|
||||||
if ($validhex === false || $validhex == 0) {
|
|
||||||
$this->clientError(_('Not a valid hex color.'), 400);
|
|
||||||
}
|
|
||||||
|
|
||||||
// save the new color
|
|
||||||
$original = clone($this->auth_user);
|
|
||||||
$this->auth_user->backgroundcolor = $this->backgroundcolor;
|
|
||||||
if (!$this->auth_user->update($original)) {
|
|
||||||
$this->clientError(_('Error updating user.'), 404);
|
|
||||||
}
|
|
||||||
|
|
||||||
$twitter_user = $this->twitterUserArray($this->scoped, true);
|
|
||||||
|
|
||||||
$this->initDocument('json');
|
|
||||||
$this->showJsonObjects($twitter_user);
|
|
||||||
$this->endDocument('json');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,147 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StatusNet, the distributed open-source microblogging tool
|
|
||||||
*
|
|
||||||
* Update the authenticating user notification channels
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Siebrand Mazeland <s.mazeland@xs4all.nl>
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @copyright 2009 StatusNet, Inc.
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('STATUSNET')) {
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets which channel (device) StatusNet delivers updates to for
|
|
||||||
* the authenticating user. Sending none as the device parameter
|
|
||||||
* will disable IM and/or SMS updates.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
class ApiAccountUpdateDeliveryDeviceAction extends ApiAuthAction
|
|
||||||
{
|
|
||||||
protected $needPost = true;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Take arguments for running
|
|
||||||
*
|
|
||||||
* @param array $args $_REQUEST args
|
|
||||||
*
|
|
||||||
* @return boolean success flag
|
|
||||||
*/
|
|
||||||
function prepare($args)
|
|
||||||
{
|
|
||||||
parent::prepare($args);
|
|
||||||
|
|
||||||
$this->user = $this->auth_user;
|
|
||||||
$this->device = $this->trimmed('device');
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle the request
|
|
||||||
*
|
|
||||||
* See which request params have been set, and update the user settings
|
|
||||||
*
|
|
||||||
* @param array $args $_REQUEST data (unused)
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function handle($args)
|
|
||||||
{
|
|
||||||
parent::handle($args);
|
|
||||||
|
|
||||||
if (!in_array($this->format, array('xml', 'json'))) {
|
|
||||||
$this->clientError(
|
|
||||||
// TRANS: Client error displayed when coming across a non-supported API method.
|
|
||||||
_('API method not found.'),
|
|
||||||
404,
|
|
||||||
$this->format
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Note: Twitter no longer supports IM
|
|
||||||
|
|
||||||
if (!in_array(strtolower($this->device), array('sms', 'im', 'none'))) {
|
|
||||||
// TRANS: Client error displayed when no valid device parameter is provided for a user's delivery device setting.
|
|
||||||
$this->clientError(_( 'You must specify a parameter named ' .
|
|
||||||
'\'device\' with a value of one of: sms, im, none.' ));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (empty($this->user)) {
|
|
||||||
// TRANS: Client error displayed when no existing user is provided for a user's delivery device setting.
|
|
||||||
$this->clientError(_('No such user.'), 404);
|
|
||||||
}
|
|
||||||
|
|
||||||
$original = clone($this->user);
|
|
||||||
|
|
||||||
if (strtolower($this->device) == 'sms') {
|
|
||||||
$this->user->smsnotify = true;
|
|
||||||
} elseif (strtolower($this->device) == 'im') {
|
|
||||||
//TODO IM is pluginized now, so what should we do?
|
|
||||||
//Enable notifications for all IM plugins?
|
|
||||||
//For now, don't do anything
|
|
||||||
//$this->user->jabbernotify = true;
|
|
||||||
} elseif (strtolower($this->device == 'none')) {
|
|
||||||
$this->user->smsnotify = false;
|
|
||||||
//TODO IM is pluginized now, so what should we do?
|
|
||||||
//Disable notifications for all IM plugins?
|
|
||||||
//For now, don't do anything
|
|
||||||
//$this->user->jabbernotify = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$result = $this->user->update($original);
|
|
||||||
|
|
||||||
if ($result === false) {
|
|
||||||
common_log_db_error($this->user, 'UPDATE', __FILE__);
|
|
||||||
// TRANS: Server error displayed when a user's delivery device cannot be updated.
|
|
||||||
$this->serverError(_('Could not update user.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$profile = $this->user->getProfile();
|
|
||||||
|
|
||||||
$twitter_user = $this->twitterUserArray($profile, true);
|
|
||||||
|
|
||||||
// Note: this Twitter API method is retarded because it doesn't give
|
|
||||||
// any success/failure information. Twitter's docs claim that the
|
|
||||||
// notification field will change to reflect notification choice,
|
|
||||||
// but that's not true; notification> is used to indicate
|
|
||||||
// whether the auth user is following the user in question.
|
|
||||||
|
|
||||||
if ($this->format == 'xml') {
|
|
||||||
$this->initDocument('xml');
|
|
||||||
$this->showTwitterXmlUser($twitter_user, 'user', true);
|
|
||||||
$this->endDocument('xml');
|
|
||||||
} elseif ($this->format == 'json') {
|
|
||||||
$this->initDocument('json');
|
|
||||||
$this->showJsonObjects($twitter_user);
|
|
||||||
$this->endDocument('json');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,89 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StatusNet, the distributed open-source microblogging tool
|
|
||||||
*
|
|
||||||
* Update a user's link color
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package GNUsocial
|
|
||||||
* @author Hannes Mannerheim <h@nnesmannerhe.im>
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://www.gnu.org/software/social/
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('GNUSOCIAL')) { exit(1); }
|
|
||||||
|
|
||||||
class ApiAccountUpdateLinkColorAction extends ApiAuthAction
|
|
||||||
{
|
|
||||||
var $linkcolor = null;
|
|
||||||
|
|
||||||
protected $needPost = true;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Take arguments for running
|
|
||||||
*
|
|
||||||
* @param array $args $_REQUEST args
|
|
||||||
*
|
|
||||||
* @return boolean success flag
|
|
||||||
*/
|
|
||||||
protected function prepare(array $args=array())
|
|
||||||
{
|
|
||||||
parent::prepare($args);
|
|
||||||
|
|
||||||
if ($this->format !== 'json') {
|
|
||||||
$this->clientError('This method currently only serves JSON.', 415);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->linkcolor = $this->trimmed('linkcolor');
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle the request
|
|
||||||
*
|
|
||||||
* Try to save the user's colors in her design. Create a new design
|
|
||||||
* if the user doesn't already have one.
|
|
||||||
*
|
|
||||||
* @param array $args $_REQUEST data (unused)
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
protected function handle()
|
|
||||||
{
|
|
||||||
parent::handle();
|
|
||||||
|
|
||||||
$validhex = preg_match('/^[a-f0-9]{6}$/i',$this->linkcolor);
|
|
||||||
if ($validhex === false || $validhex == 0) {
|
|
||||||
$this->clientError(_('Not a valid hex color.'), 400);
|
|
||||||
}
|
|
||||||
|
|
||||||
// save the new color
|
|
||||||
$original = clone($this->auth_user);
|
|
||||||
$this->auth_user->linkcolor = $this->linkcolor;
|
|
||||||
if (!$this->auth_user->update($original)) {
|
|
||||||
$this->clientError(_('Error updating user.'), 400);
|
|
||||||
}
|
|
||||||
|
|
||||||
$twitter_user = $this->twitterUserArray($this->scoped, true);
|
|
||||||
|
|
||||||
$this->initDocument('json');
|
|
||||||
$this->showJsonObjects($twitter_user);
|
|
||||||
$this->endDocument('json');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,144 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StatusNet, the distributed open-source microblogging tool
|
|
||||||
*
|
|
||||||
* Update the authenticating user's profile
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @copyright 2009 StatusNet, Inc.
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('STATUSNET')) {
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* API analog to the profile settings page
|
|
||||||
* Only the parameters specified will be updated.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
class ApiAccountUpdateProfileAction extends ApiAuthAction
|
|
||||||
{
|
|
||||||
protected $needPost = true;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Take arguments for running
|
|
||||||
*
|
|
||||||
* @param array $args $_REQUEST args
|
|
||||||
*
|
|
||||||
* @return boolean success flag
|
|
||||||
*/
|
|
||||||
protected function prepare(array $args=array())
|
|
||||||
{
|
|
||||||
parent::prepare($args);
|
|
||||||
|
|
||||||
$this->user = $this->auth_user;
|
|
||||||
|
|
||||||
$this->name = $this->trimmed('name');
|
|
||||||
$this->url = $this->trimmed('url');
|
|
||||||
$this->location = $this->trimmed('location');
|
|
||||||
$this->description = $this->trimmed('description');
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle the request
|
|
||||||
*
|
|
||||||
* See which request params have been set, and update the profile
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
protected function handle()
|
|
||||||
{
|
|
||||||
parent::handle();
|
|
||||||
|
|
||||||
if (!in_array($this->format, array('xml', 'json'))) {
|
|
||||||
// TRANS: Client error displayed when coming across a non-supported API method.
|
|
||||||
$this->clientError(_('API method not found.'), 404);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (empty($this->user)) {
|
|
||||||
// TRANS: Client error displayed if a user could not be found.
|
|
||||||
$this->clientError(_('No such user.'), 404);
|
|
||||||
}
|
|
||||||
|
|
||||||
$profile = $this->user->getProfile();
|
|
||||||
|
|
||||||
if (empty($profile)) {
|
|
||||||
// TRANS: Error message displayed when referring to a user without a profile.
|
|
||||||
$this->clientError(_('User has no profile.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$original = clone($profile);
|
|
||||||
|
|
||||||
if (!empty($this->name)) {
|
|
||||||
$profile->fullname = $this->name;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($this->url)) {
|
|
||||||
$profile->homepage = $this->url;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($this->description)) {
|
|
||||||
$profile->bio = $this->description;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($this->location)) {
|
|
||||||
$profile->location = $this->location;
|
|
||||||
|
|
||||||
$loc = Location::fromName($this->location);
|
|
||||||
|
|
||||||
if (!empty($loc)) {
|
|
||||||
$profile->lat = $loc->lat;
|
|
||||||
$profile->lon = $loc->lon;
|
|
||||||
$profile->location_id = $loc->location_id;
|
|
||||||
$profile->location_ns = $loc->location_ns;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$result = $profile->update($original);
|
|
||||||
|
|
||||||
if (!$result) {
|
|
||||||
common_log_db_error($profile, 'UPDATE', __FILE__);
|
|
||||||
// TRANS: Server error displayed if a user profile could not be saved.
|
|
||||||
$this->serverError(_('Could not save profile.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$twitter_user = $this->twitterUserArray($profile, true);
|
|
||||||
|
|
||||||
if ($this->format == 'xml') {
|
|
||||||
$this->initDocument('xml');
|
|
||||||
$this->showTwitterXmlUser($twitter_user, 'user', true);
|
|
||||||
$this->endDocument('xml');
|
|
||||||
} elseif ($this->format == 'json') {
|
|
||||||
$this->initDocument('json');
|
|
||||||
$this->showJsonObjects($twitter_user);
|
|
||||||
$this->endDocument('json');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,112 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StatusNet, the distributed open-source microblogging tool
|
|
||||||
*
|
|
||||||
* Update the authenticating user's profile image
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @copyright 2009 StatusNet, Inc.
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('STATUSNET')) {
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates the authenticating user's profile image. Note that this API method
|
|
||||||
* expects raw multipart data, not a URL to an image.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
class ApiAccountUpdateProfileImageAction extends ApiAuthAction
|
|
||||||
{
|
|
||||||
protected $needPost = true;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle the request
|
|
||||||
*
|
|
||||||
* Check whether the credentials are valid and output the result
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
protected function handle()
|
|
||||||
{
|
|
||||||
parent::handle();
|
|
||||||
|
|
||||||
// Workaround for PHP returning empty $_POST and $_FILES when POST
|
|
||||||
// length > post_max_size in php.ini
|
|
||||||
|
|
||||||
if (empty($_FILES)
|
|
||||||
&& empty($_POST)
|
|
||||||
&& ($_SERVER['CONTENT_LENGTH'] > 0)
|
|
||||||
) {
|
|
||||||
// TRANS: Client error displayed when the number of bytes in a POST request exceeds a limit.
|
|
||||||
// TRANS: %s is the number of bytes of the CONTENT_LENGTH.
|
|
||||||
$msg = _m('The server was unable to handle that much POST data (%s byte) due to its current configuration.',
|
|
||||||
'The server was unable to handle that much POST data (%s bytes) due to its current configuration.',
|
|
||||||
intval($_SERVER['CONTENT_LENGTH']));
|
|
||||||
$this->clientError(sprintf($msg, $_SERVER['CONTENT_LENGTH']));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (empty($this->user)) {
|
|
||||||
// TRANS: Client error displayed updating profile image without having a user object.
|
|
||||||
$this->clientError(_('No such user.'), 404);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
$imagefile = ImageFile::fromUpload('image');
|
|
||||||
} catch (Exception $e) {
|
|
||||||
$this->clientError($e->getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
$type = $imagefile->preferredType();
|
|
||||||
$filename = Avatar::filename(
|
|
||||||
$user->id,
|
|
||||||
image_type_to_extension($type),
|
|
||||||
null,
|
|
||||||
'tmp'.common_timestamp()
|
|
||||||
);
|
|
||||||
|
|
||||||
$filepath = Avatar::path($filename);
|
|
||||||
|
|
||||||
$imagefile->copyTo($filepath);
|
|
||||||
|
|
||||||
$profile = $this->user->getProfile();
|
|
||||||
$profile->setOriginal($filename);
|
|
||||||
|
|
||||||
$twitter_user = $this->twitterUserArray($profile, true);
|
|
||||||
|
|
||||||
if ($this->format == 'xml') {
|
|
||||||
$this->initDocument('xml');
|
|
||||||
$this->showTwitterXmlUser($twitter_user, 'user', true);
|
|
||||||
$this->endDocument('xml');
|
|
||||||
} elseif ($this->format == 'json') {
|
|
||||||
$this->initDocument('json');
|
|
||||||
$this->showJsonObjects($twitter_user);
|
|
||||||
$this->endDocument('json');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,85 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StatusNet, the distributed open-source microblogging tool
|
|
||||||
*
|
|
||||||
* Test if supplied user credentials are valid.
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @author Robin Millette <robin@millette.info>
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @copyright 2009 StatusNet, Inc.
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('STATUSNET')) {
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check a user's credentials. Returns an HTTP 200 OK response code and a
|
|
||||||
* representation of the requesting user if authentication was successful;
|
|
||||||
* returns a 401 status code and an error message if not.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @author Robin Millette <robin@millette.info>
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
class ApiAccountVerifyCredentialsAction extends ApiAuthAction
|
|
||||||
{
|
|
||||||
protected function handle()
|
|
||||||
{
|
|
||||||
parent::handle();
|
|
||||||
|
|
||||||
if (!in_array($this->format, array('xml', 'json'))) {
|
|
||||||
// TRANS: Client error displayed when coming across a non-supported API method.
|
|
||||||
$this->clientError(_('API method not found.'), $code = 404);
|
|
||||||
}
|
|
||||||
|
|
||||||
$twitter_user = $this->twitterUserArray($this->auth_user->getProfile(), true);
|
|
||||||
|
|
||||||
if ($this->format == 'xml') {
|
|
||||||
$this->initDocument('xml');
|
|
||||||
$this->showTwitterXmlUser($twitter_user, 'user', true);
|
|
||||||
$this->endDocument('xml');
|
|
||||||
} elseif ($this->format == 'json') {
|
|
||||||
$this->initDocument('json');
|
|
||||||
$this->showJsonObjects($twitter_user);
|
|
||||||
$this->endDocument('json');
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Is this action read only?
|
|
||||||
*
|
|
||||||
* @param array $args other arguments
|
|
||||||
*
|
|
||||||
* @return boolean true
|
|
||||||
*/
|
|
||||||
function isReadOnly($args)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,136 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StatusNet, the distributed open-source microblogging tool
|
|
||||||
*
|
|
||||||
* An AtomPub service document for a user
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @copyright 2010 StatusNet, Inc.
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPLv3
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('STATUSNET')) {
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Shows an AtomPub service document for a user
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @copyright 2010 StatusNet, Inc.
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPLv3
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
class ApiAtomServiceAction extends ApiBareAuthAction
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Take arguments for running
|
|
||||||
*
|
|
||||||
* @param array $args $_REQUEST args
|
|
||||||
*
|
|
||||||
* @return boolean success flag
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
function prepare($args)
|
|
||||||
{
|
|
||||||
parent::prepare($args);
|
|
||||||
$this->user = $this->getTargetUser($this->arg('id'));
|
|
||||||
|
|
||||||
if (empty($this->user)) {
|
|
||||||
// TRANS: Client error displayed when making an Atom API request for an unknown user.
|
|
||||||
$this->clientError(_('No such user.'), 404);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle the arguments. In our case, show a service document.
|
|
||||||
*
|
|
||||||
* @param Array $args unused.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function handle($args)
|
|
||||||
{
|
|
||||||
parent::handle($args);
|
|
||||||
|
|
||||||
header('Content-Type: application/atomsvc+xml');
|
|
||||||
|
|
||||||
$this->startXML();
|
|
||||||
$this->elementStart('service', array('xmlns' => 'http://www.w3.org/2007/app',
|
|
||||||
'xmlns:atom' => 'http://www.w3.org/2005/Atom',
|
|
||||||
'xmlns:activity' => 'http://activitystrea.ms/spec/1.0/'));
|
|
||||||
$this->elementStart('workspace');
|
|
||||||
// TRANS: Title for Atom feed.
|
|
||||||
$this->element('atom:title', null, _m('ATOM','Main'));
|
|
||||||
$this->elementStart('collection',
|
|
||||||
array('href' => common_local_url('ApiTimelineUser',
|
|
||||||
array('id' => $this->user->id,
|
|
||||||
'format' => 'atom'))));
|
|
||||||
$this->element('atom:title',
|
|
||||||
null,
|
|
||||||
// TRANS: Title for Atom feed. %s is a user nickname.
|
|
||||||
sprintf(_("%s timeline"),
|
|
||||||
$this->user->nickname));
|
|
||||||
$this->element('accept', null, 'application/atom+xml;type=entry');
|
|
||||||
$this->element('activity:verb', null, ActivityVerb::POST);
|
|
||||||
$this->elementEnd('collection');
|
|
||||||
$this->elementStart('collection',
|
|
||||||
array('href' => common_local_url('AtomPubSubscriptionFeed',
|
|
||||||
array('subscriber' => $this->user->id))));
|
|
||||||
$this->element('atom:title',
|
|
||||||
null,
|
|
||||||
// TRANS: Title for Atom feed with a user's subscriptions. %s is a user nickname.
|
|
||||||
sprintf(_("%s subscriptions"),
|
|
||||||
$this->user->nickname));
|
|
||||||
$this->element('accept', null, 'application/atom+xml;type=entry');
|
|
||||||
$this->element('activity:verb', null, ActivityVerb::FOLLOW);
|
|
||||||
$this->elementEnd('collection');
|
|
||||||
$this->elementStart('collection',
|
|
||||||
array('href' => common_local_url('AtomPubFavoriteFeed',
|
|
||||||
array('profile' => $this->user->id))));
|
|
||||||
$this->element('atom:title',
|
|
||||||
null,
|
|
||||||
// TRANS: Title for Atom feed with a user's favorite notices. %s is a user nickname.
|
|
||||||
sprintf(_("%s favorites"),
|
|
||||||
$this->user->nickname));
|
|
||||||
$this->element('accept', null, 'application/atom+xml;type=entry');
|
|
||||||
$this->element('activity:verb', null, ActivityVerb::FAVORITE);
|
|
||||||
$this->elementEnd('collection');
|
|
||||||
$this->elementStart('collection',
|
|
||||||
array('href' => common_local_url('AtomPubMembershipFeed',
|
|
||||||
array('profile' => $this->user->id))));
|
|
||||||
$this->element('atom:title',
|
|
||||||
null,
|
|
||||||
// TRANS: Title for Atom feed with a user's memberships. %s is a user nickname.
|
|
||||||
sprintf(_("%s memberships"),
|
|
||||||
$this->user->nickname));
|
|
||||||
$this->element('accept', null, 'application/atom+xml;type=entry');
|
|
||||||
$this->element('activity:verb', null, ActivityVerb::JOIN);
|
|
||||||
$this->elementEnd('collection');
|
|
||||||
$this->elementEnd('workspace');
|
|
||||||
$this->elementEnd('service');
|
|
||||||
$this->endXML();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,106 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StatusNet, the distributed open-source microblogging tool
|
|
||||||
*
|
|
||||||
* Show a notice's attachment
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package GNUsocial
|
|
||||||
* @author Hannes Mannerheim <h@nnesmannerhe.im>
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://www.gnu.org/software/social/
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('GNUSOCIAL')) { exit(1); }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show a notice's attachment
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class ApiAttachmentAction extends ApiAuthAction
|
|
||||||
{
|
|
||||||
const MAXCOUNT = 100;
|
|
||||||
|
|
||||||
var $original = null;
|
|
||||||
var $cnt = self::MAXCOUNT;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Take arguments for running
|
|
||||||
*
|
|
||||||
* @param array $args $_REQUEST args
|
|
||||||
*
|
|
||||||
* @return boolean success flag
|
|
||||||
*/
|
|
||||||
protected function prepare(array $args=array())
|
|
||||||
{
|
|
||||||
parent::prepare($args);
|
|
||||||
|
|
||||||
if ($this->format !== 'json') {
|
|
||||||
$this->clientError('This method currently only serves JSON.', 415);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle the request
|
|
||||||
*
|
|
||||||
* Make a new notice for the update, save it, and show it
|
|
||||||
*
|
|
||||||
* @param array $args $_REQUEST data (unused)
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
protected function handle()
|
|
||||||
{
|
|
||||||
parent::handle();
|
|
||||||
|
|
||||||
$file = new File();
|
|
||||||
$file->selectAdd(); // clears it
|
|
||||||
$file->selectAdd('url');
|
|
||||||
$file->id = $this->trimmed('id');
|
|
||||||
$url = $file->fetchAll('url');
|
|
||||||
|
|
||||||
$file_txt = '';
|
|
||||||
if(strstr($url[0],'.html')) {
|
|
||||||
$file_txt['txt'] = file_get_contents($url[0]);
|
|
||||||
$file_txt['body_start'] = strpos($file_txt['txt'],'<body>')+6;
|
|
||||||
$file_txt['body_end'] = strpos($file_txt['txt'],'</body>');
|
|
||||||
$file_txt = substr($file_txt['txt'],$file_txt['body_start'],$file_txt['body_end']-$file_txt['body_start']);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->initDocument('json');
|
|
||||||
$this->showJsonObjects($file_txt);
|
|
||||||
$this->endDocument('json');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return true if read only.
|
|
||||||
*
|
|
||||||
* MAY override
|
|
||||||
*
|
|
||||||
* @param array $args other arguments
|
|
||||||
*
|
|
||||||
* @return boolean is read only action?
|
|
||||||
*/
|
|
||||||
|
|
||||||
function isReadOnly($args)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,113 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StatusNet, the distributed open-source microblogging tool
|
|
||||||
*
|
|
||||||
* Block a user via the API
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @copyright 2009-2010 StatusNet, Inc.
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('STATUSNET')) {
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Blocks the user specified in the ID parameter as the authenticating user.
|
|
||||||
* Destroys a friendship to the blocked user if it exists. Returns the
|
|
||||||
* blocked user in the requested format when successful.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
class ApiBlockCreateAction extends ApiAuthAction
|
|
||||||
{
|
|
||||||
protected $needPost = true;
|
|
||||||
|
|
||||||
var $other = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Take arguments for running
|
|
||||||
*
|
|
||||||
* @param array $args $_REQUEST args
|
|
||||||
*
|
|
||||||
* @return boolean success flag
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
protected function prepare(array $args=array())
|
|
||||||
{
|
|
||||||
parent::prepare($args);
|
|
||||||
|
|
||||||
$this->other = $this->getTargetProfile($this->arg('id'));
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle the request
|
|
||||||
*
|
|
||||||
* Save the new message
|
|
||||||
*
|
|
||||||
* @param array $args $_REQUEST data (unused)
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
protected function handle()
|
|
||||||
{
|
|
||||||
parent::handle();
|
|
||||||
|
|
||||||
if (empty($this->user) || empty($this->other)) {
|
|
||||||
// TRANS: Client error displayed when trying to block a non-existing user or a user from another site.
|
|
||||||
$this->clientError(_('No such user.'), 404);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Don't allow blocking yourself!
|
|
||||||
|
|
||||||
if ($this->user->id == $this->other->id) {
|
|
||||||
// TRANS: Client error displayed when users try to block themselves.
|
|
||||||
$this->clientError(_("You cannot block yourself!"), 403);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$this->user->hasBlocked($this->other)) {
|
|
||||||
if (Event::handle('StartBlockProfile', array($this->user, $this->other))) {
|
|
||||||
$result = $this->user->block($this->other);
|
|
||||||
if ($result) {
|
|
||||||
Event::handle('EndBlockProfile', array($this->user, $this->other));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->user->hasBlocked($this->other)) {
|
|
||||||
$this->initDocument($this->format);
|
|
||||||
$this->showProfile($this->other, $this->format);
|
|
||||||
$this->endDocument($this->format);
|
|
||||||
} else {
|
|
||||||
// TRANS: Server error displayed when blocking a user has failed.
|
|
||||||
$this->serverError(_('Block user failed.'), 500);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,102 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StatusNet, the distributed open-source microblogging tool
|
|
||||||
*
|
|
||||||
* Un-block a user via the API
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @copyright 2009-2010 StatusNet, Inc.
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('STATUSNET')) {
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Un-blocks the user specified in the ID parameter for the authenticating user.
|
|
||||||
* Returns the un-blocked user in the requested format when successful.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
class ApiBlockDestroyAction extends ApiAuthAction
|
|
||||||
{
|
|
||||||
protected $needPost = true;
|
|
||||||
|
|
||||||
var $other = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Take arguments for running
|
|
||||||
*
|
|
||||||
* @param array $args $_REQUEST args
|
|
||||||
*
|
|
||||||
* @return boolean success flag
|
|
||||||
*/
|
|
||||||
protected function prepare(array $args=array())
|
|
||||||
{
|
|
||||||
parent::prepare($args);
|
|
||||||
|
|
||||||
$this->other = $this->getTargetProfile($this->arg('id'));
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle the request
|
|
||||||
*
|
|
||||||
* Save the new message
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
protected function handle()
|
|
||||||
{
|
|
||||||
parent::handle();
|
|
||||||
|
|
||||||
if (empty($this->user) || empty($this->other)) {
|
|
||||||
// TRANS: Client error when user not found for an API action to remove a block for a user.
|
|
||||||
$this->clientError(_('No such user.'), 404);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->user->hasBlocked($this->other)) {
|
|
||||||
if (Event::handle('StartUnblockProfile', array($this->user, $this->other))) {
|
|
||||||
$result = $this->user->unblock($this->other);
|
|
||||||
if ($result) {
|
|
||||||
Event::handle('EndUnblockProfile', array($this->user, $this->other));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$this->user->hasBlocked($this->other)) {
|
|
||||||
$this->initDocument($this->format);
|
|
||||||
$this->showProfile($this->other, $this->format);
|
|
||||||
$this->endDocument($this->format);
|
|
||||||
} else {
|
|
||||||
// TRANS: Server error displayed when unblocking a user has failed.
|
|
||||||
$this->serverError(_('Unblock user failed.'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,115 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StatusNet, the distributed open-source microblogging tool
|
|
||||||
*
|
|
||||||
* Show a notice's attachment
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package GNUsocial
|
|
||||||
* @author Hannes Mannerheim <h@nnesmannerhe.im>
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://www.gnu.org/software/social/
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('GNUSOCIAL')) { exit(1); }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if a url have a push-hub, i.e. if it is possible to subscribe
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class ApiCheckHubAction extends ApiAuthAction
|
|
||||||
{
|
|
||||||
protected $url = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Take arguments for running
|
|
||||||
*
|
|
||||||
* @param array $args $_REQUEST args
|
|
||||||
*
|
|
||||||
* @return boolean success flag
|
|
||||||
*/
|
|
||||||
protected function prepare(array $args=array())
|
|
||||||
{
|
|
||||||
parent::prepare($args);
|
|
||||||
|
|
||||||
if ($this->format !== 'json') {
|
|
||||||
$this->clientError('This method currently only serves JSON.', 415);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->url = urldecode($args['url']);
|
|
||||||
|
|
||||||
if (empty($this->url)) {
|
|
||||||
$this->clientError(_('No URL.'), 403);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!common_valid_http_url($this->url)) {
|
|
||||||
$this->clientError(_('Invalid URL.'), 403);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle the request
|
|
||||||
*
|
|
||||||
* @param array $args $_REQUEST data (unused)
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
protected function handle()
|
|
||||||
{
|
|
||||||
parent::handle();
|
|
||||||
|
|
||||||
$discover = new FeedDiscovery();
|
|
||||||
|
|
||||||
try {
|
|
||||||
$feeduri = $discover->discoverFromURL($this->url);
|
|
||||||
if($feeduri) {
|
|
||||||
$huburi = $discover->getHubLink();
|
|
||||||
}
|
|
||||||
} catch (FeedSubNoFeedException $e) {
|
|
||||||
$this->clientError(_('No feed found'), 403);
|
|
||||||
} catch (FeedSubBadResponseException $e) {
|
|
||||||
$this->clientError(_('No hub found'), 403);
|
|
||||||
}
|
|
||||||
|
|
||||||
$hub_status = array();
|
|
||||||
if ($huburi) {
|
|
||||||
$hub_status = array('huburi' => $huburi);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->initDocument('json');
|
|
||||||
$this->showJsonObjects($hub_status);
|
|
||||||
$this->endDocument('json');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return true if read only.
|
|
||||||
*
|
|
||||||
* MAY override
|
|
||||||
*
|
|
||||||
* @param array $args other arguments
|
|
||||||
*
|
|
||||||
* @return boolean is read only action?
|
|
||||||
*/
|
|
||||||
|
|
||||||
function isReadOnly($args)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* StatusNet, the distributed open-source microblogging tool
|
|
||||||
*
|
|
||||||
* Check nickname
|
|
||||||
*
|
|
||||||
* Returns 1 if nickname is available on this instance, 0 if not. Error if site is private.
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package GNUsocial
|
|
||||||
* @author Hannes Mannerheim <h@nnesmannerhe.im>
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://www.gnu.org/software/social/
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('GNUSOCIAL')) { exit(1); }
|
|
||||||
|
|
||||||
class ApiCheckNicknameAction extends ApiAction
|
|
||||||
{
|
|
||||||
|
|
||||||
protected function prepare(array $args=array())
|
|
||||||
{
|
|
||||||
parent::prepare($args);
|
|
||||||
|
|
||||||
if (common_config('site', 'private')) {
|
|
||||||
$this->clientError(_('This site is private.'), 403);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->format !== 'json') {
|
|
||||||
$this->clientError('This method currently only serves JSON.', 415);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function handle()
|
|
||||||
{
|
|
||||||
parent::handle();
|
|
||||||
|
|
||||||
$nickname = $this->trimmed('nickname');
|
|
||||||
|
|
||||||
try {
|
|
||||||
Nickname::normalize($nickname, true);
|
|
||||||
$nickname_ok = 1;
|
|
||||||
} catch (NicknameException $e) {
|
|
||||||
$nickname_ok = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->initDocument('json');
|
|
||||||
$this->showJsonObjects($nickname_ok);
|
|
||||||
$this->endDocument('json');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,234 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StatusNet - the distributed open-source microblogging tool
|
|
||||||
* Copyright (C) 2011, StatusNet, Inc.
|
|
||||||
*
|
|
||||||
* Show a stream of notices in a particular conversation
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @copyright 2011 StatusNet, Inc.
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('STATUSNET')) {
|
|
||||||
// This check helps protect against security problems;
|
|
||||||
// your code file can't be executed directly from the web.
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show a stream of notices in a particular conversation
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @copyright 2011 StatusNet, Inc.
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
class ApiconversationAction extends ApiAuthAction
|
|
||||||
{
|
|
||||||
protected $conversation = null;
|
|
||||||
protected $notices = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* For initializing members of the class.
|
|
||||||
*
|
|
||||||
* @param array $argarray misc. arguments
|
|
||||||
*
|
|
||||||
* @return boolean true
|
|
||||||
*/
|
|
||||||
function prepare($argarray)
|
|
||||||
{
|
|
||||||
parent::prepare($argarray);
|
|
||||||
|
|
||||||
$convId = $this->trimmed('id');
|
|
||||||
|
|
||||||
if (empty($convId)) {
|
|
||||||
// TRANS: Client exception thrown when no conversation ID is given.
|
|
||||||
throw new ClientException(_('No conversation ID.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->conversation = Conversation::getKV('id', $convId);
|
|
||||||
|
|
||||||
if (empty($this->conversation)) {
|
|
||||||
// TRANS: Client exception thrown when referring to a non-existing conversation ID (%d).
|
|
||||||
throw new ClientException(sprintf(_('No conversation with ID %d.'), $convId),
|
|
||||||
404);
|
|
||||||
}
|
|
||||||
|
|
||||||
$stream = new ConversationNoticeStream($convId, $this->scoped);
|
|
||||||
|
|
||||||
$notice = $stream->getNotices(($this->page-1) * $this->count,
|
|
||||||
$this->count,
|
|
||||||
$this->since_id,
|
|
||||||
$this->max_id);
|
|
||||||
|
|
||||||
$this->notices = $notice->fetchAll();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handler method
|
|
||||||
*
|
|
||||||
* @param array $argarray is ignored since it's now passed in in prepare()
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function handle($argarray=null)
|
|
||||||
{
|
|
||||||
$sitename = common_config('site', 'name');
|
|
||||||
// TRANS: Title for conversion timeline.
|
|
||||||
$title = _m('TITLE', 'Conversation');
|
|
||||||
$id = common_local_url('apiconversation', array('id' => $this->conversation->id, 'format' => $this->format));
|
|
||||||
$link = common_local_url('conversation', array('id' => $this->conversation->id));
|
|
||||||
|
|
||||||
$self = $id;
|
|
||||||
|
|
||||||
switch($this->format) {
|
|
||||||
case 'xml':
|
|
||||||
$this->showXmlTimeline($this->notices);
|
|
||||||
break;
|
|
||||||
case 'rss':
|
|
||||||
$this->showRssTimeline(
|
|
||||||
$this->notices,
|
|
||||||
$title,
|
|
||||||
$link,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
$self
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case 'atom':
|
|
||||||
|
|
||||||
header('Content-Type: application/atom+xml; charset=utf-8');
|
|
||||||
|
|
||||||
$atom = new AtomNoticeFeed($this->auth_user);
|
|
||||||
|
|
||||||
$atom->setId($id);
|
|
||||||
$atom->setTitle($title);
|
|
||||||
$atom->setUpdated('now');
|
|
||||||
|
|
||||||
$atom->addLink($link);
|
|
||||||
$atom->setSelfLink($self);
|
|
||||||
|
|
||||||
$atom->addEntryFromNotices($this->notices);
|
|
||||||
$this->raw($atom->getString());
|
|
||||||
|
|
||||||
break;
|
|
||||||
case 'json':
|
|
||||||
$this->showJsonTimeline($this->notices);
|
|
||||||
break;
|
|
||||||
case 'as':
|
|
||||||
header('Content-Type: ' . ActivityStreamJSONDocument::CONTENT_TYPE);
|
|
||||||
$doc = new ActivityStreamJSONDocument($this->auth_user);
|
|
||||||
$doc->setTitle($title);
|
|
||||||
$doc->addLink($link, 'alternate', 'text/html');
|
|
||||||
$doc->addItemsFromNotices($this->notices);
|
|
||||||
$this->raw($doc->asString());
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// TRANS: Client error displayed when coming across a non-supported API method.
|
|
||||||
$this->clientError(_('API method not found.'), $code = 404);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return true if read only.
|
|
||||||
*
|
|
||||||
* MAY override
|
|
||||||
*
|
|
||||||
* @param array $args other arguments
|
|
||||||
*
|
|
||||||
* @return boolean is read only action?
|
|
||||||
*/
|
|
||||||
function isReadOnly($args)
|
|
||||||
{
|
|
||||||
if ($_SERVER['REQUEST_METHOD'] == 'GET' ||
|
|
||||||
$_SERVER['REQUEST_METHOD'] == 'HEAD') {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return last modified, if applicable.
|
|
||||||
*
|
|
||||||
* MAY override
|
|
||||||
*
|
|
||||||
* @return string last modified http header
|
|
||||||
*/
|
|
||||||
function lastModified()
|
|
||||||
{
|
|
||||||
if (!empty($this->notices) && (count($this->notices) > 0)) {
|
|
||||||
return strtotime($this->notices[0]->created);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return etag, if applicable.
|
|
||||||
*
|
|
||||||
* MAY override
|
|
||||||
*
|
|
||||||
* @return string etag http header
|
|
||||||
*/
|
|
||||||
function etag()
|
|
||||||
{
|
|
||||||
if (!empty($this->notices) && (count($this->notices) > 0)) {
|
|
||||||
|
|
||||||
$last = count($this->notices) - 1;
|
|
||||||
|
|
||||||
return '"' . implode(
|
|
||||||
':',
|
|
||||||
array($this->arg('action'),
|
|
||||||
common_user_cache_hash($this->auth_user),
|
|
||||||
common_language(),
|
|
||||||
$this->user->id,
|
|
||||||
strtotime($this->notices[0]->created),
|
|
||||||
strtotime($this->notices[$last]->created))
|
|
||||||
)
|
|
||||||
. '"';
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Does this require authentication?
|
|
||||||
*
|
|
||||||
* @return boolean true if delete, else false
|
|
||||||
*/
|
|
||||||
function requiresAuth()
|
|
||||||
{
|
|
||||||
if ($_SERVER['REQUEST_METHOD'] == 'GET' ||
|
|
||||||
$_SERVER['REQUEST_METHOD'] == 'HEAD') {
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,99 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StatusNet, the distributed open-source microblogging tool
|
|
||||||
*
|
|
||||||
* Show an external user's profile information
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package GNUsocial
|
|
||||||
* @author Hannes Mannerheim <h@nnesmannerhe.im>
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://www.gnu.org/software/social/
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('GNUSOCIAL')) { exit(1); }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Ouputs information for a user, specified by ID or screen name.
|
|
||||||
* The user's most recent status will be returned inline.
|
|
||||||
*/
|
|
||||||
class ApiExternalProfileShowAction extends ApiPrivateAuthAction
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Take arguments for running
|
|
||||||
*
|
|
||||||
* @param array $args $_REQUEST args
|
|
||||||
*
|
|
||||||
* @return boolean success flag
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
protected function prepare(array $args=array())
|
|
||||||
{
|
|
||||||
parent::prepare($args);
|
|
||||||
|
|
||||||
if ($this->format !== 'json') {
|
|
||||||
$this->clientError('This method currently only serves JSON.', 415);
|
|
||||||
}
|
|
||||||
|
|
||||||
$profileurl = urldecode($this->arg('profileurl'));
|
|
||||||
|
|
||||||
// TODO: Make this more ... unique!
|
|
||||||
$this->profile = Profile::getKV('profileurl', $profileurl);
|
|
||||||
|
|
||||||
if (!($this->profile instanceof Profile)) {
|
|
||||||
// TRANS: Client error displayed when requesting profile information for a non-existing profile.
|
|
||||||
$this->clientError(_('Profile not found.'), 404);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle the request
|
|
||||||
*
|
|
||||||
* Check the format and show the user info
|
|
||||||
*
|
|
||||||
* @param array $args $_REQUEST data (unused)
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
protected function handle()
|
|
||||||
{
|
|
||||||
parent::handle();
|
|
||||||
|
|
||||||
$twitter_user = $this->twitterUserArray($this->profile, true);
|
|
||||||
|
|
||||||
$this->initDocument('json');
|
|
||||||
$this->showJsonObjects($twitter_user);
|
|
||||||
$this->endDocument('json');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return true if read only.
|
|
||||||
*
|
|
||||||
* MAY override
|
|
||||||
*
|
|
||||||
* @param array $args other arguments
|
|
||||||
*
|
|
||||||
* @return boolean is read only action?
|
|
||||||
*/
|
|
||||||
function isReadOnly($args)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,113 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StatusNet, the distributed open-source microblogging tool
|
|
||||||
*
|
|
||||||
* Subscribe to a user via the API
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Dan Moore <dan@moore.cx>
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @copyright 2009-2010 StatusNet, Inc.
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('STATUSNET')) {
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Allows the authenticating users to follow (subscribe) the user specified in
|
|
||||||
* the ID parameter. Returns the befriended user in the requested format when
|
|
||||||
* successful. Returns a string describing the failure condition when unsuccessful.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Dan Moore <dan@moore.cx>
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
class ApiFriendshipsCreateAction extends ApiAuthAction
|
|
||||||
{
|
|
||||||
protected $needPost = true;
|
|
||||||
|
|
||||||
var $other = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Take arguments for running
|
|
||||||
*
|
|
||||||
* @param array $args $_REQUEST args
|
|
||||||
*
|
|
||||||
* @return boolean success flag
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
protected function prepare(array $args=array())
|
|
||||||
{
|
|
||||||
parent::prepare($args);
|
|
||||||
|
|
||||||
$this->other = $this->getTargetProfile($this->arg('id'));
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle the request
|
|
||||||
*
|
|
||||||
* Check the format and show the user info
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
protected function handle()
|
|
||||||
{
|
|
||||||
parent::handle();
|
|
||||||
|
|
||||||
if (!in_array($this->format, array('xml', 'json'))) {
|
|
||||||
// TRANS: Client error displayed when coming across a non-supported API method.
|
|
||||||
$this->clientError(_('API method not found.'), 404);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (empty($this->other)) {
|
|
||||||
// TRANS: Client error displayed when trying follow who's profile could not be found.
|
|
||||||
$this->clientError(_('Could not follow user: profile not found.'), 403);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->user->isSubscribed($this->other)) {
|
|
||||||
$errmsg = sprintf(
|
|
||||||
// TRANS: Client error displayed when trying to follow a user that's already being followed.
|
|
||||||
// TRANS: %s is the nickname of the user that is already being followed.
|
|
||||||
_('Could not follow user: %s is already on your list.'),
|
|
||||||
$this->other->nickname
|
|
||||||
);
|
|
||||||
$this->clientError($errmsg, 403);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
Subscription::start($this->user->getProfile(), $this->other);
|
|
||||||
} catch (Exception $e) {
|
|
||||||
$this->clientError($e->getMessage(), 403);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->initDocument($this->format);
|
|
||||||
$this->showProfile($this->other, $this->format);
|
|
||||||
$this->endDocument($this->format);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,133 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StatusNet, the distributed open-source microblogging tool
|
|
||||||
*
|
|
||||||
* Unsubscribe to a user via API
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Dan Moore <dan@moore.cx>
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @copyright 2009-2010 StatusNet, Inc.
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('STATUSNET')) {
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Allows the authenticating users to unfollow (unsubscribe) the user specified in
|
|
||||||
* the ID parameter. Returns the unfollowed user in the requested format when
|
|
||||||
* successful. Returns a string describing the failure condition when unsuccessful.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Dan Moore <dan@moore.cx>
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
class ApiFriendshipsDestroyAction extends ApiAuthAction
|
|
||||||
{
|
|
||||||
var $other = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Take arguments for running
|
|
||||||
*
|
|
||||||
* @param array $args $_REQUEST args
|
|
||||||
*
|
|
||||||
* @return boolean success flag
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
function prepare($args)
|
|
||||||
{
|
|
||||||
parent::prepare($args);
|
|
||||||
|
|
||||||
$this->user = $this->auth_user;
|
|
||||||
$this->other = $this->getTargetProfile($this->arg('id'));
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle the request
|
|
||||||
*
|
|
||||||
* Check the format and show the user info
|
|
||||||
*
|
|
||||||
* @param array $args $_REQUEST data (unused)
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function handle($args)
|
|
||||||
{
|
|
||||||
parent::handle($args);
|
|
||||||
|
|
||||||
if ($_SERVER['REQUEST_METHOD'] != 'POST') {
|
|
||||||
$this->clientError(
|
|
||||||
// TRANS: Client error. POST is a HTTP command. It should not be translated.
|
|
||||||
_('This method requires a POST.'),
|
|
||||||
400,
|
|
||||||
$this->format
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!in_array($this->format, array('xml', 'json'))) {
|
|
||||||
$this->clientError(
|
|
||||||
// TRANS: Client error displayed when coming across a non-supported API method.
|
|
||||||
_('API method not found.'),
|
|
||||||
404,
|
|
||||||
$this->format
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (empty($this->other)) {
|
|
||||||
$this->clientError(
|
|
||||||
// TRANS: Client error displayed when trying to unfollow a user that cannot be found.
|
|
||||||
_('Could not unfollow user: User not found.'),
|
|
||||||
403,
|
|
||||||
$this->format
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Don't allow unsubscribing from yourself!
|
|
||||||
|
|
||||||
if ($this->user->id == $this->other->id) {
|
|
||||||
$this->clientError(
|
|
||||||
// TRANS: Client error displayed when trying to unfollow self.
|
|
||||||
_("You cannot unfollow yourself."),
|
|
||||||
403,
|
|
||||||
$this->format
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// throws an exception on error
|
|
||||||
Subscription::cancel($this->user->getProfile(), $this->other);
|
|
||||||
|
|
||||||
$this->initDocument($this->format);
|
|
||||||
$this->showProfile($this->other, $this->format);
|
|
||||||
$this->endDocument($this->format);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,124 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StatusNet, the distributed open-source microblogging tool
|
|
||||||
*
|
|
||||||
* Show whether there is a friendship between two users
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Dan Moore <dan@moore.cx>
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @copyright 2009-2010 StatusNet, Inc.
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('STATUSNET')) {
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests for the existence of friendship between two users. Will return true if
|
|
||||||
* user_a follows user_b, otherwise will return false.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Dan Moore <dan@moore.cx>
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
class ApiFriendshipsExistsAction extends ApiPrivateAuthAction
|
|
||||||
{
|
|
||||||
var $profile_a = null;
|
|
||||||
var $profile_b = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Take arguments for running
|
|
||||||
*
|
|
||||||
* @param array $args $_REQUEST args
|
|
||||||
*
|
|
||||||
* @return boolean success flag
|
|
||||||
*/
|
|
||||||
function prepare($args)
|
|
||||||
{
|
|
||||||
parent::prepare($args);
|
|
||||||
|
|
||||||
$this->profile_a = $this->getTargetProfile($this->trimmed('user_a'));
|
|
||||||
$this->profile_b = $this->getTargetProfile($this->trimmed('user_b'));
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle the request
|
|
||||||
*
|
|
||||||
* Check the format and show the user info
|
|
||||||
*
|
|
||||||
* @param array $args $_REQUEST data (unused)
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function handle($args)
|
|
||||||
{
|
|
||||||
parent::handle($args);
|
|
||||||
|
|
||||||
if (empty($this->profile_a) || empty($this->profile_b)) {
|
|
||||||
$this->clientError(
|
|
||||||
// TRANS: Client error displayed when supplying invalid parameters to an API call checking if a friendship exists.
|
|
||||||
_('Two valid IDs or nick names must be supplied.'),
|
|
||||||
400,
|
|
||||||
$this->format
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$result = Subscription::exists($this->profile_a, $this->profile_b);
|
|
||||||
|
|
||||||
switch ($this->format) {
|
|
||||||
case 'xml':
|
|
||||||
$this->initDocument('xml');
|
|
||||||
$this->element('friends', null, $result);
|
|
||||||
$this->endDocument('xml');
|
|
||||||
break;
|
|
||||||
case 'json':
|
|
||||||
$this->initDocument('json');
|
|
||||||
print json_encode($result);
|
|
||||||
$this->endDocument('json');
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return true if read only.
|
|
||||||
*
|
|
||||||
* MAY override
|
|
||||||
*
|
|
||||||
* @param array $args other arguments
|
|
||||||
*
|
|
||||||
* @return boolean is read only action?
|
|
||||||
*/
|
|
||||||
function isReadOnly($args)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,173 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StatusNet, the distributed open-source microblogging tool
|
|
||||||
*
|
|
||||||
* Show information about the relationship between two users
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Dan Moore <dan@moore.cx>
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @copyright 2009 StatusNet, Inc.
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('STATUSNET')) {
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Outputs detailed information about the relationship between two users
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Dan Moore <dan@moore.cx>
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
class ApiFriendshipsShowAction extends ApiBareAuthAction
|
|
||||||
{
|
|
||||||
var $source = null;
|
|
||||||
var $target = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Take arguments for running
|
|
||||||
*
|
|
||||||
* @param array $args $_REQUEST args
|
|
||||||
*
|
|
||||||
* @return boolean success flag
|
|
||||||
*/
|
|
||||||
function prepare($args)
|
|
||||||
{
|
|
||||||
parent::prepare($args);
|
|
||||||
|
|
||||||
$source_id = (int)$this->trimmed('source_id');
|
|
||||||
$source_screen_name = $this->trimmed('source_screen_name');
|
|
||||||
$target_id = (int)$this->trimmed('target_id');
|
|
||||||
$target_screen_name = $this->trimmed('target_screen_name');
|
|
||||||
|
|
||||||
if (!empty($source_id)) {
|
|
||||||
$this->source = User::getKV($source_id);
|
|
||||||
} elseif (!empty($source_screen_name)) {
|
|
||||||
$this->source = User::getKV('nickname', $source_screen_name);
|
|
||||||
} else {
|
|
||||||
$this->source = $this->auth_user;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($target_id)) {
|
|
||||||
$this->target = User::getKV($target_id);
|
|
||||||
} elseif (!empty($target_screen_name)) {
|
|
||||||
$this->target = User::getKV('nickname', $target_screen_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determines whether this API resource requires auth. Overloaded to look
|
|
||||||
* return true in case source_id and source_screen_name are both empty
|
|
||||||
*
|
|
||||||
* @return boolean true or false
|
|
||||||
*/
|
|
||||||
function requiresAuth()
|
|
||||||
{
|
|
||||||
if (common_config('site', 'private')) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
$source_id = $this->trimmed('source_id');
|
|
||||||
$source_screen_name = $this->trimmed('source_screen_name');
|
|
||||||
|
|
||||||
if (empty($source_id) && empty($source_screen_name)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle the request
|
|
||||||
*
|
|
||||||
* Check the format and show the user info
|
|
||||||
*
|
|
||||||
* @param array $args $_REQUEST data (unused)
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function handle($args)
|
|
||||||
{
|
|
||||||
parent::handle($args);
|
|
||||||
|
|
||||||
if (!in_array($this->format, array('xml', 'json'))) {
|
|
||||||
// TRANS: Client error displayed when coming across a non-supported API method.
|
|
||||||
$this->clientError(_('API method not found.'), 404);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (empty($this->source)) {
|
|
||||||
$this->clientError(
|
|
||||||
// TRANS: Client error displayed when a source user could not be determined showing friendship.
|
|
||||||
_('Could not determine source user.'),
|
|
||||||
404
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (empty($this->target)) {
|
|
||||||
$this->clientError(
|
|
||||||
// TRANS: Client error displayed when a target user could not be determined showing friendship.
|
|
||||||
_('Could not find target user.'),
|
|
||||||
404
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
$result = $this->twitterRelationshipArray($this->source, $this->target);
|
|
||||||
|
|
||||||
switch ($this->format) {
|
|
||||||
case 'xml':
|
|
||||||
$this->initDocument('xml');
|
|
||||||
$this->showTwitterXmlRelationship($result[relationship]);
|
|
||||||
$this->endDocument('xml');
|
|
||||||
break;
|
|
||||||
case 'json':
|
|
||||||
$this->initDocument('json');
|
|
||||||
print json_encode($result);
|
|
||||||
$this->endDocument('json');
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return true if read only.
|
|
||||||
*
|
|
||||||
* MAY override
|
|
||||||
*
|
|
||||||
* @param array $args other arguments
|
|
||||||
*
|
|
||||||
* @return boolean is read only action?
|
|
||||||
*/
|
|
||||||
|
|
||||||
function isReadOnly($args)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,148 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StatusNet, the distributed open-source microblogging tool
|
|
||||||
*
|
|
||||||
* Dump of configuration variables
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package GNUsocial
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @copyright 2009 StatusNet, Inc.
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://www.gnu.org/software/social/
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('GNUSOCIAL')) { exit(1); }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gives a full dump of configuration variables for this instance
|
|
||||||
* of GNU social, minus variables that may be security-sensitive (like
|
|
||||||
* passwords).
|
|
||||||
* URL: https://example.com/api/gnusocial/config.(xml|json)
|
|
||||||
* Formats: xml, json
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package GNUsocial
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://www.gnu.org/software/social/
|
|
||||||
*/
|
|
||||||
class ApiGNUsocialConfigAction extends ApiAction
|
|
||||||
{
|
|
||||||
var $keys = array(
|
|
||||||
'site' => array('name', 'server', 'theme', 'path', 'logo', 'fancy', 'language',
|
|
||||||
'email', 'broughtby', 'broughtbyurl', 'timezone', 'closed',
|
|
||||||
'inviteonly', 'private', 'textlimit', 'ssl', 'sslserver'),
|
|
||||||
'license' => array('type', 'owner', 'url', 'title', 'image'),
|
|
||||||
'nickname' => array('featured'),
|
|
||||||
'profile' => array('biolimit'),
|
|
||||||
'group' => array('desclimit'),
|
|
||||||
'notice' => array('contentlimit'),
|
|
||||||
'throttle' => array('enabled', 'count', 'timespan'),
|
|
||||||
'xmpp' => array('enabled', 'server', 'port', 'user'),
|
|
||||||
'integration' => array('source'),
|
|
||||||
'attachments' => array('uploads', 'file_quota'),
|
|
||||||
'url' => array('maxurllength', 'maxnoticelength'),
|
|
||||||
);
|
|
||||||
|
|
||||||
protected function handle()
|
|
||||||
{
|
|
||||||
parent::handle();
|
|
||||||
|
|
||||||
switch ($this->format) {
|
|
||||||
case 'xml':
|
|
||||||
$this->initDocument('xml');
|
|
||||||
$this->elementStart('config');
|
|
||||||
|
|
||||||
// XXX: check that all sections and settings are legal XML elements
|
|
||||||
|
|
||||||
foreach ($this->keys as $section => $settings) {
|
|
||||||
$this->elementStart($section);
|
|
||||||
foreach ($settings as $setting) {
|
|
||||||
$value = $this->setting($section, $setting);
|
|
||||||
if (is_array($value)) {
|
|
||||||
$value = implode(',', $value);
|
|
||||||
} else if ($value === false || $value == '0') {
|
|
||||||
$value = 'false';
|
|
||||||
} else if ($value === true || $value == '1') {
|
|
||||||
$value = 'true';
|
|
||||||
}
|
|
||||||
|
|
||||||
// return theme logo if there's no site specific one
|
|
||||||
if (empty($value)) {
|
|
||||||
if ($section == 'site' && $setting == 'logo') {
|
|
||||||
$value = Theme::path('logo.png');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->element($setting, null, $value);
|
|
||||||
}
|
|
||||||
$this->elementEnd($section);
|
|
||||||
}
|
|
||||||
$this->elementEnd('config');
|
|
||||||
$this->endDocument('xml');
|
|
||||||
break;
|
|
||||||
case 'json':
|
|
||||||
$result = array();
|
|
||||||
foreach ($this->keys as $section => $settings) {
|
|
||||||
$result[$section] = array();
|
|
||||||
foreach ($settings as $setting) {
|
|
||||||
$result[$section][$setting]
|
|
||||||
= $this->setting($section, $setting);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$this->initDocument('json');
|
|
||||||
$this->showJsonObjects($result);
|
|
||||||
$this->endDocument('json');
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// TRANS: Client error displayed when coming across a non-supported API method.
|
|
||||||
$this->clientError(_('API method not found.'), 404);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function setting($section, $key) {
|
|
||||||
$result = common_config($section, $key);
|
|
||||||
if ($key == 'file_quota') {
|
|
||||||
// hack: adjust for the live upload limit
|
|
||||||
if (common_config($section, 'uploads')) {
|
|
||||||
$max = ImageFile::maxFileSizeInt();
|
|
||||||
} else {
|
|
||||||
$max = 0;
|
|
||||||
}
|
|
||||||
return min($result, $max);
|
|
||||||
}
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return true if read only.
|
|
||||||
*
|
|
||||||
* MAY override
|
|
||||||
*
|
|
||||||
* @param array $args other arguments
|
|
||||||
*
|
|
||||||
* @return boolean is read only action?
|
|
||||||
*/
|
|
||||||
function isReadOnly($args)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,82 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StatusNet, the distributed open-source microblogging tool
|
|
||||||
*
|
|
||||||
* A version stamp for the API
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package GNUsocial
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @copyright 2009 StatusNet, Inc.
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://www.gnu.org/software/social/
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('GNUSOCIAL')) { exit(1); }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a version number for this version of GNU social, which
|
|
||||||
* should make things a bit easier for upgrades.
|
|
||||||
* URL: http://identi.ca/api/statusnet/version.(xml|json)
|
|
||||||
* Formats: xml, js
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package GNUsocial
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://www.gnu.org/software/social/
|
|
||||||
*/
|
|
||||||
class ApiGNUsocialVersionAction extends ApiPrivateAuthAction
|
|
||||||
{
|
|
||||||
protected function handle()
|
|
||||||
{
|
|
||||||
parent::handle();
|
|
||||||
|
|
||||||
switch ($this->format) {
|
|
||||||
case 'xml':
|
|
||||||
$this->initDocument('xml');
|
|
||||||
$this->element('version', null, GNUSOCIAL_VERSION);
|
|
||||||
$this->endDocument('xml');
|
|
||||||
break;
|
|
||||||
case 'json':
|
|
||||||
$this->initDocument('json');
|
|
||||||
print '"'.GNUSOCIAL_VERSION.'"';
|
|
||||||
$this->endDocument('json');
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// TRANS: Client error displayed when coming across a non-supported API method.
|
|
||||||
$this->clientError(_('API method not found.'), 404);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return true if read only.
|
|
||||||
*
|
|
||||||
* MAY override
|
|
||||||
*
|
|
||||||
* @param array $args other arguments
|
|
||||||
*
|
|
||||||
* @return boolean is read only action?
|
|
||||||
*/
|
|
||||||
function isReadOnly($args)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,190 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StatusNet, the distributed open-source microblogging tool
|
|
||||||
*
|
|
||||||
* List a group's admins
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package GNUsocial
|
|
||||||
* @author Craig Andrews <candrews@integralblue.com>
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @author Jeffery To <jeffery.to@gmail.com>
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @author Hannes Mannerheim <h@nnesmannerhe.im>
|
|
||||||
* @copyright 2009 StatusNet, Inc.
|
|
||||||
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://www.gnu.org/software/social/
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('GNUSOCIAL')) {
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* List 20 newest admins of the group specified by name or ID.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package GNUsocial
|
|
||||||
* @author Craig Andrews <candrews@integralblue.com>
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @author Jeffery To <jeffery.to@gmail.com>
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @author Hannes Mannerheim <h@nnesmannerhe.im>
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://www.gnu.org/software/social/
|
|
||||||
*/
|
|
||||||
class ApiGroupAdminsAction extends ApiPrivateAuthAction
|
|
||||||
{
|
|
||||||
var $group = null;
|
|
||||||
var $profiles = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Take arguments for running
|
|
||||||
*
|
|
||||||
* @param array $args $_REQUEST args
|
|
||||||
*
|
|
||||||
* @return boolean success flag
|
|
||||||
*/
|
|
||||||
protected function prepare(array $args=array())
|
|
||||||
{
|
|
||||||
parent::prepare($args);
|
|
||||||
|
|
||||||
$this->group = $this->getTargetGroup($this->arg('id'));
|
|
||||||
if (empty($this->group)) {
|
|
||||||
// TRANS: Client error displayed trying to show group membership on a non-existing group.
|
|
||||||
$this->clientError(_('Group not found.'), 404);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->profiles = $this->getProfiles();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle the request
|
|
||||||
*
|
|
||||||
* Show the admin of the group
|
|
||||||
*
|
|
||||||
* @param array $args $_REQUEST data (unused)
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
protected function handle()
|
|
||||||
{
|
|
||||||
parent::handle();
|
|
||||||
|
|
||||||
// XXX: RSS and Atom
|
|
||||||
|
|
||||||
switch($this->format) {
|
|
||||||
case 'xml':
|
|
||||||
$this->showTwitterXmlUsers($this->profiles);
|
|
||||||
break;
|
|
||||||
case 'json':
|
|
||||||
$this->showJsonUsers($this->profiles);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
$this->clientError(
|
|
||||||
// TRANS: Client error displayed when coming across a non-supported API method.
|
|
||||||
_('API method not found.'),
|
|
||||||
404,
|
|
||||||
$this->format
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetch the admins of a group
|
|
||||||
*
|
|
||||||
* @return array $profiles list of profiles
|
|
||||||
*/
|
|
||||||
function getProfiles()
|
|
||||||
{
|
|
||||||
$profiles = array();
|
|
||||||
|
|
||||||
$profile = $this->group->getAdmins(
|
|
||||||
($this->page - 1) * $this->count,
|
|
||||||
$this->count,
|
|
||||||
$this->since_id,
|
|
||||||
$this->max_id
|
|
||||||
);
|
|
||||||
|
|
||||||
while ($profile->fetch()) {
|
|
||||||
$profiles[] = clone($profile);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $profiles;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Is this action read only?
|
|
||||||
*
|
|
||||||
* @param array $args other arguments
|
|
||||||
*
|
|
||||||
* @return boolean true
|
|
||||||
*/
|
|
||||||
function isReadOnly($args)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* When was this list of profiles last modified?
|
|
||||||
*
|
|
||||||
* @return string datestamp of the lastest profile in the group
|
|
||||||
*/
|
|
||||||
function lastModified()
|
|
||||||
{
|
|
||||||
if (!empty($this->profiles) && (count($this->profiles) > 0)) {
|
|
||||||
return strtotime($this->profiles[0]->created);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An entity tag for this list of groups
|
|
||||||
*
|
|
||||||
* Returns an Etag based on the action name, language
|
|
||||||
* the group id, and timestamps of the first and last
|
|
||||||
* user who has joined the group
|
|
||||||
*
|
|
||||||
* @return string etag
|
|
||||||
*/
|
|
||||||
function etag()
|
|
||||||
{
|
|
||||||
if (!empty($this->profiles) && (count($this->profiles) > 0)) {
|
|
||||||
|
|
||||||
$last = count($this->profiles) - 1;
|
|
||||||
|
|
||||||
return '"' . implode(
|
|
||||||
':',
|
|
||||||
array($this->arg('action'),
|
|
||||||
common_user_cache_hash($this->auth_user),
|
|
||||||
common_language(),
|
|
||||||
$this->group->id,
|
|
||||||
strtotime($this->profiles[0]->created),
|
|
||||||
strtotime($this->profiles[$last]->created))
|
|
||||||
)
|
|
||||||
. '"';
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,181 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StatusNet, the distributed open-source microblogging tool
|
|
||||||
*
|
|
||||||
* Create a group via the API
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Craig Andrews <candrews@integralblue.com>
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @author Jeffery To <jeffery.to@gmail.com>
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @copyright 2009 StatusNet, Inc.
|
|
||||||
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('STATUSNET')) {
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Make a new group. Sets the authenticated user as the administrator of the group.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Craig Andrews <candrews@integralblue.com>
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @author Jeffery To <jeffery.to@gmail.com>
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
class ApiGroupCreateAction extends ApiAuthAction
|
|
||||||
{
|
|
||||||
protected $needPost = true;
|
|
||||||
|
|
||||||
var $group = null;
|
|
||||||
var $nickname = null;
|
|
||||||
var $fullname = null;
|
|
||||||
var $homepage = null;
|
|
||||||
var $description = null;
|
|
||||||
var $location = null;
|
|
||||||
var $aliasstring = null;
|
|
||||||
var $aliases = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Take arguments for running
|
|
||||||
*
|
|
||||||
* @param array $args $_REQUEST args
|
|
||||||
*
|
|
||||||
* @return boolean success flag
|
|
||||||
*/
|
|
||||||
protected function prepare(array $args=array())
|
|
||||||
{
|
|
||||||
parent::prepare($args);
|
|
||||||
|
|
||||||
$this->nickname = Nickname::normalize($this->arg('nickname'), true);
|
|
||||||
$this->fullname = $this->arg('full_name');
|
|
||||||
$this->homepage = $this->arg('homepage');
|
|
||||||
$this->description = $this->arg('description');
|
|
||||||
$this->location = $this->arg('location');
|
|
||||||
$this->aliasstring = $this->arg('aliases');
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle the request
|
|
||||||
*
|
|
||||||
* Save the new group
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
protected function handle()
|
|
||||||
{
|
|
||||||
parent::handle();
|
|
||||||
|
|
||||||
if (empty($this->user)) {
|
|
||||||
// TRANS: Client error given when a user was not found (404).
|
|
||||||
$this->clientError(_('No such user.'), 404);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->validateParams() == false) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$group = User_group::register(array('nickname' => $this->nickname,
|
|
||||||
'fullname' => $this->fullname,
|
|
||||||
'homepage' => $this->homepage,
|
|
||||||
'description' => $this->description,
|
|
||||||
'location' => $this->location,
|
|
||||||
'aliases' => $this->aliases,
|
|
||||||
'userid' => $this->user->id,
|
|
||||||
'local' => true));
|
|
||||||
|
|
||||||
switch($this->format) {
|
|
||||||
case 'xml':
|
|
||||||
$this->showSingleXmlGroup($group);
|
|
||||||
break;
|
|
||||||
case 'json':
|
|
||||||
$this->showSingleJsonGroup($group);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// TRANS: Client error displayed when coming across a non-supported API method.
|
|
||||||
$this->clientError(_('API method not found.'), 404);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validate params for the new group
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function validateParams()
|
|
||||||
{
|
|
||||||
if (!is_null($this->homepage)
|
|
||||||
&& strlen($this->homepage) > 0
|
|
||||||
&& !common_valid_http_url($this->homepage)) {
|
|
||||||
// TRANS: Client error in form for group creation.
|
|
||||||
$this->clientError(_('Homepage is not a valid URL.'), 403);
|
|
||||||
|
|
||||||
} elseif (!is_null($this->fullname)
|
|
||||||
&& mb_strlen($this->fullname) > 255) {
|
|
||||||
// TRANS: Client error in form for group creation.
|
|
||||||
$this->clientError(_('Full name is too long (maximum 255 characters).'), 403);
|
|
||||||
|
|
||||||
} elseif (User_group::descriptionTooLong($this->description)) {
|
|
||||||
// TRANS: Client error shown when providing too long a description during group creation.
|
|
||||||
// TRANS: %d is the maximum number of allowed characters.
|
|
||||||
$this->clientError(sprintf(_m('Description is too long (maximum %d character).',
|
|
||||||
'Description is too long (maximum %d characters).',
|
|
||||||
User_group::maxDescription()), User_group::maxDescription()), 403);
|
|
||||||
|
|
||||||
} elseif (!is_null($this->location)
|
|
||||||
&& mb_strlen($this->location) > 255) {
|
|
||||||
// TRANS: Client error shown when providing too long a location during group creation.
|
|
||||||
$this->clientError(_('Location is too long (maximum 255 characters).'), 403);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($this->aliasstring)) {
|
|
||||||
$this->aliases = array_map(
|
|
||||||
array('Nickname', 'normalize'), // static call to Nickname::normalize
|
|
||||||
array_unique(preg_split('/[\s,]+/', $this->aliasstring))
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
$this->aliases = array();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count($this->aliases) > common_config('group', 'maxaliases')) {
|
|
||||||
$this->clientError(sprintf(
|
|
||||||
// TRANS: Client error shown when providing too many aliases during group creation.
|
|
||||||
// TRANS: %d is the maximum number of allowed aliases.
|
|
||||||
_m('Too many aliases! Maximum %d allowed.',
|
|
||||||
'Too many aliases! Maximum %d allowed.',
|
|
||||||
common_config('group', 'maxaliases')),
|
|
||||||
common_config('group', 'maxaliases')),
|
|
||||||
403);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Everything looks OK
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,125 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StatusNet, the distributed open-source microblogging tool
|
|
||||||
*
|
|
||||||
* Check to see whether a user a member of a group
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Craig Andrews <candrews@integralblue.com>
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @author Jeffery To <jeffery.to@gmail.com>
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @copyright 2009 StatusNet, Inc.
|
|
||||||
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('STATUSNET')) {
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns whether a user is a member of a specified group.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Craig Andrews <candrews@integralblue.com>
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @author Jeffery To <jeffery.to@gmail.com>
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
class ApiGroupIsMemberAction extends ApiBareAuthAction
|
|
||||||
{
|
|
||||||
var $group = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Take arguments for running
|
|
||||||
*
|
|
||||||
* @param array $args $_REQUEST args
|
|
||||||
*
|
|
||||||
* @return boolean success flag
|
|
||||||
*/
|
|
||||||
|
|
||||||
protected function prepare(array $args=array())
|
|
||||||
{
|
|
||||||
parent::prepare($args);
|
|
||||||
|
|
||||||
$this->target = $this->getTargetProfile(null);
|
|
||||||
$this->group = $this->getTargetGroup(null);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle the request
|
|
||||||
*
|
|
||||||
* Save the new message
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
protected function handle()
|
|
||||||
{
|
|
||||||
parent::handle();
|
|
||||||
|
|
||||||
if (empty($this->target)) {
|
|
||||||
// TRANS: Client error displayed when checking group membership for a non-existing user.
|
|
||||||
$this->clientError(_('No such user.'), 404);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (empty($this->group)) {
|
|
||||||
// TRANS: Client error displayed when checking group membership for a non-existing group.
|
|
||||||
$this->clientError(_('Group not found.'), 404);
|
|
||||||
}
|
|
||||||
|
|
||||||
$is_member = $this->target->isMember($this->group);
|
|
||||||
|
|
||||||
switch($this->format) {
|
|
||||||
case 'xml':
|
|
||||||
$this->initDocument('xml');
|
|
||||||
$this->element('is_member', null, $is_member);
|
|
||||||
$this->endDocument('xml');
|
|
||||||
break;
|
|
||||||
case 'json':
|
|
||||||
$this->initDocument('json');
|
|
||||||
$this->showJsonObjects(array('is_member' => $is_member));
|
|
||||||
$this->endDocument('json');
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// TRANS: Client error displayed when coming across a non-supported API method.
|
|
||||||
$this->clientError(_('API method not found.'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return true if read only.
|
|
||||||
*
|
|
||||||
* MAY override
|
|
||||||
*
|
|
||||||
* @param array $args other arguments
|
|
||||||
*
|
|
||||||
* @return boolean is read only action?
|
|
||||||
*/
|
|
||||||
function isReadOnly($args)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,124 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StatusNet, the distributed open-source microblogging tool
|
|
||||||
*
|
|
||||||
* Join a group via the API
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Craig Andrews <candrews@integralblue.com>
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @author Jeffery To <jeffery.to@gmail.com>
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @copyright 2009 StatusNet, Inc.
|
|
||||||
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('STATUSNET')) {
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Joins the authenticated user to the group speicified by ID
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Craig Andrews <candrews@integralblue.com>
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @author Jeffery To <jeffery.to@gmail.com>
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
class ApiGroupJoinAction extends ApiAuthAction
|
|
||||||
{
|
|
||||||
protected $needPost = true;
|
|
||||||
|
|
||||||
var $group = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Take arguments for running
|
|
||||||
*
|
|
||||||
* @param array $args $_REQUEST args
|
|
||||||
*
|
|
||||||
* @return boolean success flag
|
|
||||||
*/
|
|
||||||
protected function prepare(array $args=array())
|
|
||||||
{
|
|
||||||
parent::prepare($args);
|
|
||||||
|
|
||||||
$this->group = $this->getTargetGroup($this->arg('id'));
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle the request
|
|
||||||
*
|
|
||||||
* Join the authenticated user to the group
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
protected function handle()
|
|
||||||
{
|
|
||||||
parent::handle();
|
|
||||||
|
|
||||||
if (empty($this->scoped)) {
|
|
||||||
// TRANS: Client error displayed when trying to have a non-existing user join a group.
|
|
||||||
$this->clientError(_('No such user.'), 404);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (empty($this->group)) {
|
|
||||||
// TRANS: Client error displayed when trying to join a group that does not exist.
|
|
||||||
$this->clientError(_('Group not found.'), 404);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->scoped->isMember($this->group)) {
|
|
||||||
// TRANS: Server error displayed when trying to join a group the user is already a member of.
|
|
||||||
$this->clientError(_('You are already a member of that group.'), 403);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Group_block::isBlocked($this->group, $this->scoped)) {
|
|
||||||
// TRANS: Server error displayed when trying to join a group the user is blocked from joining.
|
|
||||||
$this->clientError(_('You have been blocked from that group by the admin.'), 403);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
$this->scoped->joinGroup($this->group);
|
|
||||||
} catch (Exception $e) {
|
|
||||||
// TRANS: Server error displayed when joining a group failed in the database.
|
|
||||||
// TRANS: %1$s is the joining user's nickname, $2$s is the group nickname for which the join failed.
|
|
||||||
$this->serverError(sprintf(_('Could not join user %1$s to group %2$s.'),
|
|
||||||
$this->scoped->nickname, $this->group->nickname));
|
|
||||||
}
|
|
||||||
|
|
||||||
switch($this->format) {
|
|
||||||
case 'xml':
|
|
||||||
$this->showSingleXmlGroup($this->group);
|
|
||||||
break;
|
|
||||||
case 'json':
|
|
||||||
$this->showSingleJsonGroup($this->group);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// TRANS: Client error displayed when coming across a non-supported API method.
|
|
||||||
$this->clientError(_('API method not found.'), 404);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,123 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StatusNet, the distributed open-source microblogging tool
|
|
||||||
*
|
|
||||||
* Leave a group via the API
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Craig Andrews <candrews@integralblue.com>
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @author Jeffery To <jeffery.to@gmail.com>
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @copyright 2009 StatusNet, Inc.
|
|
||||||
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('STATUSNET')) {
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes the authenticated user from the group specified by ID
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Craig Andrews <candrews@integralblue.com>
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @author Jeffery To <jeffery.to@gmail.com>
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
class ApiGroupLeaveAction extends ApiAuthAction
|
|
||||||
{
|
|
||||||
protected $needPost = true;
|
|
||||||
|
|
||||||
var $group = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Take arguments for running
|
|
||||||
*
|
|
||||||
* @param array $args $_REQUEST args
|
|
||||||
*
|
|
||||||
* @return boolean success flag
|
|
||||||
*/
|
|
||||||
protected function prepare(array $args=array())
|
|
||||||
{
|
|
||||||
parent::prepare($args);
|
|
||||||
|
|
||||||
$this->group = $this->getTargetGroup($this->arg('id'));
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle the request
|
|
||||||
*
|
|
||||||
* Save the new message
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
protected function handle()
|
|
||||||
{
|
|
||||||
parent::handle();
|
|
||||||
|
|
||||||
if (!$this->scoped instanceof Profile) {
|
|
||||||
// TRANS: Client error displayed when trying to have a non-existing user leave a group.
|
|
||||||
$this->clientError(_('No such user.'), 404);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$this->group instanceof User_group) {
|
|
||||||
// TRANS: Client error displayed when trying to leave a group that does not exist.
|
|
||||||
$this->clientError(_('Group not found.'), 404);
|
|
||||||
}
|
|
||||||
|
|
||||||
$member = new Group_member();
|
|
||||||
|
|
||||||
$member->group_id = $this->group->id;
|
|
||||||
$member->profile_id = $this->scoped->id;
|
|
||||||
|
|
||||||
if (!$member->find(true)) {
|
|
||||||
// TRANS: Server error displayed when trying to leave a group the user is not a member of.
|
|
||||||
$this->serverError(_('You are not a member of this group.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
$this->user->leaveGroup($this->group);
|
|
||||||
} catch (Exception $e) {
|
|
||||||
// TRANS: Server error displayed when leaving a group failed in the database.
|
|
||||||
// TRANS: %1$s is the leaving user's nickname, $2$s is the group nickname for which the leave failed.
|
|
||||||
$this->serverError(sprintf(_('Could not remove user %1$s from group %2$s.'),
|
|
||||||
$this->scoped->getNickname(), $this->group->nickname));
|
|
||||||
}
|
|
||||||
switch($this->format) {
|
|
||||||
case 'xml':
|
|
||||||
$this->showSingleXmlGroup($this->group);
|
|
||||||
break;
|
|
||||||
case 'json':
|
|
||||||
$this->showSingleJsonGroup($this->group);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// TRANS: Client error displayed when coming across a non-supported API method.
|
|
||||||
$this->clientError(_('API method not found.'), 404);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,211 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StatusNet, the distributed open-source microblogging tool
|
|
||||||
*
|
|
||||||
* Check to see whether a user a member of a group
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Craig Andrews <candrews@integralblue.com>
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @author Jeffery To <jeffery.to@gmail.com>
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @copyright 2009 StatusNet, Inc.
|
|
||||||
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('STATUSNET')) {
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns whether a user is a member of a specified group.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Craig Andrews <candrews@integralblue.com>
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @author Jeffery To <jeffery.to@gmail.com>
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
class ApiGroupListAction extends ApiBareAuthAction
|
|
||||||
{
|
|
||||||
var $groups = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Take arguments for running
|
|
||||||
*
|
|
||||||
* @param array $args $_REQUEST args
|
|
||||||
*
|
|
||||||
* @return boolean success flag
|
|
||||||
*/
|
|
||||||
protected function prepare(array $args=array())
|
|
||||||
{
|
|
||||||
parent::prepare($args);
|
|
||||||
|
|
||||||
//TODO: Make sure this doesn't leak unwantedly for federated users
|
|
||||||
$this->target = $this->getTargetProfile(null);
|
|
||||||
|
|
||||||
if (!($this->target instanceof Profile)) {
|
|
||||||
// TRANS: Client error displayed when user not found for an action.
|
|
||||||
$this->clientError(_('No such user.'), 404);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->groups = $this->getGroups();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle the request
|
|
||||||
*
|
|
||||||
* Show the user's groups
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
protected function handle()
|
|
||||||
{
|
|
||||||
parent::handle();
|
|
||||||
|
|
||||||
$sitename = common_config('site', 'name');
|
|
||||||
// TRANS: Used as title in check for group membership. %s is a user name.
|
|
||||||
$title = sprintf(_("%s's groups"), $this->target->nickname);
|
|
||||||
$taguribase = TagURI::base();
|
|
||||||
$id = "tag:$taguribase:Groups";
|
|
||||||
$link = common_local_url(
|
|
||||||
'usergroups',
|
|
||||||
array('nickname' => $this->target->nickname)
|
|
||||||
);
|
|
||||||
|
|
||||||
$subtitle = sprintf(
|
|
||||||
// TRANS: Used as subtitle in check for group membership. %1$s is the site name, %2$s is a user name.
|
|
||||||
_('%1$s groups %2$s is a member of.'),
|
|
||||||
$sitename,
|
|
||||||
$this->target->nickname
|
|
||||||
);
|
|
||||||
|
|
||||||
switch($this->format) {
|
|
||||||
case 'xml':
|
|
||||||
$this->showXmlGroups($this->groups);
|
|
||||||
break;
|
|
||||||
case 'rss':
|
|
||||||
$this->showRssGroups($this->groups, $title, $link, $subtitle);
|
|
||||||
break;
|
|
||||||
case 'atom':
|
|
||||||
$selfuri = common_local_url('ApiGroupList', array('id'=>$this->target->id, 'format'=>'atom'));
|
|
||||||
$this->showAtomGroups(
|
|
||||||
$this->groups,
|
|
||||||
$title,
|
|
||||||
$id,
|
|
||||||
$link,
|
|
||||||
$subtitle,
|
|
||||||
$selfuri
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case 'json':
|
|
||||||
$this->showJsonGroups($this->groups);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// TRANS: Client error displayed when coming across a non-supported API method.
|
|
||||||
$this->clientError(_('API method not found.'), 404);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get groups
|
|
||||||
*
|
|
||||||
* @return array groups
|
|
||||||
*/
|
|
||||||
function getGroups()
|
|
||||||
{
|
|
||||||
$groups = array();
|
|
||||||
|
|
||||||
$group = $this->target->getGroups(
|
|
||||||
($this->page - 1) * $this->count,
|
|
||||||
$this->count,
|
|
||||||
$this->since_id,
|
|
||||||
$this->max_id
|
|
||||||
);
|
|
||||||
|
|
||||||
while ($group->fetch()) {
|
|
||||||
$groups[] = clone($group);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $groups;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Is this action read only?
|
|
||||||
*
|
|
||||||
* @param array $args other arguments
|
|
||||||
*
|
|
||||||
* @return boolean true
|
|
||||||
*/
|
|
||||||
function isReadOnly($args)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* When was this feed last modified?
|
|
||||||
*
|
|
||||||
* @return string datestamp of the latest group the user has joined
|
|
||||||
*/
|
|
||||||
|
|
||||||
function lastModified()
|
|
||||||
{
|
|
||||||
if (!empty($this->groups) && (count($this->groups) > 0)) {
|
|
||||||
return strtotime($this->groups[0]->created);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An entity tag for this list of groups
|
|
||||||
*
|
|
||||||
* Returns an Etag based on the action name, language, user ID and
|
|
||||||
* timestamps of the first and last group the user has joined
|
|
||||||
*
|
|
||||||
* @return string etag
|
|
||||||
*/
|
|
||||||
function etag()
|
|
||||||
{
|
|
||||||
if (!empty($this->groups) && (count($this->groups) > 0)) {
|
|
||||||
|
|
||||||
$last = count($this->groups) - 1;
|
|
||||||
|
|
||||||
return '"' . implode(
|
|
||||||
':',
|
|
||||||
array($this->arg('action'),
|
|
||||||
common_user_cache_hash($this->auth_user),
|
|
||||||
common_language(),
|
|
||||||
$this->target->id,
|
|
||||||
strtotime($this->groups[0]->created),
|
|
||||||
strtotime($this->groups[$last]->created))
|
|
||||||
)
|
|
||||||
. '"';
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,208 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StatusNet, the distributed open-source microblogging tool
|
|
||||||
*
|
|
||||||
* Show the newest groups
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Craig Andrews <candrews@integralblue.com>
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @author Jeffery To <jeffery.to@gmail.com>
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @copyright 2009 StatusNet, Inc.
|
|
||||||
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('STATUSNET')) {
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns of the lastest 20 groups for the site
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Craig Andrews <candrews@integralblue.com>
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @author Jeffery To <jeffery.to@gmail.com>
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
class ApiGroupListAllAction extends ApiPrivateAuthAction
|
|
||||||
{
|
|
||||||
var $groups = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Take arguments for running
|
|
||||||
*
|
|
||||||
* @param array $args $_REQUEST args
|
|
||||||
*
|
|
||||||
* @return boolean success flag
|
|
||||||
*/
|
|
||||||
function prepare($args)
|
|
||||||
{
|
|
||||||
parent::prepare($args);
|
|
||||||
|
|
||||||
$this->user = $this->getTargetUser(null);
|
|
||||||
$this->groups = $this->getGroups();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle the request
|
|
||||||
*
|
|
||||||
* Show the user's groups
|
|
||||||
*
|
|
||||||
* @param array $args $_REQUEST data (unused)
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function handle($args)
|
|
||||||
{
|
|
||||||
parent::handle($args);
|
|
||||||
|
|
||||||
$sitename = common_config('site', 'name');
|
|
||||||
// TRANS: Message is used as a title when listing the lastest 20 groups. %s is a site name.
|
|
||||||
$title = sprintf(_("%s groups"), $sitename);
|
|
||||||
$taguribase = TagURI::base();
|
|
||||||
$id = "tag:$taguribase:Groups";
|
|
||||||
$link = common_local_url('groups');
|
|
||||||
// TRANS: Message is used as a subtitle when listing the latest 20 groups. %s is a site name.
|
|
||||||
$subtitle = sprintf(_("groups on %s"), $sitename);
|
|
||||||
|
|
||||||
switch($this->format) {
|
|
||||||
case 'xml':
|
|
||||||
$this->showXmlGroups($this->groups);
|
|
||||||
break;
|
|
||||||
case 'rss':
|
|
||||||
$this->showRssGroups($this->groups, $title, $link, $subtitle);
|
|
||||||
break;
|
|
||||||
case 'atom':
|
|
||||||
$selfuri = common_root_url() .
|
|
||||||
'api/statusnet/groups/list_all.atom';
|
|
||||||
$this->showAtomGroups(
|
|
||||||
$this->groups,
|
|
||||||
$title,
|
|
||||||
$id,
|
|
||||||
$link,
|
|
||||||
$subtitle,
|
|
||||||
$selfuri
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case 'json':
|
|
||||||
$this->showJsonGroups($this->groups);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
$this->clientError(
|
|
||||||
// TRANS: Client error displayed when coming across a non-supported API method.
|
|
||||||
_('API method not found.'),
|
|
||||||
404,
|
|
||||||
$this->format
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get groups
|
|
||||||
*
|
|
||||||
* @return array groups
|
|
||||||
*/
|
|
||||||
function getGroups()
|
|
||||||
{
|
|
||||||
$qry = 'SELECT user_group.* '.
|
|
||||||
'from user_group join local_group on user_group.id = local_group.group_id '.
|
|
||||||
'order by created desc ';
|
|
||||||
$offset = intval($this->page - 1) * intval($this->count);
|
|
||||||
$limit = intval($this->count);
|
|
||||||
if (common_config('db', 'type') == 'pgsql') {
|
|
||||||
$qry .= ' LIMIT ' . $limit . ' OFFSET ' . $offset;
|
|
||||||
} else {
|
|
||||||
$qry .= ' LIMIT ' . $offset . ', ' . $limit;
|
|
||||||
}
|
|
||||||
$group = new User_group();
|
|
||||||
|
|
||||||
$group->query($qry);
|
|
||||||
|
|
||||||
$groups = array();
|
|
||||||
while ($group->fetch()) {
|
|
||||||
$groups[] = clone($group);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $groups;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Is this action read only?
|
|
||||||
*
|
|
||||||
* @param array $args other arguments
|
|
||||||
*
|
|
||||||
* @return boolean true
|
|
||||||
*/
|
|
||||||
function isReadOnly($args)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* When was this feed last modified?
|
|
||||||
*
|
|
||||||
* @return string datestamp of the site's latest group
|
|
||||||
*/
|
|
||||||
function lastModified()
|
|
||||||
{
|
|
||||||
if (!empty($this->groups) && (count($this->groups) > 0)) {
|
|
||||||
return strtotime($this->groups[0]->created);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An entity tag for this list of groups
|
|
||||||
*
|
|
||||||
* Returns an Etag based on the action name, language, and
|
|
||||||
* timestamps of the first and last group the user has joined
|
|
||||||
*
|
|
||||||
* @return string etag
|
|
||||||
*/
|
|
||||||
function etag()
|
|
||||||
{
|
|
||||||
if (!empty($this->groups) && (count($this->groups) > 0)) {
|
|
||||||
|
|
||||||
$last = count($this->groups) - 1;
|
|
||||||
|
|
||||||
return '"' . implode(
|
|
||||||
':',
|
|
||||||
array($this->arg('action'),
|
|
||||||
common_user_cache_hash($this->auth_user),
|
|
||||||
common_language(),
|
|
||||||
strtotime($this->groups[0]->created),
|
|
||||||
strtotime($this->groups[$last]->created))
|
|
||||||
)
|
|
||||||
. '"';
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,181 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StatusNet, the distributed open-source microblogging tool
|
|
||||||
*
|
|
||||||
* List a group's members
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Craig Andrews <candrews@integralblue.com>
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @author Jeffery To <jeffery.to@gmail.com>
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @copyright 2009 StatusNet, Inc.
|
|
||||||
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('STATUSNET')) {
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* List 20 newest members of the group specified by name or ID.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Craig Andrews <candrews@integralblue.com>
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @author Jeffery To <jeffery.to@gmail.com>
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
class ApiGroupMembershipAction extends ApiPrivateAuthAction
|
|
||||||
{
|
|
||||||
var $group = null;
|
|
||||||
var $profiles = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Take arguments for running
|
|
||||||
*
|
|
||||||
* @param array $args $_REQUEST args
|
|
||||||
*
|
|
||||||
* @return boolean success flag
|
|
||||||
*/
|
|
||||||
protected function prepare(array $args=array())
|
|
||||||
{
|
|
||||||
parent::prepare($args);
|
|
||||||
|
|
||||||
$this->group = $this->getTargetGroup($this->arg('id'));
|
|
||||||
if (empty($this->group)) {
|
|
||||||
// TRANS: Client error displayed trying to show group membership on a non-existing group.
|
|
||||||
$this->clientError(_('Group not found.'), 404);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->profiles = $this->getProfiles();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle the request
|
|
||||||
*
|
|
||||||
* Show the members of the group
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
protected function handle()
|
|
||||||
{
|
|
||||||
parent::handle();
|
|
||||||
|
|
||||||
// XXX: RSS and Atom
|
|
||||||
|
|
||||||
switch($this->format) {
|
|
||||||
case 'xml':
|
|
||||||
$this->showTwitterXmlUsers($this->profiles);
|
|
||||||
break;
|
|
||||||
case 'json':
|
|
||||||
$this->showJsonUsers($this->profiles);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// TRANS: Client error displayed when coming across a non-supported API method.
|
|
||||||
$this->clientError(_('API method not found.'), 404);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetch the members of a group
|
|
||||||
*
|
|
||||||
* @return array $profiles list of profiles
|
|
||||||
*/
|
|
||||||
function getProfiles()
|
|
||||||
{
|
|
||||||
$profiles = array();
|
|
||||||
|
|
||||||
$profile = $this->group->getMembers(
|
|
||||||
($this->page - 1) * $this->count,
|
|
||||||
$this->count,
|
|
||||||
$this->since_id,
|
|
||||||
$this->max_id
|
|
||||||
);
|
|
||||||
|
|
||||||
while ($profile->fetch()) {
|
|
||||||
$profiles[] = clone($profile);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $profiles;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Is this action read only?
|
|
||||||
*
|
|
||||||
* @param array $args other arguments
|
|
||||||
*
|
|
||||||
* @return boolean true
|
|
||||||
*/
|
|
||||||
function isReadOnly($args)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* When was this list of profiles last modified?
|
|
||||||
*
|
|
||||||
* @return string datestamp of the lastest profile in the group
|
|
||||||
*/
|
|
||||||
function lastModified()
|
|
||||||
{
|
|
||||||
if (!empty($this->profiles) && (count($this->profiles) > 0)) {
|
|
||||||
return strtotime($this->profiles[0]->created);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An entity tag for this list of groups
|
|
||||||
*
|
|
||||||
* Returns an Etag based on the action name, language
|
|
||||||
* the group id, and timestamps of the first and last
|
|
||||||
* user who has joined the group
|
|
||||||
*
|
|
||||||
* @return string etag
|
|
||||||
*/
|
|
||||||
function etag()
|
|
||||||
{
|
|
||||||
if (!empty($this->profiles) && (count($this->profiles) > 0)) {
|
|
||||||
|
|
||||||
$last = count($this->profiles) - 1;
|
|
||||||
|
|
||||||
return '"' . implode(
|
|
||||||
':',
|
|
||||||
array($this->arg('action'),
|
|
||||||
common_user_cache_hash($this->auth_user),
|
|
||||||
common_language(),
|
|
||||||
$this->group->id,
|
|
||||||
strtotime($this->profiles[0]->created),
|
|
||||||
strtotime($this->profiles[$last]->created))
|
|
||||||
)
|
|
||||||
. '"';
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,247 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StatusNet, the distributed open-source microblogging tool
|
|
||||||
*
|
|
||||||
* Update a group's profile
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @copyright 2010 StatusNet, Inc.
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('STATUSNET')) {
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* API analog to the group edit page
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
class ApiGroupProfileUpdateAction extends ApiAuthAction
|
|
||||||
{
|
|
||||||
protected $needPost = true;
|
|
||||||
/**
|
|
||||||
* Take arguments for running
|
|
||||||
*
|
|
||||||
* @param array $args $_REQUEST args
|
|
||||||
*
|
|
||||||
* @return boolean success flag
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
protected function prepare(array $args=array())
|
|
||||||
{
|
|
||||||
parent::prepare($args);
|
|
||||||
|
|
||||||
$this->nickname = Nickname::normalize($this->trimmed('nickname'));
|
|
||||||
|
|
||||||
$this->fullname = $this->trimmed('fullname');
|
|
||||||
$this->homepage = $this->trimmed('homepage');
|
|
||||||
$this->description = $this->trimmed('description');
|
|
||||||
$this->location = $this->trimmed('location');
|
|
||||||
$this->aliasstring = $this->trimmed('aliases');
|
|
||||||
|
|
||||||
$this->user = $this->auth_user;
|
|
||||||
$this->group = $this->getTargetGroup($this->arg('id'));
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle the request
|
|
||||||
*
|
|
||||||
* See which request params have been set, and update the profile
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
protected function handle()
|
|
||||||
{
|
|
||||||
parent::handle();
|
|
||||||
|
|
||||||
if (!in_array($this->format, array('xml', 'json'))) {
|
|
||||||
// TRANS: Client error displayed when coming across a non-supported API method.
|
|
||||||
$this->clientError(_('API method not found.'), 404);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (empty($this->user)) {
|
|
||||||
// TRANS: Client error displayed when not providing a user or an invalid user.
|
|
||||||
$this->clientError(_('No such user.'), 404);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (empty($this->group)) {
|
|
||||||
// TRANS: Client error displayed when not providing a group or an invalid group.
|
|
||||||
$this->clientError(_('Group not found.'), 404);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$this->user->isAdmin($this->group)) {
|
|
||||||
// TRANS: Client error displayed when trying to edit a group without being an admin.
|
|
||||||
$this->clientError(_('You must be an admin to edit the group.'), 403);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->group->query('BEGIN');
|
|
||||||
|
|
||||||
$orig = clone($this->group);
|
|
||||||
|
|
||||||
try {
|
|
||||||
|
|
||||||
if (common_config('profile', 'changenick') == true && $this->group->nickname !== $this->nickname) {
|
|
||||||
try {
|
|
||||||
$this->group->nickname = Nickname::normalize($this->nickname, true);
|
|
||||||
} catch (NicknameException $e) {
|
|
||||||
throw new ApiValidationException($e->getMessage());
|
|
||||||
}
|
|
||||||
$this->group->mainpage = common_local_url('showgroup',
|
|
||||||
array('nickname' => $this->group->nickname));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($this->fullname)) {
|
|
||||||
$this->validateFullname();
|
|
||||||
$this->group->fullname = $this->fullname;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($this->homepage)) {
|
|
||||||
$this->validateHomepage();
|
|
||||||
$this->group->homepage = $this->homepage;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($this->description)) {
|
|
||||||
$this->validateDescription();
|
|
||||||
$this->group->description = $this->decription;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($this->location)) {
|
|
||||||
$this->validateLocation();
|
|
||||||
$this->group->location = $this->location;
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (ApiValidationException $ave) {
|
|
||||||
$this->clientError($ave->getMessage(), 400);
|
|
||||||
}
|
|
||||||
|
|
||||||
$result = $this->group->update($orig);
|
|
||||||
|
|
||||||
if (!$result) {
|
|
||||||
common_log_db_error($this->group, 'UPDATE', __FILE__);
|
|
||||||
// TRANS: Server error displayed when group update fails.
|
|
||||||
$this->serverError(_('Could not update group.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$aliases = array();
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (!empty($this->aliasstring)) {
|
|
||||||
$aliases = $this->validateAliases();
|
|
||||||
}
|
|
||||||
} catch (ApiValidationException $ave) {
|
|
||||||
$this->clientError($ave->getMessage(), 403);
|
|
||||||
}
|
|
||||||
|
|
||||||
$result = $this->group->setAliases($aliases);
|
|
||||||
|
|
||||||
if (!$result) {
|
|
||||||
// TRANS: Server error displayed when adding group aliases fails.
|
|
||||||
$this->serverError(_('Could not create aliases.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->group->query('COMMIT');
|
|
||||||
|
|
||||||
switch($this->format) {
|
|
||||||
case 'xml':
|
|
||||||
$this->showSingleXmlGroup($this->group);
|
|
||||||
break;
|
|
||||||
case 'json':
|
|
||||||
$this->showSingleJsonGroup($this->group);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// TRANS: Client error displayed when coming across a non-supported API method.
|
|
||||||
$this->clientError(_('API method not found.'), 404);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function validateHomepage()
|
|
||||||
{
|
|
||||||
if (!is_null($this->homepage)
|
|
||||||
&& (strlen($this->homepage) > 0)
|
|
||||||
&& !common_valid_http_url($this->homepage)) {
|
|
||||||
throw new ApiValidationException(
|
|
||||||
// TRANS: API validation exception thrown when homepage URL does not validate.
|
|
||||||
_('Homepage is not a valid URL.')
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function validateFullname()
|
|
||||||
{
|
|
||||||
if (!is_null($this->fullname) && mb_strlen($this->fullname) > 255) {
|
|
||||||
throw new ApiValidationException(
|
|
||||||
// TRANS: API validation exception thrown when full name does not validate.
|
|
||||||
_('Full name is too long (maximum 255 characters).')
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function validateDescription()
|
|
||||||
{
|
|
||||||
if (User_group::descriptionTooLong($this->description)) {
|
|
||||||
// TRANS: API validation exception thrown when description does not validate.
|
|
||||||
// TRANS: %d is the maximum description length and used for plural.
|
|
||||||
throw new ApiValidationException(sprintf(_m('Description is too long (maximum %d character).',
|
|
||||||
'Description is too long (maximum %d characters).',
|
|
||||||
User_group::maxDescription()),
|
|
||||||
User_group::maxDescription()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function validateLocation()
|
|
||||||
{
|
|
||||||
if (!is_null($this->location) && mb_strlen($this->location) > 255) {
|
|
||||||
throw new ApiValidationException(
|
|
||||||
// TRANS: API validation exception thrown when location does not validate.
|
|
||||||
_('Location is too long (maximum 255 characters).')
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function validateAliases()
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
$aliases = array_map(array('Nickname', 'normalize'),
|
|
||||||
array_unique(preg_split('/[\s,]+/', $this->aliasstring)));
|
|
||||||
} catch (NicknameException $e) {
|
|
||||||
throw new ApiValidationException(sprintf('Error processing aliases: %s', $e->getMessage()));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count($aliases) > common_config('group', 'maxaliases')) {
|
|
||||||
// TRANS: API validation exception thrown when aliases do not validate.
|
|
||||||
// TRANS: %d is the maximum number of aliases and used for plural.
|
|
||||||
throw new ApiValidationException(sprintf(_m('Too many aliases! Maximum %d allowed.',
|
|
||||||
'Too many aliases! Maximum %d allowed.',
|
|
||||||
common_config('group', 'maxaliases')),
|
|
||||||
common_config('group', 'maxaliases')));
|
|
||||||
}
|
|
||||||
|
|
||||||
return $aliases;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,163 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StatusNet, the distributed open-source microblogging tool
|
|
||||||
*
|
|
||||||
* Show information about a group
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Craig Andrews <candrews@integralblue.com>
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @author Jeffery To <jeffery.to@gmail.com>
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @copyright 2009 StatusNet, Inc.
|
|
||||||
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('STATUSNET')) {
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Outputs detailed information about the group specified by ID
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Craig Andrews <candrews@integralblue.com>
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @author Jeffery To <jeffery.to@gmail.com>
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @author Michele <macno@macno.org>
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
class ApiGroupShowAction extends ApiPrivateAuthAction
|
|
||||||
{
|
|
||||||
var $group = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Take arguments for running
|
|
||||||
*
|
|
||||||
* @param array $args $_REQUEST args
|
|
||||||
*
|
|
||||||
* @return boolean success flag
|
|
||||||
*/
|
|
||||||
protected function prepare(array $args=array())
|
|
||||||
{
|
|
||||||
parent::prepare($args);
|
|
||||||
|
|
||||||
$this->group = $this->getTargetGroup($this->arg('id'));
|
|
||||||
|
|
||||||
if (empty($this->group)) {
|
|
||||||
$alias = Group_alias::getKV(
|
|
||||||
'alias',
|
|
||||||
common_canonical_nickname($this->arg('id'))
|
|
||||||
);
|
|
||||||
if (!empty($alias)) {
|
|
||||||
$args = array('id' => $alias->group_id, 'format' => $this->format);
|
|
||||||
common_redirect(common_local_url('ApiGroupShow', $args), 301);
|
|
||||||
} else {
|
|
||||||
// TRANS: Client error displayed when trying to show a group that could not be found.
|
|
||||||
$this->clientError(_('Group not found.'), 404);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle the request
|
|
||||||
*
|
|
||||||
* Check the format and show the user info
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
protected function handle()
|
|
||||||
{
|
|
||||||
parent::handle();
|
|
||||||
|
|
||||||
switch($this->format) {
|
|
||||||
case 'xml':
|
|
||||||
$this->showSingleXmlGroup($this->group);
|
|
||||||
break;
|
|
||||||
case 'json':
|
|
||||||
$this->showSingleJsonGroup($this->group);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// TRANS: Client error displayed when coming across a non-supported API method.
|
|
||||||
$this->clientError(_('API method not found.'), 404);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* When was this group last modified?
|
|
||||||
*
|
|
||||||
* @return string datestamp of the latest notice in the stream
|
|
||||||
*/
|
|
||||||
function lastModified()
|
|
||||||
{
|
|
||||||
if (!empty($this->group)) {
|
|
||||||
return strtotime($this->group->modified);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An entity tag for this group
|
|
||||||
*
|
|
||||||
* Returns an Etag based on the action name, language, and
|
|
||||||
* timestamps of the notice
|
|
||||||
*
|
|
||||||
* @return string etag
|
|
||||||
*/
|
|
||||||
function etag()
|
|
||||||
{
|
|
||||||
if (!empty($this->group)) {
|
|
||||||
|
|
||||||
return '"' . implode(
|
|
||||||
':',
|
|
||||||
array($this->arg('action'),
|
|
||||||
common_user_cache_hash($this->auth_user),
|
|
||||||
common_language(),
|
|
||||||
$this->group->id,
|
|
||||||
strtotime($this->group->modified))
|
|
||||||
)
|
|
||||||
. '"';
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return true if read only.
|
|
||||||
*
|
|
||||||
* MAY override
|
|
||||||
*
|
|
||||||
* @param array $args other arguments
|
|
||||||
*
|
|
||||||
* @return boolean is read only action?
|
|
||||||
*/
|
|
||||||
function isReadOnly($args)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,102 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StatusNet, the distributed open-source microblogging tool
|
|
||||||
*
|
|
||||||
* Test that you can connect to the API
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @copyright 2009 StatusNet, Inc.
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('STATUSNET')) {
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the string "ok" in the requested format with a 200 OK HTTP status code.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
class ApiHelpTestAction extends ApiPrivateAuthAction
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Take arguments for running
|
|
||||||
*
|
|
||||||
* @param array $args $_REQUEST args
|
|
||||||
*
|
|
||||||
* @return boolean success flag
|
|
||||||
*/
|
|
||||||
function prepare($args)
|
|
||||||
{
|
|
||||||
parent::prepare($args);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle the request
|
|
||||||
*
|
|
||||||
* @param array $args $_REQUEST data (unused)
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function handle($args)
|
|
||||||
{
|
|
||||||
parent::handle($args);
|
|
||||||
|
|
||||||
if ($this->format == 'xml') {
|
|
||||||
$this->initDocument('xml');
|
|
||||||
$this->element('ok', null, 'true');
|
|
||||||
$this->endDocument('xml');
|
|
||||||
} elseif ($this->format == 'json') {
|
|
||||||
$this->initDocument('json');
|
|
||||||
print '"ok"';
|
|
||||||
$this->endDocument('json');
|
|
||||||
} else {
|
|
||||||
$this->clientError(
|
|
||||||
// TRANS: Client error displayed when coming across a non-supported API method.
|
|
||||||
_('API method not found.'),
|
|
||||||
404,
|
|
||||||
$this->format
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return true if read only.
|
|
||||||
*
|
|
||||||
* MAY override
|
|
||||||
*
|
|
||||||
* @param array $args other arguments
|
|
||||||
*
|
|
||||||
* @return boolean is read only action?
|
|
||||||
*/
|
|
||||||
function isReadOnly($args)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,240 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StatusNet, the distributed open-source microblogging tool
|
|
||||||
*
|
|
||||||
* Show, update or delete a list.
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Shashi Gowda <connect2shashi@gmail.com>
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('STATUSNET')) {
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
class ApiListAction extends ApiBareAuthAction
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* The list in question in the current request
|
|
||||||
*/
|
|
||||||
var $list = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Is this an update request?
|
|
||||||
*/
|
|
||||||
var $update = false;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Is this a delete request?
|
|
||||||
*/
|
|
||||||
var $delete = false;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the flags for handling the request. Show list if this is a GET
|
|
||||||
* request, update it if it is POST, delete list if method is DELETE
|
|
||||||
* or if method is POST and an argument _method is set to DELETE. Act
|
|
||||||
* like we don't know if the current user has no access to the list.
|
|
||||||
*
|
|
||||||
* Takes parameters:
|
|
||||||
* - user: the user id or nickname
|
|
||||||
* - id: the id of the tag or the tag itself
|
|
||||||
*
|
|
||||||
* @return boolean success flag
|
|
||||||
*/
|
|
||||||
protected function prepare(array $args=array())
|
|
||||||
{
|
|
||||||
parent::prepare($args);
|
|
||||||
|
|
||||||
$this->delete = ($_SERVER['REQUEST_METHOD'] == 'DELETE' ||
|
|
||||||
($this->trimmed('_method') == 'DELETE' &&
|
|
||||||
$_SERVER['REQUEST_METHOD'] == 'POST'));
|
|
||||||
|
|
||||||
// update list if method is POST or PUT and $this->delete is not true
|
|
||||||
$this->update = (!$this->delete &&
|
|
||||||
in_array($_SERVER['REQUEST_METHOD'], array('POST', 'PUT')));
|
|
||||||
|
|
||||||
$this->user = $this->getTargetUser($this->arg('user'));
|
|
||||||
$this->list = $this->getTargetList($this->arg('user'), $this->arg('id'));
|
|
||||||
|
|
||||||
if (empty($this->list)) {
|
|
||||||
// TRANS: Client error displayed when referring to a non-existing list.
|
|
||||||
$this->clientError(_('List not found.'), 404);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle the request
|
|
||||||
*
|
|
||||||
* @return boolean success flag
|
|
||||||
*/
|
|
||||||
protected function handle()
|
|
||||||
{
|
|
||||||
parent::handle();
|
|
||||||
|
|
||||||
if($this->delete) {
|
|
||||||
$this->handleDelete();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if($this->update) {
|
|
||||||
$this->handlePut();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch($this->format) {
|
|
||||||
case 'xml':
|
|
||||||
$this->showSingleXmlList($this->list);
|
|
||||||
break;
|
|
||||||
case 'json':
|
|
||||||
$this->showSingleJsonList($this->list);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// TRANS: Client error displayed when coming across a non-supported API method.
|
|
||||||
$this->clientError(_('API method not found.'), 404);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* require authentication if it is a write action or user is ambiguous
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
function requiresAuth()
|
|
||||||
{
|
|
||||||
return parent::requiresAuth() ||
|
|
||||||
$this->create || $this->delete;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update a list
|
|
||||||
*
|
|
||||||
* @return boolean success
|
|
||||||
*/
|
|
||||||
function handlePut()
|
|
||||||
{
|
|
||||||
if($this->auth_user->id != $this->list->tagger) {
|
|
||||||
// TRANS: Client error displayed when trying to update another user's list.
|
|
||||||
$this->clientError(_('You cannot update lists that do not belong to you.'), 401);
|
|
||||||
}
|
|
||||||
|
|
||||||
$new_list = clone($this->list);
|
|
||||||
$new_list->tag = common_canonical_tag($this->arg('name'));
|
|
||||||
$new_list->description = common_canonical_tag($this->arg('description'));
|
|
||||||
$new_list->private = ($this->arg('mode') === 'private') ? true : false;
|
|
||||||
|
|
||||||
$result = $new_list->update($this->list);
|
|
||||||
|
|
||||||
if(!$result) {
|
|
||||||
// TRANS: Client error displayed when an unknown error occurs updating a list.
|
|
||||||
$this->clientError(_('An error occured.'), 503);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch($this->format) {
|
|
||||||
case 'xml':
|
|
||||||
$this->showSingleXmlList($new_list);
|
|
||||||
break;
|
|
||||||
case 'json':
|
|
||||||
$this->showSingleJsonList($new_list);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// TRANS: Client error displayed when coming across a non-supported API method.
|
|
||||||
$this->clientError(_('API method not found.'), 404);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Delete a list
|
|
||||||
*
|
|
||||||
* @return boolean success
|
|
||||||
*/
|
|
||||||
function handleDelete()
|
|
||||||
{
|
|
||||||
if($this->auth_user->id != $this->list->tagger) {
|
|
||||||
// TRANS: Client error displayed when trying to delete another user's list.
|
|
||||||
$this->clientError(_('You cannot delete lists that do not belong to you.'), 401);
|
|
||||||
}
|
|
||||||
|
|
||||||
$record = clone($this->list);
|
|
||||||
$this->list->delete();
|
|
||||||
|
|
||||||
switch($this->format) {
|
|
||||||
case 'xml':
|
|
||||||
$this->showSingleXmlList($record);
|
|
||||||
break;
|
|
||||||
case 'json':
|
|
||||||
$this->showSingleJsonList($record);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// TRANS: Client error displayed when coming across a non-supported API method.
|
|
||||||
$this->clientError(_('API method not found.'), 404);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Indicate that this resource is not read-only.
|
|
||||||
*
|
|
||||||
* @return boolean is_read-only=false
|
|
||||||
*/
|
|
||||||
function isReadOnly($args)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* When was the list (people tag) last updated?
|
|
||||||
*
|
|
||||||
* @return String time_last_modified
|
|
||||||
*/
|
|
||||||
function lastModified()
|
|
||||||
{
|
|
||||||
if(!empty($this->list)) {
|
|
||||||
return strtotime($this->list->modified);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An entity tag for this list
|
|
||||||
*
|
|
||||||
* Returns an Etag based on the action name, language, user ID and
|
|
||||||
* timestamps of the first and last list the user has joined
|
|
||||||
*
|
|
||||||
* @return string etag
|
|
||||||
*/
|
|
||||||
function etag()
|
|
||||||
{
|
|
||||||
if (!empty($this->list)) {
|
|
||||||
|
|
||||||
return '"' . implode(
|
|
||||||
':',
|
|
||||||
array($this->arg('action'),
|
|
||||||
common_language(),
|
|
||||||
$this->user->id,
|
|
||||||
strtotime($this->list->created),
|
|
||||||
strtotime($this->list->modified))
|
|
||||||
)
|
|
||||||
. '"';
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,112 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StatusNet, the distributed open-source microblogging tool
|
|
||||||
*
|
|
||||||
* API method to check if a user belongs to a list.
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Shashi Gowda <connect2shashi@gmail.com>
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('STATUSNET')) {
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Action handler for Twitter list_memeber methods
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Shashi Gowda <connect2shashi@gmail.com>
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
* @see ApiBareAuthAction
|
|
||||||
*/
|
|
||||||
class ApiListMemberAction extends ApiBareAuthAction
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Set the flags for handling the request. Show the profile if this
|
|
||||||
* is a GET request AND the profile is a member of the list, add a member
|
|
||||||
* if it is a POST, remove the profile from the list if method is DELETE
|
|
||||||
* or if method is POST and an argument _method is set to DELETE. Act
|
|
||||||
* like we don't know if the current user has no access to the list.
|
|
||||||
*
|
|
||||||
* Takes parameters:
|
|
||||||
* - user: the user id or nickname
|
|
||||||
* - list_id: the id of the tag or the tag itself
|
|
||||||
* - id: the id of the member being looked for/added/removed
|
|
||||||
*
|
|
||||||
* @return boolean success flag
|
|
||||||
*/
|
|
||||||
protected function prepare(array $args=array())
|
|
||||||
{
|
|
||||||
parent::prepare($args);
|
|
||||||
|
|
||||||
$this->target = $this->getTargetProfile($this->arg('id'));
|
|
||||||
$this->list = $this->getTargetList($this->arg('user'), $this->arg('list_id'));
|
|
||||||
|
|
||||||
if (empty($this->list)) {
|
|
||||||
// TRANS: Client error displayed when referring to a non-existing list.
|
|
||||||
$this->clientError(_('List not found.'), 404);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!($this->target instanceof Profile)) {
|
|
||||||
// TRANS: Client error displayed when referring to a non-existing user.
|
|
||||||
$this->clientError(_('No such user.'), 404);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle the request
|
|
||||||
*
|
|
||||||
* @return boolean success flag
|
|
||||||
*/
|
|
||||||
protected function handle()
|
|
||||||
{
|
|
||||||
parent::handle();
|
|
||||||
|
|
||||||
$arr = array('tagger' => $this->list->tagger,
|
|
||||||
'tag' => $this->list->tag,
|
|
||||||
'tagged' => $this->target->id);
|
|
||||||
$ptag = Profile_tag::pkeyGet($arr);
|
|
||||||
|
|
||||||
if(empty($ptag)) {
|
|
||||||
// TRANS: Client error displayed when referring to a non-list member.
|
|
||||||
$this->clientError(_('The specified user is not a member of this list.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$user = $this->twitterUserArray($this->target, true);
|
|
||||||
|
|
||||||
switch($this->format) {
|
|
||||||
case 'xml':
|
|
||||||
$this->showTwitterXmlUser($user, 'user', true);
|
|
||||||
break;
|
|
||||||
case 'json':
|
|
||||||
$this->showSingleJsonUser($user);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// TRANS: Client error displayed when coming across a non-supported API method.
|
|
||||||
$this->clientError(_('API method not found.'), 404);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,131 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StatusNet, the distributed open-source microblogging tool
|
|
||||||
*
|
|
||||||
* List/add/remove list members.
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Shashi Gowda <connect2shashi@gmail.com>
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('STATUSNET')) {
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
require_once INSTALLDIR . '/lib/apilistusers.php';
|
|
||||||
|
|
||||||
class ApiListMembersAction extends ApiListUsersAction
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Add a user to a list (tag someone)
|
|
||||||
*
|
|
||||||
* @return boolean success
|
|
||||||
*/
|
|
||||||
function handlePost()
|
|
||||||
{
|
|
||||||
if($this->auth_user->id != $this->list->tagger) {
|
|
||||||
// TRANS: Client error displayed when trying to add members to a list without having the right to do so.
|
|
||||||
$this->clientError(_('You are not allowed to add members to this list.'), 401);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!($this->target instanceof Profile)) {
|
|
||||||
// TRANS: Client error displayed when trying to modify list members without specifying them.
|
|
||||||
$this->clientError(_('You must specify a member.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$result = Profile_tag::setTag($this->auth_user->id,
|
|
||||||
$this->target->id, $this->list->tag);
|
|
||||||
|
|
||||||
if(empty($result)) {
|
|
||||||
// TRANS: Client error displayed when an unknown error occurs viewing list members.
|
|
||||||
$this->clientError(_('An error occured.'), 500);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch($this->format) {
|
|
||||||
case 'xml':
|
|
||||||
$this->showSingleXmlList($this->list);
|
|
||||||
break;
|
|
||||||
case 'json':
|
|
||||||
$this->showSingleJsonList($this->list);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// TRANS: Client error displayed when coming across a non-supported API method.
|
|
||||||
$this->clientError(_('API method not found.'), 404);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove a user from a list (untag someone)
|
|
||||||
*
|
|
||||||
* @return boolean success
|
|
||||||
*/
|
|
||||||
function handleDelete()
|
|
||||||
{
|
|
||||||
if($this->auth_user->id != $this->list->tagger) {
|
|
||||||
// TRANS: Client error displayed when trying to remove members from a list without having the right to do so.
|
|
||||||
$this->clientError(_('You are not allowed to remove members from this list.'), 401);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!($this->target instanceof Profile)) {
|
|
||||||
// TRANS: Client error displayed when trying to modify list members without specifying them.
|
|
||||||
$this->clientError(_('You must specify a member.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$args = array('tagger' => $this->auth_user->id,
|
|
||||||
'tagged' => $this->target->id,
|
|
||||||
'tag' => $this->list->tag);
|
|
||||||
$ptag = Profile_tag::pkeyGet($args);
|
|
||||||
|
|
||||||
if (empty($ptag)) {
|
|
||||||
// TRANS: Client error displayed when trying to remove a list member that is not part of a list.
|
|
||||||
$this->clientError(_('The user you are trying to remove from the list is not a member.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$ptag->delete()) {
|
|
||||||
// TRANS: Client error displayed when an unknown error occurs viewing list members.
|
|
||||||
$this->clientError(_('An error occured.'), 500);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch($this->format) {
|
|
||||||
case 'xml':
|
|
||||||
$this->showSingleXmlList($this->list);
|
|
||||||
break;
|
|
||||||
case 'json':
|
|
||||||
$this->showSingleJsonList($this->list);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// TRANS: Client error displayed when coming across a non-supported API method.
|
|
||||||
$this->clientError(_('API method not found.'), 404);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* List the members of a list (people tagged)
|
|
||||||
*/
|
|
||||||
function getUsers()
|
|
||||||
{
|
|
||||||
$fn = array($this->list, 'getTagged');
|
|
||||||
list($this->users, $this->next_cursor, $this->prev_cursor) =
|
|
||||||
Profile_list::getAtCursor($fn, array(), $this->cursor, 20);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,125 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StatusNet, the distributed open-source microblogging tool
|
|
||||||
*
|
|
||||||
* Get a list of lists a user belongs to. (people tags for a user)
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Shashi Gowda <connect2shashi@gmail.com>
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('STATUSNET')) {
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Action handler for API method to list lists a user belongs to.
|
|
||||||
* (people tags for a user)
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Shashi Gowda <connect2shashi@gmail.com>
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
* @see ApiBareAuthAction
|
|
||||||
*/
|
|
||||||
class ApiListMembershipsAction extends ApiBareAuthAction
|
|
||||||
{
|
|
||||||
var $lists = array();
|
|
||||||
var $cursor = -1;
|
|
||||||
var $next_cursor = 0;
|
|
||||||
var $prev_cursor = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prepare for running the action
|
|
||||||
* Take arguments for running:s
|
|
||||||
*
|
|
||||||
* @param array $args $_REQUEST args
|
|
||||||
*
|
|
||||||
* @return boolean success flag
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
protected function prepare(array $args=array())
|
|
||||||
{
|
|
||||||
parent::prepare($args);
|
|
||||||
|
|
||||||
$this->cursor = (int) $this->arg('cursor', -1);
|
|
||||||
$user = $this->getTargetUser($this->arg('user'));
|
|
||||||
|
|
||||||
if (!($user instanceof User)) {
|
|
||||||
// TRANS: Client error displayed trying to perform an action related to a non-existing user.
|
|
||||||
$this->clientError(_('No such user.'), 404);
|
|
||||||
}
|
|
||||||
$this->target = $user->getProfile();
|
|
||||||
|
|
||||||
$this->getLists();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle the request
|
|
||||||
*
|
|
||||||
* Show the lists
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
protected function handle()
|
|
||||||
{
|
|
||||||
parent::handle();
|
|
||||||
|
|
||||||
switch($this->format) {
|
|
||||||
case 'xml':
|
|
||||||
$this->showXmlLists($this->lists, $this->next_cursor, $this->prev_cursor);
|
|
||||||
break;
|
|
||||||
case 'json':
|
|
||||||
$this->showJsonLists($this->lists, $this->next_cursor, $this->prev_cursor);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// TRANS: Client error displayed when coming across a non-supported API method.
|
|
||||||
$this->clientError(_('API method not found.'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return true if read only.
|
|
||||||
*
|
|
||||||
* MAY override
|
|
||||||
*
|
|
||||||
* @param array $args other arguments
|
|
||||||
*
|
|
||||||
* @return boolean is read only action?
|
|
||||||
*/
|
|
||||||
function isReadOnly($args)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getLists()
|
|
||||||
{
|
|
||||||
$profile = $this->target;
|
|
||||||
$fn = array($profile, 'getOtherTags');
|
|
||||||
|
|
||||||
# 20 lists
|
|
||||||
list($this->lists, $this->next_cursor, $this->prev_cursor) =
|
|
||||||
Profile_list::getAtCursor($fn, array($this->auth_user), $this->cursor, 20);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,232 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StatusNet, the distributed open-source microblogging tool
|
|
||||||
*
|
|
||||||
* List existing lists or create a new list.
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Shashi Gowda <connect2shashi@gmail.com>
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('STATUSNET')) {
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Action handler for Twitter list_memeber methods
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Shashi Gowda <connect2shashi@gmail.com>
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
* @see ApiBareAuthAction
|
|
||||||
*/
|
|
||||||
class ApiListsAction extends ApiBareAuthAction
|
|
||||||
{
|
|
||||||
var $lists = null;
|
|
||||||
var $cursor = 0;
|
|
||||||
var $next_cursor = 0;
|
|
||||||
var $prev_cursor = 0;
|
|
||||||
var $create = false;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the flags for handling the request. List lists created by user if this
|
|
||||||
* is a GET request, create a new list if it is a POST request.
|
|
||||||
*
|
|
||||||
* Takes parameters:
|
|
||||||
* - user: the user id or nickname
|
|
||||||
* Parameters for POST request
|
|
||||||
* - name: name of the new list (the people tag itself)
|
|
||||||
* - mode: (optional) mode for the new list private/public
|
|
||||||
* - description: (optional) description for the list
|
|
||||||
*
|
|
||||||
* @return boolean success flag
|
|
||||||
*/
|
|
||||||
protected function prepare(array $args=array())
|
|
||||||
{
|
|
||||||
parent::prepare($args);
|
|
||||||
|
|
||||||
$this->create = ($_SERVER['REQUEST_METHOD'] == 'POST');
|
|
||||||
|
|
||||||
if (!$this->create) {
|
|
||||||
|
|
||||||
$this->user = $this->getTargetUser($this->arg('user'));
|
|
||||||
|
|
||||||
if (!($user instanceof User)) {
|
|
||||||
// TRANS: Client error displayed trying to perform an action related to a non-existing user.
|
|
||||||
$this->clientError(_('No such user.'), 404);
|
|
||||||
}
|
|
||||||
$this->target = $user->getProfile();
|
|
||||||
$this->getLists();
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* require authentication if it is a write action or user is ambiguous
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
function requiresAuth()
|
|
||||||
{
|
|
||||||
return parent::requiresAuth() ||
|
|
||||||
$this->create || $this->delete;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle request:
|
|
||||||
* Show the lists the user has created if the request method is GET
|
|
||||||
* Create a new list by diferring to handlePost() if it is POST.
|
|
||||||
*/
|
|
||||||
protected function handle()
|
|
||||||
{
|
|
||||||
parent::handle();
|
|
||||||
|
|
||||||
if($this->create) {
|
|
||||||
return $this->handlePost();
|
|
||||||
}
|
|
||||||
|
|
||||||
switch($this->format) {
|
|
||||||
case 'xml':
|
|
||||||
$this->showXmlLists($this->lists, $this->next_cursor, $this->prev_cursor);
|
|
||||||
break;
|
|
||||||
case 'json':
|
|
||||||
$this->showJsonLists($this->lists, $this->next_cursor, $this->prev_cursor);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
$this->clientError(
|
|
||||||
// TRANS: Client error displayed when coming across a non-supported API method.
|
|
||||||
_('API method not found.'),
|
|
||||||
404,
|
|
||||||
$this->format
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new list
|
|
||||||
*
|
|
||||||
* @return boolean success
|
|
||||||
*/
|
|
||||||
function handlePost()
|
|
||||||
{
|
|
||||||
$name=$this->arg('name');
|
|
||||||
if(empty($name)) {
|
|
||||||
// mimick twitter
|
|
||||||
// TRANS: Client error displayed when trying to create a list without a name.
|
|
||||||
print _("A list must have a name.");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// twitter creates a new list by appending a number to the end
|
|
||||||
// if the list by the given name already exists
|
|
||||||
// it makes more sense to return the existing list instead
|
|
||||||
|
|
||||||
$private = null;
|
|
||||||
if ($this->arg('mode') === 'public') {
|
|
||||||
$private = false;
|
|
||||||
} else if ($this->arg('mode') === 'private') {
|
|
||||||
$private = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
$list = Profile_list::ensureTag($this->auth_user->id,
|
|
||||||
$this->arg('name'),
|
|
||||||
$this->arg('description'),
|
|
||||||
$private);
|
|
||||||
if (empty($list)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch($this->format) {
|
|
||||||
case 'xml':
|
|
||||||
$this->showSingleXmlList($list);
|
|
||||||
break;
|
|
||||||
case 'json':
|
|
||||||
$this->showSingleJsonList($list);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// TRANS: Client error displayed when coming across a non-supported API method.
|
|
||||||
$this->clientError(_('API method not found.'), 404);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get lists
|
|
||||||
*/
|
|
||||||
function getLists()
|
|
||||||
{
|
|
||||||
$cursor = (int) $this->arg('cursor', -1);
|
|
||||||
|
|
||||||
// twitter fixes count at 20
|
|
||||||
// there is no argument named count
|
|
||||||
$count = 20;
|
|
||||||
$fn = array($this->target, 'getLists');
|
|
||||||
|
|
||||||
list($this->lists,
|
|
||||||
$this->next_cursor,
|
|
||||||
$this->prev_cursor) = Profile_list::getAtCursor($fn, array($this->auth_user), $cursor, $count);
|
|
||||||
}
|
|
||||||
|
|
||||||
function isReadOnly($args)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function lastModified()
|
|
||||||
{
|
|
||||||
if (!$this->create && !empty($this->lists) && (count($this->lists) > 0)) {
|
|
||||||
return strtotime($this->lists[0]->created);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An entity tag for this list of lists
|
|
||||||
*
|
|
||||||
* Returns an Etag based on the action name, language, user ID and
|
|
||||||
* timestamps of the first and last list the user has joined
|
|
||||||
*
|
|
||||||
* @return string etag
|
|
||||||
*/
|
|
||||||
function etag()
|
|
||||||
{
|
|
||||||
if (!$this->create && !empty($this->lists) && (count($this->lists) > 0)) {
|
|
||||||
|
|
||||||
$last = count($this->lists) - 1;
|
|
||||||
|
|
||||||
return '"' . implode(
|
|
||||||
':',
|
|
||||||
array($this->arg('action'),
|
|
||||||
common_language(),
|
|
||||||
$this->target->id,
|
|
||||||
strtotime($this->lists[0]->created),
|
|
||||||
strtotime($this->lists[$last]->created))
|
|
||||||
)
|
|
||||||
. '"';
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,87 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StatusNet, the distributed open-source microblogging tool
|
|
||||||
*
|
|
||||||
* Check if a user is subscribed to a list
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('STATUSNET')) {
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
class ApiListSubscriberAction extends ApiBareAuthAction
|
|
||||||
{
|
|
||||||
var $list = null;
|
|
||||||
|
|
||||||
function prepare($args)
|
|
||||||
{
|
|
||||||
parent::prepare($args);
|
|
||||||
|
|
||||||
$this->target = $this->getTargetProfile($this->arg('id'));
|
|
||||||
$this->list = $this->getTargetList($this->arg('user'), $this->arg('list_id'));
|
|
||||||
|
|
||||||
if (empty($this->list)) {
|
|
||||||
// TRANS: Client error displayed trying to perform an action related to a non-existing list.
|
|
||||||
$this->clientError(_('List not found.'), 404);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!($this->target instanceof Profile)) {
|
|
||||||
// TRANS: Client error displayed trying to perform an action related to a non-existing user.
|
|
||||||
$this->clientError(_('No such user.'), 404);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function handle($args)
|
|
||||||
{
|
|
||||||
parent::handle($args);
|
|
||||||
|
|
||||||
$arr = array('profile_tag_id' => $this->list->id,
|
|
||||||
'profile_id' => $this->target->id);
|
|
||||||
$sub = Profile_tag_subscription::pkeyGet($arr);
|
|
||||||
|
|
||||||
if(empty($sub)) {
|
|
||||||
// TRANS: Client error displayed when a membership check for a user is nagative.
|
|
||||||
$this->clientError(_('The specified user is not a subscriber of this list.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$user = $this->twitterUserArray($this->target, true);
|
|
||||||
|
|
||||||
switch($this->format) {
|
|
||||||
case 'xml':
|
|
||||||
$this->showTwitterXmlUser($user, 'user', true);
|
|
||||||
break;
|
|
||||||
case 'json':
|
|
||||||
$this->showSingleJsonUser($user);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
$this->clientError(
|
|
||||||
// TRANS: Client error displayed when coming across a non-supported API method.
|
|
||||||
_('API method not found.'),
|
|
||||||
404,
|
|
||||||
$this->format
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,102 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StatusNet, the distributed open-source microblogging tool
|
|
||||||
*
|
|
||||||
* Show/add/remove list subscribers.
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('STATUSNET')) {
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
require_once INSTALLDIR . '/lib/apilistusers.php';
|
|
||||||
|
|
||||||
class ApiListSubscribersAction extends ApiListUsersAction
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Subscribe to list
|
|
||||||
*
|
|
||||||
* @return boolean success
|
|
||||||
*/
|
|
||||||
function handlePost()
|
|
||||||
{
|
|
||||||
$result = Profile_tag_subscription::add($this->list,
|
|
||||||
$this->auth_user);
|
|
||||||
|
|
||||||
if(empty($result)) {
|
|
||||||
// TRANS: Client error displayed when an unknown error occurs in the list subscribers action.
|
|
||||||
$this->clientError(_('An error occured.'), 500);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch($this->format) {
|
|
||||||
case 'xml':
|
|
||||||
$this->showSingleXmlList($this->list);
|
|
||||||
break;
|
|
||||||
case 'json':
|
|
||||||
$this->showSingleJsonList($this->list);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// TRANS: Client error displayed when coming across a non-supported API method.
|
|
||||||
$this->clientError(_('API method not found.'), 404);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleDelete()
|
|
||||||
{
|
|
||||||
$args = array('profile_tag_id' => $this->list->id,
|
|
||||||
'profile_id' => $this->auth_user->id);
|
|
||||||
$ptag = Profile_tag_subscription::pkeyGet($args);
|
|
||||||
|
|
||||||
if(empty($ptag)) {
|
|
||||||
// TRANS: Client error displayed when trying to unsubscribe from a non-subscribed list.
|
|
||||||
$this->clientError(_('You are not subscribed to this list.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$result = Profile_tag_subscription::remove($this->list, $this->auth_user);
|
|
||||||
|
|
||||||
if (empty($result)) {
|
|
||||||
// TRANS: Client error displayed when an unknown error occurs unsubscribing from a list.
|
|
||||||
$this->clientError(_('An error occured.'), 500);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch($this->format) {
|
|
||||||
case 'xml':
|
|
||||||
$this->showSingleXmlList($this->list);
|
|
||||||
break;
|
|
||||||
case 'json':
|
|
||||||
$this->showSingleJsonList($this->list);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// TRANS: Client error displayed when coming across a non-supported API method.
|
|
||||||
$this->clientError(_('API method not found.'), 404);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getUsers()
|
|
||||||
{
|
|
||||||
$fn = array($this->list, 'getSubscribers');
|
|
||||||
list($this->users, $this->next_cursor, $this->prev_cursor) =
|
|
||||||
Profile_list::getAtCursor($fn, array(), $this->cursor, 20);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,110 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StatusNet, the distributed open-source microblogging tool
|
|
||||||
*
|
|
||||||
* Get a list of lists a user is subscribed to.
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @copyright 2009 StatusNet, Inc.
|
|
||||||
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('STATUSNET')) {
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
class ApiListSubscriptionsAction extends ApiBareAuthAction
|
|
||||||
{
|
|
||||||
var $lists = array();
|
|
||||||
var $cursor = -1;
|
|
||||||
var $next_cursor = 0;
|
|
||||||
var $prev_cursor = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Take arguments for running
|
|
||||||
*
|
|
||||||
* @param array $args $_REQUEST args
|
|
||||||
*
|
|
||||||
* @return boolean success flag
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
protected function prepare(array $args=array())
|
|
||||||
{
|
|
||||||
parent::prepare($args);
|
|
||||||
|
|
||||||
$this->cursor = (int) $this->arg('cursor', -1);
|
|
||||||
$user = $this->getTargetUser($this->arg('user'));
|
|
||||||
if (!($user instanceof User)) {
|
|
||||||
// TRANS: Client error displayed trying to perform an action related to a non-existing user.
|
|
||||||
$this->clientError(_('No such user.'), 404);
|
|
||||||
}
|
|
||||||
$this->target = $user->getProfile();
|
|
||||||
$this->getLists();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle the request
|
|
||||||
*
|
|
||||||
* Show the lists
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
protected function handle()
|
|
||||||
{
|
|
||||||
parent::handle();
|
|
||||||
|
|
||||||
switch($this->format) {
|
|
||||||
case 'xml':
|
|
||||||
$this->showXmlLists($this->lists, $this->next_cursor, $this->prev_cursor);
|
|
||||||
break;
|
|
||||||
case 'json':
|
|
||||||
$this->showJsonLists($this->lists, $this->next_cursor, $this->prev_cursor);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// TRANS: Client error displayed when coming across a non-supported API method.
|
|
||||||
$this->clientError(_('API method not found.'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return true if read only.
|
|
||||||
*
|
|
||||||
* MAY override
|
|
||||||
*
|
|
||||||
* @param array $args other arguments
|
|
||||||
*
|
|
||||||
* @return boolean is read only action?
|
|
||||||
*/
|
|
||||||
function isReadOnly($args)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getLists()
|
|
||||||
{
|
|
||||||
$fn = array($this->target, 'getTagSubscriptions');
|
|
||||||
# 20 lists
|
|
||||||
list($this->lists, $this->next_cursor, $this->prev_cursor) =
|
|
||||||
Profile_list::getAtCursor($fn, array(), $this->cursor, 20);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,118 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StatusNet, the distributed open-source microblogging tool
|
|
||||||
*
|
|
||||||
* Upload an image via the API
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @copyright 2010 StatusNet, Inc.
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('GNUSOCIAL')) { exit(1); }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Upload an image via the API. Returns a shortened URL for the image
|
|
||||||
* to the user.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
class ApiMediaUploadAction extends ApiAuthAction
|
|
||||||
{
|
|
||||||
protected $needPost = true;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle the request
|
|
||||||
*
|
|
||||||
* Grab the file from the 'media' param, then store, and shorten
|
|
||||||
*
|
|
||||||
* @todo Upload throttle!
|
|
||||||
*
|
|
||||||
* @param array $args $_REQUEST data (unused)
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
protected function handle()
|
|
||||||
{
|
|
||||||
parent::handle();
|
|
||||||
|
|
||||||
// Workaround for PHP returning empty $_POST and $_FILES when POST
|
|
||||||
// length > post_max_size in php.ini
|
|
||||||
|
|
||||||
if (empty($_FILES)
|
|
||||||
&& empty($_POST)
|
|
||||||
&& ($_SERVER['CONTENT_LENGTH'] > 0)
|
|
||||||
) {
|
|
||||||
// TRANS: Client error displayed when the number of bytes in a POST request exceeds a limit.
|
|
||||||
// TRANS: %s is the number of bytes of the CONTENT_LENGTH.
|
|
||||||
$msg = _m('The server was unable to handle that much POST data (%s byte) due to its current configuration.',
|
|
||||||
'The server was unable to handle that much POST data (%s bytes) due to its current configuration.',
|
|
||||||
intval($_SERVER['CONTENT_LENGTH']));
|
|
||||||
$this->clientError(sprintf($msg, $_SERVER['CONTENT_LENGTH']));
|
|
||||||
}
|
|
||||||
|
|
||||||
// we could catch "NoUploadedMediaException" as "no media uploaded", but here we _always_ want an upload
|
|
||||||
$upload = MediaFile::fromUpload('media', $this->scoped);
|
|
||||||
|
|
||||||
// Thumbnails will be generated/cached on demand when accessed (such as with /attachment/:id/thumbnail)
|
|
||||||
|
|
||||||
$this->showResponse($upload);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show a Twitpic-like response with the ID of the media file
|
|
||||||
* and a (hopefully) shortened URL for it.
|
|
||||||
*
|
|
||||||
* @param MediaFile $upload the uploaded file
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function showResponse(MediaFile $upload)
|
|
||||||
{
|
|
||||||
$this->initDocument();
|
|
||||||
$this->elementStart('rsp', array('stat' => 'ok'));
|
|
||||||
$this->element('mediaid', null, $upload->fileRecord->id);
|
|
||||||
$this->element('mediaurl', null, $upload->shortUrl());
|
|
||||||
$this->elementEnd('rsp');
|
|
||||||
$this->endDocument();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Overrided clientError to show a more Twitpic-like error
|
|
||||||
*
|
|
||||||
* @param String $msg an error message
|
|
||||||
*/
|
|
||||||
function clientError($msg)
|
|
||||||
{
|
|
||||||
$this->initDocument();
|
|
||||||
$this->elementStart('rsp', array('stat' => 'fail'));
|
|
||||||
|
|
||||||
// @todo add in error code
|
|
||||||
$errAttr = array('msg' => $msg);
|
|
||||||
|
|
||||||
$this->element('err', $errAttr, null);
|
|
||||||
$this->elementEnd('rsp');
|
|
||||||
$this->endDocument();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,122 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StatusNet, the distributed open-source microblogging tool
|
|
||||||
*
|
|
||||||
* Action for getting OAuth token credentials (exchange an authorized
|
|
||||||
* request token for an access token)
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @copyright 2010 StatusNet, Inc.
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('GNUSOCIAL')) { exit(1); }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Action for getting OAuth token credentials (exchange an authorized
|
|
||||||
* request token for an access token)
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
class ApiOAuthAccessTokenAction extends ApiOAuthAction
|
|
||||||
{
|
|
||||||
protected $reqToken = null;
|
|
||||||
protected $verifier = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class handler.
|
|
||||||
*
|
|
||||||
* @param array $args array of arguments
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function handle($args)
|
|
||||||
{
|
|
||||||
parent::handle($args);
|
|
||||||
|
|
||||||
$datastore = new ApiGNUsocialOAuthDataStore();
|
|
||||||
$server = new OAuthServer($datastore);
|
|
||||||
$hmac_method = new OAuthSignatureMethod_HMAC_SHA1();
|
|
||||||
|
|
||||||
$server->add_signature_method($hmac_method);
|
|
||||||
|
|
||||||
$atok = $app = null;
|
|
||||||
|
|
||||||
// XXX: Insist that oauth_token and oauth_verifier be populated?
|
|
||||||
// Spec doesn't say they MUST be.
|
|
||||||
|
|
||||||
try {
|
|
||||||
$req = OAuthRequest::from_request();
|
|
||||||
|
|
||||||
$this->reqToken = $req->get_parameter('oauth_token');
|
|
||||||
$this->verifier = $req->get_parameter('oauth_verifier');
|
|
||||||
|
|
||||||
$app = $datastore->getAppByRequestToken($this->reqToken);
|
|
||||||
$atok = $server->fetch_access_token($req);
|
|
||||||
} catch (Exception $e) {
|
|
||||||
common_log(LOG_WARNING, 'API OAuthException - ' . $e->getMessage());
|
|
||||||
common_debug(var_export($req, true));
|
|
||||||
$code = $e->getCode();
|
|
||||||
$this->clientError($e->getMessage(), empty($code) ? 401 : $code, 'text');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (empty($atok)) {
|
|
||||||
// Token exchange failed -- log it
|
|
||||||
|
|
||||||
$msg = sprintf(
|
|
||||||
'API OAuth - Failure exchanging OAuth request token for access token, '
|
|
||||||
. 'request token = %s, verifier = %s',
|
|
||||||
$this->reqToken,
|
|
||||||
$this->verifier
|
|
||||||
);
|
|
||||||
|
|
||||||
common_log(LOG_WARNING, $msg);
|
|
||||||
// TRANS: Client error given from the OAuth API when the request token or verifier is invalid.
|
|
||||||
$this->clientError(_('Invalid request token or verifier.'), 400, 'text');
|
|
||||||
} else {
|
|
||||||
common_log(
|
|
||||||
LOG_INFO,
|
|
||||||
sprintf(
|
|
||||||
"Issued access token '%s' for application %d (%s).",
|
|
||||||
$atok->key,
|
|
||||||
$app->id,
|
|
||||||
$app->name
|
|
||||||
)
|
|
||||||
);
|
|
||||||
$this->showAccessToken($atok);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Display OAuth token credentials
|
|
||||||
*
|
|
||||||
* @param OAuthToken token the access token
|
|
||||||
*/
|
|
||||||
function showAccessToken($token)
|
|
||||||
{
|
|
||||||
header('Content-Type: application/x-www-form-urlencoded');
|
|
||||||
print $token;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,707 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StatusNet, the distributed open-source microblogging tool
|
|
||||||
*
|
|
||||||
* Authorize an OAuth request token
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @copyright 2010-2011 StatusNet, Inc.
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('STATUSNET')) {
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Authorize an OAuth request token
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
class ApiOAuthAuthorizeAction extends ApiOAuthAction
|
|
||||||
{
|
|
||||||
var $oauthTokenParam;
|
|
||||||
var $reqToken;
|
|
||||||
var $callback;
|
|
||||||
var $app;
|
|
||||||
var $nickname;
|
|
||||||
var $password;
|
|
||||||
var $store;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Is this a read-only action?
|
|
||||||
*
|
|
||||||
* @return boolean false
|
|
||||||
*/
|
|
||||||
function isReadOnly($args)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function prepare($args)
|
|
||||||
{
|
|
||||||
parent::prepare($args);
|
|
||||||
|
|
||||||
$this->nickname = $this->trimmed('nickname');
|
|
||||||
$this->password = $this->arg('password');
|
|
||||||
$this->oauthTokenParam = $this->arg('oauth_token');
|
|
||||||
$this->mode = $this->arg('mode');
|
|
||||||
$this->store = new ApiGNUsocialOAuthDataStore();
|
|
||||||
|
|
||||||
try {
|
|
||||||
$this->app = $this->store->getAppByRequestToken($this->oauthTokenParam);
|
|
||||||
} catch (Exception $e) {
|
|
||||||
$this->clientError($e->getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle input, produce output
|
|
||||||
*
|
|
||||||
* Switches on request method; either shows the form or handles its input.
|
|
||||||
*
|
|
||||||
* @param array $args $_REQUEST data
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function handle($args)
|
|
||||||
{
|
|
||||||
parent::handle($args);
|
|
||||||
|
|
||||||
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
|
|
||||||
|
|
||||||
$this->handlePost();
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// Make sure a oauth_token parameter was provided
|
|
||||||
if (empty($this->oauthTokenParam)) {
|
|
||||||
// TRANS: Client error given when no oauth_token was passed to the OAuth API.
|
|
||||||
$this->clientError(_('No oauth_token parameter provided.'));
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// Check to make sure the token exists
|
|
||||||
$this->reqToken = $this->store->getTokenByKey($this->oauthTokenParam);
|
|
||||||
|
|
||||||
if (empty($this->reqToken)) {
|
|
||||||
// TRANS: Client error given when an invalid request token was passed to the OAuth API.
|
|
||||||
$this->clientError(_('Invalid request token.'));
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// Check to make sure we haven't already authorized the token
|
|
||||||
if ($this->reqToken->state != 0) {
|
|
||||||
// TRANS: Client error given when an invalid request token was passed to the OAuth API.
|
|
||||||
$this->clientError(_('Request token already authorized.'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// make sure there's an app associated with this token
|
|
||||||
if (empty($this->app)) {
|
|
||||||
// TRANS: Client error given when an invalid request token was passed to the OAuth API.
|
|
||||||
$this->clientError(_('Invalid request token.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$name = $this->app->name;
|
|
||||||
|
|
||||||
$this->showForm();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function handlePost()
|
|
||||||
{
|
|
||||||
// check session token for CSRF protection.
|
|
||||||
|
|
||||||
$token = $this->trimmed('token');
|
|
||||||
|
|
||||||
if (!$token || $token != common_session_token()) {
|
|
||||||
$this->showForm(
|
|
||||||
// TRANS: Form validation error in API OAuth authorisation because of an invalid session token.
|
|
||||||
_('There was a problem with your session token. Try again, please.'));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check creds
|
|
||||||
|
|
||||||
$user = null;
|
|
||||||
|
|
||||||
if (!common_logged_in()) {
|
|
||||||
|
|
||||||
// XXX Force credentials check?
|
|
||||||
|
|
||||||
// @fixme this should probably use a unified login form handler
|
|
||||||
$user = null;
|
|
||||||
if (Event::handle('StartOAuthLoginCheck', array($this, &$user))) {
|
|
||||||
$user = common_check_user($this->nickname, $this->password);
|
|
||||||
}
|
|
||||||
Event::handle('EndOAuthLoginCheck', array($this, &$user));
|
|
||||||
|
|
||||||
if (empty($user)) {
|
|
||||||
// TRANS: Form validation error given when an invalid username and/or password was passed to the OAuth API.
|
|
||||||
$this->showForm(_("Invalid nickname / password!"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$user = common_current_user();
|
|
||||||
}
|
|
||||||
|
|
||||||
// fetch the token
|
|
||||||
$this->reqToken = $this->store->getTokenByKey($this->oauthTokenParam);
|
|
||||||
assert(!empty($this->reqToken));
|
|
||||||
|
|
||||||
if ($this->arg('allow')) {
|
|
||||||
// mark the req token as authorized
|
|
||||||
try {
|
|
||||||
$this->store->authorize_token($this->oauthTokenParam);
|
|
||||||
} catch (Exception $e) {
|
|
||||||
$this->serverError($e->getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
common_log(
|
|
||||||
LOG_INFO,
|
|
||||||
sprintf(
|
|
||||||
"API OAuth - User %d (%s) has authorized request token %s for OAuth application %d (%s).",
|
|
||||||
$user->id,
|
|
||||||
$user->nickname,
|
|
||||||
$this->reqToken->tok,
|
|
||||||
$this->app->id,
|
|
||||||
$this->app->name
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
$tokenAssoc = new Oauth_token_association();
|
|
||||||
|
|
||||||
$tokenAssoc->profile_id = $user->id;
|
|
||||||
$tokenAssoc->application_id = $this->app->id;
|
|
||||||
$tokenAssoc->token = $this->oauthTokenParam;
|
|
||||||
$tokenAssoc->created = common_sql_now();
|
|
||||||
|
|
||||||
$result = $tokenAssoc->insert();
|
|
||||||
|
|
||||||
if (!$result) {
|
|
||||||
common_log_db_error($tokenAssoc, 'INSERT', __FILE__);
|
|
||||||
// TRANS: Server error displayed when a database action fails.
|
|
||||||
$this->serverError(_('Database error inserting oauth_token_association.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$callback = $this->getCallback();
|
|
||||||
|
|
||||||
if (!empty($callback) && $this->reqToken->verified_callback != 'oob') {
|
|
||||||
$targetUrl = $this->buildCallbackUrl(
|
|
||||||
$callback,
|
|
||||||
array(
|
|
||||||
'oauth_token' => $this->oauthTokenParam,
|
|
||||||
'oauth_verifier' => $this->reqToken->verifier // 1.0a
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
common_log(LOG_INFO, "Redirecting to callback: $targetUrl");
|
|
||||||
|
|
||||||
// Redirect the user to the provided OAuth callback
|
|
||||||
common_redirect($targetUrl, 303);
|
|
||||||
|
|
||||||
} elseif ($this->app->type == 2) {
|
|
||||||
// Strangely, a web application seems to want to do the OOB
|
|
||||||
// workflow. Because no callback was specified anywhere.
|
|
||||||
common_log(
|
|
||||||
LOG_WARNING,
|
|
||||||
sprintf(
|
|
||||||
"API OAuth - No callback provided for OAuth web client ID %s (%s) "
|
|
||||||
. "during authorization step. Falling back to OOB workflow.",
|
|
||||||
$this->app->id,
|
|
||||||
$this->app->name
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise, inform the user that the rt was authorized
|
|
||||||
$this->showAuthorized();
|
|
||||||
} else if ($this->arg('cancel')) {
|
|
||||||
common_log(
|
|
||||||
LOG_INFO,
|
|
||||||
sprintf(
|
|
||||||
"API OAuth - User %d (%s) refused to authorize request token %s for OAuth application %d (%s).",
|
|
||||||
$user->id,
|
|
||||||
$user->nickname,
|
|
||||||
$this->reqToken->tok,
|
|
||||||
$this->app->id,
|
|
||||||
$this->app->name
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
try {
|
|
||||||
$this->store->revoke_token($this->oauthTokenParam, 0);
|
|
||||||
} catch (Exception $e) {
|
|
||||||
$this->ServerError($e->getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
$callback = $this->getCallback();
|
|
||||||
|
|
||||||
// If there's a callback available, inform the consumer the user
|
|
||||||
// has refused authorization
|
|
||||||
if (!empty($callback) && $this->reqToken->verified_callback != 'oob') {
|
|
||||||
$targetUrl = $this->buildCallbackUrl(
|
|
||||||
$callback,
|
|
||||||
array(
|
|
||||||
'oauth_problem' => 'user_refused',
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
common_log(LOG_INFO, "Redirecting to callback: $targetUrl");
|
|
||||||
|
|
||||||
// Redirect the user to the provided OAuth callback
|
|
||||||
common_redirect($targetUrl, 303);
|
|
||||||
}
|
|
||||||
|
|
||||||
// otherwise inform the user that authorization for the rt was declined
|
|
||||||
$this->showCanceled();
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// TRANS: Client error given on when invalid data was passed through a form in the OAuth API.
|
|
||||||
$this->clientError(_('Unexpected form submission.'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show body - override to add a special CSS class for the authorize
|
|
||||||
* page's "desktop mode" (minimal display)
|
|
||||||
*
|
|
||||||
* Calls template methods
|
|
||||||
*
|
|
||||||
* @return nothing
|
|
||||||
*/
|
|
||||||
function showBody()
|
|
||||||
{
|
|
||||||
$bodyClasses = array();
|
|
||||||
|
|
||||||
if ($this->desktopMode()) {
|
|
||||||
$bodyClasses[] = 'oauth-desktop-mode';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (common_current_user()) {
|
|
||||||
$bodyClasses[] = 'user_in';
|
|
||||||
}
|
|
||||||
|
|
||||||
$attrs = array('id' => strtolower($this->trimmed('action')));
|
|
||||||
|
|
||||||
if (!empty($bodyClasses)) {
|
|
||||||
$attrs['class'] = implode(' ', $bodyClasses);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->elementStart('body', $attrs);
|
|
||||||
|
|
||||||
$this->elementStart('div', array('id' => 'wrap'));
|
|
||||||
if (Event::handle('StartShowHeader', array($this))) {
|
|
||||||
$this->showHeader();
|
|
||||||
Event::handle('EndShowHeader', array($this));
|
|
||||||
}
|
|
||||||
$this->showCore();
|
|
||||||
if (Event::handle('StartShowFooter', array($this))) {
|
|
||||||
$this->showFooter();
|
|
||||||
Event::handle('EndShowFooter', array($this));
|
|
||||||
}
|
|
||||||
$this->elementEnd('div');
|
|
||||||
$this->showScripts();
|
|
||||||
$this->elementEnd('body');
|
|
||||||
}
|
|
||||||
|
|
||||||
function showForm($error=null)
|
|
||||||
{
|
|
||||||
$this->error = $error;
|
|
||||||
$this->showPage();
|
|
||||||
}
|
|
||||||
|
|
||||||
function showScripts()
|
|
||||||
{
|
|
||||||
parent::showScripts();
|
|
||||||
if (!common_logged_in()) {
|
|
||||||
$this->autofocus('nickname');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Title of the page
|
|
||||||
*
|
|
||||||
* @return string title of the page
|
|
||||||
*/
|
|
||||||
function title()
|
|
||||||
{
|
|
||||||
// TRANS: Title for a page where a user can confirm/deny account access by an external application.
|
|
||||||
return _('An application would like to connect to your account');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Shows the authorization form.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function showContent()
|
|
||||||
{
|
|
||||||
$this->elementStart('form', array('method' => 'post',
|
|
||||||
'id' => 'form_apioauthauthorize',
|
|
||||||
'class' => 'form_settings',
|
|
||||||
'action' => common_local_url('ApiOAuthAuthorize')));
|
|
||||||
$this->elementStart('fieldset');
|
|
||||||
$this->element('legend', array('id' => 'apioauthauthorize_allowdeny'),
|
|
||||||
// TRANS: Fieldset legend.
|
|
||||||
_('Allow or deny access'));
|
|
||||||
|
|
||||||
$this->hidden('token', common_session_token());
|
|
||||||
$this->hidden('mode', $this->mode);
|
|
||||||
$this->hidden('oauth_token', $this->oauthTokenParam);
|
|
||||||
$this->hidden('oauth_callback', $this->callback);
|
|
||||||
|
|
||||||
$this->elementStart('ul', 'form_data');
|
|
||||||
$this->elementStart('li');
|
|
||||||
$this->elementStart('p');
|
|
||||||
if (!empty($this->app->icon) && $this->app->name != 'anonymous') {
|
|
||||||
$this->element('img', array('src' => $this->app->icon));
|
|
||||||
}
|
|
||||||
|
|
||||||
$access = ($this->app->access_type & Oauth_application::$writeAccess) ?
|
|
||||||
'access and update' : 'access';
|
|
||||||
|
|
||||||
if ($this->app->name == 'anonymous') {
|
|
||||||
// Special message for the anonymous app and consumer.
|
|
||||||
// TRANS: User notification of external application requesting account access.
|
|
||||||
// TRANS: %3$s is the access type requested (read-write or read-only), %4$s is the StatusNet sitename.
|
|
||||||
$msg = _('An application would like the ability ' .
|
|
||||||
'to <strong>%3$s</strong> your %4$s account data. ' .
|
|
||||||
'You should only give access to your %4$s account ' .
|
|
||||||
'to third parties you trust.');
|
|
||||||
} else {
|
|
||||||
// TRANS: User notification of external application requesting account access.
|
|
||||||
// TRANS: %1$s is the application name requesting access, %2$s is the organisation behind the application,
|
|
||||||
// TRANS: %3$s is the access type requested, %4$s is the StatusNet sitename.
|
|
||||||
$msg = _('The application <strong>%1$s</strong> by ' .
|
|
||||||
'<strong>%2$s</strong> would like the ability ' .
|
|
||||||
'to <strong>%3$s</strong> your %4$s account data. ' .
|
|
||||||
'You should only give access to your %4$s account ' .
|
|
||||||
'to third parties you trust.');
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->raw(sprintf($msg,
|
|
||||||
$this->app->name,
|
|
||||||
$this->app->organization,
|
|
||||||
$access,
|
|
||||||
common_config('site', 'name')));
|
|
||||||
$this->elementEnd('p');
|
|
||||||
$this->elementEnd('li');
|
|
||||||
$this->elementEnd('ul');
|
|
||||||
|
|
||||||
// quickie hack
|
|
||||||
$button = false;
|
|
||||||
if (!common_logged_in()) {
|
|
||||||
if (Event::handle('StartOAuthLoginForm', array($this, &$button))) {
|
|
||||||
$this->elementStart('fieldset');
|
|
||||||
// TRANS: Fieldset legend.
|
|
||||||
$this->element('legend', null, _m('LEGEND','Account'));
|
|
||||||
$this->elementStart('ul', 'form_data');
|
|
||||||
$this->elementStart('li');
|
|
||||||
// TRANS: Field label on OAuth API authorisation form.
|
|
||||||
$this->input('nickname', _('Nickname'));
|
|
||||||
$this->elementEnd('li');
|
|
||||||
$this->elementStart('li');
|
|
||||||
// TRANS: Field label on OAuth API authorisation form.
|
|
||||||
$this->password('password', _('Password'));
|
|
||||||
$this->elementEnd('li');
|
|
||||||
$this->elementEnd('ul');
|
|
||||||
|
|
||||||
$this->elementEnd('fieldset');
|
|
||||||
}
|
|
||||||
Event::handle('EndOAuthLoginForm', array($this, &$button));
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->element('input', array('id' => 'cancel_submit',
|
|
||||||
'class' => 'submit submit form_action-primary',
|
|
||||||
'name' => 'cancel',
|
|
||||||
'type' => 'submit',
|
|
||||||
// TRANS: Button text that when clicked will cancel the process of allowing access to an account
|
|
||||||
// TRANS: by an external application.
|
|
||||||
'value' => _m('BUTTON','Cancel')));
|
|
||||||
|
|
||||||
$this->element('input', array('id' => 'allow_submit',
|
|
||||||
'class' => 'submit submit form_action-secondary',
|
|
||||||
'name' => 'allow',
|
|
||||||
'type' => 'submit',
|
|
||||||
// TRANS: Button text that when clicked will allow access to an account by an external application.
|
|
||||||
'value' => $button ? $button : _m('BUTTON','Allow')));
|
|
||||||
|
|
||||||
$this->elementEnd('fieldset');
|
|
||||||
$this->elementEnd('form');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Instructions for using the form
|
|
||||||
*
|
|
||||||
* For "remembered" logins, we make the user re-login when they
|
|
||||||
* try to change settings. Different instructions for this case.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function getInstructions()
|
|
||||||
{
|
|
||||||
// TRANS: Form instructions.
|
|
||||||
return _('Authorize access to your account information.');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A local menu
|
|
||||||
*
|
|
||||||
* Shows different login/register actions.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function showLocalNav()
|
|
||||||
{
|
|
||||||
// NOP
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Checks to see if a the "mode" parameter is present in the request
|
|
||||||
* and set to "desktop". If it is, the page is meant to be displayed in
|
|
||||||
* a small frame of another application, and we should suppress the
|
|
||||||
* header, aside, and footer.
|
|
||||||
*/
|
|
||||||
function desktopMode()
|
|
||||||
{
|
|
||||||
if (isset($this->mode) && $this->mode == 'desktop') {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Override - suppress output in "desktop" mode
|
|
||||||
*/
|
|
||||||
function showHeader()
|
|
||||||
{
|
|
||||||
if ($this->desktopMode() == false) {
|
|
||||||
parent::showHeader();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Override - suppress output in "desktop" mode
|
|
||||||
*/
|
|
||||||
function showAside()
|
|
||||||
{
|
|
||||||
if ($this->desktopMode() == false) {
|
|
||||||
parent::showAside();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Override - suppress output in "desktop" mode
|
|
||||||
*/
|
|
||||||
function showFooter()
|
|
||||||
{
|
|
||||||
if ($this->desktopMode() == false) {
|
|
||||||
parent::showFooter();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show site notice.
|
|
||||||
*
|
|
||||||
* @return nothing
|
|
||||||
*/
|
|
||||||
function showSiteNotice()
|
|
||||||
{
|
|
||||||
// NOP
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show notice form.
|
|
||||||
*
|
|
||||||
* Show the form for posting a new notice
|
|
||||||
*
|
|
||||||
* @return nothing
|
|
||||||
*/
|
|
||||||
function showNoticeForm()
|
|
||||||
{
|
|
||||||
// NOP
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Show a nice message confirming the authorization
|
|
||||||
* operation was canceled.
|
|
||||||
*
|
|
||||||
* @return nothing
|
|
||||||
*/
|
|
||||||
function showCanceled()
|
|
||||||
{
|
|
||||||
$info = new InfoAction(
|
|
||||||
// TRANS: Header for user notification after revoking OAuth access to an application.
|
|
||||||
_('Authorization canceled.'),
|
|
||||||
sprintf(
|
|
||||||
// TRANS: User notification after revoking OAuth access to an application.
|
|
||||||
// TRANS: %s is an OAuth token.
|
|
||||||
_('The request token %s has been revoked.'),
|
|
||||||
$this->oauthTokenParam
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
$info->showPage();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Show a nice message that the authorization was successful.
|
|
||||||
* If the operation is out-of-band, show a pin.
|
|
||||||
*
|
|
||||||
* @return nothing
|
|
||||||
*/
|
|
||||||
function showAuthorized()
|
|
||||||
{
|
|
||||||
$title = null;
|
|
||||||
$msg = null;
|
|
||||||
|
|
||||||
if ($this->app->name == 'anonymous') {
|
|
||||||
|
|
||||||
$title =
|
|
||||||
// TRANS: Title of the page notifying the user that an anonymous client application was successfully authorized to access the user's account with OAuth.
|
|
||||||
_('You have successfully authorized the application');
|
|
||||||
|
|
||||||
$msg =
|
|
||||||
// TRANS: Message notifying the user that an anonymous client application was successfully authorized to access the user's account with OAuth.
|
|
||||||
_('Please return to the application and enter the following security code to complete the process.');
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
$title = sprintf(
|
|
||||||
// TRANS: Title of the page notifying the user that the client application was successfully authorized to access the user's account with OAuth.
|
|
||||||
// TRANS: %s is the authorised application name.
|
|
||||||
_('You have successfully authorized %s'),
|
|
||||||
$this->app->name
|
|
||||||
);
|
|
||||||
|
|
||||||
$msg = sprintf(
|
|
||||||
// TRANS: Message notifying the user that the client application was successfully authorized to access the user's account with OAuth.
|
|
||||||
// TRANS: %s is the authorised application name.
|
|
||||||
_('Please return to %s and enter the following security code to complete the process.'),
|
|
||||||
$this->app->name
|
|
||||||
);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->reqToken->verified_callback == 'oob') {
|
|
||||||
$pin = new ApiOAuthPinAction(
|
|
||||||
$title,
|
|
||||||
$msg,
|
|
||||||
$this->reqToken->verifier,
|
|
||||||
$this->desktopMode()
|
|
||||||
);
|
|
||||||
$pin->showPage();
|
|
||||||
} else {
|
|
||||||
// NOTE: This would only happen if an application registered as
|
|
||||||
// a web application but sent in 'oob' for the oauth_callback
|
|
||||||
// parameter. Usually web apps will send in a callback and
|
|
||||||
// not use the pin-based workflow.
|
|
||||||
|
|
||||||
$info = new InfoAction(
|
|
||||||
$title,
|
|
||||||
$msg,
|
|
||||||
$this->oauthTokenParam,
|
|
||||||
$this->reqToken->verifier
|
|
||||||
);
|
|
||||||
|
|
||||||
$info->showPage();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Figure out what the callback should be
|
|
||||||
*/
|
|
||||||
function getCallback()
|
|
||||||
{
|
|
||||||
$callback = null;
|
|
||||||
|
|
||||||
// Return the verified callback if we have one
|
|
||||||
if ($this->reqToken->verified_callback != 'oob') {
|
|
||||||
|
|
||||||
$callback = $this->reqToken->verified_callback;
|
|
||||||
|
|
||||||
// Otherwise return the callback that was provided when
|
|
||||||
// registering the app
|
|
||||||
if (empty($callback)) {
|
|
||||||
|
|
||||||
common_debug(
|
|
||||||
"No verified callback found for request token, using application callback: "
|
|
||||||
. $this->app->callback_url,
|
|
||||||
__FILE__
|
|
||||||
);
|
|
||||||
|
|
||||||
$callback = $this->app->callback_url;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $callback;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Properly format the callback URL and parameters so it's
|
|
||||||
* suitable for a redirect in the OAuth dance
|
|
||||||
*
|
|
||||||
* @param string $url the URL
|
|
||||||
* @param array $params an array of parameters
|
|
||||||
*
|
|
||||||
* @return string $url a URL to use for redirecting to
|
|
||||||
*/
|
|
||||||
function buildCallbackUrl($url, $params)
|
|
||||||
{
|
|
||||||
foreach ($params as $k => $v) {
|
|
||||||
$url = $this->appendQueryVar(
|
|
||||||
$url,
|
|
||||||
OAuthUtil::urlencode_rfc3986($k),
|
|
||||||
OAuthUtil::urlencode_rfc3986($v)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $url;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Append a new query parameter after any existing query
|
|
||||||
* parameters.
|
|
||||||
*
|
|
||||||
* @param string $url the URL
|
|
||||||
* @prarm string $k the parameter name
|
|
||||||
* @param string $v value of the paramter
|
|
||||||
*
|
|
||||||
* @return string $url the new URL with added parameter
|
|
||||||
*/
|
|
||||||
function appendQueryVar($url, $k, $v) {
|
|
||||||
$url = preg_replace('/(.*)(\?|&)' . $k . '=[^&]+?(&)(.*)/i', '$1$2$4', $url . '&');
|
|
||||||
$url = substr($url, 0, -1);
|
|
||||||
if (strpos($url, '?') === false) {
|
|
||||||
return ($url . '?' . $k . '=' . $v);
|
|
||||||
} else {
|
|
||||||
return ($url . '&' . $k . '=' . $v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,172 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StatusNet, the distributed open-source microblogging tool
|
|
||||||
*
|
|
||||||
* Action for displaying an OAuth verifier pin
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category Action
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @copyright 2010 StatusNet, Inc.
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('STATUSNET') && !defined('LACONICA')) {
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class for displaying an OAuth verifier pin
|
|
||||||
*
|
|
||||||
* XXX: I'm pretty sure we don't need to check the logged in state here. -- Zach
|
|
||||||
*
|
|
||||||
* @category Action
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
class ApiOAuthPinAction extends InfoAction
|
|
||||||
{
|
|
||||||
function __construct($title, $message, $verifier, $desktopMode = false)
|
|
||||||
{
|
|
||||||
$this->verifier = $verifier;
|
|
||||||
$this->title = $title;
|
|
||||||
$this->desktopMode = $desktopMode;
|
|
||||||
parent::__construct($title, $message);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show body - override to add a special CSS class for the pin pages's
|
|
||||||
* "desktop mode" (minimal display)
|
|
||||||
*
|
|
||||||
* Calls template methods
|
|
||||||
*
|
|
||||||
* @return nothing
|
|
||||||
*/
|
|
||||||
function showBody()
|
|
||||||
{
|
|
||||||
$bodyClasses = array();
|
|
||||||
|
|
||||||
if ($this->desktopMode) {
|
|
||||||
$bodyClasses[] = 'oauth-desktop-mode';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (common_current_user()) {
|
|
||||||
$bodyClasses[] = 'user_in';
|
|
||||||
}
|
|
||||||
|
|
||||||
$attrs = array('id' => strtolower($this->trimmed('action')));
|
|
||||||
|
|
||||||
if (!empty($bodyClasses)) {
|
|
||||||
$attrs['class'] = implode(' ', $bodyClasses);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->elementStart('body', $attrs);
|
|
||||||
|
|
||||||
$this->elementStart('div', array('id' => 'wrap'));
|
|
||||||
if (Event::handle('StartShowHeader', array($this))) {
|
|
||||||
$this->showHeader();
|
|
||||||
Event::handle('EndShowHeader', array($this));
|
|
||||||
}
|
|
||||||
$this->showCore();
|
|
||||||
if (Event::handle('StartShowFooter', array($this))) {
|
|
||||||
$this->showFooter();
|
|
||||||
Event::handle('EndShowFooter', array($this));
|
|
||||||
}
|
|
||||||
$this->elementEnd('div');
|
|
||||||
$this->showScripts();
|
|
||||||
$this->elementEnd('body');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A local menu
|
|
||||||
*
|
|
||||||
* Shows different login/register actions.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function showLocalNav()
|
|
||||||
{
|
|
||||||
// NOP
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Override - suppress output in "desktop" mode
|
|
||||||
*/
|
|
||||||
function showHeader()
|
|
||||||
{
|
|
||||||
if ($this->desktopMode == false) {
|
|
||||||
parent::showHeader();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Override - suppress output in "desktop" mode
|
|
||||||
*/
|
|
||||||
function showAside()
|
|
||||||
{
|
|
||||||
if ($this->desktopMode == false) {
|
|
||||||
parent::showAside();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Override - suppress output in "desktop" mode
|
|
||||||
*/
|
|
||||||
function showFooter()
|
|
||||||
{
|
|
||||||
if ($this->desktopMode == false) {
|
|
||||||
parent::showFooter();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show site notice.
|
|
||||||
*
|
|
||||||
* @return nothing
|
|
||||||
*/
|
|
||||||
function showSiteNotice()
|
|
||||||
{
|
|
||||||
// NOP
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show notice form.
|
|
||||||
*
|
|
||||||
* Show the form for posting a new notice
|
|
||||||
*
|
|
||||||
* @return nothing
|
|
||||||
*/
|
|
||||||
function showNoticeForm()
|
|
||||||
{
|
|
||||||
// NOP
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Display content.
|
|
||||||
*
|
|
||||||
* @return nothing
|
|
||||||
*/
|
|
||||||
function showContent()
|
|
||||||
{
|
|
||||||
$this->element('div', array('class' => 'info'), $this->message);
|
|
||||||
$this->element('div', array('id' => 'oauth_pin'), $this->verifier);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,152 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StatusNet, the distributed open-source microblogging tool
|
|
||||||
*
|
|
||||||
* Issue temporary OAuth credentials (a request token)
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @copyright 2010 StatusNet, Inc.
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('STATUSNET')) {
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Issue temporary OAuth credentials (a request token)
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
class ApiOAuthRequestTokenAction extends ApiOAuthAction
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Take arguments for running
|
|
||||||
*
|
|
||||||
* @param array $args $_REQUEST args
|
|
||||||
*
|
|
||||||
* @return boolean success flag
|
|
||||||
*/
|
|
||||||
function prepare($args)
|
|
||||||
{
|
|
||||||
parent::prepare($args);
|
|
||||||
|
|
||||||
// XXX: support "force_login" parameter like Twitter? (Forces the user to enter
|
|
||||||
// their credentials to ensure the correct users account is authorized.)
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle a request for temporary OAuth credentials
|
|
||||||
*
|
|
||||||
* Make sure the request is kosher, then emit a set of temporary
|
|
||||||
* credentials -- AKA an unauthorized request token.
|
|
||||||
*
|
|
||||||
* @param array $args array of arguments
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function handle($args)
|
|
||||||
{
|
|
||||||
parent::handle($args);
|
|
||||||
|
|
||||||
$datastore = new ApiGNUsocialOAuthDataStore();
|
|
||||||
$server = new OAuthServer($datastore);
|
|
||||||
$hmac_method = new OAuthSignatureMethod_HMAC_SHA1();
|
|
||||||
|
|
||||||
$server->add_signature_method($hmac_method);
|
|
||||||
|
|
||||||
try {
|
|
||||||
|
|
||||||
$req = OAuthRequest::from_request();
|
|
||||||
|
|
||||||
// verify callback
|
|
||||||
if (!$this->verifyCallback($req->get_parameter('oauth_callback'))) {
|
|
||||||
throw new OAuthException(
|
|
||||||
"You must provide a valid URL or 'oob' in oauth_callback.",
|
|
||||||
400
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// check signature and issue a new request token
|
|
||||||
$token = $server->fetch_request_token($req);
|
|
||||||
|
|
||||||
common_log(
|
|
||||||
LOG_INFO,
|
|
||||||
sprintf(
|
|
||||||
"API OAuth - Issued request token %s for consumer %s with oauth_callback %s",
|
|
||||||
$token->key,
|
|
||||||
$req->get_parameter('oauth_consumer_key'),
|
|
||||||
"'" . $req->get_parameter('oauth_callback') ."'"
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
// return token to the client
|
|
||||||
$this->showRequestToken($token);
|
|
||||||
|
|
||||||
} catch (OAuthException $e) {
|
|
||||||
common_log(LOG_WARNING, 'API OAuthException - ' . $e->getMessage());
|
|
||||||
|
|
||||||
// Return 401 for for bad credentials or signature problems,
|
|
||||||
// and 400 for missing or unsupported parameters
|
|
||||||
|
|
||||||
$code = $e->getCode();
|
|
||||||
$this->clientError($e->getMessage(), empty($code) ? 401 : $code, 'text');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Display temporary OAuth credentials
|
|
||||||
*/
|
|
||||||
function showRequestToken($token)
|
|
||||||
{
|
|
||||||
header('Content-Type: application/x-www-form-urlencoded');
|
|
||||||
print $token;
|
|
||||||
print '&oauth_callback_confirmed=true';
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Make sure the callback parameter contains either a real URL
|
|
||||||
* or the string 'oob'.
|
|
||||||
*
|
|
||||||
* @todo Check for evil/banned URLs here
|
|
||||||
*
|
|
||||||
* @return boolean true or false
|
|
||||||
*/
|
|
||||||
function verifyCallback($callback)
|
|
||||||
{
|
|
||||||
if ($callback == "oob") {
|
|
||||||
common_debug("OAuth request token requested for out of band client.");
|
|
||||||
|
|
||||||
// XXX: Should we throw an error if a client is registered as a
|
|
||||||
// web application but requests the pin based workflow? For now I'm
|
|
||||||
// allowing the workflow to proceed and issuing a pin. --Zach
|
|
||||||
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return filter_var($callback, FILTER_VALIDATE_URL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,392 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StatusNet, the distributed open-source microblogging tool
|
|
||||||
*
|
|
||||||
* Action for showing Twitter-like Atom search results
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category Search
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @copyright 2008-2010 StatusNet, Inc.
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('STATUSNET') && !defined('LACONICA')) {
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Action for outputting search results in Twitter compatible Atom
|
|
||||||
* format.
|
|
||||||
*
|
|
||||||
* TODO: abstract Atom stuff into a ruseable base class like
|
|
||||||
* RSS10Action.
|
|
||||||
*
|
|
||||||
* @category Search
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*
|
|
||||||
* @see ApiPrivateAuthAction
|
|
||||||
*/
|
|
||||||
class ApiSearchAtomAction extends ApiPrivateAuthAction
|
|
||||||
{
|
|
||||||
var $cnt;
|
|
||||||
var $query;
|
|
||||||
var $lang;
|
|
||||||
var $rpp;
|
|
||||||
var $page;
|
|
||||||
var $since_id;
|
|
||||||
var $geocode;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor
|
|
||||||
*
|
|
||||||
* Just wraps the Action constructor.
|
|
||||||
*
|
|
||||||
* @param string $output URI to output to, default = stdout
|
|
||||||
* @param boolean $indent Whether to indent output, default true
|
|
||||||
*
|
|
||||||
* @see Action::__construct
|
|
||||||
*/
|
|
||||||
function __construct($output='php://output', $indent=null)
|
|
||||||
{
|
|
||||||
parent::__construct($output, $indent);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Do we need to write to the database?
|
|
||||||
*
|
|
||||||
* @return boolean true
|
|
||||||
*/
|
|
||||||
function isReadonly()
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read arguments and initialize members
|
|
||||||
*
|
|
||||||
* @param array $args Arguments from $_REQUEST
|
|
||||||
*
|
|
||||||
* @return boolean success
|
|
||||||
*/
|
|
||||||
function prepare($args)
|
|
||||||
{
|
|
||||||
parent::prepare($args);
|
|
||||||
|
|
||||||
$this->query = $this->trimmed('q');
|
|
||||||
$this->lang = $this->trimmed('lang');
|
|
||||||
$this->rpp = $this->trimmed('rpp');
|
|
||||||
|
|
||||||
if (!$this->rpp) {
|
|
||||||
$this->rpp = 15;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->rpp > 100) {
|
|
||||||
$this->rpp = 100;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->page = $this->trimmed('page');
|
|
||||||
|
|
||||||
if (!$this->page) {
|
|
||||||
$this->page = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Suppport max_id -- we need to tweak the backend
|
|
||||||
// Search classes to support it.
|
|
||||||
|
|
||||||
$this->since_id = $this->trimmed('since_id');
|
|
||||||
$this->geocode = $this->trimmed('geocode');
|
|
||||||
|
|
||||||
// TODO: Also, language and geocode
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle a request
|
|
||||||
*
|
|
||||||
* @param array $args Arguments from $_REQUEST
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function handle($args)
|
|
||||||
{
|
|
||||||
parent::handle($args);
|
|
||||||
common_debug("In apisearchatom handle()");
|
|
||||||
$this->showAtom();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the notices to output as results. This also sets some class
|
|
||||||
* attrs so we can use them to calculate pagination, and output
|
|
||||||
* since_id and max_id.
|
|
||||||
*
|
|
||||||
* @return array an array of Notice objects sorted in reverse chron
|
|
||||||
*/
|
|
||||||
function getNotices()
|
|
||||||
{
|
|
||||||
// TODO: Support search operators like from: and to:, boolean, etc.
|
|
||||||
|
|
||||||
$notices = array();
|
|
||||||
$notice = new Notice();
|
|
||||||
|
|
||||||
// lcase it for comparison
|
|
||||||
$q = strtolower($this->query);
|
|
||||||
|
|
||||||
$search_engine = $notice->getSearchEngine('notice');
|
|
||||||
$search_engine->set_sort_mode('chron');
|
|
||||||
$search_engine->limit(($this->page - 1) * $this->rpp,
|
|
||||||
$this->rpp + 1, true);
|
|
||||||
if (false === $search_engine->query($q)) {
|
|
||||||
$this->cnt = 0;
|
|
||||||
} else {
|
|
||||||
$this->cnt = $notice->find();
|
|
||||||
}
|
|
||||||
|
|
||||||
$cnt = 0;
|
|
||||||
$this->max_id = 0;
|
|
||||||
|
|
||||||
if ($this->cnt > 0) {
|
|
||||||
while ($notice->fetch()) {
|
|
||||||
++$cnt;
|
|
||||||
|
|
||||||
if (!$this->max_id) {
|
|
||||||
$this->max_id = $notice->id;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->since_id && $notice->id <= $this->since_id) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($cnt > $this->rpp) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
$notices[] = clone($notice);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $notices;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Output search results as an Atom feed
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function showAtom()
|
|
||||||
{
|
|
||||||
$notices = $this->getNotices();
|
|
||||||
|
|
||||||
$this->initAtom();
|
|
||||||
$this->showFeed();
|
|
||||||
|
|
||||||
foreach ($notices as $n) {
|
|
||||||
$profile = $n->getProfile();
|
|
||||||
|
|
||||||
// Don't show notices from deleted users
|
|
||||||
|
|
||||||
if (!empty($profile)) {
|
|
||||||
$this->showEntry($n);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->endAtom();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show feed specific Atom elements
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function showFeed()
|
|
||||||
{
|
|
||||||
// TODO: A9 OpenSearch stuff like search.twitter.com?
|
|
||||||
|
|
||||||
$server = common_config('site', 'server');
|
|
||||||
$sitename = common_config('site', 'name');
|
|
||||||
|
|
||||||
// XXX: Use xmlns:statusnet instead?
|
|
||||||
|
|
||||||
$this->elementStart('feed',
|
|
||||||
array('xmlns' => 'http://www.w3.org/2005/Atom',
|
|
||||||
|
|
||||||
// XXX: xmlns:twitter causes Atom validation to fail
|
|
||||||
// It's used for the source attr on notices
|
|
||||||
|
|
||||||
'xmlns:twitter' => 'http://api.twitter.com/',
|
|
||||||
'xml:lang' => 'en-US')); // XXX Other locales ?
|
|
||||||
|
|
||||||
$taguribase = TagURI::base();
|
|
||||||
$this->element('id', null, "tag:$taguribase:search/$server");
|
|
||||||
|
|
||||||
$site_uri = common_path(false);
|
|
||||||
|
|
||||||
$search_uri = $site_uri . 'api/search.atom?q=' . urlencode($this->query);
|
|
||||||
|
|
||||||
if ($this->rpp != 15) {
|
|
||||||
$search_uri .= '&rpp=' . $this->rpp;
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: this alternate link is not quite right because our
|
|
||||||
// web-based notice search doesn't support a rpp (responses per
|
|
||||||
// page) param yet
|
|
||||||
|
|
||||||
$this->element('link', array('type' => 'text/html',
|
|
||||||
'rel' => 'alternate',
|
|
||||||
'href' => $site_uri . 'search/notice?q=' .
|
|
||||||
urlencode($this->query)));
|
|
||||||
|
|
||||||
// self link
|
|
||||||
|
|
||||||
$self_uri = $search_uri;
|
|
||||||
$self_uri .= ($this->page > 1) ? '&page=' . $this->page : '';
|
|
||||||
|
|
||||||
$this->element('link', array('type' => 'application/atom+xml',
|
|
||||||
'rel' => 'self',
|
|
||||||
'href' => $self_uri));
|
|
||||||
|
|
||||||
// @todo Needs i18n?
|
|
||||||
$this->element('title', null, "$this->query - $sitename Search");
|
|
||||||
$this->element('updated', null, common_date_iso8601('now'));
|
|
||||||
|
|
||||||
// XXX: The below "rel" links are not valid Atom, but it's what
|
|
||||||
// Twitter does...
|
|
||||||
|
|
||||||
// refresh link
|
|
||||||
|
|
||||||
$refresh_uri = $search_uri . "&since_id=" . $this->max_id;
|
|
||||||
|
|
||||||
$this->element('link', array('type' => 'application/atom+xml',
|
|
||||||
'rel' => 'refresh',
|
|
||||||
'href' => $refresh_uri));
|
|
||||||
|
|
||||||
// pagination links
|
|
||||||
|
|
||||||
if ($this->cnt > $this->rpp) {
|
|
||||||
|
|
||||||
$next_uri = $search_uri . "&max_id=" . $this->max_id .
|
|
||||||
'&page=' . ($this->page + 1);
|
|
||||||
|
|
||||||
$this->element('link', array('type' => 'application/atom+xml',
|
|
||||||
'rel' => 'next',
|
|
||||||
'href' => $next_uri));
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->page > 1) {
|
|
||||||
|
|
||||||
$previous_uri = $search_uri . "&max_id=" . $this->max_id .
|
|
||||||
'&page=' . ($this->page - 1);
|
|
||||||
|
|
||||||
$this->element('link', array('type' => 'application/atom+xml',
|
|
||||||
'rel' => 'previous',
|
|
||||||
'href' => $previous_uri));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Build an Atom entry similar to search.twitter.com's based on
|
|
||||||
* a given notice
|
|
||||||
*
|
|
||||||
* @param Notice $notice the notice to use
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function showEntry($notice)
|
|
||||||
{
|
|
||||||
$server = common_config('site', 'server');
|
|
||||||
$profile = $notice->getProfile();
|
|
||||||
$nurl = common_local_url('shownotice', array('notice' => $notice->id));
|
|
||||||
|
|
||||||
$this->elementStart('entry');
|
|
||||||
|
|
||||||
$taguribase = TagURI::base();
|
|
||||||
|
|
||||||
$this->element('id', null, "tag:$taguribase:$notice->id");
|
|
||||||
$this->element('published', null, common_date_w3dtf($notice->created));
|
|
||||||
$this->element('link', array('type' => 'text/html',
|
|
||||||
'rel' => 'alternate',
|
|
||||||
'href' => $nurl));
|
|
||||||
$this->element('title', null, common_xml_safe_str(trim($notice->content)));
|
|
||||||
$this->element('content', array('type' => 'html'), $notice->rendered);
|
|
||||||
$this->element('updated', null, common_date_w3dtf($notice->created));
|
|
||||||
$this->element('link', array('type' => 'image/png',
|
|
||||||
// XXX: Twitter uses rel="image" (not valid)
|
|
||||||
'rel' => 'related',
|
|
||||||
'href' => $profile->avatarUrl()));
|
|
||||||
|
|
||||||
// @todo: Here is where we'd put in a link to an atom feed for threads
|
|
||||||
|
|
||||||
$source = null;
|
|
||||||
|
|
||||||
$ns = $notice->getSource();
|
|
||||||
if ($ns instanceof Notice_source) {
|
|
||||||
if (!empty($ns->name) && !empty($ns->url)) {
|
|
||||||
$source = '<a href="'
|
|
||||||
. htmlspecialchars($ns->url)
|
|
||||||
. '" rel="nofollow">'
|
|
||||||
. htmlspecialchars($ns->name)
|
|
||||||
. '</a>';
|
|
||||||
} else {
|
|
||||||
$source = $ns->code;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->element("twitter:source", null, $source);
|
|
||||||
|
|
||||||
$this->elementStart('author');
|
|
||||||
|
|
||||||
$name = $profile->nickname;
|
|
||||||
|
|
||||||
if ($profile->fullname) {
|
|
||||||
// @todo Needs proper i18n?
|
|
||||||
$name .= ' (' . $profile->fullname . ')';
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->element('name', null, $name);
|
|
||||||
$this->element('uri', null, common_profile_uri($profile));
|
|
||||||
$this->elementEnd('author');
|
|
||||||
|
|
||||||
$this->elementEnd('entry');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize the Atom output, send headers
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function initAtom()
|
|
||||||
{
|
|
||||||
header('Content-Type: application/atom+xml; charset=utf-8');
|
|
||||||
$this->startXml();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* End the Atom feed
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function endAtom()
|
|
||||||
{
|
|
||||||
$this->elementEnd('feed');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,136 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StatusNet, the distributed open-source microblogging tool
|
|
||||||
*
|
|
||||||
* Action for showing Twitter-like JSON search results
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category Search
|
|
||||||
* @package GNUsocial
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @copyright 2008-2010 StatusNet, Inc.
|
|
||||||
* @copyright 2013 Free Software Foundation, Inc.
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://www.gnu.org/software/social/
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('GNUSOCIAL')) { exit(1); }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Action handler for Twitter-compatible API search
|
|
||||||
*
|
|
||||||
* @category Search
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
* @see ApiAction
|
|
||||||
*/
|
|
||||||
class ApiSearchJSONAction extends ApiPrivateAuthAction
|
|
||||||
{
|
|
||||||
var $query;
|
|
||||||
var $lang;
|
|
||||||
var $rpp;
|
|
||||||
var $page;
|
|
||||||
var $since_id;
|
|
||||||
var $limit;
|
|
||||||
var $geocode;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialization.
|
|
||||||
*
|
|
||||||
* @param array $args Web and URL arguments
|
|
||||||
*
|
|
||||||
* @return boolean true if nothing goes wrong
|
|
||||||
*/
|
|
||||||
function prepare($args)
|
|
||||||
{
|
|
||||||
parent::prepare($args);
|
|
||||||
|
|
||||||
$this->query = $this->trimmed('q');
|
|
||||||
$this->lang = $this->trimmed('lang');
|
|
||||||
$this->rpp = $this->trimmed('rpp');
|
|
||||||
|
|
||||||
if (!$this->rpp) {
|
|
||||||
$this->rpp = 15;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->rpp > 100) {
|
|
||||||
$this->rpp = 100;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->page = $this->trimmed('page');
|
|
||||||
|
|
||||||
if (!$this->page) {
|
|
||||||
$this->page = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Suppport max_id -- we need to tweak the backend
|
|
||||||
// Search classes to support it.
|
|
||||||
|
|
||||||
$this->since_id = $this->trimmed('since_id');
|
|
||||||
$this->geocode = $this->trimmed('geocode');
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle a request
|
|
||||||
*
|
|
||||||
* @param array $args Arguments from $_REQUEST
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function handle($args)
|
|
||||||
{
|
|
||||||
parent::handle($args);
|
|
||||||
$this->showResults();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show search results
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function showResults()
|
|
||||||
{
|
|
||||||
// TODO: Support search operators like from: and to:, boolean, etc.
|
|
||||||
|
|
||||||
$notice = new Notice();
|
|
||||||
|
|
||||||
$this->notices = array();
|
|
||||||
$search_engine = $notice->getSearchEngine('notice');
|
|
||||||
$search_engine->set_sort_mode('chron');
|
|
||||||
$search_engine->limit(($this->page - 1) * $this->rpp, $this->rpp + 1);
|
|
||||||
if ($search_engine->query($this->query)) {
|
|
||||||
$cnt = $notice->find();
|
|
||||||
$this->notices = $notice->fetchAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->showJsonTimeline($this->notices);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Do we need to write to the database?
|
|
||||||
*
|
|
||||||
* @return boolean true
|
|
||||||
*/
|
|
||||||
function isReadOnly($args)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,156 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StatusNet, the distributed open-source microblogging tool
|
|
||||||
*
|
|
||||||
* Destroy a notice through the API
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Craig Andrews <candrews@integralblue.com>
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @author Jeffery To <jeffery.to@gmail.com>
|
|
||||||
* @author Tom Blankenship <mac65@mac65.com>
|
|
||||||
* @author Mike Cochrane <mikec@mikenz.geek.nz>
|
|
||||||
* @author Robin Millette <robin@millette.info>
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @copyright 2009 StatusNet, Inc.
|
|
||||||
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('STATUSNET')) {
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deletes one of the authenticating user's statuses (notices).
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Craig Andrews <candrews@integralblue.com>
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @author Jeffery To <jeffery.to@gmail.com>
|
|
||||||
* @author Tom Blankenship <mac65@mac65.com>
|
|
||||||
* @author Mike Cochrane <mikec@mikenz.geek.nz>
|
|
||||||
* @author Robin Millette <robin@millette.info>
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
class ApiStatusesDestroyAction extends ApiAuthAction
|
|
||||||
{
|
|
||||||
var $status = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Take arguments for running
|
|
||||||
*
|
|
||||||
* @param array $args $_REQUEST args
|
|
||||||
*
|
|
||||||
* @return boolean success flag
|
|
||||||
*/
|
|
||||||
function prepare($args)
|
|
||||||
{
|
|
||||||
parent::prepare($args);
|
|
||||||
|
|
||||||
$this->user = $this->auth_user;
|
|
||||||
$this->notice_id = (int)$this->trimmed('id');
|
|
||||||
|
|
||||||
if (empty($notice_id)) {
|
|
||||||
$this->notice_id = (int)$this->arg('id');
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->notice = Notice::getKV((int)$this->notice_id);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle the request
|
|
||||||
*
|
|
||||||
* Delete the notice and all related replies
|
|
||||||
*
|
|
||||||
* @param array $args $_REQUEST data (unused)
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function handle($args)
|
|
||||||
{
|
|
||||||
parent::handle($args);
|
|
||||||
|
|
||||||
if (!in_array($this->format, array('xml', 'json'))) {
|
|
||||||
$this->clientError(
|
|
||||||
// TRANS: Client error displayed when coming across a non-supported API method.
|
|
||||||
_('API method not found.'),
|
|
||||||
404
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!in_array($_SERVER['REQUEST_METHOD'], array('POST', 'DELETE'))) {
|
|
||||||
$this->clientError(
|
|
||||||
// TRANS: Client error displayed trying to delete a status not using POST or DELETE.
|
|
||||||
// TRANS: POST and DELETE should not be translated.
|
|
||||||
_('This method requires a POST or DELETE.'),
|
|
||||||
400,
|
|
||||||
$this->format
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (empty($this->notice)) {
|
|
||||||
$this->clientError(
|
|
||||||
// TRANS: Client error displayed trying to delete a status with an invalid ID.
|
|
||||||
_('No status found with that ID.'),
|
|
||||||
404, $this->format
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->user->id == $this->notice->profile_id) {
|
|
||||||
if (Event::handle('StartDeleteOwnNotice', array($this->user, $this->notice))) {
|
|
||||||
$this->notice->delete();
|
|
||||||
Event::handle('EndDeleteOwnNotice', array($this->user, $this->notice));
|
|
||||||
}
|
|
||||||
$this->showNotice();
|
|
||||||
} else {
|
|
||||||
$this->clientError(
|
|
||||||
// TRANS: Client error displayed trying to delete a status of another user.
|
|
||||||
_('You may not delete another user\'s status.'),
|
|
||||||
403,
|
|
||||||
$this->format
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show the deleted notice
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function showNotice()
|
|
||||||
{
|
|
||||||
if (!empty($this->notice)) {
|
|
||||||
if ($this->format == 'xml') {
|
|
||||||
$this->showSingleXmlStatus($this->notice);
|
|
||||||
} elseif ($this->format == 'json') {
|
|
||||||
$this->show_single_json_status($this->notice);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,103 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StatusNet, the distributed open-source microblogging tool
|
|
||||||
*
|
|
||||||
* Repeat a notice through the API
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @copyright 2009 StatusNet, Inc.
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('GNUSOCIAL')) { exit(1); }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Repeat a notice through the API
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
class ApiStatusesRetweetAction extends ApiAuthAction
|
|
||||||
{
|
|
||||||
protected $needPost = true;
|
|
||||||
|
|
||||||
var $original = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Take arguments for running
|
|
||||||
*
|
|
||||||
* @param array $args $_REQUEST args
|
|
||||||
*
|
|
||||||
* @return boolean success flag
|
|
||||||
*/
|
|
||||||
protected function prepare(array $args=array())
|
|
||||||
{
|
|
||||||
parent::prepare($args);
|
|
||||||
|
|
||||||
$id = $this->trimmed('id');
|
|
||||||
|
|
||||||
$this->original = Notice::getKV('id', $id);
|
|
||||||
|
|
||||||
if (!$this->original instanceof Notice) {
|
|
||||||
// TRANS: Client error displayed trying to repeat a non-existing notice through the API.
|
|
||||||
$this->clientError(_('No such notice.'), 400, $this->format);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle the request
|
|
||||||
*
|
|
||||||
* Make a new notice for the update, save it, and show it
|
|
||||||
*
|
|
||||||
* @param array $args $_REQUEST data (unused)
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
protected function handle()
|
|
||||||
{
|
|
||||||
parent::handle();
|
|
||||||
|
|
||||||
$repeat = $this->original->repeat($this->scoped, $this->source);
|
|
||||||
|
|
||||||
$this->showNotice($repeat);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show the resulting notice
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function showNotice($notice)
|
|
||||||
{
|
|
||||||
if (!empty($notice)) {
|
|
||||||
if ($this->format == 'xml') {
|
|
||||||
$this->showSingleXmlStatus($notice);
|
|
||||||
} elseif ($this->format == 'json') {
|
|
||||||
$this->show_single_json_status($notice);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,126 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StatusNet, the distributed open-source microblogging tool
|
|
||||||
*
|
|
||||||
* Show up to 100 repeats of a notice
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @copyright 2009 StatusNet, Inc.
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('STATUSNET')) {
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show up to 100 repeats of a notice
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
class ApiStatusesRetweetsAction extends ApiAuthAction
|
|
||||||
{
|
|
||||||
const MAXCOUNT = 100;
|
|
||||||
|
|
||||||
var $original = null;
|
|
||||||
var $cnt = self::MAXCOUNT;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Take arguments for running
|
|
||||||
*
|
|
||||||
* @param array $args $_REQUEST args
|
|
||||||
*
|
|
||||||
* @return boolean success flag
|
|
||||||
*/
|
|
||||||
function prepare($args)
|
|
||||||
{
|
|
||||||
parent::prepare($args);
|
|
||||||
|
|
||||||
$id = $this->trimmed('id');
|
|
||||||
|
|
||||||
$this->original = Notice::getKV('id', $id);
|
|
||||||
|
|
||||||
if (empty($this->original)) {
|
|
||||||
// TRANS: Client error displayed trying to display redents of a non-exiting notice.
|
|
||||||
$this->clientError(_('No such notice.'),
|
|
||||||
400, $this->format);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$cnt = $this->trimmed('count');
|
|
||||||
|
|
||||||
if (empty($cnt) || !is_integer($cnt)) {
|
|
||||||
$cnt = 100;
|
|
||||||
} else {
|
|
||||||
$this->cnt = min((int)$cnt, self::MAXCOUNT);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle the request
|
|
||||||
*
|
|
||||||
* Make a new notice for the update, save it, and show it
|
|
||||||
*
|
|
||||||
* @param array $args $_REQUEST data (unused)
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function handle($args)
|
|
||||||
{
|
|
||||||
parent::handle($args);
|
|
||||||
|
|
||||||
$strm = $this->original->repeatStream($this->cnt);
|
|
||||||
|
|
||||||
switch ($this->format) {
|
|
||||||
case 'xml':
|
|
||||||
$this->showXmlTimeline($strm);
|
|
||||||
break;
|
|
||||||
case 'json':
|
|
||||||
$this->showJsonTimeline($strm);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// TRANS: Client error displayed when coming across a non-supported API method.
|
|
||||||
$this->clientError(_('API method not found.'), $code = 404);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return true if read only.
|
|
||||||
*
|
|
||||||
* MAY override
|
|
||||||
*
|
|
||||||
* @param array $args other arguments
|
|
||||||
*
|
|
||||||
* @return boolean is read only action?
|
|
||||||
*/
|
|
||||||
|
|
||||||
function isReadOnly($args)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,251 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StatusNet, the distributed open-source microblogging tool
|
|
||||||
*
|
|
||||||
* Show a notice (as a Twitter-style status)
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Craig Andrews <candrews@integralblue.com>
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @author Jeffery To <jeffery.to@gmail.com>
|
|
||||||
* @author Tom Blankenship <mac65@mac65.com>
|
|
||||||
* @author Mike Cochrane <mikec@mikenz.geek.nz>
|
|
||||||
* @author Robin Millette <robin@millette.info>
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @copyright 2009 StatusNet, Inc.
|
|
||||||
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('GNUSOCIAL')) { exit(1); }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the notice specified by id as a Twitter-style status and inline user
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Craig Andrews <candrews@integralblue.com>
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @author Jeffery To <jeffery.to@gmail.com>
|
|
||||||
* @author Tom Blankenship <mac65@mac65.com>
|
|
||||||
* @author Mike Cochrane <mikec@mikenz.geek.nz>
|
|
||||||
* @author Robin Millette <robin@millette.info>
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
class ApiStatusesShowAction extends ApiPrivateAuthAction
|
|
||||||
{
|
|
||||||
var $notice_id = null;
|
|
||||||
var $notice = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Take arguments for running
|
|
||||||
*
|
|
||||||
* @param array $args $_REQUEST args
|
|
||||||
*
|
|
||||||
* @return boolean success flag
|
|
||||||
*/
|
|
||||||
protected function prepare(array $args=array())
|
|
||||||
{
|
|
||||||
parent::prepare($args);
|
|
||||||
|
|
||||||
// 'id' is an undocumented parameter in Twitter's API. Several
|
|
||||||
// clients make use of it, so we support it too.
|
|
||||||
|
|
||||||
// show.json?id=12345 takes precedence over /show/12345.json
|
|
||||||
|
|
||||||
$this->notice_id = (int)$this->trimmed('id');
|
|
||||||
|
|
||||||
$this->notice = Notice::getKV('id', $this->notice_id);
|
|
||||||
if (!$this->notice instanceof Notice) {
|
|
||||||
$deleted = Deleted_notice::getKV('id', $this->notice_id);
|
|
||||||
if ($deleted instanceof Deleted_notice) {
|
|
||||||
// TRANS: Client error displayed trying to show a deleted notice.
|
|
||||||
$this->clientError(_('Notice deleted.'), 410);
|
|
||||||
}
|
|
||||||
// TRANS: Client error displayed trying to show a non-existing notice.
|
|
||||||
$this->clientError(_('No such notice.'), 404);
|
|
||||||
}
|
|
||||||
if (!$this->notice->inScope($this->scoped)) {
|
|
||||||
// TRANS: Client exception thrown when trying a view a notice the user has no access to.
|
|
||||||
throw new ClientException(_('Access restricted.'), 403);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle the request
|
|
||||||
*
|
|
||||||
* Check the format and show the notice
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
protected function handle()
|
|
||||||
{
|
|
||||||
parent::handle();
|
|
||||||
|
|
||||||
if (!in_array($this->format, array('xml', 'json', 'atom'))) {
|
|
||||||
// TRANS: Client error displayed when coming across a non-supported API method.
|
|
||||||
$this->clientError(_('API method not found.'), 404);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch ($_SERVER['REQUEST_METHOD']) {
|
|
||||||
case 'GET':
|
|
||||||
$this->showNotice();
|
|
||||||
break;
|
|
||||||
case 'DELETE':
|
|
||||||
$this->deleteNotice();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// TRANS: Client error displayed calling an unsupported HTTP error in API status show.
|
|
||||||
$this->clientError(_('HTTP method not supported.'), 405);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show the notice
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function showNotice()
|
|
||||||
{
|
|
||||||
if (!empty($this->notice)) {
|
|
||||||
switch ($this->format) {
|
|
||||||
case 'xml':
|
|
||||||
$this->showSingleXmlStatus($this->notice);
|
|
||||||
break;
|
|
||||||
case 'json':
|
|
||||||
$this->show_single_json_status($this->notice);
|
|
||||||
break;
|
|
||||||
case 'atom':
|
|
||||||
$this->showSingleAtomStatus($this->notice);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// TRANS: Exception thrown requesting an unsupported notice output format.
|
|
||||||
// TRANS: %s is the requested output format.
|
|
||||||
throw new Exception(sprintf(_("Unsupported format: %s."), $this->format));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// XXX: Twitter just sets a 404 header and doens't bother
|
|
||||||
// to return an err msg
|
|
||||||
|
|
||||||
$deleted = Deleted_notice::getKV($this->notice_id);
|
|
||||||
|
|
||||||
if (!empty($deleted)) {
|
|
||||||
$this->clientError(
|
|
||||||
// TRANS: Client error displayed requesting a deleted status.
|
|
||||||
_('Status deleted.'),
|
|
||||||
410,
|
|
||||||
$this->format
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
$this->clientError(
|
|
||||||
// TRANS: Client error displayed requesting a status with an invalid ID.
|
|
||||||
_('No status with that ID found.'),
|
|
||||||
404,
|
|
||||||
$this->format
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* We expose AtomPub here, so non-GET/HEAD reqs must be read/write.
|
|
||||||
*
|
|
||||||
* @param array $args other arguments
|
|
||||||
*
|
|
||||||
* @return boolean true
|
|
||||||
*/
|
|
||||||
|
|
||||||
function isReadOnly($args)
|
|
||||||
{
|
|
||||||
return ($_SERVER['REQUEST_METHOD'] == 'GET' || $_SERVER['REQUEST_METHOD'] == 'HEAD');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* When was this notice last modified?
|
|
||||||
*
|
|
||||||
* @return string datestamp of the latest notice in the stream
|
|
||||||
*/
|
|
||||||
function lastModified()
|
|
||||||
{
|
|
||||||
if (!empty($this->notice)) {
|
|
||||||
return strtotime($this->notice->created);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An entity tag for this notice
|
|
||||||
*
|
|
||||||
* Returns an Etag based on the action name, language, and
|
|
||||||
* timestamps of the notice
|
|
||||||
*
|
|
||||||
* @return string etag
|
|
||||||
*/
|
|
||||||
function etag()
|
|
||||||
{
|
|
||||||
if (!empty($this->notice)) {
|
|
||||||
|
|
||||||
return '"' . implode(
|
|
||||||
':',
|
|
||||||
array($this->arg('action'),
|
|
||||||
common_user_cache_hash($this->auth_user),
|
|
||||||
common_language(),
|
|
||||||
$this->notice->id,
|
|
||||||
strtotime($this->notice->created))
|
|
||||||
)
|
|
||||||
. '"';
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
function deleteNotice()
|
|
||||||
{
|
|
||||||
if ($this->format != 'atom') {
|
|
||||||
// TRANS: Client error displayed when trying to delete a notice not using the Atom format.
|
|
||||||
$this->clientError(_('Can only delete using the Atom format.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (empty($this->auth_user) ||
|
|
||||||
($this->notice->profile_id != $this->auth_user->id &&
|
|
||||||
!$this->auth_user->hasRight(Right::DELETEOTHERSNOTICE))) {
|
|
||||||
// TRANS: Client error displayed when a user has no rights to delete notices of other users.
|
|
||||||
$this->clientError(_('Cannot delete this notice.'), 403);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Event::handle('StartDeleteOwnNotice', array($this->auth_user, $this->notice))) {
|
|
||||||
$this->notice->delete();
|
|
||||||
Event::handle('EndDeleteOwnNotice', array($this->auth_user, $this->notice));
|
|
||||||
}
|
|
||||||
|
|
||||||
// @fixme is there better output we could do here?
|
|
||||||
|
|
||||||
header('HTTP/1.1 200 OK');
|
|
||||||
header('Content-Type: text/plain');
|
|
||||||
// TRANS: Confirmation of notice deletion in API. %d is the ID (number) of the deleted notice.
|
|
||||||
print(sprintf(_('Deleted notice %d'), $this->notice->id));
|
|
||||||
print("\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,345 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StatusNet, the distributed open-source microblogging tool
|
|
||||||
*
|
|
||||||
* Post a notice (update your status) through the API
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Craig Andrews <candrews@integralblue.com>
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @author Jeffery To <jeffery.to@gmail.com>
|
|
||||||
* @author Tom Blankenship <mac65@mac65.com>
|
|
||||||
* @author Mike Cochrane <mikec@mikenz.geek.nz>
|
|
||||||
* @author Robin Millette <robin@millette.info>
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @copyright 2009-2010 StatusNet, Inc.
|
|
||||||
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* External API usage documentation. Please update when you change how this method works. */
|
|
||||||
|
|
||||||
/*! @page statusesupdate statuses/update
|
|
||||||
|
|
||||||
@section Description
|
|
||||||
Updates the authenticating user's status. Requires the status parameter specified below.
|
|
||||||
Request must be a POST.
|
|
||||||
|
|
||||||
@par URL pattern
|
|
||||||
/api/statuses/update.:format
|
|
||||||
|
|
||||||
@par Formats (:format)
|
|
||||||
xml, json
|
|
||||||
|
|
||||||
@par HTTP Method(s)
|
|
||||||
POST
|
|
||||||
|
|
||||||
@par Requires Authentication
|
|
||||||
Yes
|
|
||||||
|
|
||||||
@param status (Required) The URL-encoded text of the status update.
|
|
||||||
@param source (Optional) The source application name, if using HTTP authentication or an anonymous OAuth consumer.
|
|
||||||
@param in_reply_to_status_id (Optional) The ID of an existing status that the update is in reply to.
|
|
||||||
@param lat (Optional) The latitude the status refers to.
|
|
||||||
@param long (Optional) The longitude the status refers to.
|
|
||||||
@param media (Optional) a media upload, such as an image or movie file.
|
|
||||||
|
|
||||||
@sa @ref authentication
|
|
||||||
@sa @ref apiroot
|
|
||||||
|
|
||||||
@subsection usagenotes Usage notes
|
|
||||||
|
|
||||||
@li The URL pattern is relative to the @ref apiroot.
|
|
||||||
@li If the @e source parameter is not supplied the source of the status will default to 'api'. When authenticated via a registered OAuth application, the application's registered name and URL will always override the source parameter.
|
|
||||||
@li The XML response uses <a href="http://georss.org/Main_Page">GeoRSS</a>
|
|
||||||
to encode the latitude and longitude (see example response below <georss:point>).
|
|
||||||
@li Data uploaded via the @e media parameter should be multipart/form-data encoded.
|
|
||||||
|
|
||||||
@subsection exampleusage Example usage
|
|
||||||
|
|
||||||
@verbatim
|
|
||||||
curl -u username:password http://example.com/api/statuses/update.xml -d status='Howdy!' -d lat='30.468' -d long='-94.743'
|
|
||||||
@endverbatim
|
|
||||||
|
|
||||||
@subsection exampleresponse Example response
|
|
||||||
|
|
||||||
@verbatim
|
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<status>
|
|
||||||
<text>Howdy!</text>
|
|
||||||
<truncated>false</truncated>
|
|
||||||
<created_at>Tue Mar 30 23:28:05 +0000 2010</created_at>
|
|
||||||
<in_reply_to_status_id/>
|
|
||||||
<source>api</source>
|
|
||||||
<id>26668724</id>
|
|
||||||
<in_reply_to_user_id/>
|
|
||||||
<in_reply_to_screen_name/>
|
|
||||||
<geo xmlns:georss="http://www.georss.org/georss">
|
|
||||||
<georss:point>30.468 -94.743</georss:point>
|
|
||||||
</geo>
|
|
||||||
<favorited>false</favorited>
|
|
||||||
<user>
|
|
||||||
<id>25803</id>
|
|
||||||
<name>Jed Sanders</name>
|
|
||||||
<screen_name>jedsanders</screen_name>
|
|
||||||
<location>Hoop and Holler, Texas</location>
|
|
||||||
<description>I like to think of myself as America's Favorite.</description>
|
|
||||||
<profile_image_url>http://avatar.example.com/25803-48-20080924200604.png</profile_image_url>
|
|
||||||
<url>http://jedsanders.net</url>
|
|
||||||
<protected>false</protected>
|
|
||||||
<followers_count>5</followers_count>
|
|
||||||
<profile_background_color/>
|
|
||||||
<profile_text_color/>
|
|
||||||
<profile_link_color/>
|
|
||||||
<profile_sidebar_fill_color/>
|
|
||||||
<profile_sidebar_border_color/>
|
|
||||||
<friends_count>2</friends_count>
|
|
||||||
<created_at>Wed Sep 24 20:04:00 +0000 2008</created_at>
|
|
||||||
<favourites_count>0</favourites_count>
|
|
||||||
<utc_offset>0</utc_offset>
|
|
||||||
<time_zone>UTC</time_zone>
|
|
||||||
<profile_background_image_url/>
|
|
||||||
<profile_background_tile>false</profile_background_tile>
|
|
||||||
<statuses_count>70</statuses_count>
|
|
||||||
<following>true</following>
|
|
||||||
<notifications>true</notifications>
|
|
||||||
</user>
|
|
||||||
</status>
|
|
||||||
@endverbatim
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('STATUSNET')) {
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates the authenticating user's status (posts a notice).
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Craig Andrews <candrews@integralblue.com>
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @author Jeffery To <jeffery.to@gmail.com>
|
|
||||||
* @author Tom Blankenship <mac65@mac65.com>
|
|
||||||
* @author Mike Cochrane <mikec@mikenz.geek.nz>
|
|
||||||
* @author Robin Millette <robin@millette.info>
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
class ApiStatusesUpdateAction extends ApiAuthAction
|
|
||||||
{
|
|
||||||
protected $needPost = true;
|
|
||||||
|
|
||||||
var $status = null;
|
|
||||||
var $in_reply_to_status_id = null;
|
|
||||||
var $lat = null;
|
|
||||||
var $lon = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Take arguments for running
|
|
||||||
*
|
|
||||||
* @param array $args $_REQUEST args
|
|
||||||
*
|
|
||||||
* @return boolean success flag
|
|
||||||
*/
|
|
||||||
protected function prepare(array $args=array())
|
|
||||||
{
|
|
||||||
parent::prepare($args);
|
|
||||||
|
|
||||||
$this->status = $this->trimmed('status');
|
|
||||||
$this->lat = $this->trimmed('lat');
|
|
||||||
$this->lon = $this->trimmed('long');
|
|
||||||
|
|
||||||
$this->in_reply_to_status_id
|
|
||||||
= intval($this->trimmed('in_reply_to_status_id'));
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle the request
|
|
||||||
*
|
|
||||||
* Make a new notice for the update, save it, and show it
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
protected function handle()
|
|
||||||
{
|
|
||||||
parent::handle();
|
|
||||||
|
|
||||||
// Workaround for PHP returning empty $_POST and $_FILES when POST
|
|
||||||
// length > post_max_size in php.ini
|
|
||||||
|
|
||||||
if (empty($_FILES)
|
|
||||||
&& empty($_POST)
|
|
||||||
&& ($_SERVER['CONTENT_LENGTH'] > 0)
|
|
||||||
) {
|
|
||||||
// TRANS: Client error displayed when the number of bytes in a POST request exceeds a limit.
|
|
||||||
// TRANS: %s is the number of bytes of the CONTENT_LENGTH.
|
|
||||||
$msg = _m('The server was unable to handle that much POST data (%s byte) due to its current configuration.',
|
|
||||||
'The server was unable to handle that much POST data (%s bytes) due to its current configuration.',
|
|
||||||
intval($_SERVER['CONTENT_LENGTH']));
|
|
||||||
|
|
||||||
$this->clientError(sprintf($msg, $_SERVER['CONTENT_LENGTH']));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (empty($this->status)) {
|
|
||||||
// TRANS: Client error displayed when the parameter "status" is missing.
|
|
||||||
$this->clientError(_('Client must provide a \'status\' parameter with a value.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_null($this->scoped)) {
|
|
||||||
// TRANS: Client error displayed when updating a status for a non-existing user.
|
|
||||||
$this->clientError(_('No such user.'), 404);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Do not call shortenlinks until the whole notice has been build */
|
|
||||||
|
|
||||||
// Check for commands
|
|
||||||
|
|
||||||
$inter = new CommandInterpreter();
|
|
||||||
$cmd = $inter->handle_command($this->auth_user, $this->status);
|
|
||||||
|
|
||||||
if ($cmd) {
|
|
||||||
if ($this->supported($cmd)) {
|
|
||||||
$cmd->execute(new Channel());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cmd not supported? Twitter just returns your latest status.
|
|
||||||
// And, it returns your last status whether the cmd was successful
|
|
||||||
// or not!
|
|
||||||
|
|
||||||
$this->notice = $this->auth_user->getCurrentNotice();
|
|
||||||
} else {
|
|
||||||
$reply_to = null;
|
|
||||||
|
|
||||||
if (!empty($this->in_reply_to_status_id)) {
|
|
||||||
// Check whether notice actually exists
|
|
||||||
|
|
||||||
$reply = Notice::getKV($this->in_reply_to_status_id);
|
|
||||||
|
|
||||||
if ($reply) {
|
|
||||||
$reply_to = $this->in_reply_to_status_id;
|
|
||||||
} else {
|
|
||||||
// TRANS: Client error displayed when replying to a non-existing notice.
|
|
||||||
$this->clientError(_('Parent notice not found.'), 404);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$upload = null;
|
|
||||||
try {
|
|
||||||
$upload = MediaFile::fromUpload('media', $this->scoped);
|
|
||||||
$this->status .= ' ' . $upload->shortUrl();
|
|
||||||
/* Do not call shortenlinks until the whole notice has been build */
|
|
||||||
} catch (NoUploadedMediaException $e) {
|
|
||||||
// There was no uploaded media for us today.
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Do call shortenlinks here & check notice length since notice is about to be saved & sent */
|
|
||||||
$status_shortened = $this->auth_user->shortenlinks($this->status);
|
|
||||||
|
|
||||||
if (Notice::contentTooLong($status_shortened)) {
|
|
||||||
if ($upload instanceof MediaFile) {
|
|
||||||
$upload->delete();
|
|
||||||
}
|
|
||||||
// TRANS: Client error displayed exceeding the maximum notice length.
|
|
||||||
// TRANS: %d is the maximum lenth for a notice.
|
|
||||||
$msg = _m('Maximum notice size is %d character, including attachment URL.',
|
|
||||||
'Maximum notice size is %d characters, including attachment URL.',
|
|
||||||
Notice::maxContent());
|
|
||||||
/* Use HTTP 413 error code (Request Entity Too Large)
|
|
||||||
* instead of basic 400 for better understanding
|
|
||||||
*/
|
|
||||||
$this->clientError(sprintf($msg, Notice::maxContent()), 413);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
$content = html_entity_decode($status_shortened, ENT_NOQUOTES, 'UTF-8');
|
|
||||||
|
|
||||||
$options = array('reply_to' => $reply_to);
|
|
||||||
|
|
||||||
if ($this->scoped->shareLocation()) {
|
|
||||||
|
|
||||||
$locOptions = Notice::locationOptions($this->lat,
|
|
||||||
$this->lon,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
$this->scoped);
|
|
||||||
|
|
||||||
$options = array_merge($options, $locOptions);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
$this->notice = Notice::saveNew(
|
|
||||||
$this->scoped->id,
|
|
||||||
$content,
|
|
||||||
$this->source,
|
|
||||||
$options
|
|
||||||
);
|
|
||||||
} catch (Exception $e) {
|
|
||||||
$this->clientError($e->getMessage(), $e->getCode());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($upload)) {
|
|
||||||
$upload->attachToNotice($this->notice);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->showNotice();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show the resulting notice
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function showNotice()
|
|
||||||
{
|
|
||||||
if (!empty($this->notice)) {
|
|
||||||
if ($this->format == 'xml') {
|
|
||||||
$this->showSingleXmlStatus($this->notice);
|
|
||||||
} elseif ($this->format == 'json') {
|
|
||||||
$this->show_single_json_status($this->notice);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Is this command supported when doing an update from the API?
|
|
||||||
*
|
|
||||||
* @param string $cmd the command to check for
|
|
||||||
*
|
|
||||||
* @return boolean true or false
|
|
||||||
*/
|
|
||||||
function supported($cmd)
|
|
||||||
{
|
|
||||||
static $cmdlist = array('SubCommand', 'UnsubCommand',
|
|
||||||
'OnCommand', 'OffCommand', 'JoinCommand', 'LeaveCommand');
|
|
||||||
|
|
||||||
$supported = null;
|
|
||||||
|
|
||||||
if (Event::handle('CommandSupportedAPI', array($cmd, &$supported))) {
|
|
||||||
$supported = $supported || in_array(get_class($cmd), $cmdlist);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $supported;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,254 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StatusNet, the distributed open-source microblogging tool
|
|
||||||
*
|
|
||||||
* Base class for showing subscription information in the API
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Dan Moore <dan@moore.cx>
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @copyright 2009 StatusNet, Inc.
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('STATUSNET')) {
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class outputs a list of profiles as Twitter-style user and status objects.
|
|
||||||
* It is used by the API methods /api/statuses/(friends|followers). To support the
|
|
||||||
* social graph methods it also can output a simple list of IDs.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Dan Moore <dan@moore.cx>
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
abstract class ApiSubscriptionsAction extends ApiBareAuthAction
|
|
||||||
{
|
|
||||||
var $profiles = null;
|
|
||||||
var $tag = null;
|
|
||||||
var $lite = null;
|
|
||||||
var $ids_only = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Take arguments for running
|
|
||||||
*
|
|
||||||
* @param array $args $_REQUEST args
|
|
||||||
*
|
|
||||||
* @return boolean success flag
|
|
||||||
*/
|
|
||||||
protected function prepare(array $args=array())
|
|
||||||
{
|
|
||||||
parent::prepare($args);
|
|
||||||
|
|
||||||
$this->tag = $this->arg('tag');
|
|
||||||
|
|
||||||
// Note: Twitter no longer supports 'lite'
|
|
||||||
$this->lite = $this->arg('lite');
|
|
||||||
|
|
||||||
$this->ids_only = $this->arg('ids_only');
|
|
||||||
|
|
||||||
// If called as a social graph method, show 5000 per page, otherwise 100
|
|
||||||
|
|
||||||
$this->count = isset($this->ids_only) ?
|
|
||||||
5000 : (int)$this->arg('count', 100);
|
|
||||||
|
|
||||||
$this->target = $this->getTargetProfile($this->arg('id'));
|
|
||||||
|
|
||||||
if (!($this->target instanceof Profile)) {
|
|
||||||
// TRANS: Client error displayed when requesting a list of followers for a non-existing user.
|
|
||||||
$this->clientError(_('No such user.'), 404);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->profiles = $this->getProfiles();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle the request
|
|
||||||
*
|
|
||||||
* Show the profiles
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
protected function handle()
|
|
||||||
{
|
|
||||||
parent::handle();
|
|
||||||
|
|
||||||
if (!in_array($this->format, array('xml', 'json'))) {
|
|
||||||
// TRANS: Client error displayed when coming across a non-supported API method.
|
|
||||||
$this->clientError(_('API method not found.'), 404);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->initDocument($this->format);
|
|
||||||
|
|
||||||
if (isset($this->ids_only)) {
|
|
||||||
$this->showIds();
|
|
||||||
} else {
|
|
||||||
$this->showProfiles(isset($this->lite) ? false : true);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->endDocument($this->format);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get profiles related to the type of subscriber/subscription action
|
|
||||||
*
|
|
||||||
* @return array Profiles
|
|
||||||
*/
|
|
||||||
abstract protected function getProfiles();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Is this action read only?
|
|
||||||
*
|
|
||||||
* @param array $args other arguments
|
|
||||||
*
|
|
||||||
* @return boolean true
|
|
||||||
*/
|
|
||||||
function isReadOnly($args)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* When was this feed last modified?
|
|
||||||
*
|
|
||||||
* @return string datestamp of the latest profile in the stream
|
|
||||||
*/
|
|
||||||
function lastModified()
|
|
||||||
{
|
|
||||||
if (!empty($this->profiles) && (count($this->profiles) > 0)) {
|
|
||||||
return strtotime($this->profiles[0]->created);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An entity tag for this action
|
|
||||||
*
|
|
||||||
* Returns an Etag based on the action name, language, user ID, and
|
|
||||||
* timestamps of the first and last profiles in the subscriptions list
|
|
||||||
* There's also an indicator to show whether this action is being called
|
|
||||||
* as /api/statuses/(friends|followers) or /api/(friends|followers)/ids
|
|
||||||
*
|
|
||||||
* @return string etag
|
|
||||||
*/
|
|
||||||
function etag()
|
|
||||||
{
|
|
||||||
if (!empty($this->profiles) && (count($this->profiles) > 0)) {
|
|
||||||
|
|
||||||
$last = count($this->profiles) - 1;
|
|
||||||
|
|
||||||
return '"' . implode(
|
|
||||||
':',
|
|
||||||
array($this->arg('action'),
|
|
||||||
common_user_cache_hash($this->auth_user),
|
|
||||||
common_language(),
|
|
||||||
$this->target->id,
|
|
||||||
// Caching tags.
|
|
||||||
isset($this->ids_only) ? 'IDs' : 'Profiles',
|
|
||||||
strtotime($this->profiles[0]->created),
|
|
||||||
strtotime($this->profiles[$last]->created))
|
|
||||||
)
|
|
||||||
. '"';
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show the profiles as Twitter-style useres and statuses
|
|
||||||
*
|
|
||||||
* @param boolean $include_statuses Whether to include the latest status
|
|
||||||
* with each user. Default true.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function showProfiles($include_statuses = true)
|
|
||||||
{
|
|
||||||
switch ($this->format) {
|
|
||||||
case 'xml':
|
|
||||||
$this->elementStart('users', array('type' => 'array',
|
|
||||||
'xmlns:statusnet' => 'http://status.net/schema/api/1/'));
|
|
||||||
foreach ($this->profiles as $profile) {
|
|
||||||
$this->showProfile(
|
|
||||||
$profile,
|
|
||||||
$this->format,
|
|
||||||
null,
|
|
||||||
$include_statuses
|
|
||||||
);
|
|
||||||
}
|
|
||||||
$this->elementEnd('users');
|
|
||||||
break;
|
|
||||||
case 'json':
|
|
||||||
$arrays = array();
|
|
||||||
foreach ($this->profiles as $profile) {
|
|
||||||
$arrays[] = $this->twitterUserArray(
|
|
||||||
$profile,
|
|
||||||
$include_statuses
|
|
||||||
);
|
|
||||||
}
|
|
||||||
print json_encode($arrays);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// TRANS: Client error displayed when requesting profiles of followers in an unsupported format.
|
|
||||||
$this->clientError(_('Unsupported format.'));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show the IDs of the profiles only. 5000 per page. To support
|
|
||||||
* the 'social graph' methods: /api/(friends|followers)/ids
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function showIds()
|
|
||||||
{
|
|
||||||
switch ($this->format) {
|
|
||||||
case 'xml':
|
|
||||||
$this->elementStart('ids');
|
|
||||||
foreach ($this->profiles as $profile) {
|
|
||||||
$this->element('id', null, $profile->id);
|
|
||||||
}
|
|
||||||
$this->elementEnd('ids');
|
|
||||||
break;
|
|
||||||
case 'json':
|
|
||||||
$ids = array();
|
|
||||||
foreach ($this->profiles as $profile) {
|
|
||||||
$ids[] = (int)$profile->id;
|
|
||||||
}
|
|
||||||
print json_encode($ids);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// TRANS: Client error displayed when requesting IDs of followers in an unsupported format.
|
|
||||||
$this->clientError(_('Unsupported format.'));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,344 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StatusNet, the distributed open-source microblogging tool
|
|
||||||
*
|
|
||||||
* Show the friends timeline
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Craig Andrews <candrews@integralblue.com>
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @author Jeffery To <jeffery.to@gmail.com>
|
|
||||||
* @author mac65 <mac65@mac65.com>
|
|
||||||
* @author Mike Cochrane <mikec@mikenz.geek.nz>
|
|
||||||
* @author Robin Millette <robin@millette.info>
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @copyright 2009-2010 StatusNet, Inc.
|
|
||||||
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* External API usage documentation. Please update when you change how this method works. */
|
|
||||||
|
|
||||||
/*! @page friendstimeline statuses/friends_timeline
|
|
||||||
|
|
||||||
@section Description
|
|
||||||
Returns the 20 most recent statuses posted by the authenticating
|
|
||||||
user and that user's friends. This is the equivalent of "You and
|
|
||||||
friends" page in the web interface.
|
|
||||||
|
|
||||||
@par URL patterns
|
|
||||||
@li /api/statuses/friends_timeline.:format
|
|
||||||
@li /api/statuses/friends_timeline/:id.:format
|
|
||||||
|
|
||||||
@par Formats (:format)
|
|
||||||
xml, json, rss, atom
|
|
||||||
|
|
||||||
@par ID (:id)
|
|
||||||
username, user id
|
|
||||||
|
|
||||||
@par HTTP Method(s)
|
|
||||||
GET
|
|
||||||
|
|
||||||
@par Requires Authentication
|
|
||||||
Sometimes (see: @ref authentication)
|
|
||||||
|
|
||||||
@param user_id (Optional) Specifies a user by ID
|
|
||||||
@param screen_name (Optional) Specifies a user by screename (nickname)
|
|
||||||
@param since_id (Optional) Returns only statuses with an ID greater
|
|
||||||
than (that is, more recent than) the specified ID.
|
|
||||||
@param max_id (Optional) Returns only statuses with an ID less than
|
|
||||||
(that is, older than) or equal to the specified ID.
|
|
||||||
@param count (Optional) Specifies the number of statuses to retrieve.
|
|
||||||
@param page (Optional) Specifies the page of results to retrieve.
|
|
||||||
|
|
||||||
@sa @ref authentication
|
|
||||||
@sa @ref apiroot
|
|
||||||
|
|
||||||
@subsection usagenotes Usage notes
|
|
||||||
@li The URL pattern is relative to the @ref apiroot.
|
|
||||||
@li The XML response uses <a href="http://georss.org/Main_Page">GeoRSS</a>
|
|
||||||
to encode the latitude and longitude (see example response below <georss:point>).
|
|
||||||
|
|
||||||
@subsection exampleusage Example usage
|
|
||||||
|
|
||||||
@verbatim
|
|
||||||
curl http://identi.ca/api/statuses/friends_timeline/evan.xml?count=1&page=2
|
|
||||||
@endverbatim
|
|
||||||
|
|
||||||
@subsection exampleresponse Example response
|
|
||||||
|
|
||||||
@verbatim
|
|
||||||
<?xml version="1.0"?>
|
|
||||||
<statuses type="array">
|
|
||||||
<status>
|
|
||||||
<text>back from the !yul !drupal meet with Evolving Web folk, @anarcat, @webchick and others, and an interesting refresher on SQL indexing</text>
|
|
||||||
<truncated>false</truncated>
|
|
||||||
<created_at>Wed Mar 31 01:33:02 +0000 2010</created_at>
|
|
||||||
<in_reply_to_status_id/>
|
|
||||||
<source><a href="http://code.google.com/p/microblog-purple/">mbpidgin</a></source>
|
|
||||||
<id>26674201</id>
|
|
||||||
<in_reply_to_user_id/>
|
|
||||||
<in_reply_to_screen_name/>
|
|
||||||
<geo/>
|
|
||||||
<favorited>false</favorited>
|
|
||||||
<user>
|
|
||||||
<id>246</id>
|
|
||||||
<name>Mark</name>
|
|
||||||
<screen_name>lambic</screen_name>
|
|
||||||
<location>Montreal, Canada</location>
|
|
||||||
<description>Geek</description>
|
|
||||||
<profile_image_url>http://avatar.identi.ca/246-48-20080702141545.png</profile_image_url>
|
|
||||||
<url>http://lambic.co.uk</url>
|
|
||||||
<protected>false</protected>
|
|
||||||
<followers_count>73</followers_count>
|
|
||||||
<profile_background_color>#F0F2F5</profile_background_color>
|
|
||||||
<profile_text_color/>
|
|
||||||
<profile_link_color>#002E6E</profile_link_color>
|
|
||||||
<profile_sidebar_fill_color>#CEE1E9</profile_sidebar_fill_color>
|
|
||||||
<profile_sidebar_border_color/>
|
|
||||||
<friends_count>58</friends_count>
|
|
||||||
<created_at>Wed Jul 02 14:12:15 +0000 2008</created_at>
|
|
||||||
<favourites_count>2</favourites_count>
|
|
||||||
<utc_offset>-14400</utc_offset>
|
|
||||||
<time_zone>US/Eastern</time_zone>
|
|
||||||
<profile_background_image_url/>
|
|
||||||
<profile_background_tile>false</profile_background_tile>
|
|
||||||
<statuses_count>933</statuses_count>
|
|
||||||
<following>false</following>
|
|
||||||
<notifications>false</notifications>
|
|
||||||
</user>
|
|
||||||
</status>
|
|
||||||
</statuses>
|
|
||||||
@endverbatim
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('STATUSNET')) {
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the most recent notices (default 20) posted by the target user.
|
|
||||||
* This is the equivalent of 'You and friends' page accessed via Web.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Craig Andrews <candrews@integralblue.com>
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @author Jeffery To <jeffery.to@gmail.com>
|
|
||||||
* @author mac65 <mac65@mac65.com>
|
|
||||||
* @author Mike Cochrane <mikec@mikenz.geek.nz>
|
|
||||||
* @author Robin Millette <robin@millette.info>
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
class ApiTimelineFriendsAction extends ApiBareAuthAction
|
|
||||||
{
|
|
||||||
var $notices = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Take arguments for running
|
|
||||||
*
|
|
||||||
* @param array $args $_REQUEST args
|
|
||||||
*
|
|
||||||
* @return boolean success flag
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
protected function prepare(array $args=array())
|
|
||||||
{
|
|
||||||
parent::prepare($args);
|
|
||||||
$this->target = $this->getTargetProfile($this->arg('id'));
|
|
||||||
|
|
||||||
if (!($this->target instanceof Profile)) {
|
|
||||||
// TRANS: Client error displayed when requesting dents of a user and friends for a user that does not exist.
|
|
||||||
$this->clientError(_('No such user.'), 404);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->notices = $this->getNotices();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle the request
|
|
||||||
*
|
|
||||||
* Just show the notices
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
protected function handle()
|
|
||||||
{
|
|
||||||
parent::handle();
|
|
||||||
$this->showTimeline();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show the timeline of notices
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function showTimeline()
|
|
||||||
{
|
|
||||||
$sitename = common_config('site', 'name');
|
|
||||||
// TRANS: Title of API timeline for a user and friends.
|
|
||||||
// TRANS: %s is a username.
|
|
||||||
$title = sprintf(_("%s and friends"), $this->target->nickname);
|
|
||||||
$taguribase = TagURI::base();
|
|
||||||
$id = "tag:$taguribase:FriendsTimeline:" . $this->target->id;
|
|
||||||
|
|
||||||
$subtitle = sprintf(
|
|
||||||
// TRANS: Message is used as a subtitle. %1$s is a user nickname, %2$s is a site name.
|
|
||||||
_('Updates from %1$s and friends on %2$s!'),
|
|
||||||
$this->target->nickname,
|
|
||||||
$sitename
|
|
||||||
);
|
|
||||||
|
|
||||||
$logo = $this->target->avatarUrl(AVATAR_PROFILE_SIZE);
|
|
||||||
$link = common_local_url('all',
|
|
||||||
array('nickname' => $this->target->nickname));
|
|
||||||
$self = $this->getSelfUri();
|
|
||||||
|
|
||||||
switch($this->format) {
|
|
||||||
case 'xml':
|
|
||||||
$this->showXmlTimeline($this->notices);
|
|
||||||
break;
|
|
||||||
case 'rss':
|
|
||||||
|
|
||||||
$this->showRssTimeline(
|
|
||||||
$this->notices,
|
|
||||||
$title,
|
|
||||||
$link,
|
|
||||||
$subtitle,
|
|
||||||
null,
|
|
||||||
$logo,
|
|
||||||
$self
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case 'atom':
|
|
||||||
header('Content-Type: application/atom+xml; charset=utf-8');
|
|
||||||
|
|
||||||
$atom = new AtomNoticeFeed($this->auth_user);
|
|
||||||
|
|
||||||
$atom->setId($id);
|
|
||||||
$atom->setTitle($title);
|
|
||||||
$atom->setSubtitle($subtitle);
|
|
||||||
$atom->setLogo($logo);
|
|
||||||
$atom->setUpdated('now');
|
|
||||||
$atom->addLink($link);
|
|
||||||
$atom->setSelfLink($self);
|
|
||||||
|
|
||||||
$atom->addEntryFromNotices($this->notices);
|
|
||||||
|
|
||||||
$this->raw($atom->getString());
|
|
||||||
|
|
||||||
break;
|
|
||||||
case 'json':
|
|
||||||
$this->showJsonTimeline($this->notices);
|
|
||||||
break;
|
|
||||||
case 'as':
|
|
||||||
header('Content-Type: ' . ActivityStreamJSONDocument::CONTENT_TYPE);
|
|
||||||
$doc = new ActivityStreamJSONDocument($this->auth_user, $title);
|
|
||||||
$doc->addLink($link, 'alternate', 'text/html');
|
|
||||||
$doc->addItemsFromNotices($this->notices);
|
|
||||||
$this->raw($doc->asString());
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// TRANS: Client error displayed when coming across a non-supported API method.
|
|
||||||
$this->clientError(_('API method not found.'), 404);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get notices
|
|
||||||
*
|
|
||||||
* @return array notices
|
|
||||||
*/
|
|
||||||
function getNotices()
|
|
||||||
{
|
|
||||||
$notices = array();
|
|
||||||
|
|
||||||
$stream = new InboxNoticeStream($this->target, $this->scoped);
|
|
||||||
|
|
||||||
$notice = $stream->getNotices(($this->page-1) * $this->count,
|
|
||||||
$this->count,
|
|
||||||
$this->since_id,
|
|
||||||
$this->max_id);
|
|
||||||
|
|
||||||
while ($notice->fetch()) {
|
|
||||||
$notices[] = clone($notice);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $notices;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Is this action read only?
|
|
||||||
*
|
|
||||||
* @param array $args other arguments
|
|
||||||
*
|
|
||||||
* @return boolean true
|
|
||||||
*/
|
|
||||||
function isReadOnly($args)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* When was this feed last modified?
|
|
||||||
*
|
|
||||||
* @return string datestamp of the latest notice in the stream
|
|
||||||
*/
|
|
||||||
function lastModified()
|
|
||||||
{
|
|
||||||
if (!empty($this->notices) && (count($this->notices) > 0)) {
|
|
||||||
return strtotime($this->notices[0]->created);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An entity tag for this stream
|
|
||||||
*
|
|
||||||
* Returns an Etag based on the action name, language, user ID, and
|
|
||||||
* timestamps of the first and last notice in the timeline
|
|
||||||
*
|
|
||||||
* @return string etag
|
|
||||||
*/
|
|
||||||
function etag()
|
|
||||||
{
|
|
||||||
if (!empty($this->notices) && (count($this->notices) > 0)) {
|
|
||||||
$last = count($this->notices) - 1;
|
|
||||||
|
|
||||||
return '"' . implode(
|
|
||||||
':',
|
|
||||||
array($this->arg('action'),
|
|
||||||
common_user_cache_hash($this->auth_user),
|
|
||||||
common_language(),
|
|
||||||
$this->target->id,
|
|
||||||
strtotime($this->notices[0]->created),
|
|
||||||
strtotime($this->notices[$last]->created))
|
|
||||||
)
|
|
||||||
. '"';
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,221 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StatusNet, the distributed open-source microblogging tool
|
|
||||||
*
|
|
||||||
* Show a group's notices
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Craig Andrews <candrews@integralblue.com>
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @author Jeffery To <jeffery.to@gmail.com>
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @copyright 2009-2010 StatusNet, Inc.
|
|
||||||
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('STATUSNET')) {
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the most recent notices (default 20) posted to the group specified by ID
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Craig Andrews <candrews@integralblue.com>
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @author Jeffery To <jeffery.to@gmail.com>
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
class ApiTimelineGroupAction extends ApiPrivateAuthAction
|
|
||||||
{
|
|
||||||
var $group = null;
|
|
||||||
var $notices = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Take arguments for running
|
|
||||||
*
|
|
||||||
* @param array $args $_REQUEST args
|
|
||||||
*
|
|
||||||
* @return boolean success flag
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
protected function prepare(array $args=array())
|
|
||||||
{
|
|
||||||
parent::prepare($args);
|
|
||||||
|
|
||||||
$this->group = $this->getTargetGroup($this->arg('id'));
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle the request
|
|
||||||
*
|
|
||||||
* Just show the notices
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
protected function handle()
|
|
||||||
{
|
|
||||||
parent::handle();
|
|
||||||
|
|
||||||
if (empty($this->group)) {
|
|
||||||
// TRANS: Client error displayed requesting most recent notices to a group for a non-existing group.
|
|
||||||
$this->clientError(_('Group not found.'), 404);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->notices = $this->getNotices();
|
|
||||||
$this->showTimeline();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show the timeline of notices
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function showTimeline()
|
|
||||||
{
|
|
||||||
// We'll pull common formatting out of this for other formats
|
|
||||||
$atom = new AtomGroupNoticeFeed($this->group, $this->auth_user);
|
|
||||||
|
|
||||||
$self = $this->getSelfUri();
|
|
||||||
|
|
||||||
$link = common_local_url('showgroup',
|
|
||||||
array('nickname' => $this->group->nickname));
|
|
||||||
|
|
||||||
switch($this->format) {
|
|
||||||
case 'xml':
|
|
||||||
$this->showXmlTimeline($this->notices);
|
|
||||||
break;
|
|
||||||
case 'rss':
|
|
||||||
$this->showRssTimeline(
|
|
||||||
$this->notices,
|
|
||||||
$atom->title,
|
|
||||||
$this->group->homeUrl(),
|
|
||||||
$atom->subtitle,
|
|
||||||
null,
|
|
||||||
$atom->logo,
|
|
||||||
$self
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case 'atom':
|
|
||||||
header('Content-Type: application/atom+xml; charset=utf-8');
|
|
||||||
$atom->addEntryFromNotices($this->notices);
|
|
||||||
$this->raw($atom->getString());
|
|
||||||
break;
|
|
||||||
case 'json':
|
|
||||||
$this->showJsonTimeline($this->notices);
|
|
||||||
break;
|
|
||||||
case 'as':
|
|
||||||
header('Content-Type: ' . ActivityStreamJSONDocument::CONTENT_TYPE);
|
|
||||||
$doc = new ActivityStreamJSONDocument($this->auth_user);
|
|
||||||
$doc->setTitle($atom->title);
|
|
||||||
$doc->addLink($link, 'alternate', 'text/html');
|
|
||||||
$doc->addItemsFromNotices($this->notices);
|
|
||||||
$this->raw($doc->asString());
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// TRANS: Client error displayed when trying to handle an unknown API method.
|
|
||||||
$this->clientError(_('API method not found.'), 404);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get notices
|
|
||||||
*
|
|
||||||
* @return array notices
|
|
||||||
*/
|
|
||||||
function getNotices()
|
|
||||||
{
|
|
||||||
$notices = array();
|
|
||||||
|
|
||||||
$notice = $this->group->getNotices(
|
|
||||||
($this->page-1) * $this->count,
|
|
||||||
$this->count,
|
|
||||||
$this->since_id,
|
|
||||||
$this->max_id
|
|
||||||
);
|
|
||||||
|
|
||||||
while ($notice->fetch()) {
|
|
||||||
$notices[] = clone($notice);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $notices;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Is this action read only?
|
|
||||||
*
|
|
||||||
* @param array $args other arguments
|
|
||||||
*
|
|
||||||
* @return boolean true
|
|
||||||
*/
|
|
||||||
function isReadOnly($args)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* When was this feed last modified?
|
|
||||||
*
|
|
||||||
* @return string datestamp of the latest notice in the stream
|
|
||||||
*/
|
|
||||||
function lastModified()
|
|
||||||
{
|
|
||||||
if (!empty($this->notices) && (count($this->notices) > 0)) {
|
|
||||||
return strtotime($this->notices[0]->created);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An entity tag for this stream
|
|
||||||
*
|
|
||||||
* Returns an Etag based on the action name, language, group ID and
|
|
||||||
* timestamps of the first and last notice in the timeline
|
|
||||||
*
|
|
||||||
* @return string etag
|
|
||||||
*/
|
|
||||||
function etag()
|
|
||||||
{
|
|
||||||
if (!empty($this->notices) && (count($this->notices) > 0)) {
|
|
||||||
|
|
||||||
$last = count($this->notices) - 1;
|
|
||||||
|
|
||||||
return '"' . implode(
|
|
||||||
':',
|
|
||||||
array($this->arg('action'),
|
|
||||||
common_user_cache_hash($this->auth_user),
|
|
||||||
common_language(),
|
|
||||||
$this->group->id,
|
|
||||||
strtotime($this->notices[0]->created),
|
|
||||||
strtotime($this->notices[$last]->created))
|
|
||||||
)
|
|
||||||
. '"';
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,249 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StatusNet, the distributed open-source microblogging tool
|
|
||||||
*
|
|
||||||
* Show the home timeline
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Craig Andrews <candrews@integralblue.com>
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @author Jeffery To <jeffery.to@gmail.com>
|
|
||||||
* @author mac65 <mac65@mac65.com>
|
|
||||||
* @author Mike Cochrane <mikec@mikenz.geek.nz>
|
|
||||||
* @author Robin Millette <robin@millette.info>
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @copyright 2009 StatusNet, Inc.
|
|
||||||
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('STATUSNET')) {
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the most recent notices (default 20) posted by the target user.
|
|
||||||
* This is the equivalent of 'You and friends' page accessed via Web.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Craig Andrews <candrews@integralblue.com>
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @author Jeffery To <jeffery.to@gmail.com>
|
|
||||||
* @author mac65 <mac65@mac65.com>
|
|
||||||
* @author Mike Cochrane <mikec@mikenz.geek.nz>
|
|
||||||
* @author Robin Millette <robin@millette.info>
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
class ApiTimelineHomeAction extends ApiBareAuthAction
|
|
||||||
{
|
|
||||||
var $notices = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Take arguments for running
|
|
||||||
*
|
|
||||||
* @param array $args $_REQUEST args
|
|
||||||
*
|
|
||||||
* @return boolean success flag
|
|
||||||
*/
|
|
||||||
protected function prepare(array $args=array())
|
|
||||||
{
|
|
||||||
parent::prepare($args);
|
|
||||||
|
|
||||||
$this->target = $this->getTargetProfile($this->arg('id'));
|
|
||||||
|
|
||||||
if (!($this->target instanceof Profile)) {
|
|
||||||
// TRANS: Client error displayed when requesting most recent dents by user and friends for a non-existing user.
|
|
||||||
$this->clientError(_('No such user.'), 404);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->notices = $this->getNotices();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle the request
|
|
||||||
*
|
|
||||||
* Just show the notices
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
protected function handle()
|
|
||||||
{
|
|
||||||
parent::handle();
|
|
||||||
$this->showTimeline();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show the timeline of notices
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function showTimeline()
|
|
||||||
{
|
|
||||||
$sitename = common_config('site', 'name');
|
|
||||||
// TRANS: Timeline title for user and friends. %s is a user nickname.
|
|
||||||
$title = sprintf(_("%s and friends"), $this->target->nickname);
|
|
||||||
$taguribase = TagURI::base();
|
|
||||||
$id = "tag:$taguribase:HomeTimeline:" . $this->target->id;
|
|
||||||
|
|
||||||
$subtitle = sprintf(
|
|
||||||
// TRANS: Message is used as a subtitle. %1$s is a user nickname, %2$s is a site name.
|
|
||||||
_('Updates from %1$s and friends on %2$s!'),
|
|
||||||
$this->target->nickname, $sitename
|
|
||||||
);
|
|
||||||
|
|
||||||
$logo = $this->target->avatarUrl(AVATAR_PROFILE_SIZE);
|
|
||||||
$link = common_local_url('all',
|
|
||||||
array('nickname' => $this->target->nickname));
|
|
||||||
$self = $this->getSelfUri();
|
|
||||||
|
|
||||||
switch($this->format) {
|
|
||||||
case 'xml':
|
|
||||||
$this->showXmlTimeline($this->notices);
|
|
||||||
break;
|
|
||||||
case 'rss':
|
|
||||||
$this->showRssTimeline(
|
|
||||||
$this->notices,
|
|
||||||
$title,
|
|
||||||
$link,
|
|
||||||
$subtitle,
|
|
||||||
null,
|
|
||||||
$logo,
|
|
||||||
$self
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case 'atom':
|
|
||||||
|
|
||||||
header('Content-Type: application/atom+xml; charset=utf-8');
|
|
||||||
|
|
||||||
$atom = new AtomNoticeFeed($this->auth_user);
|
|
||||||
|
|
||||||
$atom->setId($id);
|
|
||||||
$atom->setTitle($title);
|
|
||||||
$atom->setSubtitle($subtitle);
|
|
||||||
$atom->setLogo($logo);
|
|
||||||
$atom->setUpdated('now');
|
|
||||||
|
|
||||||
$atom->addLink($link);
|
|
||||||
$atom->setSelfLink($self);
|
|
||||||
|
|
||||||
$atom->addEntryFromNotices($this->notices);
|
|
||||||
$this->raw($atom->getString());
|
|
||||||
|
|
||||||
break;
|
|
||||||
case 'json':
|
|
||||||
$this->showJsonTimeline($this->notices);
|
|
||||||
break;
|
|
||||||
case 'as':
|
|
||||||
header('Content-Type: ' . ActivityStreamJSONDocument::CONTENT_TYPE);
|
|
||||||
$doc = new ActivityStreamJSONDocument($this->auth_user);
|
|
||||||
$doc->setTitle($title);
|
|
||||||
$doc->addLink($link, 'alternate', 'text/html');
|
|
||||||
$doc->addItemsFromNotices($this->notices);
|
|
||||||
$this->raw($doc->asString());
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// TRANS: Client error displayed when coming across a non-supported API method.
|
|
||||||
$this->clientError(_('API method not found.'), 404);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get notices
|
|
||||||
*
|
|
||||||
* @return array notices
|
|
||||||
*/
|
|
||||||
function getNotices()
|
|
||||||
{
|
|
||||||
$notices = array();
|
|
||||||
|
|
||||||
$stream = new InboxNoticeStream($this->target, $this->scoped);
|
|
||||||
|
|
||||||
$notice = $stream->getNotices(($this->page-1) * $this->count,
|
|
||||||
$this->count,
|
|
||||||
$this->since_id,
|
|
||||||
$this->max_id);
|
|
||||||
|
|
||||||
while ($notice->fetch()) {
|
|
||||||
$notices[] = clone($notice);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $notices;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Is this action read only?
|
|
||||||
*
|
|
||||||
* @param array $args other arguments
|
|
||||||
*
|
|
||||||
* @return boolean true
|
|
||||||
*/
|
|
||||||
function isReadOnly($args)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* When was this feed last modified?
|
|
||||||
*
|
|
||||||
* @return string datestamp of the latest notice in the stream
|
|
||||||
*/
|
|
||||||
function lastModified()
|
|
||||||
{
|
|
||||||
if (!empty($this->notices) && (count($this->notices) > 0)) {
|
|
||||||
return strtotime($this->notices[0]->created);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An entity tag for this stream
|
|
||||||
*
|
|
||||||
* Returns an Etag based on the action name, language, user ID, and
|
|
||||||
* timestamps of the first and last notice in the timeline
|
|
||||||
*
|
|
||||||
* @return string etag
|
|
||||||
*/
|
|
||||||
function etag()
|
|
||||||
{
|
|
||||||
if (!empty($this->notices) && (count($this->notices) > 0)) {
|
|
||||||
|
|
||||||
$last = count($this->notices) - 1;
|
|
||||||
|
|
||||||
return '"' . implode(
|
|
||||||
':',
|
|
||||||
array($this->arg('action'),
|
|
||||||
common_user_cache_hash($this->auth_user),
|
|
||||||
common_language(),
|
|
||||||
$this->target->id,
|
|
||||||
strtotime($this->notices[0]->created),
|
|
||||||
strtotime($this->notices[$last]->created))
|
|
||||||
)
|
|
||||||
. '"';
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,248 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StatusNet, the distributed open-source microblogging tool
|
|
||||||
*
|
|
||||||
* Show a list's notices
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Craig Andrews <candrews@integralblue.com>
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @author Jeffery To <jeffery.to@gmail.com>
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @copyright 2009 StatusNet, Inc.
|
|
||||||
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('STATUSNET')) {
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
require_once INSTALLDIR . '/lib/atomlistnoticefeed.php';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the most recent notices (default 20) posted to the list specified by ID
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Craig Andrews <candrews@integralblue.com>
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @author Jeffery To <jeffery.to@gmail.com>
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
class ApiTimelineListAction extends ApiPrivateAuthAction
|
|
||||||
{
|
|
||||||
|
|
||||||
var $list = null;
|
|
||||||
var $notices = array();
|
|
||||||
var $next_cursor = 0;
|
|
||||||
var $prev_cursor = 0;
|
|
||||||
var $cursor = -1;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Take arguments for running
|
|
||||||
*
|
|
||||||
* @param array $args $_REQUEST args
|
|
||||||
*
|
|
||||||
* @return boolean success flag
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
protected function prepare(array $args=array())
|
|
||||||
{
|
|
||||||
parent::prepare($args);
|
|
||||||
|
|
||||||
$this->cursor = (int) $this->arg('cursor', -1);
|
|
||||||
$this->list = $this->getTargetList($this->arg('user'), $this->arg('id'));
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle the request
|
|
||||||
*
|
|
||||||
* Just show the notices
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
protected function handle()
|
|
||||||
{
|
|
||||||
parent::handle();
|
|
||||||
|
|
||||||
if (empty($this->list)) {
|
|
||||||
// TRANS: Client error displayed trying to perform an action related to a non-existing list.
|
|
||||||
$this->clientError(_('List not found.'), 404);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->getNotices();
|
|
||||||
$this->showTimeline();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show the timeline of notices
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function showTimeline()
|
|
||||||
{
|
|
||||||
// We'll pull common formatting out of this for other formats
|
|
||||||
$atom = new AtomListNoticeFeed($this->list, $this->auth_user);
|
|
||||||
|
|
||||||
$self = $this->getSelfUri();
|
|
||||||
|
|
||||||
switch($this->format) {
|
|
||||||
case 'xml':
|
|
||||||
$this->initDocument('xml');
|
|
||||||
$this->elementStart('statuses_list',
|
|
||||||
array('xmlns:statusnet' => 'http://status.net/schema/api/1/'));
|
|
||||||
$this->elementStart('statuses', array('type' => 'array'));
|
|
||||||
|
|
||||||
foreach ($this->notices as $n) {
|
|
||||||
$twitter_status = $this->twitterStatusArray($n);
|
|
||||||
$this->showTwitterXmlStatus($twitter_status);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->elementEnd('statuses');
|
|
||||||
$this->element('next_cursor', null, $this->next_cursor);
|
|
||||||
$this->element('previous_cursor', null, $this->prev_cursor);
|
|
||||||
$this->elementEnd('statuses_list');
|
|
||||||
$this->endDocument('xml');
|
|
||||||
break;
|
|
||||||
case 'rss':
|
|
||||||
$this->showRssTimeline(
|
|
||||||
$this->notices,
|
|
||||||
$atom->title,
|
|
||||||
$this->list->getUri(),
|
|
||||||
$atom->subtitle,
|
|
||||||
null,
|
|
||||||
$atom->logo,
|
|
||||||
$self
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case 'atom':
|
|
||||||
header('Content-Type: application/atom+xml; charset=utf-8');
|
|
||||||
|
|
||||||
try {
|
|
||||||
$atom->setId($self);
|
|
||||||
$atom->setSelfLink($self);
|
|
||||||
$atom->addEntryFromNotices($this->notices);
|
|
||||||
$this->raw($atom->getString());
|
|
||||||
} catch (Atom10FeedException $e) {
|
|
||||||
// TRANS: Server error displayed whe trying to get a timeline fails.
|
|
||||||
// TRANS: %s is the error message.
|
|
||||||
$this->serverError(sprintf(_('Could not generate feed for list - %s'), $e->getMessage()));
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
case 'json':
|
|
||||||
$this->initDocument('json');
|
|
||||||
|
|
||||||
$statuses = array();
|
|
||||||
foreach ($this->notices as $n) {
|
|
||||||
$twitter_status = $this->twitterStatusArray($n);
|
|
||||||
array_push($statuses, $twitter_status);
|
|
||||||
}
|
|
||||||
|
|
||||||
$statuses_list = array('statuses' => $statuses,
|
|
||||||
'next_cursor' => $this->next_cusror,
|
|
||||||
'next_cursor_str' => strval($this->next_cusror),
|
|
||||||
'previous_cursor' => $this->prev_cusror,
|
|
||||||
'previous_cursor_str' => strval($this->prev_cusror)
|
|
||||||
);
|
|
||||||
$this->showJsonObjects($statuses_list);
|
|
||||||
|
|
||||||
$this->initDocument('json');
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// TRANS: Client error displayed when coming across a non-supported API method.
|
|
||||||
$this->clientError(_('API method not found.'), 404);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get notices
|
|
||||||
*
|
|
||||||
* @return array notices
|
|
||||||
*/
|
|
||||||
function getNotices()
|
|
||||||
{
|
|
||||||
$fn = array($this->list, 'getNotices');
|
|
||||||
list($this->notices, $this->next_cursor, $this->prev_cursor) =
|
|
||||||
Profile_list::getAtCursor($fn, array(), $this->cursor, 20);
|
|
||||||
if (!$this->notices) {
|
|
||||||
$this->notices = array();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Is this action read only?
|
|
||||||
*
|
|
||||||
* @param array $args other arguments
|
|
||||||
*
|
|
||||||
* @return boolean true
|
|
||||||
*/
|
|
||||||
function isReadOnly($args)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* When was this feed last modified?
|
|
||||||
*
|
|
||||||
* @return string datestamp of the latest notice in the stream
|
|
||||||
*/
|
|
||||||
function lastModified()
|
|
||||||
{
|
|
||||||
if (!empty($this->notices) && (count($this->notices) > 0)) {
|
|
||||||
return strtotime($this->notices[0]->created);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An entity tag for this stream
|
|
||||||
*
|
|
||||||
* Returns an Etag based on the action name, language, list ID and
|
|
||||||
* timestamps of the first and last notice in the timeline
|
|
||||||
*
|
|
||||||
* @return string etag
|
|
||||||
*/
|
|
||||||
function etag()
|
|
||||||
{
|
|
||||||
if (!empty($this->notices) && (count($this->notices) > 0)) {
|
|
||||||
|
|
||||||
$last = count($this->notices) - 1;
|
|
||||||
|
|
||||||
return '"' . implode(
|
|
||||||
':',
|
|
||||||
array($this->arg('action'),
|
|
||||||
common_language(),
|
|
||||||
$this->list->id,
|
|
||||||
strtotime($this->notices[0]->created),
|
|
||||||
strtotime($this->notices[$last]->created))
|
|
||||||
)
|
|
||||||
. '"';
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,254 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StatusNet, the distributed open-source microblogging tool
|
|
||||||
*
|
|
||||||
* Show notices mentioning a user (@nickname)
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Craig Andrews <candrews@integralblue.com>
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @author Jeffery To <jeffery.to@gmail.com>
|
|
||||||
* @author mac65 <mac65@mac65.com>
|
|
||||||
* @author Mike Cochrane <mikec@mikenz.geek.nz>
|
|
||||||
* @author Robin Millette <robin@millette.info>
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @copyright 2009 StatusNet, Inc.
|
|
||||||
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('STATUSNET')) {
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the most recent (default 20) mentions (status containing @nickname)
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Craig Andrews <candrews@integralblue.com>
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @author Jeffery To <jeffery.to@gmail.com>
|
|
||||||
* @author mac65 <mac65@mac65.com>
|
|
||||||
* @author Mike Cochrane <mikec@mikenz.geek.nz>
|
|
||||||
* @author Robin Millette <robin@millette.info>
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
class ApiTimelineMentionsAction extends ApiBareAuthAction
|
|
||||||
{
|
|
||||||
var $notices = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Take arguments for running
|
|
||||||
*
|
|
||||||
* @param array $args $_REQUEST args
|
|
||||||
*
|
|
||||||
* @return boolean success flag
|
|
||||||
*/
|
|
||||||
protected function prepare(array $args=array())
|
|
||||||
{
|
|
||||||
parent::prepare($args);
|
|
||||||
|
|
||||||
$this->target = $this->getTargetProfile($this->arg('id'));
|
|
||||||
|
|
||||||
if (!($this->target instanceof Profile)) {
|
|
||||||
// TRANS: Client error displayed when requesting most recent mentions for a non-existing user.
|
|
||||||
$this->clientError(_('No such user.'), 404);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->notices = $this->getNotices();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle the request
|
|
||||||
*
|
|
||||||
* Just show the notices
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
protected function handle()
|
|
||||||
{
|
|
||||||
parent::handle();
|
|
||||||
$this->showTimeline();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show the timeline of notices
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function showTimeline()
|
|
||||||
{
|
|
||||||
$sitename = common_config('site', 'name');
|
|
||||||
$title = sprintf(
|
|
||||||
// TRANS: Title for timeline of most recent mentions of a user.
|
|
||||||
// TRANS: %1$s is the StatusNet sitename, %2$s is a user nickname.
|
|
||||||
_('%1$s / Updates mentioning %2$s'),
|
|
||||||
$sitename, $this->target->nickname
|
|
||||||
);
|
|
||||||
$taguribase = TagURI::base();
|
|
||||||
$id = "tag:$taguribase:Mentions:" . $this->target->id;
|
|
||||||
|
|
||||||
$logo = $this->target->avatarUrl(AVATAR_PROFILE_SIZE);
|
|
||||||
$link = common_local_url('replies',
|
|
||||||
array('nickname' => $this->target->nickname));
|
|
||||||
$self = $this->getSelfUri();
|
|
||||||
|
|
||||||
$subtitle = sprintf(
|
|
||||||
// TRANS: Subtitle for timeline of most recent mentions of a user.
|
|
||||||
// TRANS: %1$s is the StatusNet sitename, %2$s is a user nickname,
|
|
||||||
// TRANS: %3$s is a user's full name.
|
|
||||||
_('%1$s updates that reply to updates from %3$s / %2$s.'),
|
|
||||||
$sitename, $this->target->nickname, $this->target->getBestName()
|
|
||||||
);
|
|
||||||
|
|
||||||
switch($this->format) {
|
|
||||||
case 'xml':
|
|
||||||
$this->showXmlTimeline($this->notices);
|
|
||||||
break;
|
|
||||||
case 'rss':
|
|
||||||
$this->showRssTimeline(
|
|
||||||
$this->notices,
|
|
||||||
$title,
|
|
||||||
$link,
|
|
||||||
$subtitle,
|
|
||||||
null,
|
|
||||||
$logo,
|
|
||||||
$self
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case 'atom':
|
|
||||||
header('Content-Type: application/atom+xml; charset=utf-8');
|
|
||||||
|
|
||||||
$atom = new AtomNoticeFeed($this->auth_user);
|
|
||||||
|
|
||||||
$atom->setId($id);
|
|
||||||
$atom->setTitle($title);
|
|
||||||
$atom->setSubtitle($subtitle);
|
|
||||||
$atom->setLogo($logo);
|
|
||||||
$atom->setUpdated('now');
|
|
||||||
|
|
||||||
$atom->addLink($link);
|
|
||||||
$atom->setSelfLink($self);
|
|
||||||
|
|
||||||
$atom->addEntryFromNotices($this->notices);
|
|
||||||
$this->raw($atom->getString());
|
|
||||||
|
|
||||||
break;
|
|
||||||
case 'json':
|
|
||||||
$this->showJsonTimeline($this->notices);
|
|
||||||
break;
|
|
||||||
case 'as':
|
|
||||||
header('Content-Type: ' . ActivityStreamJSONDocument::CONTENT_TYPE);
|
|
||||||
$doc = new ActivityStreamJSONDocument($this->auth_user);
|
|
||||||
$doc->setTitle($title);
|
|
||||||
$doc->addLink($link, 'alternate', 'text/html');
|
|
||||||
$doc->addItemsFromNotices($this->notices);
|
|
||||||
$this->raw($doc->asString());
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// TRANS: Client error displayed when coming across a non-supported API method.
|
|
||||||
$this->clientError(_('API method not found.'), $code = 404);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get notices
|
|
||||||
*
|
|
||||||
* @return array notices
|
|
||||||
*/
|
|
||||||
function getNotices()
|
|
||||||
{
|
|
||||||
$notices = array();
|
|
||||||
|
|
||||||
$stream = new ReplyNoticeStream($this->target->id, $this->scoped);
|
|
||||||
|
|
||||||
$notice = $stream->getNotices(($this->page - 1) * $this->count,
|
|
||||||
$this->count,
|
|
||||||
$this->since_id,
|
|
||||||
$this->max_id);
|
|
||||||
|
|
||||||
while ($notice->fetch()) {
|
|
||||||
$notices[] = clone($notice);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $notices;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Is this action read only?
|
|
||||||
*
|
|
||||||
* @param array $args other arguments
|
|
||||||
*
|
|
||||||
* @return boolean true
|
|
||||||
*/
|
|
||||||
function isReadOnly($args)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* When was this feed last modified?
|
|
||||||
*
|
|
||||||
* @return string datestamp of the latest notice in the stream
|
|
||||||
*/
|
|
||||||
function lastModified()
|
|
||||||
{
|
|
||||||
if (!empty($this->notices) && (count($this->notices) > 0)) {
|
|
||||||
return strtotime($this->notices[0]->created);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An entity tag for this stream
|
|
||||||
*
|
|
||||||
* Returns an Etag based on the action name, language, user ID, and
|
|
||||||
* timestamps of the first and last notice in the timeline
|
|
||||||
*
|
|
||||||
* @return string etag
|
|
||||||
*/
|
|
||||||
function etag()
|
|
||||||
{
|
|
||||||
if (!empty($this->notices) && (count($this->notices) > 0)) {
|
|
||||||
|
|
||||||
$last = count($this->notices) - 1;
|
|
||||||
|
|
||||||
return '"' . implode(
|
|
||||||
':',
|
|
||||||
array($this->arg('action'),
|
|
||||||
common_user_cache_hash($this->auth_user),
|
|
||||||
common_language(),
|
|
||||||
$this->target->id,
|
|
||||||
strtotime($this->notices[0]->created),
|
|
||||||
strtotime($this->notices[$last]->created))
|
|
||||||
)
|
|
||||||
. '"';
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
if (!defined('GNUSOCIAL')) { exit(1); }
|
|
||||||
|
|
||||||
class ApiTimelineNetworkPublicAction extends ApiTimelinePublicAction
|
|
||||||
{
|
|
||||||
function title()
|
|
||||||
{
|
|
||||||
return sprintf(_("%s network public timeline"), common_config('site', 'name'));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function getStream()
|
|
||||||
{
|
|
||||||
if (!$this->scoped instanceof Profile && common_config('public', 'localonly')) {
|
|
||||||
$this->clientError(_('Network wide public feed is not permitted without authorization'), 403);
|
|
||||||
}
|
|
||||||
return new NetworkPublicNoticeStream($this->scoped);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,335 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StatusNet, the distributed open-source microblogging tool
|
|
||||||
*
|
|
||||||
* Show the public timeline
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Craig Andrews <candrews@integralblue.com>
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @author Jeffery To <jeffery.to@gmail.com>
|
|
||||||
* @author mac65 <mac65@mac65.com>
|
|
||||||
* @author Mike Cochrane <mikec@mikenz.geek.nz>
|
|
||||||
* @author Robin Millette <robin@millette.info>
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @copyright 2009 StatusNet, Inc.
|
|
||||||
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('STATUSNET')) {
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the most recent notices (default 20) posted by everybody
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Craig Andrews <candrews@integralblue.com>
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @author Jeffery To <jeffery.to@gmail.com>
|
|
||||||
* @author mac65 <mac65@mac65.com>
|
|
||||||
* @author Mike Cochrane <mikec@mikenz.geek.nz>
|
|
||||||
* @author Robin Millette <robin@millette.info>
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* External API usage documentation. Please update when you change how this method works. */
|
|
||||||
|
|
||||||
/*! @page publictimeline statuses/public_timeline
|
|
||||||
|
|
||||||
@section Description
|
|
||||||
Returns the 20 most recent notices from users throughout the system who have
|
|
||||||
uploaded their own avatars. Depending on configuration, it may or may not
|
|
||||||
not include notices from automatic posting services.
|
|
||||||
|
|
||||||
@par URL patterns
|
|
||||||
@li /api/statuses/public_timeline.:format
|
|
||||||
|
|
||||||
@par Formats (:format)
|
|
||||||
xml, json, rss, atom
|
|
||||||
|
|
||||||
@par HTTP Method(s)
|
|
||||||
GET
|
|
||||||
|
|
||||||
@par Requires Authentication
|
|
||||||
No
|
|
||||||
|
|
||||||
@param since_id (Optional) Returns only statuses with an ID greater
|
|
||||||
than (that is, more recent than) the specified ID.
|
|
||||||
@param max_id (Optional) Returns only statuses with an ID less than
|
|
||||||
(that is, older than) or equal to the specified ID.
|
|
||||||
@param count (Optional) Specifies the number of statuses to retrieve.
|
|
||||||
@param page (Optional) Specifies the page of results to retrieve.
|
|
||||||
|
|
||||||
@sa @ref apiroot
|
|
||||||
|
|
||||||
@subsection usagenotes Usage notes
|
|
||||||
@li The URL pattern is relative to the @ref apiroot.
|
|
||||||
@li The XML response uses <a href="http://georss.org/Main_Page">GeoRSS</a>
|
|
||||||
to encode the latitude and longitude (see example response below <georss:point>).
|
|
||||||
|
|
||||||
@subsection exampleusage Example usage
|
|
||||||
|
|
||||||
@verbatim
|
|
||||||
curl http://identi.ca/api/statuses/friends_timeline/evan.xml?count=1&page=2
|
|
||||||
@endverbatim
|
|
||||||
|
|
||||||
@subsection exampleresponse Example response
|
|
||||||
|
|
||||||
@verbatim
|
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<statuses type="array">
|
|
||||||
<status>
|
|
||||||
<text>@skwashd oh, commbank reenabled me super quick both times. but disconcerting when you don't expect it though</text>
|
|
||||||
<truncated>false</truncated>
|
|
||||||
<created_at>Sat Apr 17 00:49:12 +0000 2010</created_at>
|
|
||||||
<in_reply_to_status_id>28838393</in_reply_to_status_id>
|
|
||||||
<source>xmpp</source>
|
|
||||||
<id>28838456</id>
|
|
||||||
<in_reply_to_user_id>39303</in_reply_to_user_id>
|
|
||||||
<in_reply_to_screen_name>skwashd</in_reply_to_screen_name>
|
|
||||||
<geo></geo>
|
|
||||||
<favorited>false</favorited>
|
|
||||||
<user>
|
|
||||||
<id>44517</id>
|
|
||||||
<name>joshua may</name>
|
|
||||||
<screen_name>notjosh</screen_name>
|
|
||||||
<location></location>
|
|
||||||
<description></description>
|
|
||||||
<profile_image_url>http://avatar.identi.ca/44517-48-20090321004106.jpeg</profile_image_url>
|
|
||||||
<url></url>
|
|
||||||
<protected>false</protected>
|
|
||||||
<followers_count>17</followers_count>
|
|
||||||
<profile_background_color></profile_background_color>
|
|
||||||
<profile_text_color></profile_text_color>
|
|
||||||
<profile_link_color></profile_link_color>
|
|
||||||
<profile_sidebar_fill_color></profile_sidebar_fill_color>
|
|
||||||
<profile_sidebar_border_color></profile_sidebar_border_color>
|
|
||||||
<friends_count>20</friends_count>
|
|
||||||
<created_at>Sat Mar 21 00:40:25 +0000 2009</created_at>
|
|
||||||
<favourites_count>0</favourites_count>
|
|
||||||
<utc_offset>0</utc_offset>
|
|
||||||
<time_zone>UTC</time_zone>
|
|
||||||
<profile_background_image_url></profile_background_image_url>
|
|
||||||
<profile_background_tile>false</profile_background_tile>
|
|
||||||
<statuses_count>100</statuses_count>
|
|
||||||
<following>false</following>
|
|
||||||
<notifications>false</notifications>
|
|
||||||
</user>
|
|
||||||
</status>
|
|
||||||
[....]
|
|
||||||
</statuses>
|
|
||||||
@endverbatim
|
|
||||||
*/
|
|
||||||
class ApiTimelinePublicAction extends ApiPrivateAuthAction
|
|
||||||
{
|
|
||||||
var $notices = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Take arguments for running
|
|
||||||
*
|
|
||||||
* @param array $args $_REQUEST args
|
|
||||||
*
|
|
||||||
* @return boolean success flag
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
protected function prepare(array $args=array())
|
|
||||||
{
|
|
||||||
parent::prepare($args);
|
|
||||||
|
|
||||||
$this->notices = $this->getNotices();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle the request
|
|
||||||
*
|
|
||||||
* Just show the notices
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
protected function handle()
|
|
||||||
{
|
|
||||||
parent::handle();
|
|
||||||
$this->showTimeline();
|
|
||||||
}
|
|
||||||
|
|
||||||
function title()
|
|
||||||
{
|
|
||||||
// TRANS: Title for site timeline. %s is the GNU social sitename.
|
|
||||||
return sprintf(_("%s public timeline"), common_config('site', 'name'));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show the timeline of notices
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function showTimeline()
|
|
||||||
{
|
|
||||||
$nonapi_action = substr($this->action, strlen('apitimeline')); // Just so we don't need to set this explicitly
|
|
||||||
|
|
||||||
$sitelogo = (common_config('site', 'logo')) ? common_config('site', 'logo') : Theme::path('logo.png');
|
|
||||||
$title = $this->title();
|
|
||||||
$taguribase = TagURI::base();
|
|
||||||
$id = "tag:$taguribase:" . ucfirst($nonapi_action) . 'Timeline'; // Public or Networkpublic probably
|
|
||||||
$link = common_local_url($nonapi_action);
|
|
||||||
$self = $this->getSelfUri();
|
|
||||||
// TRANS: Subtitle for site timeline. %s is the GNU social sitename.
|
|
||||||
$subtitle = sprintf(_("%s updates from everyone!"), common_config('site', 'name'));
|
|
||||||
|
|
||||||
switch($this->format) {
|
|
||||||
case 'xml':
|
|
||||||
$this->showXmlTimeline($this->notices);
|
|
||||||
break;
|
|
||||||
case 'rss':
|
|
||||||
$this->showRssTimeline(
|
|
||||||
$this->notices,
|
|
||||||
$title,
|
|
||||||
$link,
|
|
||||||
$subtitle,
|
|
||||||
null,
|
|
||||||
$sitelogo,
|
|
||||||
$self
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case 'atom':
|
|
||||||
|
|
||||||
header('Content-Type: application/atom+xml; charset=utf-8');
|
|
||||||
|
|
||||||
$atom = new AtomNoticeFeed($this->auth_user);
|
|
||||||
|
|
||||||
$atom->setId($id);
|
|
||||||
$atom->setTitle($title);
|
|
||||||
$atom->setSubtitle($subtitle);
|
|
||||||
$atom->setLogo($sitelogo);
|
|
||||||
$atom->setUpdated('now');
|
|
||||||
$atom->addLink(common_local_url($nonapi_action));
|
|
||||||
$atom->setSelfLink($self);
|
|
||||||
$atom->addEntryFromNotices($this->notices);
|
|
||||||
|
|
||||||
$this->raw($atom->getString());
|
|
||||||
|
|
||||||
break;
|
|
||||||
case 'json':
|
|
||||||
$this->showJsonTimeline($this->notices);
|
|
||||||
break;
|
|
||||||
case 'as':
|
|
||||||
header('Content-Type: ' . ActivityStreamJSONDocument::CONTENT_TYPE);
|
|
||||||
$doc = new ActivityStreamJSONDocument($this->auth_user);
|
|
||||||
$doc->setTitle($title);
|
|
||||||
$doc->addLink($link, 'alternate', 'text/html');
|
|
||||||
$doc->addItemsFromNotices($this->notices);
|
|
||||||
$this->raw($doc->asString());
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// TRANS: Client error displayed when coming across a non-supported API method.
|
|
||||||
$this->clientError(_('API method not found.'), $code = 404);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get notices
|
|
||||||
*
|
|
||||||
* @return array notices
|
|
||||||
*/
|
|
||||||
function getNotices()
|
|
||||||
{
|
|
||||||
$notices = array();
|
|
||||||
|
|
||||||
$stream = $this->getStream();
|
|
||||||
|
|
||||||
$notice = $stream->getNotices(($this->page - 1) * $this->count,
|
|
||||||
$this->count,
|
|
||||||
$this->since_id,
|
|
||||||
$this->max_id);
|
|
||||||
|
|
||||||
$notices = $notice->fetchAll();
|
|
||||||
|
|
||||||
NoticeList::prefill($notices);
|
|
||||||
|
|
||||||
return $notices;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function getStream()
|
|
||||||
{
|
|
||||||
return new PublicNoticeStream($this->scoped);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Is this action read only?
|
|
||||||
*
|
|
||||||
* @param array $args other arguments
|
|
||||||
*
|
|
||||||
* @return boolean true
|
|
||||||
*/
|
|
||||||
function isReadOnly($args)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* When was this feed last modified?
|
|
||||||
*
|
|
||||||
* @return string datestamp of the latest notice in the stream
|
|
||||||
*/
|
|
||||||
function lastModified()
|
|
||||||
{
|
|
||||||
if (!empty($this->notices) && (count($this->notices) > 0)) {
|
|
||||||
return strtotime($this->notices[0]->created);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An entity tag for this stream
|
|
||||||
*
|
|
||||||
* Returns an Etag based on the action name, language, and
|
|
||||||
* timestamps of the first and last notice in the timeline
|
|
||||||
*
|
|
||||||
* @return string etag
|
|
||||||
*/
|
|
||||||
function etag()
|
|
||||||
{
|
|
||||||
if (!empty($this->notices) && (count($this->notices) > 0)) {
|
|
||||||
|
|
||||||
$last = count($this->notices) - 1;
|
|
||||||
|
|
||||||
return '"' . implode(
|
|
||||||
':',
|
|
||||||
array($this->arg('action'),
|
|
||||||
common_user_cache_hash($this->auth_user),
|
|
||||||
common_language(),
|
|
||||||
strtotime($this->notices[0]->created),
|
|
||||||
strtotime($this->notices[$last]->created))
|
|
||||||
)
|
|
||||||
. '"';
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,84 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StatusNet, the distributed open-source microblogging tool
|
|
||||||
*
|
|
||||||
* Show authenticating user's most recent repeats
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @copyright 2009 StatusNet, Inc.
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('STATUSNET')) {
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show authenticating user's most recent repeats
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
class ApiTimelineRetweetedByMeAction extends ApiAuthAction
|
|
||||||
{
|
|
||||||
const DEFAULTCOUNT = 20;
|
|
||||||
const MAXCOUNT = 200;
|
|
||||||
const MAXNOTICES = 3200;
|
|
||||||
|
|
||||||
var $repeats = null;
|
|
||||||
var $cnt = self::DEFAULTCOUNT;
|
|
||||||
var $page = 1;
|
|
||||||
var $since_id = null;
|
|
||||||
var $max_id = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Take arguments for running
|
|
||||||
*
|
|
||||||
* @param array $args $_REQUEST args
|
|
||||||
*
|
|
||||||
* @return boolean success flag
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
function prepare($args)
|
|
||||||
{
|
|
||||||
parent::prepare($args);
|
|
||||||
|
|
||||||
// TRANS: Server error displayed calling unimplemented API method for 'retweeted by me'.
|
|
||||||
$this->serverError(_('Unimplemented.'), 503);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return true if read only.
|
|
||||||
*
|
|
||||||
* @param array $args other arguments
|
|
||||||
*
|
|
||||||
* @return boolean is read only action?
|
|
||||||
*/
|
|
||||||
function isReadOnly($args)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,166 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StatusNet, the distributed open-source microblogging tool
|
|
||||||
*
|
|
||||||
* Show most recent notices that are repeats in user's inbox
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @copyright 2009 StatusNet, Inc.
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('STATUSNET')) {
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show most recent notices that are repeats in user's inbox
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
class ApiTimelineRetweetedToMeAction extends ApiAuthAction
|
|
||||||
{
|
|
||||||
const DEFAULTCOUNT = 20;
|
|
||||||
const MAXCOUNT = 200;
|
|
||||||
const MAXNOTICES = 3200;
|
|
||||||
|
|
||||||
var $repeats = null;
|
|
||||||
var $cnt = self::DEFAULTCOUNT;
|
|
||||||
var $page = 1;
|
|
||||||
var $since_id = null;
|
|
||||||
var $max_id = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Take arguments for running
|
|
||||||
*
|
|
||||||
* @param array $args $_REQUEST args
|
|
||||||
*
|
|
||||||
* @return boolean success flag
|
|
||||||
*/
|
|
||||||
function prepare($args)
|
|
||||||
{
|
|
||||||
parent::prepare($args);
|
|
||||||
|
|
||||||
$cnt = $this->int('count', self::DEFAULTCOUNT, self::MAXCOUNT, 1);
|
|
||||||
|
|
||||||
$page = $this->int('page', 1, (self::MAXNOTICES/$this->cnt));
|
|
||||||
|
|
||||||
$since_id = $this->int('since_id');
|
|
||||||
|
|
||||||
$max_id = $this->int('max_id');
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle the request
|
|
||||||
*
|
|
||||||
* show a timeline of the user's repeated notices
|
|
||||||
*
|
|
||||||
* @param array $args $_REQUEST data (unused)
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function handle($args)
|
|
||||||
{
|
|
||||||
parent::handle($args);
|
|
||||||
|
|
||||||
$offset = ($this->page-1) * $this->cnt;
|
|
||||||
$limit = $this->cnt;
|
|
||||||
|
|
||||||
// TRANS: Title for Atom feed "repeated to me". %s is the user nickname.
|
|
||||||
$title = sprintf(_("Repeated to %s"), $this->auth_user->nickname);
|
|
||||||
$subtitle = sprintf(
|
|
||||||
// @todo FIXME: $profile is not defined.
|
|
||||||
// TRANS: Subtitle for API action that shows most recent notices that are repeats in user's inbox.
|
|
||||||
// TRANS: %1$s is the sitename, %2$s is a user nickname, %3$s is a user profile name.
|
|
||||||
_('%1$s notices that were to repeated to %2$s / %3$s.'),
|
|
||||||
$sitename, $this->user->nickname, $profile->getBestName()
|
|
||||||
);
|
|
||||||
$taguribase = TagURI::base();
|
|
||||||
$id = "tag:$taguribase:RepeatedToMe:" . $this->auth_user->id;
|
|
||||||
|
|
||||||
$link = common_local_url(
|
|
||||||
'all',
|
|
||||||
array('nickname' => $this->auth_user->nickname)
|
|
||||||
);
|
|
||||||
|
|
||||||
$strm = $this->auth_user->repeatedToMe($offset, $limit, $this->since_id, $this->max_id);
|
|
||||||
|
|
||||||
switch ($this->format) {
|
|
||||||
case 'xml':
|
|
||||||
$this->showXmlTimeline($strm);
|
|
||||||
break;
|
|
||||||
case 'json':
|
|
||||||
$this->showJsonTimeline($strm);
|
|
||||||
break;
|
|
||||||
case 'atom':
|
|
||||||
header('Content-Type: application/atom+xml; charset=utf-8');
|
|
||||||
|
|
||||||
$atom = new AtomNoticeFeed($this->auth_user);
|
|
||||||
|
|
||||||
$atom->setId($id);
|
|
||||||
$atom->setTitle($title);
|
|
||||||
$atom->setSubtitle($subtitle);
|
|
||||||
$atom->setUpdated('now');
|
|
||||||
$atom->addLink($link);
|
|
||||||
|
|
||||||
$id = $this->arg('id');
|
|
||||||
|
|
||||||
$atom->setSelfLink($self);
|
|
||||||
$atom->addEntryFromNotices($strm);
|
|
||||||
|
|
||||||
$this->raw($atom->getString());
|
|
||||||
|
|
||||||
break;
|
|
||||||
case 'as':
|
|
||||||
header('Content-Type: ' . ActivityStreamJSONDocument::CONTENT_TYPE);
|
|
||||||
$doc = new ActivityStreamJSONDocument($this->auth_user);
|
|
||||||
$doc->setTitle($title);
|
|
||||||
$doc->addLink($link, 'alternate', 'text/html');
|
|
||||||
$doc->addItemsFromNotices($strm);
|
|
||||||
$this->raw($doc->asString());
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// TRANS: Client error displayed when coming across a non-supported API method.
|
|
||||||
$this->clientError(_('API method not found.'), $code = 404);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return true if read only.
|
|
||||||
*
|
|
||||||
* MAY override
|
|
||||||
*
|
|
||||||
* @param array $args other arguments
|
|
||||||
*
|
|
||||||
* @return boolean is read only action?
|
|
||||||
*/
|
|
||||||
function isReadOnly($args)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,172 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StatusNet, the distributed open-source microblogging tool
|
|
||||||
*
|
|
||||||
* Show authenticating user's most recent notices that have been repeated
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @copyright 2009 StatusNet, Inc.
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('STATUSNET')) {
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show authenticating user's most recent notices that have been repeated
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
class ApiTimelineRetweetsOfMeAction extends ApiAuthAction
|
|
||||||
{
|
|
||||||
const DEFAULTCOUNT = 20;
|
|
||||||
const MAXCOUNT = 200;
|
|
||||||
const MAXNOTICES = 3200;
|
|
||||||
|
|
||||||
var $repeats = null;
|
|
||||||
var $cnt = self::DEFAULTCOUNT;
|
|
||||||
var $page = 1;
|
|
||||||
var $since_id = null;
|
|
||||||
var $max_id = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Take arguments for running
|
|
||||||
*
|
|
||||||
* @param array $args $_REQUEST args
|
|
||||||
*
|
|
||||||
* @return boolean success flag
|
|
||||||
*/
|
|
||||||
function prepare($args)
|
|
||||||
{
|
|
||||||
parent::prepare($args);
|
|
||||||
|
|
||||||
$cnt = $this->int('count', self::DEFAULTCOUNT, self::MAXCOUNT, 1);
|
|
||||||
|
|
||||||
$page = $this->int('page', 1, (self::MAXNOTICES/$this->cnt));
|
|
||||||
|
|
||||||
$since_id = $this->int('since_id');
|
|
||||||
|
|
||||||
$max_id = $this->int('max_id');
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle the request
|
|
||||||
*
|
|
||||||
* show a timeline of the user's repeated notices
|
|
||||||
*
|
|
||||||
* @param array $args $_REQUEST data (unused)
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function handle($args)
|
|
||||||
{
|
|
||||||
parent::handle($args);
|
|
||||||
|
|
||||||
$offset = ($this->page-1) * $this->cnt;
|
|
||||||
$limit = $this->cnt;
|
|
||||||
|
|
||||||
// TRANS: Title of list of repeated notices of the logged in user.
|
|
||||||
// TRANS: %s is the nickname of the logged in user.
|
|
||||||
$title = sprintf(_("Repeats of %s"), $this->auth_user->nickname);
|
|
||||||
$sitename = common_config('site', 'name');
|
|
||||||
|
|
||||||
$profile = $this->auth_user->getProfile();
|
|
||||||
|
|
||||||
$subtitle = sprintf(
|
|
||||||
// TRANS: Subtitle of API time with retweets of me.
|
|
||||||
// TRANS: %1$s is the StatusNet sitename, %2$s is the user nickname, %3$s is the user profile name.
|
|
||||||
_('%1$s notices that %2$s / %3$s has repeated.'),
|
|
||||||
$sitename, $this->auth_user->nickname, $profile->getBestName()
|
|
||||||
);
|
|
||||||
|
|
||||||
$taguribase = TagURI::base();
|
|
||||||
$id = "tag:$taguribase:RepeatsOfMe:" . $this->auth_user->id;
|
|
||||||
|
|
||||||
$link = common_local_url(
|
|
||||||
'all',
|
|
||||||
array('nickname' => $this->auth_user->nickname)
|
|
||||||
);
|
|
||||||
|
|
||||||
// This is a really bad query for some reason
|
|
||||||
|
|
||||||
if (!common_config('performance', 'high')) {
|
|
||||||
$strm = $this->auth_user->repeatsOfMe($offset, $limit, $this->since_id, $this->max_id);
|
|
||||||
} else {
|
|
||||||
$strm = new Notice();
|
|
||||||
$strm->whereAdd('0 = 1');
|
|
||||||
$strm->find();
|
|
||||||
}
|
|
||||||
|
|
||||||
switch ($this->format) {
|
|
||||||
case 'xml':
|
|
||||||
$this->showXmlTimeline($strm);
|
|
||||||
break;
|
|
||||||
case 'json':
|
|
||||||
$this->showJsonTimeline($strm);
|
|
||||||
break;
|
|
||||||
case 'atom':
|
|
||||||
header('Content-Type: application/atom+xml; charset=utf-8');
|
|
||||||
$atom = new AtomNoticeFeed($this->auth_user);
|
|
||||||
$atom->setId($id);
|
|
||||||
$atom->setTitle($title);
|
|
||||||
$atom->setSubtitle($subtitle);
|
|
||||||
$atom->setUpdated('now');
|
|
||||||
$atom->addLink($link);
|
|
||||||
$atom->setSelfLink($this->getSelfUri());
|
|
||||||
$atom->addEntryFromNotices($strm);
|
|
||||||
$this->raw($atom->getString());
|
|
||||||
break;
|
|
||||||
case 'as':
|
|
||||||
header('Content-Type: ' . ActivityStreamJSONDocument::CONTENT_TYPE);
|
|
||||||
$doc = new ActivityStreamJSONDocument($this->auth_user);
|
|
||||||
$doc->setTitle($title);
|
|
||||||
$doc->addLink($link, 'alternate', 'text/html');
|
|
||||||
$doc->addItemsFromNotices($strm);
|
|
||||||
$this->raw($doc->asString());
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// TRANS: Client error displayed when coming across a non-supported API method.
|
|
||||||
$this->clientError(_('API method not found.'), 404);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return true if read only.
|
|
||||||
*
|
|
||||||
* MAY override
|
|
||||||
*
|
|
||||||
* @param array $args other arguments
|
|
||||||
*
|
|
||||||
* @return boolean is read only action?
|
|
||||||
*/
|
|
||||||
function isReadOnly($args)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,246 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StatusNet, the distributed open-source microblogging tool
|
|
||||||
*
|
|
||||||
* Show the latest notices for a given tag
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Craig Andrews <candrews@integralblue.com>
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @author Jeffery To <jeffery.to@gmail.com>
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @copyright 2009-2010 StatusNet, Inc.
|
|
||||||
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('STATUSNET')) {
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the 20 most recent notices tagged by a given tag
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Craig Andrews <candrews@integralblue.com>
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @author Jeffery To <jeffery.to@gmail.com>
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
class ApiTimelineTagAction extends ApiPrivateAuthAction
|
|
||||||
{
|
|
||||||
var $notices = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Take arguments for running
|
|
||||||
*
|
|
||||||
* @param array $args $_REQUEST args
|
|
||||||
*
|
|
||||||
* @return boolean success flag
|
|
||||||
*/
|
|
||||||
function prepare($args)
|
|
||||||
{
|
|
||||||
parent::prepare($args);
|
|
||||||
|
|
||||||
common_debug("apitimelinetag prepare()");
|
|
||||||
|
|
||||||
$this->tag = $this->arg('tag');
|
|
||||||
$this->notices = $this->getNotices();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle the request
|
|
||||||
*
|
|
||||||
* Just show the notices
|
|
||||||
*
|
|
||||||
* @param array $args $_REQUEST data (unused)
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function handle($args)
|
|
||||||
{
|
|
||||||
parent::handle($args);
|
|
||||||
$this->showTimeline();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show the timeline of notices
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function showTimeline()
|
|
||||||
{
|
|
||||||
$sitename = common_config('site', 'name');
|
|
||||||
$sitelogo = (common_config('site', 'logo')) ? common_config('site', 'logo') : Theme::path('logo.png');
|
|
||||||
// TRANS: Title for timeline with lastest notices with a given tag.
|
|
||||||
// TRANS: %s is the tag.
|
|
||||||
$title = sprintf(_("Notices tagged with %s"), $this->tag);
|
|
||||||
$subtitle = sprintf(
|
|
||||||
// TRANS: Subtitle for timeline with lastest notices with a given tag.
|
|
||||||
// TRANS: %1$s is the tag, $2$s is the StatusNet sitename.
|
|
||||||
_('Updates tagged with %1$s on %2$s!'),
|
|
||||||
$this->tag,
|
|
||||||
$sitename
|
|
||||||
);
|
|
||||||
$taguribase = TagURI::base();
|
|
||||||
$id = "tag:$taguribase:TagTimeline:".$this->tag;
|
|
||||||
|
|
||||||
$link = common_local_url(
|
|
||||||
'tag',
|
|
||||||
array('tag' => $this->tag)
|
|
||||||
);
|
|
||||||
|
|
||||||
$self = $this->getSelfUri();
|
|
||||||
|
|
||||||
switch($this->format) {
|
|
||||||
case 'xml':
|
|
||||||
$this->showXmlTimeline($this->notices);
|
|
||||||
break;
|
|
||||||
case 'rss':
|
|
||||||
$this->showRssTimeline(
|
|
||||||
$this->notices,
|
|
||||||
$title,
|
|
||||||
$link,
|
|
||||||
$subtitle,
|
|
||||||
null,
|
|
||||||
$sitelogo,
|
|
||||||
$self
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case 'atom':
|
|
||||||
header('Content-Type: application/atom+xml; charset=utf-8');
|
|
||||||
|
|
||||||
$atom = new AtomNoticeFeed($this->auth_user);
|
|
||||||
|
|
||||||
$atom->setId($id);
|
|
||||||
$atom->setTitle($title);
|
|
||||||
$atom->setSubtitle($subtitle);
|
|
||||||
$atom->setLogo($sitelogo);
|
|
||||||
$atom->setUpdated('now');
|
|
||||||
|
|
||||||
$atom->addLink($link);
|
|
||||||
$atom->setSelfLink($self);
|
|
||||||
|
|
||||||
$atom->addEntryFromNotices($this->notices);
|
|
||||||
$this->raw($atom->getString());
|
|
||||||
|
|
||||||
break;
|
|
||||||
case 'json':
|
|
||||||
$this->showJsonTimeline($this->notices);
|
|
||||||
break;
|
|
||||||
case 'as':
|
|
||||||
header('Content-Type: ' . ActivityStreamJSONDocument::CONTENT_TYPE);
|
|
||||||
$doc = new ActivityStreamJSONDocument($this->auth_user);
|
|
||||||
$doc->setTitle($title);
|
|
||||||
$doc->addLink($link, 'alternate', 'text/html');
|
|
||||||
$doc->addItemsFromNotices($this->notices);
|
|
||||||
$this->raw($doc->asString());
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// TRANS: Client error displayed when coming across a non-supported API method.
|
|
||||||
$this->clientError(_('API method not found.'), $code = 404);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get notices
|
|
||||||
*
|
|
||||||
* @return array notices
|
|
||||||
*/
|
|
||||||
function getNotices()
|
|
||||||
{
|
|
||||||
$notices = array();
|
|
||||||
|
|
||||||
$notice = Notice_tag::getStream(
|
|
||||||
$this->tag,
|
|
||||||
($this->page - 1) * $this->count,
|
|
||||||
$this->count + 1,
|
|
||||||
$this->since_id,
|
|
||||||
$this->max_id
|
|
||||||
);
|
|
||||||
|
|
||||||
while ($notice->fetch()) {
|
|
||||||
$notices[] = clone($notice);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $notices;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Is this action read only?
|
|
||||||
*
|
|
||||||
* @param array $args other arguments
|
|
||||||
*
|
|
||||||
* @return boolean true
|
|
||||||
*/
|
|
||||||
function isReadOnly($args)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* When was this feed last modified?
|
|
||||||
*
|
|
||||||
* @return string datestamp of the latest notice in the stream
|
|
||||||
*/
|
|
||||||
function lastModified()
|
|
||||||
{
|
|
||||||
if (!empty($this->notices) && (count($this->notices) > 0)) {
|
|
||||||
return strtotime($this->notices[0]->created);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An entity tag for this stream
|
|
||||||
*
|
|
||||||
* Returns an Etag based on the action name, language, and
|
|
||||||
* timestamps of the first and last notice in the timeline
|
|
||||||
*
|
|
||||||
* @return string etag
|
|
||||||
*/
|
|
||||||
function etag()
|
|
||||||
{
|
|
||||||
if (!empty($this->notices) && (count($this->notices) > 0)) {
|
|
||||||
|
|
||||||
$last = count($this->notices) - 1;
|
|
||||||
|
|
||||||
return '"' . implode(
|
|
||||||
':',
|
|
||||||
array($this->arg('action'),
|
|
||||||
common_user_cache_hash($this->auth_user),
|
|
||||||
common_language(),
|
|
||||||
$this->tag,
|
|
||||||
strtotime($this->notices[0]->created),
|
|
||||||
strtotime($this->notices[$last]->created))
|
|
||||||
)
|
|
||||||
. '"';
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,516 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StatusNet, the distributed open-source microblogging tool
|
|
||||||
*
|
|
||||||
* Show a user's timeline
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Craig Andrews <candrews@integralblue.com>
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @author Jeffery To <jeffery.to@gmail.com>
|
|
||||||
* @author mac65 <mac65@mac65.com>
|
|
||||||
* @author Mike Cochrane <mikec@mikenz.geek.nz>
|
|
||||||
* @author Robin Millette <robin@millette.info>
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @copyright 2009 StatusNet, Inc.
|
|
||||||
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('STATUSNET')) {
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the most recent notices (default 20) posted by the authenticating
|
|
||||||
* user. Another user's timeline can be requested via the id parameter. This
|
|
||||||
* is the API equivalent of the user profile web page.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Craig Andrews <candrews@integralblue.com>
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @author Jeffery To <jeffery.to@gmail.com>
|
|
||||||
* @author mac65 <mac65@mac65.com>
|
|
||||||
* @author Mike Cochrane <mikec@mikenz.geek.nz>
|
|
||||||
* @author Robin Millette <robin@millette.info>
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
class ApiTimelineUserAction extends ApiBareAuthAction
|
|
||||||
{
|
|
||||||
var $notices = null;
|
|
||||||
|
|
||||||
var $next_id = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Take arguments for running
|
|
||||||
*
|
|
||||||
* @param array $args $_REQUEST args
|
|
||||||
*
|
|
||||||
* @return boolean success flag
|
|
||||||
*/
|
|
||||||
protected function prepare(array $args=array())
|
|
||||||
{
|
|
||||||
parent::prepare($args);
|
|
||||||
|
|
||||||
$this->target = $this->getTargetProfile($this->arg('id'));
|
|
||||||
|
|
||||||
if (!($this->target instanceof Profile)) {
|
|
||||||
// TRANS: Client error displayed requesting most recent notices for a non-existing user.
|
|
||||||
$this->clientError(_('No such user.'), 404);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->notices = $this->getNotices();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle the request
|
|
||||||
*
|
|
||||||
* Just show the notices
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
protected function handle()
|
|
||||||
{
|
|
||||||
parent::handle();
|
|
||||||
|
|
||||||
if ($this->isPost()) {
|
|
||||||
$this->handlePost();
|
|
||||||
} else {
|
|
||||||
$this->showTimeline();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show the timeline of notices
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function showTimeline()
|
|
||||||
{
|
|
||||||
// We'll use the shared params from the Atom stub
|
|
||||||
// for other feed types.
|
|
||||||
$atom = new AtomUserNoticeFeed($this->target->getUser(), $this->auth_user);
|
|
||||||
|
|
||||||
$link = common_local_url(
|
|
||||||
'showstream',
|
|
||||||
array('nickname' => $this->target->nickname)
|
|
||||||
);
|
|
||||||
|
|
||||||
$self = $this->getSelfUri();
|
|
||||||
|
|
||||||
// FriendFeed's SUP protocol
|
|
||||||
// Also added RSS and Atom feeds
|
|
||||||
|
|
||||||
$suplink = common_local_url('sup', null, null, $this->target->id);
|
|
||||||
header('X-SUP-ID: ' . $suplink);
|
|
||||||
|
|
||||||
|
|
||||||
// paging links
|
|
||||||
$nextUrl = !empty($this->next_id)
|
|
||||||
? common_local_url('ApiTimelineUser',
|
|
||||||
array('format' => $this->format,
|
|
||||||
'id' => $this->target->id),
|
|
||||||
array('max_id' => $this->next_id))
|
|
||||||
: null;
|
|
||||||
|
|
||||||
$prevExtra = array();
|
|
||||||
if (!empty($this->notices)) {
|
|
||||||
assert($this->notices[0] instanceof Notice);
|
|
||||||
$prevExtra['since_id'] = $this->notices[0]->id;
|
|
||||||
}
|
|
||||||
|
|
||||||
$prevUrl = common_local_url('ApiTimelineUser',
|
|
||||||
array('format' => $this->format,
|
|
||||||
'id' => $this->target->id),
|
|
||||||
$prevExtra);
|
|
||||||
$firstUrl = common_local_url('ApiTimelineUser',
|
|
||||||
array('format' => $this->format,
|
|
||||||
'id' => $this->target->id));
|
|
||||||
|
|
||||||
switch($this->format) {
|
|
||||||
case 'xml':
|
|
||||||
$this->showXmlTimeline($this->notices);
|
|
||||||
break;
|
|
||||||
case 'rss':
|
|
||||||
$this->showRssTimeline(
|
|
||||||
$this->notices,
|
|
||||||
$atom->title,
|
|
||||||
$link,
|
|
||||||
$atom->subtitle,
|
|
||||||
$suplink,
|
|
||||||
$atom->logo,
|
|
||||||
$self
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case 'atom':
|
|
||||||
header('Content-Type: application/atom+xml; charset=utf-8');
|
|
||||||
|
|
||||||
$atom->setId($self);
|
|
||||||
$atom->setSelfLink($self);
|
|
||||||
|
|
||||||
// Add navigation links: next, prev, first
|
|
||||||
// Note: we use IDs rather than pages for navigation; page boundaries
|
|
||||||
// change too quickly!
|
|
||||||
|
|
||||||
if (!empty($this->next_id)) {
|
|
||||||
$atom->addLink($nextUrl,
|
|
||||||
array('rel' => 'next',
|
|
||||||
'type' => 'application/atom+xml'));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (($this->page > 1 || !empty($this->max_id)) && !empty($this->notices)) {
|
|
||||||
$atom->addLink($prevUrl,
|
|
||||||
array('rel' => 'prev',
|
|
||||||
'type' => 'application/atom+xml'));
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->page > 1 || !empty($this->since_id) || !empty($this->max_id)) {
|
|
||||||
$atom->addLink($firstUrl,
|
|
||||||
array('rel' => 'first',
|
|
||||||
'type' => 'application/atom+xml'));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
$atom->addEntryFromNotices($this->notices);
|
|
||||||
$this->raw($atom->getString());
|
|
||||||
|
|
||||||
break;
|
|
||||||
case 'json':
|
|
||||||
$this->showJsonTimeline($this->notices);
|
|
||||||
break;
|
|
||||||
case 'as':
|
|
||||||
header('Content-Type: ' . ActivityStreamJSONDocument::CONTENT_TYPE);
|
|
||||||
$doc = new ActivityStreamJSONDocument($this->auth_user);
|
|
||||||
$doc->setTitle($atom->title);
|
|
||||||
$doc->addLink($link, 'alternate', 'text/html');
|
|
||||||
$doc->addItemsFromNotices($this->notices);
|
|
||||||
|
|
||||||
if (!empty($this->next_id)) {
|
|
||||||
$doc->addLink($nextUrl,
|
|
||||||
array('rel' => 'next',
|
|
||||||
'type' => ActivityStreamJSONDocument::CONTENT_TYPE));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (($this->page > 1 || !empty($this->max_id)) && !empty($this->notices)) {
|
|
||||||
$doc->addLink($prevUrl,
|
|
||||||
array('rel' => 'prev',
|
|
||||||
'type' => ActivityStreamJSONDocument::CONTENT_TYPE));
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->page > 1 || !empty($this->since_id) || !empty($this->max_id)) {
|
|
||||||
$doc->addLink($firstUrl,
|
|
||||||
array('rel' => 'first',
|
|
||||||
'type' => ActivityStreamJSONDocument::CONTENT_TYPE));
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->raw($doc->asString());
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// TRANS: Client error displayed when coming across a non-supported API method.
|
|
||||||
$this->clientError(_('API method not found.'), 404);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get notices
|
|
||||||
*
|
|
||||||
* @return array notices
|
|
||||||
*/
|
|
||||||
function getNotices()
|
|
||||||
{
|
|
||||||
$notices = array();
|
|
||||||
|
|
||||||
$notice = $this->target->getNotices(($this->page-1) * $this->count,
|
|
||||||
$this->count + 1,
|
|
||||||
$this->since_id,
|
|
||||||
$this->max_id,
|
|
||||||
$this->scoped);
|
|
||||||
|
|
||||||
while ($notice->fetch()) {
|
|
||||||
if (count($notices) < $this->count) {
|
|
||||||
$notices[] = clone($notice);
|
|
||||||
} else {
|
|
||||||
$this->next_id = $notice->id;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $notices;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* We expose AtomPub here, so non-GET/HEAD reqs must be read/write.
|
|
||||||
*
|
|
||||||
* @param array $args other arguments
|
|
||||||
*
|
|
||||||
* @return boolean true
|
|
||||||
*/
|
|
||||||
|
|
||||||
function isReadOnly($args)
|
|
||||||
{
|
|
||||||
return ($_SERVER['REQUEST_METHOD'] == 'GET' || $_SERVER['REQUEST_METHOD'] == 'HEAD');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* When was this feed last modified?
|
|
||||||
*
|
|
||||||
* @return string datestamp of the latest notice in the stream
|
|
||||||
*/
|
|
||||||
function lastModified()
|
|
||||||
{
|
|
||||||
if (!empty($this->notices) && (count($this->notices) > 0)) {
|
|
||||||
return strtotime($this->notices[0]->created);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An entity tag for this stream
|
|
||||||
*
|
|
||||||
* Returns an Etag based on the action name, language, user ID, and
|
|
||||||
* timestamps of the first and last notice in the timeline
|
|
||||||
*
|
|
||||||
* @return string etag
|
|
||||||
*/
|
|
||||||
function etag()
|
|
||||||
{
|
|
||||||
if (!empty($this->notices) && (count($this->notices) > 0)) {
|
|
||||||
$last = count($this->notices) - 1;
|
|
||||||
|
|
||||||
return '"' . implode(
|
|
||||||
':',
|
|
||||||
array($this->arg('action'),
|
|
||||||
common_user_cache_hash($this->auth_user),
|
|
||||||
common_language(),
|
|
||||||
$this->target->id,
|
|
||||||
strtotime($this->notices[0]->created),
|
|
||||||
strtotime($this->notices[$last]->created))
|
|
||||||
)
|
|
||||||
. '"';
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
function handlePost()
|
|
||||||
{
|
|
||||||
if (empty($this->auth_user) ||
|
|
||||||
$this->auth_user->id != $this->target->id) {
|
|
||||||
// TRANS: Client error displayed trying to add a notice to another user's timeline.
|
|
||||||
$this->clientError(_('Only the user can add to their own timeline.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only handle posts for Atom
|
|
||||||
if ($this->format != 'atom') {
|
|
||||||
// TRANS: Client error displayed when using another format than AtomPub.
|
|
||||||
$this->clientError(_('Only accept AtomPub for Atom feeds.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$xml = trim(file_get_contents('php://input'));
|
|
||||||
if (empty($xml)) {
|
|
||||||
// TRANS: Client error displayed attempting to post an empty API notice.
|
|
||||||
$this->clientError(_('Atom post must not be empty.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$old = error_reporting(error_reporting() & ~(E_WARNING | E_NOTICE));
|
|
||||||
$dom = new DOMDocument();
|
|
||||||
$ok = $dom->loadXML($xml);
|
|
||||||
error_reporting($old);
|
|
||||||
if (!$ok) {
|
|
||||||
// TRANS: Client error displayed attempting to post an API that is not well-formed XML.
|
|
||||||
$this->clientError(_('Atom post must be well-formed XML.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($dom->documentElement->namespaceURI != Activity::ATOM ||
|
|
||||||
$dom->documentElement->localName != 'entry') {
|
|
||||||
// TRANS: Client error displayed when not using an Atom entry.
|
|
||||||
$this->clientError(_('Atom post must be an Atom entry.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$activity = new Activity($dom->documentElement);
|
|
||||||
|
|
||||||
$saved = null;
|
|
||||||
|
|
||||||
if (Event::handle('StartAtomPubNewActivity', array(&$activity, $this->target->getUser(), &$saved))) {
|
|
||||||
if ($activity->verb != ActivityVerb::POST) {
|
|
||||||
// TRANS: Client error displayed when not using the POST verb. Do not translate POST.
|
|
||||||
$this->clientError(_('Can only handle POST activities.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$note = $activity->objects[0];
|
|
||||||
|
|
||||||
if (!in_array($note->type, array(ActivityObject::NOTE,
|
|
||||||
ActivityObject::BLOGENTRY,
|
|
||||||
ActivityObject::STATUS))) {
|
|
||||||
// TRANS: Client error displayed when using an unsupported activity object type.
|
|
||||||
// TRANS: %s is the unsupported activity object type.
|
|
||||||
$this->clientError(sprintf(_('Cannot handle activity object type "%s".'),
|
|
||||||
$note->type));
|
|
||||||
}
|
|
||||||
|
|
||||||
$saved = $this->postNote($activity);
|
|
||||||
|
|
||||||
Event::handle('EndAtomPubNewActivity', array($activity, $this->target->getUser(), $saved));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($saved)) {
|
|
||||||
header('HTTP/1.1 201 Created');
|
|
||||||
header("Location: " . common_local_url('ApiStatusesShow', array('id' => $saved->id,
|
|
||||||
'format' => 'atom')));
|
|
||||||
$this->showSingleAtomStatus($saved);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function postNote($activity)
|
|
||||||
{
|
|
||||||
$note = $activity->objects[0];
|
|
||||||
|
|
||||||
// Use summary as fallback for content
|
|
||||||
|
|
||||||
if (!empty($note->content)) {
|
|
||||||
$sourceContent = $note->content;
|
|
||||||
} else if (!empty($note->summary)) {
|
|
||||||
$sourceContent = $note->summary;
|
|
||||||
} else if (!empty($note->title)) {
|
|
||||||
$sourceContent = $note->title;
|
|
||||||
} else {
|
|
||||||
// @fixme fetch from $sourceUrl?
|
|
||||||
// TRANS: Client error displayed when posting a notice without content through the API.
|
|
||||||
// TRANS: %d is the notice ID (number).
|
|
||||||
$this->clientError(sprintf(_('No content for notice %d.'), $note->id));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get (safe!) HTML and text versions of the content
|
|
||||||
|
|
||||||
$rendered = $this->purify($sourceContent);
|
|
||||||
$content = common_strip_html($rendered);
|
|
||||||
|
|
||||||
$shortened = $this->auth_user->shortenLinks($content);
|
|
||||||
|
|
||||||
$options = array('is_local' => Notice::LOCAL_PUBLIC,
|
|
||||||
'rendered' => $rendered,
|
|
||||||
'replies' => array(),
|
|
||||||
'groups' => array(),
|
|
||||||
'tags' => array(),
|
|
||||||
'urls' => array());
|
|
||||||
|
|
||||||
// accept remote URI (not necessarily a good idea)
|
|
||||||
|
|
||||||
common_debug("Note ID is {$note->id}");
|
|
||||||
|
|
||||||
if (!empty($note->id)) {
|
|
||||||
$notice = Notice::getKV('uri', trim($note->id));
|
|
||||||
|
|
||||||
if (!empty($notice)) {
|
|
||||||
// TRANS: Client error displayed when using another format than AtomPub.
|
|
||||||
// TRANS: %s is the notice URI.
|
|
||||||
$this->clientError(sprintf(_('Notice with URI "%s" already exists.'), $note->id));
|
|
||||||
}
|
|
||||||
common_log(LOG_NOTICE, "Saving client-supplied notice URI '$note->id'");
|
|
||||||
$options['uri'] = $note->id;
|
|
||||||
}
|
|
||||||
|
|
||||||
// accept remote create time (also maybe not such a good idea)
|
|
||||||
|
|
||||||
if (!empty($activity->time)) {
|
|
||||||
common_log(LOG_NOTICE, "Saving client-supplied create time {$activity->time}");
|
|
||||||
$options['created'] = common_sql_date($activity->time);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for optional attributes...
|
|
||||||
|
|
||||||
if ($activity->context instanceof ActivityContext) {
|
|
||||||
|
|
||||||
foreach ($activity->context->attention as $uri=>$type) {
|
|
||||||
try {
|
|
||||||
$profile = Profile::fromUri($uri);
|
|
||||||
if ($profile->isGroup()) {
|
|
||||||
$options['groups'][] = $profile->id;
|
|
||||||
} else {
|
|
||||||
$options['replies'][] = $uri;
|
|
||||||
}
|
|
||||||
} catch (UnknownUriException $e) {
|
|
||||||
common_log(LOG_WARNING, sprintf('AtomPub post with unknown attention URI %s', $uri));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Maintain direct reply associations
|
|
||||||
// @fixme what about conversation ID?
|
|
||||||
|
|
||||||
if (!empty($activity->context->replyToID)) {
|
|
||||||
$orig = Notice::getKV('uri',
|
|
||||||
$activity->context->replyToID);
|
|
||||||
if (!empty($orig)) {
|
|
||||||
$options['reply_to'] = $orig->id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$location = $activity->context->location;
|
|
||||||
|
|
||||||
if ($location) {
|
|
||||||
$options['lat'] = $location->lat;
|
|
||||||
$options['lon'] = $location->lon;
|
|
||||||
if ($location->location_id) {
|
|
||||||
$options['location_ns'] = $location->location_ns;
|
|
||||||
$options['location_id'] = $location->location_id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Atom categories <-> hashtags
|
|
||||||
|
|
||||||
foreach ($activity->categories as $cat) {
|
|
||||||
if ($cat->term) {
|
|
||||||
$term = common_canonical_tag($cat->term);
|
|
||||||
if ($term) {
|
|
||||||
$options['tags'][] = $term;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Atom enclosures -> attachment URLs
|
|
||||||
foreach ($activity->enclosures as $href) {
|
|
||||||
// @fixme save these locally or....?
|
|
||||||
$options['urls'][] = $href;
|
|
||||||
}
|
|
||||||
|
|
||||||
$saved = Notice::saveNew($this->target->id,
|
|
||||||
$content,
|
|
||||||
'atompub', // TODO: deal with this
|
|
||||||
$options);
|
|
||||||
|
|
||||||
return $saved;
|
|
||||||
}
|
|
||||||
|
|
||||||
function purify($content)
|
|
||||||
{
|
|
||||||
require_once INSTALLDIR.'/extlib/htmLawed/htmLawed.php';
|
|
||||||
|
|
||||||
$config = array('safe' => 1,
|
|
||||||
'deny_attribute' => 'id,style,on*');
|
|
||||||
return htmLawed($content, $config);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,85 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StatusNet, the distributed open-source microblogging tool
|
|
||||||
*
|
|
||||||
* List of replies
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category Search
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @copyright 2008-2010 StatusNet, Inc.
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('STATUSNET') && !defined('LACONICA')) {
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the top ten queries that are currently trending
|
|
||||||
*
|
|
||||||
* @category Search
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*
|
|
||||||
* @see ApiAction
|
|
||||||
*/
|
|
||||||
class ApiTrendsAction extends ApiPrivateAuthAction
|
|
||||||
{
|
|
||||||
var $callback;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialization.
|
|
||||||
*
|
|
||||||
* @param array $args Web and URL arguments
|
|
||||||
*
|
|
||||||
* @return boolean false if user doesn't exist
|
|
||||||
*/
|
|
||||||
function prepare($args)
|
|
||||||
{
|
|
||||||
parent::prepare($args);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle a request
|
|
||||||
*
|
|
||||||
* @param array $args Arguments from $_REQUEST
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function handle($args)
|
|
||||||
{
|
|
||||||
parent::handle($args);
|
|
||||||
$this->showTrends();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Output the trends
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function showTrends()
|
|
||||||
{
|
|
||||||
// TRANS: Server error for unfinished API method showTrends.
|
|
||||||
$this->serverError(_('API method under construction.'), 501);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,80 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StatusNet, the distributed open-source microblogging tool
|
|
||||||
*
|
|
||||||
* Show a user's followers (subscribers)
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Dan Moore <dan@moore.cx>
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @copyright 2009 StatusNet, Inc.
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('GNUSOCIAL')) { exit(1); }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Ouputs the authenticating user's followers (subscribers), each with
|
|
||||||
* current Twitter-style status inline. They are ordered by the order
|
|
||||||
* in which they subscribed to the user, 100 at a time.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Dan Moore <dan@moore.cx>
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
class ApiUserFollowersAction extends ApiSubscriptionsAction
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Get the user's subscribers (followers) as an array of profiles
|
|
||||||
*
|
|
||||||
* @return array Profiles
|
|
||||||
*/
|
|
||||||
protected function getProfiles()
|
|
||||||
{
|
|
||||||
$offset = ($this->page - 1) * $this->count;
|
|
||||||
$limit = $this->count + 1;
|
|
||||||
|
|
||||||
$subs = null;
|
|
||||||
|
|
||||||
if (isset($this->tag)) {
|
|
||||||
$subs = $this->target->getTaggedSubscribers(
|
|
||||||
$this->tag, $offset, $limit
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
$subs = $this->target->getSubscribers(
|
|
||||||
$offset,
|
|
||||||
$limit
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
$profiles = array();
|
|
||||||
|
|
||||||
while ($subs->fetch()) {
|
|
||||||
$profiles[] = clone($subs);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $profiles;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,80 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StatusNet, the distributed open-source microblogging tool
|
|
||||||
*
|
|
||||||
* Show a user's friends (subscriptions)
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Dan Moore <dan@moore.cx>
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @copyright 2009 StatusNet, Inc.
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('GNUSOCIAL')) { exit(1); }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Ouputs the authenticating user's friends (subscriptions), each with
|
|
||||||
* current Twitter-style status inline. They are ordered by the date
|
|
||||||
* in which the user subscribed to them, 100 at a time.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Dan Moore <dan@moore.cx>
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
class ApiUserFriendsAction extends ApiSubscriptionsAction
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Get the user's subscriptions (friends) as an array of profiles
|
|
||||||
*
|
|
||||||
* @return array Profiles
|
|
||||||
*/
|
|
||||||
protected function getProfiles()
|
|
||||||
{
|
|
||||||
$offset = ($this->page - 1) * $this->count;
|
|
||||||
$limit = $this->count + 1;
|
|
||||||
|
|
||||||
$subs = null;
|
|
||||||
|
|
||||||
if (isset($this->tag)) {
|
|
||||||
$subs = $this->target->getTaggedSubscriptions(
|
|
||||||
$this->tag, $offset, $limit
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
$subs = $this->target->getSubscribed(
|
|
||||||
$offset,
|
|
||||||
$limit
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
$profiles = array();
|
|
||||||
|
|
||||||
while ($subs->fetch()) {
|
|
||||||
$profiles[] = clone($subs);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $profiles;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,117 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StatusNet, the distributed open-source microblogging tool
|
|
||||||
*
|
|
||||||
* Return a user's avatar image
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Brion Vibber <brion@status.net>
|
|
||||||
* @copyright 2010 StatusNet, Inc.
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('STATUSNET')) {
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Ouputs avatar URL for a user, specified by screen name.
|
|
||||||
* Unlike most API endpoints, this returns an HTTP redirect rather than direct data.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Brion Vibber <brion@status.net>
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
class ApiUserProfileImageAction extends ApiPrivateAuthAction
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Take arguments for running
|
|
||||||
*
|
|
||||||
* @param array $args $_REQUEST args
|
|
||||||
*
|
|
||||||
* @return boolean success flag
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
protected function prepare(array $args=array())
|
|
||||||
{
|
|
||||||
parent::prepare($args);
|
|
||||||
$user = User::getKV('nickname', $this->arg('screen_name'));
|
|
||||||
if (!($user instanceof User)) {
|
|
||||||
// TRANS: Client error displayed when requesting user information for a non-existing user.
|
|
||||||
$this->clientError(_('User not found.'), 404);
|
|
||||||
}
|
|
||||||
$this->target = $user->getProfile();
|
|
||||||
$this->size = $this->arg('size');
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle the request
|
|
||||||
*
|
|
||||||
* Check the format and show the user info
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
protected function handle()
|
|
||||||
{
|
|
||||||
parent::handle();
|
|
||||||
|
|
||||||
$size = $this->avatarSize();
|
|
||||||
$url = $this->target->avatarUrl($size);
|
|
||||||
|
|
||||||
// We don't actually output JSON or XML data -- redirect!
|
|
||||||
common_redirect($url, 302);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the appropriate pixel size for an avatar based on the request...
|
|
||||||
*
|
|
||||||
* @return int
|
|
||||||
*/
|
|
||||||
private function avatarSize()
|
|
||||||
{
|
|
||||||
switch ($this->size) {
|
|
||||||
case 'mini':
|
|
||||||
return AVATAR_MINI_SIZE; // 24x24
|
|
||||||
case 'bigger':
|
|
||||||
return AVATAR_PROFILE_SIZE; // Twitter does 73x73, but we do 96x96
|
|
||||||
case 'normal': // fall through
|
|
||||||
default:
|
|
||||||
return AVATAR_STREAM_SIZE; // 48x48
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return true if read only.
|
|
||||||
*
|
|
||||||
* MAY override
|
|
||||||
*
|
|
||||||
* @param array $args other arguments
|
|
||||||
*
|
|
||||||
* @return boolean is read only action?
|
|
||||||
*/
|
|
||||||
function isReadOnly($args)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,125 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StatusNet, the distributed open-source microblogging tool
|
|
||||||
*
|
|
||||||
* Show a user's profile information
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Dan Moore <dan@moore.cx>
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @author mac65 <mac65@mac65.com>
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @copyright 2009 StatusNet, Inc.
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('STATUSNET')) {
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Ouputs information for a user, specified by ID or screen name.
|
|
||||||
* The user's most recent status will be returned inline.
|
|
||||||
*
|
|
||||||
* @category API
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Dan Moore <dan@moore.cx>
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @author mac65 <mac65@mac65.com>
|
|
||||||
* @author Zach Copley <zach@status.net>
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
class ApiUserShowAction extends ApiPrivateAuthAction
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Take arguments for running
|
|
||||||
*
|
|
||||||
* @param array $args $_REQUEST args
|
|
||||||
*
|
|
||||||
* @return boolean success flag
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
protected function prepare(array $args=array())
|
|
||||||
{
|
|
||||||
parent::prepare($args);
|
|
||||||
|
|
||||||
$email = $this->arg('email');
|
|
||||||
|
|
||||||
// XXX: email field deprecated in Twitter's API
|
|
||||||
|
|
||||||
if (!empty($email)) {
|
|
||||||
$user = User::getKV('email', $email);
|
|
||||||
} else {
|
|
||||||
$user = $this->getTargetUser($this->arg('id'));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!($user instanceof User)) {
|
|
||||||
// TRANS: Client error displayed when requesting user information for a non-existing user.
|
|
||||||
$this->clientError(_('User not found.'), 404);
|
|
||||||
}
|
|
||||||
$this->target = $user->getProfile();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle the request
|
|
||||||
*
|
|
||||||
* Check the format and show the user info
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
protected function handle()
|
|
||||||
{
|
|
||||||
parent::handle();
|
|
||||||
|
|
||||||
if (!in_array($this->format, array('xml', 'json'))) {
|
|
||||||
// TRANS: Client error displayed when coming across a non-supported API method.
|
|
||||||
$this->clientError(_('API method not found.'), 404);
|
|
||||||
}
|
|
||||||
|
|
||||||
$twitter_user = $this->twitterUserArray($this->target, true);
|
|
||||||
|
|
||||||
if ($this->format == 'xml') {
|
|
||||||
$this->initDocument('xml');
|
|
||||||
$this->showTwitterXmlUser($twitter_user, 'user', true);
|
|
||||||
$this->endDocument('xml');
|
|
||||||
} elseif ($this->format == 'json') {
|
|
||||||
$this->initDocument('json');
|
|
||||||
$this->showJsonObjects($twitter_user);
|
|
||||||
$this->endDocument('json');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return true if read only.
|
|
||||||
*
|
|
||||||
* MAY override
|
|
||||||
*
|
|
||||||
* @param array $args other arguments
|
|
||||||
*
|
|
||||||
* @return boolean is read only action?
|
|
||||||
*/
|
|
||||||
function isReadOnly($args)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,184 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StatusNet, the distributed open-source microblogging tool
|
|
||||||
*
|
|
||||||
* Leave a group
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category Group
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @copyright 2008-2009 StatusNet, Inc.
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('STATUSNET') && !defined('LACONICA')) {
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Leave a group
|
|
||||||
*
|
|
||||||
* This is the action for leaving a group. It works more or less like the subscribe action
|
|
||||||
* for users.
|
|
||||||
*
|
|
||||||
* @category Group
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
class ApprovegroupAction extends Action
|
|
||||||
{
|
|
||||||
var $group = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prepare to run
|
|
||||||
*/
|
|
||||||
function prepare($args)
|
|
||||||
{
|
|
||||||
parent::prepare($args);
|
|
||||||
|
|
||||||
if (!common_logged_in()) {
|
|
||||||
// TRANS: Client error displayed when trying to leave a group while not logged in.
|
|
||||||
$this->clientError(_('You must be logged in to leave a group.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$nickname_arg = $this->trimmed('nickname');
|
|
||||||
$id = intval($this->arg('id'));
|
|
||||||
if ($id) {
|
|
||||||
$this->group = User_group::getKV('id', $id);
|
|
||||||
} else if ($nickname_arg) {
|
|
||||||
$nickname = common_canonical_nickname($nickname_arg);
|
|
||||||
|
|
||||||
// Permanent redirect on non-canonical nickname
|
|
||||||
|
|
||||||
if ($nickname_arg != $nickname) {
|
|
||||||
$args = array('nickname' => $nickname);
|
|
||||||
common_redirect(common_local_url('leavegroup', $args), 301);
|
|
||||||
}
|
|
||||||
|
|
||||||
$local = Local_group::getKV('nickname', $nickname);
|
|
||||||
|
|
||||||
if (!$local) {
|
|
||||||
// TRANS: Client error displayed when trying to leave a non-local group.
|
|
||||||
$this->clientError(_('No such group.'), 404);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->group = User_group::getKV('id', $local->group_id);
|
|
||||||
} else {
|
|
||||||
// TRANS: Client error displayed when trying to leave a group without providing a group name or group ID.
|
|
||||||
$this->clientError(_('No nickname or ID.'), 404);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$this->group) {
|
|
||||||
// TRANS: Client error displayed when trying to leave a non-existing group.
|
|
||||||
$this->clientError(_('No such group.'), 404);
|
|
||||||
}
|
|
||||||
|
|
||||||
$cur = common_current_user();
|
|
||||||
if (empty($cur)) {
|
|
||||||
// TRANS: Client error displayed trying to approve group membership while not logged in.
|
|
||||||
$this->clientError(_('Must be logged in.'), 403);
|
|
||||||
}
|
|
||||||
if ($this->arg('profile_id')) {
|
|
||||||
if ($cur->isAdmin($this->group)) {
|
|
||||||
$this->profile = Profile::getKV('id', $this->arg('profile_id'));
|
|
||||||
} else {
|
|
||||||
// TRANS: Client error displayed trying to approve group membership while not a group administrator.
|
|
||||||
$this->clientError(_('Only group admin can approve or cancel join requests.'), 403);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// TRANS: Client error displayed trying to approve group membership without specifying a profile to approve.
|
|
||||||
$this->clientError(_('Must specify a profile.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->request = Group_join_queue::pkeyGet(array('profile_id' => $this->profile->id,
|
|
||||||
'group_id' => $this->group->id));
|
|
||||||
|
|
||||||
if (empty($this->request)) {
|
|
||||||
// TRANS: Client error displayed trying to approve group membership for a non-existing request.
|
|
||||||
// TRANS: %s is a nickname.
|
|
||||||
$this->clientError(sprintf(_('%s is not in the moderation queue for this group.'), $this->profile->nickname), 403);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->approve = (bool)$this->arg('approve');
|
|
||||||
$this->cancel = (bool)$this->arg('cancel');
|
|
||||||
if (!$this->approve && !$this->cancel) {
|
|
||||||
// TRANS: Client error displayed trying to approve/deny group membership.
|
|
||||||
$this->clientError(_('Internal error: received neither cancel nor abort.'));
|
|
||||||
}
|
|
||||||
if ($this->approve && $this->cancel) {
|
|
||||||
// TRANS: Client error displayed trying to approve/deny group membership.
|
|
||||||
$this->clientError(_('Internal error: received both cancel and abort.'));
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle the request
|
|
||||||
*
|
|
||||||
* On POST, add the current user to the group
|
|
||||||
*
|
|
||||||
* @param array $args unused
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function handle($args)
|
|
||||||
{
|
|
||||||
parent::handle($args);
|
|
||||||
|
|
||||||
try {
|
|
||||||
if ($this->approve) {
|
|
||||||
$this->request->complete();
|
|
||||||
} elseif ($this->cancel) {
|
|
||||||
$this->request->abort();
|
|
||||||
}
|
|
||||||
} catch (Exception $e) {
|
|
||||||
common_log(LOG_ERR, "Exception canceling group sub: " . $e->getMessage());
|
|
||||||
// TRANS: Server error displayed when cancelling a queued group join request fails.
|
|
||||||
// TRANS: %1$s is the leaving user's nickname, $2$s is the group nickname for which the leave failed.
|
|
||||||
$this->serverError(sprintf(_('Could not cancel request for user %1$s to join group %2$s.'),
|
|
||||||
$this->profile->nickname, $this->group->nickname));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->boolean('ajax')) {
|
|
||||||
$this->startHTML('text/xml;charset=utf-8');
|
|
||||||
$this->elementStart('head');
|
|
||||||
// TRANS: Title for leave group page after group join request is approved/disapproved.
|
|
||||||
// TRANS: %1$s is the user nickname, %2$s is the group nickname.
|
|
||||||
$this->element('title', null, sprintf(_m('TITLE','%1$s\'s request for %2$s'),
|
|
||||||
$this->profile->nickname,
|
|
||||||
$this->group->nickname));
|
|
||||||
$this->elementEnd('head');
|
|
||||||
$this->elementStart('body');
|
|
||||||
if ($this->approve) {
|
|
||||||
// TRANS: Message on page for group admin after approving a join request.
|
|
||||||
$this->element('p', 'success', _('Join request approved.'));
|
|
||||||
} elseif ($this->cancel) {
|
|
||||||
// TRANS: Message on page for group admin after rejecting a join request.
|
|
||||||
$this->element('p', 'success', _('Join request canceled.'));
|
|
||||||
}
|
|
||||||
$this->elementEnd('body');
|
|
||||||
$this->endHTML();
|
|
||||||
} else {
|
|
||||||
common_redirect(common_local_url('groupmembers', array('nickname' => $this->group->nickname)), 303);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,144 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StatusNet, the distributed open-source microblogging tool
|
|
||||||
*
|
|
||||||
* Approve group subscription request
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category Group
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @copyright 2008-2009 StatusNet, Inc.
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('STATUSNET') && !defined('LACONICA')) {
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Leave a group
|
|
||||||
*
|
|
||||||
* This is the action for leaving a group. It works more or less like the subscribe action
|
|
||||||
* for users.
|
|
||||||
*
|
|
||||||
* @category Group
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
class ApprovesubAction extends Action
|
|
||||||
{
|
|
||||||
var $profile = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prepare to run
|
|
||||||
*/
|
|
||||||
function prepare($args)
|
|
||||||
{
|
|
||||||
parent::prepare($args);
|
|
||||||
|
|
||||||
$cur = common_current_user();
|
|
||||||
if (empty($cur)) {
|
|
||||||
// TRANS: Client error displayed trying to approve group membership while not logged in.
|
|
||||||
$this->clientError(_('Must be logged in.'), 403);
|
|
||||||
}
|
|
||||||
if ($this->arg('profile_id')) {
|
|
||||||
$this->profile = Profile::getKV('id', $this->arg('profile_id'));
|
|
||||||
} else {
|
|
||||||
// TRANS: Client error displayed trying to approve subscriptionswithout specifying a profile to approve.
|
|
||||||
$this->clientError(_('Must specify a profile.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->request = Subscription_queue::pkeyGet(array('subscriber' => $this->profile->id,
|
|
||||||
'subscribed' => $cur->id));
|
|
||||||
|
|
||||||
if (empty($this->request)) {
|
|
||||||
// TRANS: Client error displayed trying to approve subscription for a non-existing request.
|
|
||||||
// TRANS: %s is a user nickname.
|
|
||||||
$this->clientError(sprintf(_('%s is not in the moderation queue for your subscriptions.'), $this->profile->nickname), 403);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->approve = (bool)$this->arg('approve');
|
|
||||||
$this->cancel = (bool)$this->arg('cancel');
|
|
||||||
if (!$this->approve && !$this->cancel) {
|
|
||||||
// TRANS: Client error displayed trying to approve/deny subscription.
|
|
||||||
$this->clientError(_('Internal error: received neither cancel nor abort.'));
|
|
||||||
}
|
|
||||||
if ($this->approve && $this->cancel) {
|
|
||||||
// TRANS: Client error displayed trying to approve/deny subscription
|
|
||||||
$this->clientError(_('Internal error: received both cancel and abort.'));
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle the request
|
|
||||||
*
|
|
||||||
* On POST, add the current user to the group
|
|
||||||
*
|
|
||||||
* @param array $args unused
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function handle($args)
|
|
||||||
{
|
|
||||||
parent::handle($args);
|
|
||||||
$cur = common_current_user();
|
|
||||||
|
|
||||||
try {
|
|
||||||
if ($this->approve) {
|
|
||||||
$this->request->complete();
|
|
||||||
} elseif ($this->cancel) {
|
|
||||||
$this->request->abort();
|
|
||||||
}
|
|
||||||
} catch (Exception $e) {
|
|
||||||
common_log(LOG_ERR, "Exception canceling sub: " . $e->getMessage());
|
|
||||||
// TRANS: Server error displayed when cancelling a queued subscription request fails.
|
|
||||||
// TRANS: %1$s is the leaving user's nickname, $2$s is the nickname for which the leave failed.
|
|
||||||
$this->serverError(sprintf(_('Could not cancel or approve request for user %1$s to join group %2$s.'),
|
|
||||||
$this->profile->nickname, $cur->nickname));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->boolean('ajax')) {
|
|
||||||
$this->startHTML('text/xml;charset=utf-8');
|
|
||||||
$this->elementStart('head');
|
|
||||||
// TRANS: Title for subscription approval ajax return
|
|
||||||
// TRANS: %1$s is the approved user's nickname
|
|
||||||
$this->element('title', null, sprintf(_m('TITLE','%1$s\'s request'),
|
|
||||||
$this->profile->nickname));
|
|
||||||
$this->elementEnd('head');
|
|
||||||
$this->elementStart('body');
|
|
||||||
if ($this->approve) {
|
|
||||||
// TRANS: Message on page for user after approving a subscription request.
|
|
||||||
$this->element('p', 'success', _('Subscription approved.'));
|
|
||||||
} elseif ($this->cancel) {
|
|
||||||
// TRANS: Message on page for user after rejecting a subscription request.
|
|
||||||
$this->element('p', 'success', _('Subscription canceled.'));
|
|
||||||
}
|
|
||||||
$this->elementEnd('body');
|
|
||||||
$this->endHTML();
|
|
||||||
} else {
|
|
||||||
common_redirect(common_local_url('subqueue', array('nickname' =>
|
|
||||||
$cur->nickname)),
|
|
||||||
303);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,278 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StatusNet - the distributed open-source microblogging tool
|
|
||||||
* Copyright (C) 2010, StatusNet, Inc.
|
|
||||||
*
|
|
||||||
* Feed of group memberships for a user, in ActivityStreams format
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category AtomPub
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @copyright 2010 StatusNet, Inc.
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('GNUSOCIAL') && !defined('STATUSNET')) { exit(1); }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Feed of group memberships for a user, in ActivityStreams format
|
|
||||||
*
|
|
||||||
* @category Action
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @copyright 2010 StatusNet, Inc.
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
class AtompubmembershipfeedAction extends AtompubAction
|
|
||||||
{
|
|
||||||
private $_profile = null;
|
|
||||||
private $_memberships = null;
|
|
||||||
|
|
||||||
protected function atompubPrepare()
|
|
||||||
{
|
|
||||||
$this->_profile = Profile::getKV('id', $this->trimmed('profile'));
|
|
||||||
|
|
||||||
if (!$this->_profile instanceof Profile) {
|
|
||||||
// TRANS: Client exception.
|
|
||||||
throw new ClientException(_('No such profile.'), 404);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->_memberships = Group_member::byMember($this->_profile->id,
|
|
||||||
$this->offset,
|
|
||||||
$this->limit);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function handleGet()
|
|
||||||
{
|
|
||||||
return $this->showFeed();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function handlePost()
|
|
||||||
{
|
|
||||||
return $this->addMembership();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show a feed of favorite activity streams objects
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function showFeed()
|
|
||||||
{
|
|
||||||
header('Content-Type: application/atom+xml; charset=utf-8');
|
|
||||||
|
|
||||||
$url = common_local_url('AtomPubMembershipFeed',
|
|
||||||
array('profile' => $this->_profile->id));
|
|
||||||
|
|
||||||
$feed = new Atom10Feed(true);
|
|
||||||
|
|
||||||
$feed->addNamespace('activity',
|
|
||||||
'http://activitystrea.ms/spec/1.0/');
|
|
||||||
|
|
||||||
$feed->addNamespace('poco',
|
|
||||||
'http://portablecontacts.net/spec/1.0');
|
|
||||||
|
|
||||||
$feed->addNamespace('media',
|
|
||||||
'http://purl.org/syndication/atommedia');
|
|
||||||
|
|
||||||
$feed->id = $url;
|
|
||||||
|
|
||||||
$feed->setUpdated('now');
|
|
||||||
|
|
||||||
$feed->addAuthor($this->_profile->getBestName(),
|
|
||||||
$this->_profile->getURI());
|
|
||||||
|
|
||||||
// TRANS: Title for group membership feed.
|
|
||||||
// TRANS: %s is a username.
|
|
||||||
$feed->setTitle(sprintf(_('Group memberships of %s'),
|
|
||||||
$this->_profile->getBestName()));
|
|
||||||
|
|
||||||
// TRANS: Subtitle for group membership feed.
|
|
||||||
// TRANS: %1$s is a username, %2$s is the StatusNet sitename.
|
|
||||||
$feed->setSubtitle(sprintf(_('Groups %1$s is a member of on %2$s'),
|
|
||||||
$this->_profile->getBestName(),
|
|
||||||
common_config('site', 'name')));
|
|
||||||
|
|
||||||
$feed->addLink(common_local_url('usergroups',
|
|
||||||
array('nickname' =>
|
|
||||||
$this->_profile->nickname)));
|
|
||||||
|
|
||||||
$feed->addLink($url,
|
|
||||||
array('rel' => 'self',
|
|
||||||
'type' => 'application/atom+xml'));
|
|
||||||
|
|
||||||
// If there's more...
|
|
||||||
|
|
||||||
if ($this->page > 1) {
|
|
||||||
$feed->addLink($url,
|
|
||||||
array('rel' => 'first',
|
|
||||||
'type' => 'application/atom+xml'));
|
|
||||||
|
|
||||||
$feed->addLink(common_local_url('AtomPubMembershipFeed',
|
|
||||||
array('profile' =>
|
|
||||||
$this->_profile->id),
|
|
||||||
array('page' =>
|
|
||||||
$this->page - 1)),
|
|
||||||
array('rel' => 'prev',
|
|
||||||
'type' => 'application/atom+xml'));
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->_memberships->N > $this->count) {
|
|
||||||
|
|
||||||
$feed->addLink(common_local_url('AtomPubMembershipFeed',
|
|
||||||
array('profile' =>
|
|
||||||
$this->_profile->id),
|
|
||||||
array('page' =>
|
|
||||||
$this->page + 1)),
|
|
||||||
array('rel' => 'next',
|
|
||||||
'type' => 'application/atom+xml'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$i = 0;
|
|
||||||
|
|
||||||
while ($this->_memberships->fetch()) {
|
|
||||||
|
|
||||||
// We get one more than needed; skip that one
|
|
||||||
|
|
||||||
$i++;
|
|
||||||
|
|
||||||
if ($i > $this->count) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
$act = $this->_memberships->asActivity();
|
|
||||||
$feed->addEntryRaw($act->asString(false, false, false));
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->raw($feed->getString());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* add a new favorite
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function addMembership()
|
|
||||||
{
|
|
||||||
// XXX: Refactor this; all the same for atompub
|
|
||||||
|
|
||||||
if (empty($this->auth_user) ||
|
|
||||||
$this->auth_user->id != $this->_profile->id) {
|
|
||||||
// TRANS: Client exception thrown when trying subscribe someone else to a group.
|
|
||||||
throw new ClientException(_("Cannot add someone else's".
|
|
||||||
" membership."), 403);
|
|
||||||
}
|
|
||||||
|
|
||||||
$xml = file_get_contents('php://input');
|
|
||||||
|
|
||||||
$dom = DOMDocument::loadXML($xml);
|
|
||||||
|
|
||||||
if ($dom->documentElement->namespaceURI != Activity::ATOM ||
|
|
||||||
$dom->documentElement->localName != 'entry') {
|
|
||||||
// TRANS: Client error displayed when not using an Atom entry.
|
|
||||||
throw new ClientException(_('Atom post must be an Atom entry.'));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$activity = new Activity($dom->documentElement);
|
|
||||||
|
|
||||||
$membership = null;
|
|
||||||
|
|
||||||
if (Event::handle('StartAtomPubNewActivity', array(&$activity))) {
|
|
||||||
if ($activity->verb != ActivityVerb::JOIN) {
|
|
||||||
// TRANS: Client error displayed when not using the join verb.
|
|
||||||
throw new ClientException(_('Can only handle join activities.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$groupObj = $activity->objects[0];
|
|
||||||
|
|
||||||
if ($groupObj->type != ActivityObject::GROUP) {
|
|
||||||
// TRANS: Client exception thrown when trying to join something which is not a group
|
|
||||||
throw new ClientException(_('Can only join groups.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$group = User_group::getKV('uri', $groupObj->id);
|
|
||||||
|
|
||||||
if (empty($group)) {
|
|
||||||
// XXX: import from listed URL or something
|
|
||||||
// TRANS: Client exception thrown when trying to subscribe to a non-existing group.
|
|
||||||
throw new ClientException(_('Unknown group.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$old = Group_member::pkeyGet(array('profile_id' => $this->auth_user->id,
|
|
||||||
'group_id' => $group->id));
|
|
||||||
|
|
||||||
if (!empty($old)) {
|
|
||||||
// TRANS: Client exception thrown when trying to subscribe to an already subscribed group.
|
|
||||||
throw new ClientException(_('Already a member.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$profile = $this->auth_user->getProfile();
|
|
||||||
|
|
||||||
if (Group_block::isBlocked($group, $profile)) {
|
|
||||||
// XXX: import from listed URL or something
|
|
||||||
// TRANS: Client exception thrown when trying to subscribe to group while blocked from that group.
|
|
||||||
throw new ClientException(_('Blocked by admin.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->auth_user->joinGroup($group);
|
|
||||||
|
|
||||||
Event::handle('EndAtomPubNewActivity', array($activity, $membership));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($membership)) {
|
|
||||||
$act = $membership->asActivity();
|
|
||||||
|
|
||||||
header('Content-Type: application/atom+xml; charset=utf-8');
|
|
||||||
header('Content-Location: ' . $act->selfLink);
|
|
||||||
|
|
||||||
$this->startXML();
|
|
||||||
$this->raw($act->asString(true, true, true));
|
|
||||||
$this->endXML();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return last modified, if applicable.
|
|
||||||
*
|
|
||||||
* MAY override
|
|
||||||
*
|
|
||||||
* @return string last modified http header
|
|
||||||
*/
|
|
||||||
function lastModified()
|
|
||||||
{
|
|
||||||
// For comparison with If-Last-Modified
|
|
||||||
// If not applicable, return null
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return etag, if applicable.
|
|
||||||
*
|
|
||||||
* MAY override
|
|
||||||
*
|
|
||||||
* @return string etag http header
|
|
||||||
*/
|
|
||||||
function etag()
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,159 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StatusNet - the distributed open-source microblogging tool
|
|
||||||
* Copyright (C) 2010, StatusNet, Inc.
|
|
||||||
*
|
|
||||||
* Show a single membership as an Activity Streams entry
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category AtomPub
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @copyright 2010 StatusNet, Inc.
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('GNUSOCIAL') && !defined('STATUSNET')) { exit(1); }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show (or delete) a single membership event as an ActivityStreams entry
|
|
||||||
*
|
|
||||||
* @category AtomPub
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @copyright 2010 StatusNet, Inc.
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
class AtompubshowmembershipAction extends AtompubAction
|
|
||||||
{
|
|
||||||
private $_private = null;
|
|
||||||
private $_group = null;
|
|
||||||
private $_membership = null;
|
|
||||||
|
|
||||||
protected function atompubPrepare()
|
|
||||||
{
|
|
||||||
$this->_profile = Profile::getKV('id', $this->trimmed('profile'));
|
|
||||||
|
|
||||||
if (!$this->_profile instanceof Profile) {
|
|
||||||
// TRANS: Client exception.
|
|
||||||
throw new ClientException(_('No such profile.'), 404);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->_group = User_group::getKV('id', $this->trimmed('group'));
|
|
||||||
|
|
||||||
if (!$this->_group instanceof User_group) {
|
|
||||||
// TRANS: Client exception thrown when referencing a non-existing group.
|
|
||||||
throw new ClientException(_('No such group.'), 404);
|
|
||||||
}
|
|
||||||
|
|
||||||
$kv = array('group_id' => $groupId,
|
|
||||||
'profile_id' => $this->_profile->id);
|
|
||||||
|
|
||||||
$this->_membership = Group_member::pkeyGet($kv);
|
|
||||||
|
|
||||||
if (!$this->_membership instanceof Group_member) {
|
|
||||||
// TRANS: Client exception thrown when trying to show membership of a non-subscribed group
|
|
||||||
throw new ClientException(_('Not a member.'), 404);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function handleGet() {
|
|
||||||
return $this->showMembership();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function handleDelete() {
|
|
||||||
return $this->deleteMembership();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* show a single membership
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function showMembership()
|
|
||||||
{
|
|
||||||
$activity = $this->_membership->asActivity();
|
|
||||||
|
|
||||||
header('Content-Type: application/atom+xml; charset=utf-8');
|
|
||||||
|
|
||||||
$this->startXML();
|
|
||||||
$this->raw($activity->asString(true, true, true));
|
|
||||||
$this->endXML();
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Delete the membership (leave the group)
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function deleteMembership()
|
|
||||||
{
|
|
||||||
if (empty($this->auth_user) ||
|
|
||||||
$this->auth_user->id != $this->_profile->id) {
|
|
||||||
// TRANS: Client exception thrown when deleting someone else's membership.
|
|
||||||
throw new ClientException(_("Cannot delete someone else's".
|
|
||||||
" membership."), 403);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->auth_user->leaveGroup($this->_group);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return last modified, if applicable.
|
|
||||||
*
|
|
||||||
* Because the representation depends on the profile and group,
|
|
||||||
* our last modified value is the maximum of their mod time
|
|
||||||
* with the actual membership's mod time.
|
|
||||||
*
|
|
||||||
* @return string last modified http header
|
|
||||||
*/
|
|
||||||
function lastModified()
|
|
||||||
{
|
|
||||||
return max(strtotime($this->_profile->modified),
|
|
||||||
strtotime($this->_group->modified),
|
|
||||||
strtotime($this->_membership->modified));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return etag, if applicable.
|
|
||||||
*
|
|
||||||
* A "weak" Etag including the profile and group id as well as
|
|
||||||
* the admin flag and ctime of the membership.
|
|
||||||
*
|
|
||||||
* @return string etag http header
|
|
||||||
*/
|
|
||||||
function etag()
|
|
||||||
{
|
|
||||||
$ctime = strtotime($this->_membership->created);
|
|
||||||
|
|
||||||
$adminflag = ($this->_membership->is_admin) ? 't' : 'f';
|
|
||||||
|
|
||||||
return 'W/"' . implode(':', array('AtomPubShowMembership',
|
|
||||||
$this->_profile->id,
|
|
||||||
$this->_group->id,
|
|
||||||
$adminflag,
|
|
||||||
$ctime)) . '"';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,184 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StatusNet - the distributed open-source microblogging tool
|
|
||||||
* Copyright (C) 2010, StatusNet, Inc.
|
|
||||||
*
|
|
||||||
* Single subscription
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category AtomPub
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @copyright 2010 StatusNet, Inc.
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('GNUSOCIAL') && !defined('STATUSNET')) { exit(1); }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show a single subscription
|
|
||||||
*
|
|
||||||
* @category AtomPub
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @copyright 2010 StatusNet, Inc.
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
class AtompubshowsubscriptionAction extends AtompubAction
|
|
||||||
{
|
|
||||||
private $_subscriber = null;
|
|
||||||
private $_subscribed = null;
|
|
||||||
private $_subscription = null;
|
|
||||||
|
|
||||||
protected function atompubPrepare()
|
|
||||||
{
|
|
||||||
$subscriberId = $this->trimmed('subscriber');
|
|
||||||
|
|
||||||
$this->_subscriber = Profile::getKV('id', $subscriberId);
|
|
||||||
|
|
||||||
if (!$this->_subscriber instanceof Profile) {
|
|
||||||
// TRANS: Client exception thrown when trying to display a subscription for a non-existing profile ID.
|
|
||||||
// TRANS: %d is the non-existing profile ID number.
|
|
||||||
throw new ClientException(sprintf(_('No such profile id: %d.'),
|
|
||||||
$subscriberId), 404);
|
|
||||||
}
|
|
||||||
|
|
||||||
$subscribedId = $this->trimmed('subscribed');
|
|
||||||
|
|
||||||
$this->_subscribed = Profile::getKV('id', $subscribedId);
|
|
||||||
|
|
||||||
if (!$this->_subscribed instanceof Profile) {
|
|
||||||
// TRANS: Client exception thrown when trying to display a subscription for a non-existing profile ID.
|
|
||||||
// TRANS: %d is the non-existing profile ID number.
|
|
||||||
throw new ClientException(sprintf(_('No such profile id: %d.'),
|
|
||||||
$subscribedId), 404);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->_subscription = Subscription::pkeyGet(array('subscriber' => $subscriberId,
|
|
||||||
'subscribed' => $subscribedId));
|
|
||||||
if (!$this->_subscription instanceof Subscription) {
|
|
||||||
// TRANS: Client exception thrown when trying to display a subscription for a non-subscribed profile ID.
|
|
||||||
// TRANS: %1$d is the non-existing subscriber ID number, $2$d is the ID of the profile that was not subscribed to.
|
|
||||||
$msg = sprintf(_('Profile %1$d not subscribed to profile %2$d.'),
|
|
||||||
$subscriberId, $subscribedId);
|
|
||||||
throw new ClientException($msg, 404);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function handleGet()
|
|
||||||
{
|
|
||||||
$this->showSubscription();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function handleDelete()
|
|
||||||
{
|
|
||||||
$this->deleteSubscription();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show the subscription in ActivityStreams Atom format.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function showSubscription()
|
|
||||||
{
|
|
||||||
$activity = $this->_subscription->asActivity();
|
|
||||||
|
|
||||||
header('Content-Type: application/atom+xml; charset=utf-8');
|
|
||||||
|
|
||||||
$this->startXML();
|
|
||||||
$this->raw($activity->asString(true, true, true));
|
|
||||||
$this->endXML();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Delete the subscription
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function deleteSubscription()
|
|
||||||
{
|
|
||||||
if (!$this->scoped instanceof Profile ||
|
|
||||||
$this->scoped->id != $this->_subscriber->id) {
|
|
||||||
// TRANS: Client exception thrown when trying to delete a subscription of another user.
|
|
||||||
throw new ClientException(_("Cannot delete someone else's subscription."), 403);
|
|
||||||
}
|
|
||||||
|
|
||||||
Subscription::cancel($this->_subscriber, $this->_subscribed);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Is this action read only?
|
|
||||||
*
|
|
||||||
* @param array $args other arguments
|
|
||||||
*
|
|
||||||
* @return boolean true
|
|
||||||
*/
|
|
||||||
function isReadOnly($args)
|
|
||||||
{
|
|
||||||
if ($_SERVER['REQUEST_METHOD'] == 'DELETE') {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return last modified, if applicable.
|
|
||||||
*
|
|
||||||
* @return string last modified http header
|
|
||||||
*/
|
|
||||||
function lastModified()
|
|
||||||
{
|
|
||||||
return max(strtotime($this->_subscriber->modified),
|
|
||||||
strtotime($this->_subscribed->modified),
|
|
||||||
strtotime($this->_subscription->modified));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Etag for this object
|
|
||||||
*
|
|
||||||
* @return string etag http header
|
|
||||||
*/
|
|
||||||
function etag()
|
|
||||||
{
|
|
||||||
$mtime = strtotime($this->_subscription->modified);
|
|
||||||
|
|
||||||
return 'W/"' . implode(':', array('AtomPubShowSubscription',
|
|
||||||
$this->_subscriber->id,
|
|
||||||
$this->_subscribed->id,
|
|
||||||
$mtime)) . '"';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Does this require authentication?
|
|
||||||
*
|
|
||||||
* @return boolean true if delete, else false
|
|
||||||
*/
|
|
||||||
function requiresAuth()
|
|
||||||
{
|
|
||||||
if ($_SERVER['REQUEST_METHOD'] == 'DELETE') {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,261 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StatusNet - the distributed open-source microblogging tool
|
|
||||||
* Copyright (C) 2010, StatusNet, Inc.
|
|
||||||
*
|
|
||||||
* AtomPub subscription feed
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* @category Cache
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @copyright 2010 StatusNet, Inc.
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('GNUSOCIAL') && !defined('STATUSNET')) { exit(1); }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Subscription feed class for AtomPub
|
|
||||||
*
|
|
||||||
* Generates a list of the user's subscriptions
|
|
||||||
*
|
|
||||||
* @category AtomPub
|
|
||||||
* @package StatusNet
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @copyright 2010 StatusNet, Inc.
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
|
|
||||||
* @link http://status.net/
|
|
||||||
*/
|
|
||||||
class AtompubsubscriptionfeedAction extends AtompubAction
|
|
||||||
{
|
|
||||||
private $_profile = null;
|
|
||||||
private $_subscriptions = null;
|
|
||||||
|
|
||||||
protected function atompubPrepare()
|
|
||||||
{
|
|
||||||
$subscriber = $this->trimmed('subscriber');
|
|
||||||
|
|
||||||
$this->_profile = Profile::getKV('id', $subscriber);
|
|
||||||
|
|
||||||
if (!$this->_profile instanceof Profile) {
|
|
||||||
// TRANS: Client exception thrown when trying to display a subscription for a non-existing profile ID.
|
|
||||||
// TRANS: %d is the non-existing profile ID number.
|
|
||||||
throw new ClientException(sprintf(_('No such profile id: %d.'),
|
|
||||||
$subscriber), 404);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->_subscriptions = Subscription::bySubscriber($this->_profile->id,
|
|
||||||
$this->offset,
|
|
||||||
$this->limit);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function handleGet()
|
|
||||||
{
|
|
||||||
$this->showFeed();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function handlePost()
|
|
||||||
{
|
|
||||||
$this->addSubscription();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show the feed of subscriptions
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function showFeed()
|
|
||||||
{
|
|
||||||
header('Content-Type: application/atom+xml; charset=utf-8');
|
|
||||||
|
|
||||||
$url = common_local_url('AtomPubSubscriptionFeed',
|
|
||||||
array('subscriber' => $this->_profile->id));
|
|
||||||
|
|
||||||
$feed = new Atom10Feed(true);
|
|
||||||
|
|
||||||
$feed->addNamespace('activity',
|
|
||||||
'http://activitystrea.ms/spec/1.0/');
|
|
||||||
|
|
||||||
$feed->addNamespace('poco',
|
|
||||||
'http://portablecontacts.net/spec/1.0');
|
|
||||||
|
|
||||||
$feed->addNamespace('media',
|
|
||||||
'http://purl.org/syndication/atommedia');
|
|
||||||
|
|
||||||
$feed->addNamespace('georss',
|
|
||||||
'http://www.georss.org/georss');
|
|
||||||
|
|
||||||
$feed->id = $url;
|
|
||||||
|
|
||||||
$feed->setUpdated('now');
|
|
||||||
|
|
||||||
$feed->addAuthor($this->_profile->getBestName(),
|
|
||||||
$this->_profile->getURI());
|
|
||||||
|
|
||||||
// TRANS: Title for Atom subscription feed.
|
|
||||||
// TRANS: %s is a user nickname.
|
|
||||||
$feed->setTitle(sprintf(_("%s subscriptions"),
|
|
||||||
$this->_profile->getBestName()));
|
|
||||||
|
|
||||||
// TRANS: Subtitle for Atom subscription feed.
|
|
||||||
// TRANS: %1$s is a user nickname, %s$s is the StatusNet sitename.
|
|
||||||
$feed->setSubtitle(sprintf(_("People %1\$s has subscribed to on %2\$s"),
|
|
||||||
$this->_profile->getBestName(),
|
|
||||||
common_config('site', 'name')));
|
|
||||||
|
|
||||||
$feed->addLink(common_local_url('subscriptions',
|
|
||||||
array('nickname' =>
|
|
||||||
$this->_profile->nickname)));
|
|
||||||
|
|
||||||
$feed->addLink($url,
|
|
||||||
array('rel' => 'self',
|
|
||||||
'type' => 'application/atom+xml'));
|
|
||||||
|
|
||||||
// If there's more...
|
|
||||||
|
|
||||||
if ($this->page > 1) {
|
|
||||||
$feed->addLink($url,
|
|
||||||
array('rel' => 'first',
|
|
||||||
'type' => 'application/atom+xml'));
|
|
||||||
|
|
||||||
$feed->addLink(common_local_url('AtomPubSubscriptionFeed',
|
|
||||||
array('subscriber' =>
|
|
||||||
$this->_profile->id),
|
|
||||||
array('page' =>
|
|
||||||
$this->page - 1)),
|
|
||||||
array('rel' => 'prev',
|
|
||||||
'type' => 'application/atom+xml'));
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->_subscriptions->N > $this->count) {
|
|
||||||
|
|
||||||
$feed->addLink(common_local_url('AtomPubSubscriptionFeed',
|
|
||||||
array('subscriber' =>
|
|
||||||
$this->_profile->id),
|
|
||||||
array('page' =>
|
|
||||||
$this->page + 1)),
|
|
||||||
array('rel' => 'next',
|
|
||||||
'type' => 'application/atom+xml'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$i = 0;
|
|
||||||
|
|
||||||
// XXX: This is kind of inefficient
|
|
||||||
|
|
||||||
while ($this->_subscriptions->fetch()) {
|
|
||||||
|
|
||||||
// We get one more than needed; skip that one
|
|
||||||
|
|
||||||
$i++;
|
|
||||||
|
|
||||||
if ($i > $this->count) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
$act = $this->_subscriptions->asActivity();
|
|
||||||
$feed->addEntryRaw($act->asString(false, false, false));
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->raw($feed->getString());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a new subscription
|
|
||||||
*
|
|
||||||
* Handling the POST method for AtomPub
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function addSubscription()
|
|
||||||
{
|
|
||||||
if (empty($this->auth_user) ||
|
|
||||||
$this->auth_user->id != $this->_profile->id) {
|
|
||||||
// TRANS: Client exception thrown when trying to subscribe another user.
|
|
||||||
throw new ClientException(_("Cannot add someone else's".
|
|
||||||
" subscription."), 403);
|
|
||||||
}
|
|
||||||
|
|
||||||
$xml = file_get_contents('php://input');
|
|
||||||
|
|
||||||
$dom = DOMDocument::loadXML($xml);
|
|
||||||
|
|
||||||
if ($dom->documentElement->namespaceURI != Activity::ATOM ||
|
|
||||||
$dom->documentElement->localName != 'entry') {
|
|
||||||
// TRANS: Client error displayed when not using an Atom entry.
|
|
||||||
$this->clientError(_('Atom post must be an Atom entry.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$activity = new Activity($dom->documentElement);
|
|
||||||
|
|
||||||
$sub = null;
|
|
||||||
|
|
||||||
if (Event::handle('StartAtomPubNewActivity', array(&$activity))) {
|
|
||||||
|
|
||||||
if ($activity->verb != ActivityVerb::FOLLOW) {
|
|
||||||
// TRANS: Client error displayed when not using the follow verb.
|
|
||||||
$this->clientError(_('Can only handle Follow activities.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$person = $activity->objects[0];
|
|
||||||
|
|
||||||
if ($person->type != ActivityObject::PERSON) {
|
|
||||||
// TRANS: Client exception thrown when subscribing to an object that is not a person.
|
|
||||||
$this->clientError(_('Can only follow people.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
// XXX: OStatus discovery (maybe)
|
|
||||||
try {
|
|
||||||
$profile = Profile::fromUri($person->id);
|
|
||||||
} catch (UnknownUriException $e) {
|
|
||||||
// TRANS: Client exception thrown when subscribing to a non-existing profile.
|
|
||||||
// TRANS: %s is the unknown profile ID.
|
|
||||||
$this->clientError(sprintf(_('Unknown profile %s.'), $person->id));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Subscription::exists($this->_profile, $profile)) {
|
|
||||||
// 409 Conflict
|
|
||||||
// TRANS: Client error displayed trying to subscribe to an already subscribed profile.
|
|
||||||
// TRANS: %s is the profile the user already has a subscription on.
|
|
||||||
$this->clientError(sprintf(_('Already subscribed to %s.'),
|
|
||||||
$person->id),
|
|
||||||
409);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Subscription::start($this->_profile, $profile)) {
|
|
||||||
$sub = Subscription::pkeyGet(array('subscriber' => $this->_profile->id,
|
|
||||||
'subscribed' => $profile->id));
|
|
||||||
}
|
|
||||||
|
|
||||||
Event::handle('EndAtomPubNewActivity', array($activity, $sub));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($sub)) {
|
|
||||||
$act = $sub->asActivity();
|
|
||||||
|
|
||||||
header('Content-Type: application/atom+xml; charset=utf-8');
|
|
||||||
header('Content-Location: ' . $act->selfLink);
|
|
||||||
|
|
||||||
$this->startXML();
|
|
||||||
$this->raw($act->asString(true, true, true));
|
|
||||||
$this->endXML();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user