forked from GNUsocial/gnu-social
		
	Compare commits
	
		
			1589 Commits
		
	
	
		
			v1.20.9rel
			...
			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 | 
							
								
								
									
										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
 | 
			
		||||
							
								
								
									
										79
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										79
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -1,18 +1,63 @@
 | 
			
		||||
avatar/
 | 
			
		||||
files/
 | 
			
		||||
file/
 | 
			
		||||
local/
 | 
			
		||||
logs/
 | 
			
		||||
log/
 | 
			
		||||
run/
 | 
			
		||||
 | 
			
		||||
###> 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
 | 
			
		||||
.htaccess
 | 
			
		||||
httpd.conf
 | 
			
		||||
dataobject.ini
 | 
			
		||||
*.bak
 | 
			
		||||
*.orig
 | 
			
		||||
*.rej
 | 
			
		||||
TODO.rym
 | 
			
		||||
config-*.php
 | 
			
		||||
good-config.php
 | 
			
		||||
*.mo
 | 
			
		||||
/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__)
 | 
			
		||||
    );
 | 
			
		||||
@@ -1,95 +0,0 @@
 | 
			
		||||
## Code of Conduct
 | 
			
		||||
 | 
			
		||||
### Our Pledge
 | 
			
		||||
 | 
			
		||||
In the interest of fostering an open and welcoming environment, we as
 | 
			
		||||
contributors and maintainers pledge to making participation in our project and
 | 
			
		||||
our community a harassment-free experience for everyone, regardless of age, body
 | 
			
		||||
size, disability, ethnicity, gender identity and expression, level of experience,
 | 
			
		||||
nationality, personal appearance, race, religion, or sexual identity and
 | 
			
		||||
orientation.
 | 
			
		||||
 | 
			
		||||
### Our Standards
 | 
			
		||||
 | 
			
		||||
Examples of behavior that contributes to creating a positive environment
 | 
			
		||||
include:
 | 
			
		||||
 | 
			
		||||
* Using welcoming and inclusive language
 | 
			
		||||
* Being respectful of differing viewpoints and experiences
 | 
			
		||||
* Gracefully accepting constructive criticism
 | 
			
		||||
* Focusing on what is best for the community
 | 
			
		||||
* Showing empathy towards other community members
 | 
			
		||||
 | 
			
		||||
Examples of unacceptable behavior by participants include:
 | 
			
		||||
 | 
			
		||||
* The use of sexualized language or imagery and unwelcome sexual attention or
 | 
			
		||||
advances
 | 
			
		||||
* Trolling, insulting/derogatory comments, and personal or political attacks
 | 
			
		||||
* Public or private harassment
 | 
			
		||||
* Publishing others' private information, such as a physical or electronic
 | 
			
		||||
  address, without explicit permission
 | 
			
		||||
* Other conduct which could reasonably be considered inappropriate in a
 | 
			
		||||
  professional setting
 | 
			
		||||
 | 
			
		||||
### Our Responsibilities
 | 
			
		||||
 | 
			
		||||
Project maintainers are responsible for clarifying the standards of acceptable
 | 
			
		||||
behavior and are expected to take appropriate and fair corrective action in
 | 
			
		||||
response to any instances of unacceptable behavior.
 | 
			
		||||
 | 
			
		||||
Project maintainers have the right and responsibility to remove, edit, or
 | 
			
		||||
reject comments, commits, code, wiki edits, issues, and other contributions
 | 
			
		||||
that are not aligned to this Code of Conduct, or to ban temporarily or
 | 
			
		||||
permanently any contributor for other behaviors that they deem inappropriate,
 | 
			
		||||
threatening, offensive, or harmful.
 | 
			
		||||
 | 
			
		||||
### Scope
 | 
			
		||||
 | 
			
		||||
This Code of Conduct applies both within project spaces and in public spaces
 | 
			
		||||
when an individual is representing the project or its community. Examples of
 | 
			
		||||
representing a project or community include using an official project e-mail
 | 
			
		||||
address, posting via an official social media account, or acting as an appointed
 | 
			
		||||
representative at an online or offline event. Representation of a project may be
 | 
			
		||||
further defined and clarified by project maintainers.
 | 
			
		||||
 | 
			
		||||
### Enforcement
 | 
			
		||||
 | 
			
		||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
 | 
			
		||||
reported by contacting the project team at mattl@gnu.org. All
 | 
			
		||||
complaints will be reviewed and investigated and will result in a response that
 | 
			
		||||
is deemed necessary and appropriate to the circumstances. The project team is
 | 
			
		||||
obligated to maintain confidentiality with regard to the reporter of an incident.
 | 
			
		||||
Further details of specific enforcement policies may be posted separately.
 | 
			
		||||
 | 
			
		||||
Project maintainers who do not follow or enforce the Code of Conduct in good
 | 
			
		||||
faith may face temporary or permanent repercussions as determined by other
 | 
			
		||||
members of the project's leadership.
 | 
			
		||||
 | 
			
		||||
### Attribution
 | 
			
		||||
 | 
			
		||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
 | 
			
		||||
available at [http://contributor-covenant.org/version/1/4][version]
 | 
			
		||||
 | 
			
		||||
[homepage]: http://contributor-covenant.org
 | 
			
		||||
[version]: http://contributor-covenant.org/version/1/4/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## The Code of Conflict
 | 
			
		||||
 | 
			
		||||
GNU social has a high submission standard and we want to keep quality code in the
 | 
			
		||||
codebase and bad code out of it. As such your code will be closely scrutinized,
 | 
			
		||||
and you might take this criticism personally. Please understand that this is
 | 
			
		||||
meant to keep the standards of the codebase up, and isn't meant personally. All
 | 
			
		||||
the same, this isn't an excuse for poor behaviour, and a reviewer shouldn't be
 | 
			
		||||
misbehaving towards submitters.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
If however, anyone feels personally abused, threatened, or otherwise
 | 
			
		||||
uncomfortable due to this process, that is not acceptable.  If so, please
 | 
			
		||||
contact the project team at mattl@gnu.org, and they will work to resolve the issue
 | 
			
		||||
to the best of their ability.
 | 
			
		||||
 | 
			
		||||
As a reviewer of code, please strive to keep things civil and focused on the
 | 
			
		||||
technical issues involved.  We are all humans, and frustrations can be high on
 | 
			
		||||
both sides of the process.  Try to keep in mind the immortal words of Bill and
 | 
			
		||||
Ted, "Be excellent to each other."
 | 
			
		||||
							
								
								
									
										112
									
								
								CONTRIBUTING.md
									
									
									
									
									
								
							
							
						
						
									
										112
									
								
								CONTRIBUTING.md
									
									
									
									
									
								
							@@ -1,112 +0,0 @@
 | 
			
		||||
# Contributing to GNU social
 | 
			
		||||
 | 
			
		||||
First of all, if you're reading this intending to contribute to GNU social,
 | 
			
		||||
thanks! Free software development only happens when people like you take an
 | 
			
		||||
interest in giving back to the software they themselves use, and their
 | 
			
		||||
community.
 | 
			
		||||
 | 
			
		||||
When contributing to this repository, please first discuss the change you wish to
 | 
			
		||||
make via issue, email, or any other method with the owners of this repository before
 | 
			
		||||
making a change.
 | 
			
		||||
 | 
			
		||||
There's a few files you should read before going forward with a merge request
 | 
			
		||||
or a patch submission.  They detail what this file touches on in brief.  They
 | 
			
		||||
are:
 | 
			
		||||
 | 
			
		||||
* `DOCUMENTATION/DEVELOPERS/CONTRIBUTING/coding_standards.md`: How your code should be structured and formatted to be
 | 
			
		||||
  accepted into the GNU social codebase.
 | 
			
		||||
* `/DOCUMENTATION/DEVELOPERS/CONTRIBUTING/merge_request_checklist.md`: A quick checklist to review before submission.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## Merge Request Process
 | 
			
		||||
 | 
			
		||||
1. Ensure you strip any trailing spaces off and checked the file with php-cs-fixer
 | 
			
		||||
2. Increase the version numbers in any examples files and the README.md to the new version that this
 | 
			
		||||
   Pull Request would represent. The versioning scheme we use is [SemVer](http://semver.org/).
 | 
			
		||||
3. You may merge the Pull Request in once you have the sign-off of two other developers, or if you
 | 
			
		||||
   do not have permission to do that, you may request the second reviewer to merge it for you.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## Coding Standards
 | 
			
		||||
 | 
			
		||||
Since we will be expected to maintain your code once it's submitted, we ask you
 | 
			
		||||
to adhere to certain coding standards that make it easier for us to do so. If
 | 
			
		||||
code doesn't follow them, it will be rejected, so please read up on these.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## Bug Reports
 | 
			
		||||
 | 
			
		||||
Please report bugs to the issue tracker at
 | 
			
		||||
<https://notabug.org/diogo/gnu-social/issues> Avoid assigning the labels
 | 
			
		||||
yourself, as these are for the development team to assign priority and area of
 | 
			
		||||
coverage to a subject. Please only submit something here if you are certain it
 | 
			
		||||
is a bug or represents a feature enhancement that we do not presently have. If
 | 
			
		||||
you are uncertain whether it's a bug, please feel free to ask
 | 
			
		||||
at #social IRC channel on freenode.net https://www.freenode.net/.
 | 
			
		||||
 | 
			
		||||
When reporting a bug, please try to include as much information as possible,
 | 
			
		||||
including the environment being run on (if it's a common LAMP stack just give
 | 
			
		||||
us version numbers of the main stack components, that's fine), and the specific
 | 
			
		||||
error you get. If you do not get a client-facing error, please check the PHP
 | 
			
		||||
error_log and ensure there isn't something silently reported there, as well as
 | 
			
		||||
the GNU social log. Try to include steps to reproduce the error as well, as if
 | 
			
		||||
we cannot reproduce the error, we can't fix it!
 | 
			
		||||
 | 
			
		||||
It is perfectly acceptable to reference the archive page of a discussion on the
 | 
			
		||||
mailing list for the bug report, by the way, as long as it includes all the
 | 
			
		||||
information we need for a bug report.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## Submitting Feature Requests / Enhancement Requests
 | 
			
		||||
 | 
			
		||||
Social media is constantly evolving, and we welcome ideas about how we can
 | 
			
		||||
change and evolve GNU social to keep it the excellent piece of software that it
 | 
			
		||||
is. However, there are a few things we ask you do when submitting feature
 | 
			
		||||
requests:
 | 
			
		||||
 | 
			
		||||
1. Understand that since we have a limited amount of developers and these people
 | 
			
		||||
contribute in their free time, we may prioritize things differently than you
 | 
			
		||||
value them. Oftentimes this is because certain requests involve less changes
 | 
			
		||||
to the existing codebase than others, and therefore this makes them easier
 | 
			
		||||
to add.
 | 
			
		||||
2. Please search the existing feature requests and enhancements to see if a
 | 
			
		||||
similar request exists. If one does but you have different ideas about how
 | 
			
		||||
to do it or what it should entail, please add a comment to the existing idea
 | 
			
		||||
rather than create a new one for your "version" of it. Duplicate submissions
 | 
			
		||||
mean we spend more time maintaining the tracker and less time actually
 | 
			
		||||
working on the codebase!
 | 
			
		||||
3. When outlining the way that you see something working, don't be afraid to be
 | 
			
		||||
as detailed as possible! We may not implement it exactly as you describe for
 | 
			
		||||
any variety of reasons, but the more concrete and fleshed out an idea is, the
 | 
			
		||||
easier it is for us to know what you want and be able to implement it in a
 | 
			
		||||
sane and secure fashion.
 | 
			
		||||
4. When describing a possible new idea and its mechanisms of operation, the key
 | 
			
		||||
words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD",
 | 
			
		||||
"SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in the issue submission
 | 
			
		||||
are to be interpreted as described in RFC 2119.
 | 
			
		||||
<https://tools.ietf.org/html/rfc2119>
 | 
			
		||||
 | 
			
		||||
Finally, and just as a call back to the first point, realize just because we
 | 
			
		||||
might not rush to implement something, doesn't mean that we don't want to
 | 
			
		||||
implement it! We would rather take the time to do something right the first
 | 
			
		||||
time, then hurriedly apply a new idea, or a fix, only to have to patch it later.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## Branch of Code Submissions
 | 
			
		||||
 | 
			
		||||
Unless you've been specifically directed otherwise, all submissions of code
 | 
			
		||||
should be against the `nightly` branch, so make sure any modifications are based
 | 
			
		||||
on Nightly.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## Copyright / Licensing
 | 
			
		||||
 | 
			
		||||
You acknowledge that by submitting code to GNU social, you are licensing it under
 | 
			
		||||
the GNU AGPLv3 unless there is an extenuating circumstance where it would be
 | 
			
		||||
licensed differently (such as modifications to an external library we include
 | 
			
		||||
such as Stomp).
 | 
			
		||||
 | 
			
		||||
You also acknowledge that unless you assign a copyright explicitly, it will be
 | 
			
		||||
assumed to be assigned to GNU social.
 | 
			
		||||
 | 
			
		||||
Thanks for considering submission, and happy hacking!
 | 
			
		||||
							
								
								
									
										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/>.
 | 
			
		||||
							
								
								
									
										116
									
								
								CREDITS.md
									
									
									
									
									
								
							
							
						
						
									
										116
									
								
								CREDITS.md
									
									
									
									
									
								
							@@ -8,55 +8,55 @@ anyone's been overlooked in error.
 | 
			
		||||
 | 
			
		||||
Current team
 | 
			
		||||
------------
 | 
			
		||||
* Matt Lee
 | 
			
		||||
* Mikael Nordfeldth
 | 
			
		||||
* Diogo Cordeiro
 | 
			
		||||
* Bruno Casteleiro
 | 
			
		||||
* Miguel Dantas
 | 
			
		||||
* Alexei Sorokin
 | 
			
		||||
* Bruno Casteleiro
 | 
			
		||||
* Diogo Cordeiro
 | 
			
		||||
* Hugo Sales
 | 
			
		||||
 | 
			
		||||
Additional Contributors
 | 
			
		||||
-----------------------
 | 
			
		||||
* Ciaran Gultnieks
 | 
			
		||||
* Michael Landers
 | 
			
		||||
* Ori Avtalion
 | 
			
		||||
* Garret Buell
 | 
			
		||||
* Mike Cochrane
 | 
			
		||||
* Matthew Gregg
 | 
			
		||||
* 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
 | 
			
		||||
* Craig Andrews
 | 
			
		||||
* Donald Robertson
 | 
			
		||||
* Deb Nicholson
 | 
			
		||||
* Ian Denhart
 | 
			
		||||
* Steven DuBois
 | 
			
		||||
* Blaine Cook
 | 
			
		||||
* Henry Story
 | 
			
		||||
* Melvin Carvalho
 | 
			
		||||
* chimo
 | 
			
		||||
* Akio
 | 
			
		||||
* Maiyannah Bishop
 | 
			
		||||
* Blaine Cook
 | 
			
		||||
* Bob Mottram
 | 
			
		||||
* David Yip
 | 
			
		||||
* Neil E Hodges
 | 
			
		||||
* Moonman
 | 
			
		||||
* Normandy
 | 
			
		||||
* Verius
 | 
			
		||||
* Alexei Sorokin
 | 
			
		||||
* 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
 | 
			
		||||
--------------
 | 
			
		||||
@@ -65,24 +65,24 @@ Leads
 | 
			
		||||
* Zach Copley
 | 
			
		||||
 | 
			
		||||
Team
 | 
			
		||||
* Earle Martin
 | 
			
		||||
* Marie-Claude Doyon
 | 
			
		||||
* Sarven Capadisli
 | 
			
		||||
* Robin Millette
 | 
			
		||||
* Brion Vibber
 | 
			
		||||
* James Walker
 | 
			
		||||
* Samantha Doherty
 | 
			
		||||
* Florian Biree
 | 
			
		||||
* Erik Stambaugh
 | 
			
		||||
* 'drry'
 | 
			
		||||
* Gina Haeussge
 | 
			
		||||
* Tryggvi Björgvinsson
 | 
			
		||||
* Adrian Lang
 | 
			
		||||
* Ori Avtalion
 | 
			
		||||
* Meitar Moscovitz
 | 
			
		||||
* Ken Sheppardson
 | 
			
		||||
* Simon Waters, Surevine
 | 
			
		||||
* 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
 | 
			
		||||
-----------
 | 
			
		||||
 
 | 
			
		||||
@@ -1,61 +0,0 @@
 | 
			
		||||
<?php
 | 
			
		||||
// This file is part of GNU social - https://www.gnu.org/software/social
 | 
			
		||||
//
 | 
			
		||||
// GNU social 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.
 | 
			
		||||
//
 | 
			
		||||
// GNU social 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 GNU social.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Description of this file.
 | 
			
		||||
 *
 | 
			
		||||
 * @package   samples
 | 
			
		||||
 * @author    Diogo Cordeiro <diogo@fc.up.pt>
 | 
			
		||||
 * @copyright 2019 Free Software Foundation, Inc http://www.fsf.org
 | 
			
		||||
 * @license   https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
namespace samples;
 | 
			
		||||
 | 
			
		||||
defined('GNUSOCIAL') || die();
 | 
			
		||||
 | 
			
		||||
require_once(__DIR__ . DIRECTORY_SEPARATOR . 'SampleHandler.php');
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Description of this class.
 | 
			
		||||
 *
 | 
			
		||||
 * @copyright 2019 Free Software Foundation, Inc http://www.fsf.org
 | 
			
		||||
 * @license   https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
 | 
			
		||||
 */
 | 
			
		||||
class MySampleClass
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * Constructor for the sample class.
 | 
			
		||||
     *
 | 
			
		||||
     * @param string $dummy_word just because.
 | 
			
		||||
     * @param int $result another just because.
 | 
			
		||||
     */
 | 
			
		||||
    public function __construct(string $dummy_word = '', int $result = null)
 | 
			
		||||
    {
 | 
			
		||||
        global $demo;
 | 
			
		||||
        $this->niceWorld();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * How cool is this function.
 | 
			
		||||
     *
 | 
			
		||||
     * @return string
 | 
			
		||||
     */
 | 
			
		||||
    public function niceWorld() : string
 | 
			
		||||
    {
 | 
			
		||||
        return 'hello, world.';
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,275 +0,0 @@
 | 
			
		||||
GNU social Coding Style
 | 
			
		||||
===========================
 | 
			
		||||
 | 
			
		||||
Please comply with [PSR-2](https://www.php-fig.org/psr/psr-2/) and the following standard when working on GNU social
 | 
			
		||||
if you want your patches accepted and modules included in supported releases.
 | 
			
		||||
 | 
			
		||||
If you see code which doesn't comply with the below, please fix it :)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Strings
 | 
			
		||||
-------------------------------------------------------------------------------
 | 
			
		||||
Use `'` instead of `"` for strings, where substitutions aren't required.
 | 
			
		||||
This is a performance issue, and prevents a lot of inconsistent coding styles.
 | 
			
		||||
When using substitutions, use curly braces around your variables - like so:
 | 
			
		||||
 | 
			
		||||
    $var = "my_var: {$my_var}";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Comments and Documentation
 | 
			
		||||
-------------------------------------------------------------------------------
 | 
			
		||||
Comments go on the line ABOVE the code, NOT to the right of the code, unless it is very short.
 | 
			
		||||
All functions and methods are to be documented using PhpDocumentor - https://docs.phpdoc.org/guides/
 | 
			
		||||
 | 
			
		||||
File Headers
 | 
			
		||||
-------------------------------------------------------------------------------
 | 
			
		||||
File headers follow a consistent format, as such:
 | 
			
		||||
 | 
			
		||||
    // This file is part of GNU social - https://www.gnu.org/software/social
 | 
			
		||||
    //
 | 
			
		||||
    // GNU social 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.
 | 
			
		||||
    //
 | 
			
		||||
    // GNU social 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 GNU social.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Description of this file.
 | 
			
		||||
     *
 | 
			
		||||
     * @package   samples
 | 
			
		||||
     * @author    Diogo Cordeiro <diogo@fc.up.pt>
 | 
			
		||||
     * @copyright 2019 Free Software Foundation, Inc http://www.fsf.org
 | 
			
		||||
     * @license   https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
Please use it.
 | 
			
		||||
 | 
			
		||||
A few notes:
 | 
			
		||||
 | 
			
		||||
*  The description of the file doesn't have to be exhaustive.  Rather it's
 | 
			
		||||
   meant to be a short summary of what's in this file and what it does.  Try
 | 
			
		||||
   to keep it to 1-5 lines.  You can get more in-depth when documenting
 | 
			
		||||
   individual functions!
 | 
			
		||||
 | 
			
		||||
*  You'll probably see files with multiple authors, this is by
 | 
			
		||||
   design - many people contributed to GNU social or its forebears!  If you
 | 
			
		||||
   are modifying an existing file, APPEND your own author line, and update
 | 
			
		||||
   the copyright year if needed. Do not replace existing ones.
 | 
			
		||||
 | 
			
		||||
You may find `boilerplate.php` useful when creating a new file from scratch.
 | 
			
		||||
 | 
			
		||||
Paragraph spacing
 | 
			
		||||
-------------------------------------------------------------------------------
 | 
			
		||||
Where-ever possible, try to keep the lines to 80 characters.  Don't
 | 
			
		||||
sacrifice readability for it though - if it makes more sense to have it in
 | 
			
		||||
one longer line, and it's more easily read that way, that's fine.
 | 
			
		||||
 | 
			
		||||
With assignments, avoid breaking them down into multiple lines unless
 | 
			
		||||
neccesary, except for enumerations and arrays.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
'If' statements format
 | 
			
		||||
-------------------------------------------------------------------------------
 | 
			
		||||
Use switch statements where many else if's are going to be used. Switch/case is faster
 | 
			
		||||
 | 
			
		||||
    if ($var == 'example') {
 | 
			
		||||
        echo 'This is only an example';
 | 
			
		||||
    } else {
 | 
			
		||||
        echo 'This is not a test.  This is the real thing';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
Do NOT make if statements like this:
 | 
			
		||||
 | 
			
		||||
    if ($var == 'example'){ echo 'An example'; }
 | 
			
		||||
 | 
			
		||||
    OR this
 | 
			
		||||
 | 
			
		||||
    if($var = 'example')
 | 
			
		||||
            echo "An {$var}";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Associative arrays
 | 
			
		||||
-------------------------------------------------------------------------------
 | 
			
		||||
Always use `[]` instead of `array()`. Associative arrays must be written in the
 | 
			
		||||
following manner:
 | 
			
		||||
 | 
			
		||||
    $array = [
 | 
			
		||||
        'var' => 'value',
 | 
			
		||||
        'var2' => 'value2'
 | 
			
		||||
    ];
 | 
			
		||||
 | 
			
		||||
Note that spaces are preferred around the '=>'.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
A note about shorthands
 | 
			
		||||
-------------------------------------------------------------------------------
 | 
			
		||||
Some short hands are evil:
 | 
			
		||||
 | 
			
		||||
- Use the long format for `<?php`.  Do NOT use `<?`.
 | 
			
		||||
- Use the long format for `<?php` echo. Do NOT use `<?=`.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Naming conventions
 | 
			
		||||
-------------------------------------------------------------------------------
 | 
			
		||||
Respect PSR2 first.
 | 
			
		||||
 | 
			
		||||
- Classes use PascalCase (e.g. MyClass).
 | 
			
		||||
- Functions/Methods use camelCase (e.g. myFunction).
 | 
			
		||||
- Variables use snake_case (e.g. my_variable).
 | 
			
		||||
 | 
			
		||||
A note on variable names, etc. It must be possible to understand what is meant
 | 
			
		||||
without neccesarialy seeing it in context, because the code that calls something
 | 
			
		||||
might not always make it clear.
 | 
			
		||||
 | 
			
		||||
So if you have something like:
 | 
			
		||||
 | 
			
		||||
    $notice->post($contents);
 | 
			
		||||
 | 
			
		||||
Well I can easily tell what you're doing there because the names are straight-
 | 
			
		||||
forward and clear.
 | 
			
		||||
 | 
			
		||||
Something like this:
 | 
			
		||||
 | 
			
		||||
    foo->bar();
 | 
			
		||||
 | 
			
		||||
Is much less clear.
 | 
			
		||||
 | 
			
		||||
Also, whereever possible, avoid ambiguous terms.  For example, don't use text
 | 
			
		||||
as a term for a variable.  Call back to "contents" above.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Comparisons
 | 
			
		||||
-------------------------------------------------------------------------------
 | 
			
		||||
Always use symbol based comparison operators (&&, ||) instead of text based
 | 
			
		||||
operators (AND, OR) as they are evaluated in different orders and at different
 | 
			
		||||
speeds.  This is will prevent any confusion or strange results.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Use English
 | 
			
		||||
-------------------------------------------------------------------------------
 | 
			
		||||
All variables, classes, methods, functions and comments must be in English.
 | 
			
		||||
Bad english is easier to work with than having to babelfish code to work out
 | 
			
		||||
how it works.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Encoding
 | 
			
		||||
-------------------------------------------------------------------------------
 | 
			
		||||
Files should be in UTF-8 encoding with UNIX line endings.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
No ending tag
 | 
			
		||||
-------------------------------------------------------------------------------
 | 
			
		||||
Files should not end with an ending php tag "?>".  Any whitespace after the
 | 
			
		||||
closing tag is sent to the browser and cause errors, so don't include them.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Nesting Functions
 | 
			
		||||
-------------------------------------------------------------------------------
 | 
			
		||||
Avoid, if at all possible.  When not possible, document the living daylights
 | 
			
		||||
out of why you're nesting it.  It's not always avoidable, but PHP 5 has a lot
 | 
			
		||||
of obscure problems that come up with using nested functions.
 | 
			
		||||
 | 
			
		||||
If you must use a nested function, be sure to have robust error-handling.
 | 
			
		||||
This is a must and submissions including nested functions that do not have
 | 
			
		||||
robust error handling will be rejected and you'll be asked to add it.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Scoping
 | 
			
		||||
-------------------------------------------------------------------------------
 | 
			
		||||
Properly enforcing scope of functions is something many PHP programmers don't
 | 
			
		||||
do, but should.
 | 
			
		||||
 | 
			
		||||
In general:
 | 
			
		||||
*  Variables unique to a class should be protected and use interfacing to
 | 
			
		||||
   change them.  This allows for input validation and making sure we don't have
 | 
			
		||||
   injection, especially when something's exposed to the API, that any program
 | 
			
		||||
   can use, and not all of them are going to be be safe and trusted.
 | 
			
		||||
 | 
			
		||||
*  Variables not unique to a class should be validated prior to every call,
 | 
			
		||||
   which is why it's generally not a good idea to re-use stuff across classes
 | 
			
		||||
   unless there's significant performance gains to doing so.
 | 
			
		||||
 | 
			
		||||
*  Classes should protect functions that they do not want overriden, but they
 | 
			
		||||
   should avoid protecting the constructor and destructor and related helper
 | 
			
		||||
   functions as this prevents proper inheritance.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Typecasting
 | 
			
		||||
-------------------------------------------------------------------------------
 | 
			
		||||
PHP is a soft-typed language and it falls to us developers to make sure that
 | 
			
		||||
we are using the proper inputs.  Where ever possible use explicit type casting.
 | 
			
		||||
Where it in't, you're going to have to make sure that you check all your
 | 
			
		||||
inputs before you pass them.
 | 
			
		||||
 | 
			
		||||
All outputs should be cast as an explicit PHP type.
 | 
			
		||||
 | 
			
		||||
Not properly typecasting is a shooting offence.  Soft types let programmers
 | 
			
		||||
get away with a lot of lazy code, but lazy code is buggy code, and frankly, I
 | 
			
		||||
don't want it in GNU social if it's going to be buggy.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Consistent exception handling
 | 
			
		||||
-------------------------------------------------------------------------------
 | 
			
		||||
Consistency is key to good code to begin with, but it is especially important
 | 
			
		||||
to be consistent with how we handle errors.  GNU social has a variety of built-
 | 
			
		||||
in exception classes.  Use them, wherever it's possible and appropriate, and
 | 
			
		||||
they will do the heavy lifting for you.
 | 
			
		||||
 | 
			
		||||
Additionally, ensure you clean up any and all records and variables that need
 | 
			
		||||
cleanup in a function using try { } finally { } even if you do not plan on
 | 
			
		||||
catching exceptions (why wouldn't you, though?  That's silly.)
 | 
			
		||||
 | 
			
		||||
If you do not call an exception handler, you must, at a minimum, record errors
 | 
			
		||||
to the log using common_log(level, message)
 | 
			
		||||
 | 
			
		||||
Ensure all possible control flows of a function have exception handling and
 | 
			
		||||
cleanup, where appropriate.  Don't leave endpoints with unhandled exceptions.
 | 
			
		||||
Try not to leave something in an error state if it's avoidable.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Return values
 | 
			
		||||
-------------------------------------------------------------------------------
 | 
			
		||||
All functions must return a value.  Every single one.  This is not optional.
 | 
			
		||||
 | 
			
		||||
If you are simply making a procedure call, for example as part of a helper
 | 
			
		||||
function, then return boolean TRUE on success, and the exception on failure.
 | 
			
		||||
 | 
			
		||||
When returning the exception, return the whole nine yards, which is to say the
 | 
			
		||||
actual PHP exception object, not just an error message.
 | 
			
		||||
 | 
			
		||||
All return values not the above should be type cast, and you should sanitize
 | 
			
		||||
anything returned to ensure it fits into the cast.  You might technically make
 | 
			
		||||
an integer a string, for instance, but you should be making sure that integer
 | 
			
		||||
SHOULD be a string, if you're returning it, and that it is a valid return
 | 
			
		||||
value.
 | 
			
		||||
 | 
			
		||||
A vast majority of programming errors come down to not checking your inputs
 | 
			
		||||
and outputs properly, so please try to do so as best and thoroughly as you can.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Layout and Location of files
 | 
			
		||||
-------------------------------------------------------------------------------
 | 
			
		||||
`/actions/` contains files that determine what happens when something "happens":
 | 
			
		||||
for instance, when someone favourites or repeats a notice.  Code that is
 | 
			
		||||
related to a "happening" should go here.
 | 
			
		||||
 | 
			
		||||
`/classes/` contains abstract definitions of certain "things" in the codebase
 | 
			
		||||
such as a user or notice.  If you're making a new "thing", it goes here.
 | 
			
		||||
 | 
			
		||||
`/lib/` is basically the back-end.  Actions will call something in here to get
 | 
			
		||||
stuff done usually, which in turn will probably manipulate information stored
 | 
			
		||||
in one or more records represented by a class.
 | 
			
		||||
 | 
			
		||||
`/extlib/` is where external libraries are located.  If you include a new
 | 
			
		||||
external library, it goes here.
 | 
			
		||||
 | 
			
		||||
`/plugins/` This is a great way to modularize your own new features.  If you want
 | 
			
		||||
to create new core features for GNU social, it is probably best to create a
 | 
			
		||||
module unless you absolutely must override or modify the core behaviours.
 | 
			
		||||
@@ -1,32 +0,0 @@
 | 
			
		||||
Submission Checklist
 | 
			
		||||
================================================================================
 | 
			
		||||
This document serves as a handy checklist for submitted merges and patches to
 | 
			
		||||
the postActiv project.  Following it isn't a gaurantee a patch will be accepted,
 | 
			
		||||
but it will help you avoid common problems.
 | 
			
		||||
 | 
			
		||||
1. Ensure all code control paths in all functions return a value.
 | 
			
		||||
 | 
			
		||||
2. Ensure all exceptions are trapped in an exception class, or minimally,
 | 
			
		||||
   written to the log with common_log
 | 
			
		||||
 | 
			
		||||
3. Ensure the coding format standards are adhered to (see coding_standards.md)
 | 
			
		||||
 | 
			
		||||
4. Ensure that any new class that deals in public data has a corresponding new
 | 
			
		||||
   API endpoint.
 | 
			
		||||
 | 
			
		||||
5. Ensure that all new API endpoints sanitize inputs and outputs properly.
 | 
			
		||||
 | 
			
		||||
6. Ensure that your version of the code works with PHP 7 on a standard
 | 
			
		||||
   LAMP and LEMP stack (Linux+Apache+MariaDB+PHP and Linux+nginx+MariaDB+PHP)
 | 
			
		||||
 | 
			
		||||
7. If implementing new database functions, ensure they work with MariaDB
 | 
			
		||||
   and postgreSQL.
 | 
			
		||||
 | 
			
		||||
8. Ensure all data that federates does so properly and has mechanisms to
 | 
			
		||||
   catch and accomodate for federation transmission failure.
 | 
			
		||||
 | 
			
		||||
9. Ensure that nothing is left in an error state when it is avoidable.
 | 
			
		||||
 | 
			
		||||
10. Ensure that all code submitted is properly documented.
 | 
			
		||||
 | 
			
		||||
11. Ensure that there are no PHP Strict Standards or Parse errors in the code.
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -1,355 +0,0 @@
 | 
			
		||||
Plugin Development
 | 
			
		||||
=======================
 | 
			
		||||
 | 
			
		||||
SamplePlugin.php
 | 
			
		||||
-----------------------
 | 
			
		||||
 | 
			
		||||
Each plugin requires a main class to interact with the GNU social system.
 | 
			
		||||
 | 
			
		||||
The main class usually extends the Plugin class that comes with GNU social.
 | 
			
		||||
 | 
			
		||||
The class has standard-named methods that will be called when certain events
 | 
			
		||||
happen in the code base. These methods have names like 'onX' where X is an
 | 
			
		||||
event name (see EVENTS.txt for the list of available events). Event handlers
 | 
			
		||||
have pre-defined arguments, based on which event they're handling. A typical
 | 
			
		||||
event handler:
 | 
			
		||||
 | 
			
		||||
```php
 | 
			
		||||
function onSomeEvent($paramA, &$paramB)
 | 
			
		||||
{
 | 
			
		||||
    if ($paramA == 'jed') {
 | 
			
		||||
        throw new Exception(sprintf(_m("Invalid parameter %s"), $paramA));
 | 
			
		||||
    }
 | 
			
		||||
    $paramB = 'spock';
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Event Handlers
 | 
			
		||||
-----------------------
 | 
			
		||||
 | 
			
		||||
Event handlers must return a Boolean value.
 | 
			
		||||
 | 
			
		||||
If they return false, all other event handlers for this event (in other plug-in)
 | 
			
		||||
will be skipped, and in some cases the default processing for that event would
 | 
			
		||||
be skipped. This is great for replacing the default action of an event.
 | 
			
		||||
 | 
			
		||||
If the handler returns true, processing of other event handlers and the default
 | 
			
		||||
processing will continue. This is great for extending existing functionality.
 | 
			
		||||
 | 
			
		||||
If the handler throws an exception, processing will stop, and the exception's
 | 
			
		||||
error will be shown to the user.
 | 
			
		||||
 | 
			
		||||
Installation
 | 
			
		||||
------------------
 | 
			
		||||
 | 
			
		||||
To install a plugin (like this one), site admins add the following code to their
 | 
			
		||||
config.php file:
 | 
			
		||||
 | 
			
		||||
```php
 | 
			
		||||
addPlugin('Sample');
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Plugins must be installed in one of the following directories:
 | 
			
		||||
 | 
			
		||||
* local/plugins/{$pluginclass}.php
 | 
			
		||||
* local/plugins/{$name}/{$pluginclass}.php
 | 
			
		||||
* local/{$pluginclass}.php
 | 
			
		||||
* local/{$name}/{$pluginclass}.php
 | 
			
		||||
* plugins/{$pluginclass}.php
 | 
			
		||||
* plugins/{$name}/{$pluginclass}.php
 | 
			
		||||
 | 
			
		||||
Here, `{$name}` is the name of the plugin, like 'Sample', and `{$pluginclass}`
 | 
			
		||||
is the name of the main class, like 'SamplePlugin'. Plugins that are part of
 | 
			
		||||
the main GNU social distribution go in 'plugins' and third-party or local ones
 | 
			
		||||
go in 'local'.
 | 
			
		||||
 | 
			
		||||
Simple plugins can be implemented as a single module. Others are more complex
 | 
			
		||||
and require additional modules; these should use their own directory, like
 | 
			
		||||
'local/plugins/{$name}/'. All files related to the plugin, including images,
 | 
			
		||||
JavaScript, CSS, external libraries or PHP modules should go in the plugin
 | 
			
		||||
directory.
 | 
			
		||||
 | 
			
		||||
Plugin Configuration
 | 
			
		||||
------------------
 | 
			
		||||
 | 
			
		||||
Plugins are configured using public instance attributes. To set their values,
 | 
			
		||||
site administrators use this syntax:
 | 
			
		||||
 | 
			
		||||
```php
 | 
			
		||||
addPlugin('Sample', ('attr1' => 'foo', 'attr2' => 'bar'));
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
The same plugin class can be initialized multiple times with different arguments:
 | 
			
		||||
 | 
			
		||||
```php
 | 
			
		||||
addPlugin('EmailNotify', array('sendTo' => 'evan@status.net'));
 | 
			
		||||
addPlugin('EmailNotify', array('sendTo' => 'brionv@status.net'));
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
```php
 | 
			
		||||
class SamplePlugin extends Plugin
 | 
			
		||||
{
 | 
			
		||||
    public $attr1 = null;
 | 
			
		||||
    public $attr2 = null;
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Initialization
 | 
			
		||||
------------------
 | 
			
		||||
 | 
			
		||||
Plugins overload this method to do any initialization they need, like connecting
 | 
			
		||||
to remote servers or creating paths or so on. @return boolean hook value; true
 | 
			
		||||
means continue processing, false means stop.
 | 
			
		||||
 | 
			
		||||
```php
 | 
			
		||||
function initialize()
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Clean Up
 | 
			
		||||
------------------
 | 
			
		||||
 | 
			
		||||
Plugins overload this method to do any cleanup they need, like disconnecting from
 | 
			
		||||
remote servers or deleting temp files or so on.
 | 
			
		||||
 | 
			
		||||
```php
 | 
			
		||||
function cleanup()
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Database schema setup
 | 
			
		||||
------------------
 | 
			
		||||
 | 
			
		||||
Plugins can add their own tables to the GNU social database. Plugins should use
 | 
			
		||||
GNU social's schema interface to add or delete tables. The ensureTable() method
 | 
			
		||||
provides an easy way to ensure a table's structure and availability.
 | 
			
		||||
 | 
			
		||||
By default, the schema is checked every time GNU social is run (say, when a Web
 | 
			
		||||
page is hit). Admins can configure their systems to only check the schema when
 | 
			
		||||
the checkschema.php script is run, greatly improving performance. However, they
 | 
			
		||||
need to remember to run that script after installing or upgrading a plugin!
 | 
			
		||||
 | 
			
		||||
```php
 | 
			
		||||
function onCheckSchema()
 | 
			
		||||
{
 | 
			
		||||
    $schema = Schema::get();
 | 
			
		||||
 | 
			
		||||
    // '''For storing user-submitted flags on profiles'''
 | 
			
		||||
 | 
			
		||||
    $schema->ensureTable('user_greeting_count',
 | 
			
		||||
                          array(new ColumnDef('user_id', 'integer', null,
 | 
			
		||||
                                              true, 'PRI'),
 | 
			
		||||
                                new ColumnDef('greeting_count', 'integer')));
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Load related modules when needed
 | 
			
		||||
------------------
 | 
			
		||||
 | 
			
		||||
Most non-trivial plugins will require extra modules to do their work. Typically
 | 
			
		||||
these include data classes, action classes, widget classes, or external libraries.
 | 
			
		||||
 | 
			
		||||
This method receives a class name and loads the PHP file related to that class.
 | 
			
		||||
By tradition, action classes typically have files named for the action, all
 | 
			
		||||
lower-case. Data classes are in files with the data class name, initial letter
 | 
			
		||||
capitalized.
 | 
			
		||||
 | 
			
		||||
Note that this method will be called for *all* overloaded classes, not just ones
 | 
			
		||||
in this plugin! So, make sure to return true by default to let other plugins,
 | 
			
		||||
and the core code, get a chance.
 | 
			
		||||
 | 
			
		||||
```php
 | 
			
		||||
function onAutoload($cls)
 | 
			
		||||
{
 | 
			
		||||
    $dir = dirname(__FILE__);
 | 
			
		||||
 | 
			
		||||
    switch ($cls)
 | 
			
		||||
    {
 | 
			
		||||
    case 'HelloAction':
 | 
			
		||||
        include_once $dir . '/' . strtolower(mb_substr($cls, 0, -6)) . '.php';
 | 
			
		||||
        return false;
 | 
			
		||||
    case 'User_greeting_count':
 | 
			
		||||
        include_once $dir . '/'.$cls.'.php';
 | 
			
		||||
        return false;
 | 
			
		||||
    default:
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Map URLs to actions
 | 
			
		||||
------------------
 | 
			
		||||
 | 
			
		||||
This event handler lets the plugin map URLs on the site to actions (and thus an
 | 
			
		||||
action handler class). Note that the action handler class for an action will be
 | 
			
		||||
named 'FoobarAction', where action = 'foobar'. The class must be loaded in the
 | 
			
		||||
onAutoload() method.
 | 
			
		||||
 | 
			
		||||
```php
 | 
			
		||||
function onRouterInitialized($m)
 | 
			
		||||
{
 | 
			
		||||
    $m->connect('main/hello',
 | 
			
		||||
                array('action' => 'hello'));
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Modify the default menu to link to our custom action
 | 
			
		||||
------------------
 | 
			
		||||
 | 
			
		||||
Using event handlers, it's possible to modify the default UI for pages almost
 | 
			
		||||
without limit. In this method, we add a menu item to the default primary menu
 | 
			
		||||
for the interface to link to our action.
 | 
			
		||||
 | 
			
		||||
Action Class
 | 
			
		||||
------------------
 | 
			
		||||
 | 
			
		||||
The Action class provides a rich set of events to hook, as well as output methods.
 | 
			
		||||
 | 
			
		||||
```php
 | 
			
		||||
function onEndPrimaryNav($action)
 | 
			
		||||
{
 | 
			
		||||
    // '''common_local_url()''' gets the correct URL for the action name we provide
 | 
			
		||||
 | 
			
		||||
    $action->menuItem(common_local_url('hello'),
 | 
			
		||||
                      _m('Hello'), _m('A warm greeting'), false, 'nav_hello');
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function onPluginVersion(&$versions)
 | 
			
		||||
{
 | 
			
		||||
    $versions[] = array('name' => 'Sample',
 | 
			
		||||
                        'version' => STATUSNET_VERSION,
 | 
			
		||||
                        'author' => 'Brion Vibber, Evan Prodromou',
 | 
			
		||||
                        'homepage' => 'http://example.org/plugin',
 | 
			
		||||
                        'rawdescription' =>
 | 
			
		||||
                        _m('A sample plugin to show basics of development for new hackers.'));
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
hello.php
 | 
			
		||||
------------------
 | 
			
		||||
 | 
			
		||||
This section is taken directly from the 'hello.php'. ( plugins/Sample/hello.php )
 | 
			
		||||
 | 
			
		||||
Give a warm greeting to our friendly user.
 | 
			
		||||
 | 
			
		||||
This sample action shows some basic ways of doing output in an action class.
 | 
			
		||||
 | 
			
		||||
Action classes have several output methods that they override from the parent class.
 | 
			
		||||
 | 
			
		||||
```php
 | 
			
		||||
class HelloAction extends Action
 | 
			
		||||
{
 | 
			
		||||
    var $user = null;
 | 
			
		||||
    var $gc   = null;
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Take arguments for running
 | 
			
		||||
------------------
 | 
			
		||||
 | 
			
		||||
This method is called first, and it lets the action class get all its arguments
 | 
			
		||||
and validate them. It's also the time to fetch any relevant data from the database.
 | 
			
		||||
 | 
			
		||||
Action classes should run parent::prepare(array $args = []) as the first line
 | 
			
		||||
of this method to make sure the default argument-processing happens.
 | 
			
		||||
 | 
			
		||||
```php     
 | 
			
		||||
function prepare(array $args = [])
 | 
			
		||||
{
 | 
			
		||||
    parent::prepare($args);
 | 
			
		||||
 | 
			
		||||
    $this->user = common_current_user();
 | 
			
		||||
 | 
			
		||||
    if (!empty($this->user)) {
 | 
			
		||||
        $this->gc = User_greeting_count::inc($this->user->id);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Handle request
 | 
			
		||||
------------------
 | 
			
		||||
 | 
			
		||||
This is the main method for handling a request. Note that most preparation
 | 
			
		||||
should be done in the prepare() method; by the time handle() is called the
 | 
			
		||||
action should be more or less ready to go.
 | 
			
		||||
 | 
			
		||||
```php
 | 
			
		||||
function handle()
 | 
			
		||||
{
 | 
			
		||||
    parent::handle();
 | 
			
		||||
 | 
			
		||||
    $this->showPage();
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Title of this page
 | 
			
		||||
------------------
 | 
			
		||||
 | 
			
		||||
Override this method to show a custom title.
 | 
			
		||||
 | 
			
		||||
```php
 | 
			
		||||
function title()
 | 
			
		||||
{
 | 
			
		||||
    if (empty($this->user)) {
 | 
			
		||||
        return _m('Hello');
 | 
			
		||||
    } else {
 | 
			
		||||
        return sprintf(_m('Hello, %s'), $this->user->nickname);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Show content in the content area
 | 
			
		||||
------------------
 | 
			
		||||
 | 
			
		||||
The default GNU social page has a lot of decorations: menus, logos, tabs, all
 | 
			
		||||
that jazz. This method is used to show content in the content area of the
 | 
			
		||||
page; it's the main thing you want to overload. This method also demonstrates
 | 
			
		||||
use of a plural localized string.
 | 
			
		||||
 | 
			
		||||
```php
 | 
			
		||||
function showContent()
 | 
			
		||||
{
 | 
			
		||||
    if (empty($this->user)) {
 | 
			
		||||
        $this->element('p', array('class' => 'greeting'),
 | 
			
		||||
                       _m('Hello, stranger!'));
 | 
			
		||||
    } else {
 | 
			
		||||
        $this->element('p', array('class' => 'greeting'),
 | 
			
		||||
                       sprintf(_m('Hello, %s'), $this->user->nickname));
 | 
			
		||||
        $this->element('p', array('class' => 'greeting_count'),
 | 
			
		||||
                       sprintf(_m('I have greeted you %d time.',
 | 
			
		||||
                                  'I have greeted you %d times.',
 | 
			
		||||
                                  $this->gc->greeting_count),
 | 
			
		||||
                                  $this->gc->greeting_count));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Return true if read only.
 | 
			
		||||
------------------
 | 
			
		||||
 | 
			
		||||
Some actions only read from the database; others read and write. The simple
 | 
			
		||||
database load-balancer built into GNU social will direct read-only actions to
 | 
			
		||||
database mirrors (if they are configured) and read-write actions to the master database.
 | 
			
		||||
 | 
			
		||||
This defaults to false to avoid data integrity issues, but you should make sure
 | 
			
		||||
to overload it for performance gains.
 | 
			
		||||
 | 
			
		||||
```php
 | 
			
		||||
function isReadOnly($args)
 | 
			
		||||
{
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										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
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -1,44 +0,0 @@
 | 
			
		||||
Plugins
 | 
			
		||||
=======
 | 
			
		||||
 | 
			
		||||
GNU social supports 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 AddMyWebsiteLink($action)
 | 
			
		||||
    {
 | 
			
		||||
        $action->menuItem('http://mywebsite.net/', _('My web site'), _('Example web link'));
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Event::addHandler('EndPrimaryNav', 'AddMyWebsiteLink');
 | 
			
		||||
 | 
			
		||||
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 GNU social) 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.
 | 
			
		||||
							
								
								
									
										1
									
								
								DOCUMENTATION/SYSTEM_ADMINISTRATORS/install.md
									
									
									
									
									
										Symbolic link
									
								
							
							
						
						
									
										1
									
								
								DOCUMENTATION/SYSTEM_ADMINISTRATORS/install.md
									
									
									
									
									
										Symbolic link
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
../../INSTALL.md
 | 
			
		||||
@@ -1,56 +0,0 @@
 | 
			
		||||
Initial simple way to Webfinger enable your domain -- needs PHP.
 | 
			
		||||
================================================================
 | 
			
		||||
 | 
			
		||||
This guide needs some updating, since it will only guide you to present
 | 
			
		||||
XML data (while the curl command likely gives you JSON). The workaround
 | 
			
		||||
is to simply make curl get 'webfinger.xml' instead, and/or have another
 | 
			
		||||
file that contains JSON, but that requires editing the PHP file as well.
 | 
			
		||||
 | 
			
		||||
Step 1
 | 
			
		||||
======
 | 
			
		||||
 | 
			
		||||
Put the 'dot-well-known' on your website, so it loads at:
 | 
			
		||||
 | 
			
		||||
     https://example.com/.well-known/
 | 
			
		||||
 | 
			
		||||
(Remember the . at the beginning of this one, which is common practice
 | 
			
		||||
for "hidden" files and why we have renamed it "dot-")
 | 
			
		||||
 | 
			
		||||
Step 2
 | 
			
		||||
======
 | 
			
		||||
 | 
			
		||||
Edit the .well-known/host-meta file and replace "example.com" with the
 | 
			
		||||
domain name you're hosting the .well-known directory on.
 | 
			
		||||
 | 
			
		||||
Using vim you can do this as a quick method:
 | 
			
		||||
    $ vim .well-known/host-meta [ENTER]
 | 
			
		||||
    :%s/example.com/domain.com/    [ENTER]
 | 
			
		||||
    :wq [ENTER]
 | 
			
		||||
 | 
			
		||||
Step 3
 | 
			
		||||
======
 | 
			
		||||
 | 
			
		||||
For each user on your site, and this might only be you...
 | 
			
		||||
 | 
			
		||||
In the webfinger directory, make a copy of the example@example.com.xml file
 | 
			
		||||
so that it's called (replace username and example.com with appropriate
 | 
			
		||||
values, the domain name should be the same as you're "socialifying"):
 | 
			
		||||
 | 
			
		||||
     username@example.com.xml
 | 
			
		||||
 | 
			
		||||
Then edit the file contents, replacing "social.example.com" with your
 | 
			
		||||
GNU social instance's base path, and change the user ID number (and
 | 
			
		||||
nickname for the FOAF link) to that of your account on your social
 | 
			
		||||
site. If you don't know your user ID number, you can see this on your
 | 
			
		||||
GNU social profile page by looking at the destination URLs in the
 | 
			
		||||
Feeds links.
 | 
			
		||||
 | 
			
		||||
PROTIP: You can get the bulk of the contents (note the <Subject> element though)
 | 
			
		||||
        from curling down your real webfinger data:
 | 
			
		||||
$ curl https://social.example.com/.well-known/webfinger?resource=acct:username@social.example.com
 | 
			
		||||
 | 
			
		||||
Finally
 | 
			
		||||
=======
 | 
			
		||||
 | 
			
		||||
Using this method, though fiddly, you can now be @user@domain without
 | 
			
		||||
the need for any prefixes for subdomains, etc.
 | 
			
		||||
@@ -1,5 +0,0 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0" xmlns:hm="http://host-meta.net/xrd/1.0">  
 | 
			
		||||
 <Link rel="lrdd" type="application/xrd+xml"
 | 
			
		||||
        template="https://example.com/.well-known/webfinger?resource={uri}"/>
 | 
			
		||||
</XRD>
 | 
			
		||||
@@ -1,35 +0,0 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0">
 | 
			
		||||
  <Subject>acct:username@example.com</Subject>
 | 
			
		||||
  <Alias>acct:username@social.example.com</Alias>
 | 
			
		||||
  <Alias>https://social.example.com/user/1</Alias>
 | 
			
		||||
  <Link rel="http://webfinger.net/rel/profile-page"
 | 
			
		||||
        type="text/html"
 | 
			
		||||
	href="https://social.example.com/user/1"/>
 | 
			
		||||
 | 
			
		||||
  <Link rel="http://schemas.google.com/g/2010#updates-from"
 | 
			
		||||
       type="application/atom+xml"
 | 
			
		||||
       href="https://social.example.com/api/statuses/user_timeline/1.atom"/>
 | 
			
		||||
 | 
			
		||||
  <!-- Is this/was this ever supported?
 | 
			
		||||
       <Link rel="http://microformats.org/profile/hcard"
 | 
			
		||||
       type="text/html"
 | 
			
		||||
       href="https://social.example.com/hcard"/> -->
 | 
			
		||||
 | 
			
		||||
  <Link rel="http://gmpg.org/xfn/11"
 | 
			
		||||
	type="text/html"
 | 
			
		||||
	href="https://social.example.com/user/1"/>
 | 
			
		||||
 | 
			
		||||
  <Link rel="describedby"
 | 
			
		||||
	type="application/rdf+xml"
 | 
			
		||||
	href="https://social.example.com/username/foaf"/>
 | 
			
		||||
 | 
			
		||||
  <Link rel="http://salmon-protocol.org/ns/salmon-replies"
 | 
			
		||||
	href="https://social.example.com/main/salmon/user/1"/>
 | 
			
		||||
 | 
			
		||||
  <Link rel="http://salmon-protocol.org/ns/salmon-mention"
 | 
			
		||||
	href="https://social.example.com/main/salmon/user/1"/>
 | 
			
		||||
 | 
			
		||||
  <Link rel="http://ostatus.org/schema/1.0/subscribe"
 | 
			
		||||
	template="https://social.example.com/main/ostatussub?profile={uri}"/>
 | 
			
		||||
</XRD>
 | 
			
		||||
@@ -1,43 +0,0 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * GNU social
 | 
			
		||||
 * Copyright (C) 2010, Free Software Foundation, 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/>.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// basename should make sure we can't escape this directory
 | 
			
		||||
$u = basename($_GET['resource']);
 | 
			
		||||
 | 
			
		||||
if (!strpos($u, '@')) {
 | 
			
		||||
    throw new Exception('Bad resource');
 | 
			
		||||
    exit(1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
if (mb_strpos($u, 'acct:')===0) {
 | 
			
		||||
    $u = substr($u, 5);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Just to be a little bit safer, you know, with all the unicode stuff going on
 | 
			
		||||
$u = filter_var($u, FILTER_SANITIZE_EMAIL);
 | 
			
		||||
 | 
			
		||||
$f = $u . ".xml";
 | 
			
		||||
 | 
			
		||||
if (file_exists($f)) {
 | 
			
		||||
  header('Content-Disposition: attachment; filename="'.urlencode($f).'"');
 | 
			
		||||
  header('Content-type: application/xrd+xml');
 | 
			
		||||
  echo file_get_contents($f);
 | 
			
		||||
}
 | 
			
		||||
@@ -1,100 +0,0 @@
 | 
			
		||||
Upgrading
 | 
			
		||||
=========
 | 
			
		||||
 | 
			
		||||
GNU social 1.1.x to GNU social 1.2.x
 | 
			
		||||
------------------------------------
 | 
			
		||||
 | 
			
		||||
If you are tracking the GNU social git repository, we currently recommend
 | 
			
		||||
using the "master" branch (or nightly if you want to use latest features)
 | 
			
		||||
and follow this procedure: 
 | 
			
		||||
 | 
			
		||||
0. Backup your data. The StatusNet upgrade discussions below have some
 | 
			
		||||
    guidelines to back up the database and files (mysqldump and rsync).
 | 
			
		||||
 | 
			
		||||
    MAKE SURE YOU ARE THE SAME USER THAT RUNS THE PHP FILES WHILE PERFORMING
 | 
			
		||||
    THE COMMANDS BELOW (I usually prepend the commands with 'sudo -u social')
 | 
			
		||||
 | 
			
		||||
1. Stop your queue daemons (you can run this command even if you do not
 | 
			
		||||
    use the queue daemons):
 | 
			
		||||
    $ bash scripts/stopdaemons.sh
 | 
			
		||||
 | 
			
		||||
2. Run the command to fetch the latest sourcecode:
 | 
			
		||||
    $ git pull
 | 
			
		||||
    
 | 
			
		||||
    If you are not using git we recommend following the instructions below
 | 
			
		||||
    for upgrading "StatusNet 1.1.x to GNU social 1.2.x" as they are similar.
 | 
			
		||||
 | 
			
		||||
3. Run the upgrade script:
 | 
			
		||||
    $ php scripts/upgrade.php
 | 
			
		||||
 | 
			
		||||
   The upgrade script will likely take a long time because it will
 | 
			
		||||
    upgrade the tables to another character encoding and make other
 | 
			
		||||
    automated upgrades. Make sure it ends without errors. If you get
 | 
			
		||||
    errors, create a new task on https://git.gnu.io/gnu/gnu-social/issues
 | 
			
		||||
 | 
			
		||||
4. Start your queue daemons again (you can run this command even if you
 | 
			
		||||
    do not use the queue daemons):
 | 
			
		||||
    $ bash scripts/startdaemons.sh
 | 
			
		||||
 | 
			
		||||
5. Report any issues at https://git.gnu.io/gnu/gnu-social/issues
 | 
			
		||||
 | 
			
		||||
If you are using ssh keys to log in to your server, you can make this
 | 
			
		||||
procedure pretty painless (assuming you have automated backups already).
 | 
			
		||||
Make sure you "cd" into the correct directory (in this case "htdocs")
 | 
			
		||||
and use the correct login@hostname combo:
 | 
			
		||||
    $ ssh social@domain.example 'cd htdocs
 | 
			
		||||
            && bash scripts/stopdaemons.sh
 | 
			
		||||
            && git pull
 | 
			
		||||
            && time php scripts/upgrade.php
 | 
			
		||||
            && bash scripts/startdaemons.sh'
 | 
			
		||||
 | 
			
		||||
StatusNet 1.1.x to GNU social 1.2.x
 | 
			
		||||
-----------------------------------
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
1.2.x. Beware there may be changes in minimum required version of PHP
 | 
			
		||||
and the modules required, so review the INSTALL file (php5-intl is a
 | 
			
		||||
newly added dependency for example).
 | 
			
		||||
 | 
			
		||||
* Before you begin: Make backups. Always make backups. Of your entire 
 | 
			
		||||
directory structure and the database too. All tables. All data. Alles.
 | 
			
		||||
 | 
			
		||||
0. Make a backup of everything. To backup the database, you can use a
 | 
			
		||||
variant of this command (you will be prompted for the database password):
 | 
			
		||||
    $ mysqldump -u dbuser -p dbname > social-backup.sql
 | 
			
		||||
 | 
			
		||||
1. Stop your queue daemons 'bash scripts/stopdaemons.sh' should do it.
 | 
			
		||||
    Not everyone runs queue daemons, but the above command won't hurt.
 | 
			
		||||
 | 
			
		||||
2. Unpack your GNU social code to a fresh directory. You can do this
 | 
			
		||||
    by cloning our git repository:
 | 
			
		||||
    $ git clone https://git.gnu.io/gnu/gnu-social.git gnusocial
 | 
			
		||||
 | 
			
		||||
3. Synchronize your local files to the GNU social directory. These 
 | 
			
		||||
    will be the local files such as avatars, config and files:
 | 
			
		||||
 | 
			
		||||
        avatar/*
 | 
			
		||||
        file/*
 | 
			
		||||
        local/*
 | 
			
		||||
        .htaccess
 | 
			
		||||
        config.php
 | 
			
		||||
 | 
			
		||||
    This command will point you in the right direction on how to do it:
 | 
			
		||||
    $ rsync -avP statusnet/{.htaccess,avatar,file,local,config.php} gnusocial/
 | 
			
		||||
 | 
			
		||||
4. Replace your old StatusNet directory with the new GNU social
 | 
			
		||||
    directory in your webserver root.
 | 
			
		||||
 | 
			
		||||
5. Run the upgrade script: 'php scripts/upgrade.php'
 | 
			
		||||
   The upgrade script will likely take a long time because it will
 | 
			
		||||
    upgrade the tables to another character encoding and make other
 | 
			
		||||
    automated upgrades. Make sure it ends without errors. If you get
 | 
			
		||||
    errors, create a new task on https://git.gnu.io/gnu/gnu-social/issues
 | 
			
		||||
 | 
			
		||||
6. Start your queue daemons: 'bash scripts/startdaemons.sh'
 | 
			
		||||
 | 
			
		||||
7. Report any issues at https://git.gnu.io/gnu/gnu-social/issues
 | 
			
		||||
@@ -1,55 +0,0 @@
 | 
			
		||||
### GNU social "fancy URL" setup
 | 
			
		||||
#
 | 
			
		||||
#   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 '/'.
 | 
			
		||||
#
 | 
			
		||||
#   If it doesn't work, double-check that AllowOverride for the GNU Social
 | 
			
		||||
#       directory is 'All' in your Apache configuration file. This can be
 | 
			
		||||
#       * /etc/apache2/apache2.conf (generic)
 | 
			
		||||
#       * /etc/apache2/sites-available/default(on Debian and Ubuntu)
 | 
			
		||||
#       * ...many other variations depending on distribution...
 | 
			
		||||
#
 | 
			
		||||
#   See the Apache documentation for .htaccess files for more details:
 | 
			
		||||
#       https://httpd.apache.org/docs/2.4/howto/htaccess.html
 | 
			
		||||
#
 | 
			
		||||
#   Also, check that mod_rewrite is installed and enabled:
 | 
			
		||||
#       https://httpd.apache.org/docs/2.4/mod/mod_rewrite.html
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
<IfModule mod_rewrite.c>
 | 
			
		||||
  RewriteEngine On
 | 
			
		||||
 | 
			
		||||
  # NOTE: change this to your actual GNU social base URL path,
 | 
			
		||||
  # minus the domain part:
 | 
			
		||||
  #
 | 
			
		||||
  #   https://social.example.com/        => /
 | 
			
		||||
  #   https://example.com/social/ => /social/
 | 
			
		||||
  #
 | 
			
		||||
  RewriteBase /
 | 
			
		||||
  #RewriteBase /mublog/
 | 
			
		||||
 | 
			
		||||
  ## Uncomment these if having trouble with API authentication
 | 
			
		||||
  ## when PHP is running in CGI or FastCGI mode.
 | 
			
		||||
  #
 | 
			
		||||
  #RewriteCond %{HTTP:Authorization} ^(.*)
 | 
			
		||||
  #RewriteRule ^(.*) - [E=HTTP_AUTHORIZATION:%1]
 | 
			
		||||
 | 
			
		||||
  RewriteCond %{REQUEST_FILENAME} !-f
 | 
			
		||||
  RewriteCond %{REQUEST_FILENAME} !-d
 | 
			
		||||
  RewriteRule (.*) index.php?p=$1 [L,QSA]
 | 
			
		||||
 | 
			
		||||
  ## You can also use PATHINFO by using this RewriteRule instead:
 | 
			
		||||
  # RewriteRule (.*) index.php/$1 [L,QSA]
 | 
			
		||||
</IfModule>
 | 
			
		||||
 | 
			
		||||
<FilesMatch "\.(ini)">
 | 
			
		||||
    <IfVersion < 2.3>
 | 
			
		||||
        Order allow,deny
 | 
			
		||||
        Deny from all
 | 
			
		||||
    </IfVersion>
 | 
			
		||||
    <IfVersion >= 2.3>
 | 
			
		||||
        Require all denied
 | 
			
		||||
    </IfVersion>
 | 
			
		||||
</FilesMatch>
 | 
			
		||||
@@ -1,28 +0,0 @@
 | 
			
		||||
# This is completely optional, but if you're running a site with
 | 
			
		||||
# ssl="always" configured, then you might as well redirect any of
 | 
			
		||||
# your stray HTTP visitors to HTTPS.
 | 
			
		||||
#
 | 
			
		||||
#$HTTP["scheme"] == "http" {
 | 
			
		||||
#  $HTTP["host"] =~ "^(social\.example\.com)$" {
 | 
			
		||||
#    url.redirect = ( "^\/?(.*)" => "https://%1/$1" )
 | 
			
		||||
#    server.name                 = "%1"
 | 
			
		||||
#  }
 | 
			
		||||
#}
 | 
			
		||||
 | 
			
		||||
# If you're using vhosts, you should have per-vhost server.document-root
 | 
			
		||||
#   settings too! Read how in the respective alternative vhost modules.
 | 
			
		||||
#$HTTP["host"] =~ "^social\.example\.com$" {
 | 
			
		||||
 | 
			
		||||
#    NOTE: configure fastcgi/cgi/fpm here if you're using per-user cgi/fpm
 | 
			
		||||
#    fastcgi.server += ( ".php" =>
 | 
			
		||||
#      ( "localhost" => (
 | 
			
		||||
#        "host" => "127.0.0.1",
 | 
			
		||||
#        "port" => "9000"
 | 
			
		||||
#      ))
 | 
			
		||||
#    )
 | 
			
		||||
 | 
			
		||||
    dir-listing.activate = "disable"
 | 
			
		||||
 | 
			
		||||
# Make sure "mod_rewrite" is enabled in server.modules
 | 
			
		||||
    url.rewrite-if-not-file = ( "^/(.*)$" => "/index.php/$1" )
 | 
			
		||||
#}
 | 
			
		||||
@@ -1,89 +0,0 @@
 | 
			
		||||
server {
 | 
			
		||||
    listen [::]:80;
 | 
			
		||||
    listen 80;
 | 
			
		||||
 | 
			
		||||
# FIXME: Change domain name here (and also make sure you do the same in the next 'server' section)
 | 
			
		||||
    server_name social.example.org;
 | 
			
		||||
 | 
			
		||||
# redirect all traffic to HTTPS
 | 
			
		||||
    rewrite ^ https://$host$request_uri? permanent;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
server {
 | 
			
		||||
# HTTPS is mandatory on GNU social unless you are using Tor network. Seriously.
 | 
			
		||||
# Set it up with a cert (any cert) before you run the install.
 | 
			
		||||
    listen [::]:443 ssl http2;
 | 
			
		||||
    listen 443 ssl http2;
 | 
			
		||||
 | 
			
		||||
# Root
 | 
			
		||||
# FIXME: Change the path below to where you installed GNU social
 | 
			
		||||
    root /path/to/gnusocial/root;
 | 
			
		||||
 | 
			
		||||
# Server name
 | 
			
		||||
# FIXME: Change "social.example.org" to your site's domain name
 | 
			
		||||
    server_name social.example.org;
 | 
			
		||||
 | 
			
		||||
# SSL
 | 
			
		||||
# FIXME: Change the paths to setup your SSL key/cert. See https://cipherli.st/ for more information
 | 
			
		||||
    ssl_certificate       ssl/certs/social.example.org.crt;
 | 
			
		||||
    ssl_certificate_key   ssl/private/social.example.org.key;
 | 
			
		||||
 | 
			
		||||
# Index
 | 
			
		||||
    index index.php;
 | 
			
		||||
 | 
			
		||||
# PHP
 | 
			
		||||
    location ~ ^/(index|install)\.php$ {
 | 
			
		||||
    #location ^~ /index.php {
 | 
			
		||||
        include fastcgi_params;
 | 
			
		||||
        include snippets/fastcgi-php.conf;
 | 
			
		||||
 | 
			
		||||
        fastcgi_pass unix:/run/php/php-fpm.sock;
 | 
			
		||||
        fastcgi_param SCRIPT_FILENAME $request_filename;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
# Don't allow any PHP file other than index.php to be executed
 | 
			
		||||
# This will ensure that nor config.php nor plugin files with eventual hardcoded security information are downloadable
 | 
			
		||||
# And this is better than allowing php files to be executed in case of forgotten `if (!defined('GNUSOCIAL')) { exit(1); }`
 | 
			
		||||
    location ~ \.php$ {
 | 
			
		||||
        deny all;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
# Location
 | 
			
		||||
    location / {
 | 
			
		||||
        try_files $uri $uri/ @index_handler;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
# Fancy URLs
 | 
			
		||||
    error_page 404 @index_handler;
 | 
			
		||||
    location @index_handler {
 | 
			
		||||
        rewrite ^(.*)$ /index.php?p=$1 last;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
# Restrict access that is unnecessary anyway
 | 
			
		||||
    location ~ /\.(ht|git) {
 | 
			
		||||
        deny all;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Hardening (optional)
 | 
			
		||||
#
 | 
			
		||||
#    add_header Strict-Transport-Security "max-age=15768000; preload;";
 | 
			
		||||
#    add_header X-Content-Type-Options nosniff;
 | 
			
		||||
#    add_header Referrer-Policy strict-origin-when-cross-origin;
 | 
			
		||||
#    add_header Content-Security-Policy "default-src 'self' 'unsafe-inline'; frame-ancestors 'self'; form-action 'self'; style-src 'self' 'unsafe-inline'; img-src * blob: data:;";
 | 
			
		||||
#    add_header X-Permitted-Cross-Domain-Policies none;
 | 
			
		||||
#    add_header X-Robots-Tag all; # Not really hardening, just here for strictness purposes
 | 
			
		||||
#
 | 
			
		||||
#    client_max_body_size 15M;
 | 
			
		||||
#    client_body_buffer_size 128k;
 | 
			
		||||
#    gzip_vary on;
 | 
			
		||||
#
 | 
			
		||||
#    location ~* \.(?:css|js|woff|svg|gif|png|webp|ttf|ico|jpe?g)$ {
 | 
			
		||||
#        gzip on;
 | 
			
		||||
#        gzip_comp_level 4;
 | 
			
		||||
#        add_header Cache-Control "public";
 | 
			
		||||
#        expires 30d;
 | 
			
		||||
#        access_log off;
 | 
			
		||||
#        log_not_found off;
 | 
			
		||||
#    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										466
									
								
								INSTALL.md
									
									
									
									
									
								
							
							
						
						
									
										466
									
								
								INSTALL.md
									
									
									
									
									
								
							@@ -1,463 +1,5 @@
 | 
			
		||||
TABLE OF CONTENTS
 | 
			
		||||
=================
 | 
			
		||||
* Prerequisites
 | 
			
		||||
    - PHP modules
 | 
			
		||||
    - Better performance
 | 
			
		||||
* Installation
 | 
			
		||||
    - Getting it up and running
 | 
			
		||||
    - Fancy URLs
 | 
			
		||||
    - Themes
 | 
			
		||||
    - Private
 | 
			
		||||
* Extra features
 | 
			
		||||
    - Sphinx
 | 
			
		||||
    - SMS
 | 
			
		||||
    - Translation
 | 
			
		||||
    - Queues and daemons
 | 
			
		||||
* After installation
 | 
			
		||||
    - Backups
 | 
			
		||||
    - Upgrading
 | 
			
		||||
* Additional configuration
 | 
			
		||||
GNU social
 | 
			
		||||
=====
 | 
			
		||||
 | 
			
		||||
Prerequisites
 | 
			
		||||
=============
 | 
			
		||||
 | 
			
		||||
PHP modules
 | 
			
		||||
-----------
 | 
			
		||||
 | 
			
		||||
The following software packages are *required* for this software to
 | 
			
		||||
run correctly.
 | 
			
		||||
 | 
			
		||||
- PHP 7+        PHP7.x is also supported.
 | 
			
		||||
- MariaDB 5+    MariaDB 10.x is also supported.
 | 
			
		||||
- 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)
 | 
			
		||||
- php-curl      Fetching files by HTTP.
 | 
			
		||||
- php-exif      Exchangeable image information.
 | 
			
		||||
- php-gd        Image manipulation (scaling).
 | 
			
		||||
- php-intl      Internationalization support (transliteration et al).
 | 
			
		||||
- php-json      For WebFinger lookups and more.
 | 
			
		||||
- php-mbstring  String manipulation
 | 
			
		||||
- php-mysql     The native driver for MariaDB connections.
 | 
			
		||||
- php-gmp       For Salmon signatures (part of OStatus)
 | 
			
		||||
- php-bcmath    Arbitrary Precision Mathematics
 | 
			
		||||
- php-opcache   Improved PHP performance by precompilation
 | 
			
		||||
- php-readline  For interactive scripts
 | 
			
		||||
- php-xml       XML parser
 | 
			
		||||
- php-ds        Faster data structures
 | 
			
		||||
 | 
			
		||||
NOTE: Some distros require manual enabling in the relevant php.ini for some modules.
 | 
			
		||||
 | 
			
		||||
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.
 | 
			
		||||
- php-ds        For faster data structures; will be emulated if not present.
 | 
			
		||||
 | 
			
		||||
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 where it is documented 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, please note
 | 
			
		||||
   however that 'a+w' will give _all_ users write access and securing the
 | 
			
		||||
   webserver is not within the scope of this document.
 | 
			
		||||
 | 
			
		||||
       chmod a+w /var/www/gnusocial/
 | 
			
		||||
 | 
			
		||||
   On some systems, this will work as a more secure alternative:
 | 
			
		||||
 | 
			
		||||
       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. Create a database to hold your site data. Something like this
 | 
			
		||||
   should work (you will be prompted for your database password):
 | 
			
		||||
 | 
			
		||||
       mysqladmin -u "root" -p create social
 | 
			
		||||
 | 
			
		||||
   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.)
 | 
			
		||||
 | 
			
		||||
5. 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 social.*
 | 
			
		||||
       TO 'social'@'localhost'
 | 
			
		||||
       IDENTIFIED BY 'agoodpassword';
 | 
			
		||||
 | 
			
		||||
   You should change the user identifier 'social' and 'agoodpassword'
 | 
			
		||||
   to your preferred new database username and password. You may want to
 | 
			
		||||
   test logging in to MariaDB as this new user.
 | 
			
		||||
 | 
			
		||||
6. In a browser, navigate to the GNU Social install script; something like:
 | 
			
		||||
 | 
			
		||||
       https://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.
 | 
			
		||||
 | 
			
		||||
7. 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 either
 | 
			
		||||
of these URLS depending on the webserver's configuration and capabilities:
 | 
			
		||||
 | 
			
		||||
    https://social.example.net/index.php/fred
 | 
			
		||||
    https://social.example.net/index.php?p=fred
 | 
			
		||||
 | 
			
		||||
It's possible to configure the software to use fancy URLs so it looks like
 | 
			
		||||
this instead:
 | 
			
		||||
 | 
			
		||||
    https://social.example.net/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. See the instructions for each respective webserver software:
 | 
			
		||||
    * For Apache, inspect the "htaccess.sample" file and save it as
 | 
			
		||||
        ".htaccess" after making any necessary modifications. Our sample
 | 
			
		||||
        file is well commented.
 | 
			
		||||
    * For lighttpd, inspect the lighttpd.conf.example file and apply the
 | 
			
		||||
        appropriate changes in your virtualhost configuration for lighttpd.
 | 
			
		||||
    * For nginx, inspect the nginx.conf.sample file and apply the appropriate
 | 
			
		||||
        changes.
 | 
			
		||||
    * For other webservers, we gladly accept contributions of
 | 
			
		||||
        server configuration examples.
 | 
			
		||||
 | 
			
		||||
2. Assuming your webserver is properly configured and have its settings
 | 
			
		||||
    applied (remember to reload/restart it), you can add this to your
 | 
			
		||||
    GNU social's config.php file:
 | 
			
		||||
       $config['site']['fancy'] = true;
 | 
			
		||||
 | 
			
		||||
You should now be able to navigate to a "fancy" URL on your server,
 | 
			
		||||
like:
 | 
			
		||||
 | 
			
		||||
    https://social.example.net/main/register
 | 
			
		||||
 | 
			
		||||
Themes
 | 
			
		||||
------
 | 
			
		||||
 | 
			
		||||
As of right now, your ability change the theme is limited to CSS
 | 
			
		||||
stylesheets and some image files; you can't change the HTML output,
 | 
			
		||||
like adding or removing menu items, without the help of a plugin.
 | 
			
		||||
 | 
			
		||||
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.
 | 
			
		||||
 | 
			
		||||
Private
 | 
			
		||||
-------
 | 
			
		||||
 | 
			
		||||
A GNU social node can be configured as "private", which means it will not
 | 
			
		||||
federate with other nodes in the network. It is not a recommended method
 | 
			
		||||
of using GNU social and we cannot at the current state of development
 | 
			
		||||
guarantee that there are no leaks (what a public network sees as features,
 | 
			
		||||
private sites will likely see as bugs).
 | 
			
		||||
 | 
			
		||||
Private nodes are however an easy way to easily setup collaboration and
 | 
			
		||||
image sharing within a workgroup or a smaller community where federation
 | 
			
		||||
is not a desired feature. Also, it is possible to change this setting and
 | 
			
		||||
instantly gain full federation features.
 | 
			
		||||
 | 
			
		||||
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. Use this command as an initial guideline to create it:
 | 
			
		||||
 | 
			
		||||
       mkdir /var/www/gnusocial-files
 | 
			
		||||
 | 
			
		||||
2. Make the file uploads directory writeable by the web server. An
 | 
			
		||||
   insecure way to do this is (to do it properly, read up on UNIX file
 | 
			
		||||
   permissions and configure your webserver accordingly):
 | 
			
		||||
 | 
			
		||||
       chmod a+x /var/www/gnusocial-files
 | 
			
		||||
 | 
			
		||||
3. Tell GNU social to use this directory for file uploads. Add a line
 | 
			
		||||
   like this to your config.php:
 | 
			
		||||
 | 
			
		||||
       $config['attachments']['dir'] = '/var/www/gnusocial-files';
 | 
			
		||||
 | 
			
		||||
Extra features
 | 
			
		||||
==============
 | 
			
		||||
 | 
			
		||||
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';
 | 
			
		||||
 | 
			
		||||
Translations
 | 
			
		||||
------------
 | 
			
		||||
 | 
			
		||||
For info on helping with translations, see the platform currently in use
 | 
			
		||||
for translations: https://www.transifex.com/projects/p/gnu-social/
 | 
			
		||||
 | 
			
		||||
Translations use the gettext system <http://www.gnu.org/software/gettext/>.
 | 
			
		||||
If you for some reason do not wish to sign up to the Transifex service,
 | 
			
		||||
you can review the files in the "locale/" sub-directory of GNU social.
 | 
			
		||||
Each plugin also has its own translation files.
 | 
			
		||||
 | 
			
		||||
To get your own site to use all the translated languages, and you are
 | 
			
		||||
tracking the git repo, you will need to install at least 'gettext' on
 | 
			
		||||
your system and then run:
 | 
			
		||||
    $ make translations
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
jobs 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).
 | 
			
		||||
 | 
			
		||||
Whenever it has time, 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 (on the server where you run the queue
 | 
			
		||||
    daemon), set the following variable:
 | 
			
		||||
 | 
			
		||||
       $config['queue']['daemon'] = true;
 | 
			
		||||
 | 
			
		||||
   You may also want to look at the 'Queues and Daemons' section in
 | 
			
		||||
   this file for more background processing options.
 | 
			
		||||
 | 
			
		||||
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.
 | 
			
		||||
 | 
			
		||||
After installation
 | 
			
		||||
==================
 | 
			
		||||
 | 
			
		||||
Backups
 | 
			
		||||
-------
 | 
			
		||||
 | 
			
		||||
There is no built-in system for doing backups in GNU social. You can make
 | 
			
		||||
backups of a working StatusNet system by backing up the database and
 | 
			
		||||
the Web directory. To backup the database use mysqldump <https://mariadb.com/kb/en/mariadb/mysqldump/>
 | 
			
		||||
and to backup the Web directory, try tar.
 | 
			
		||||
 | 
			
		||||
Upgrading
 | 
			
		||||
---------
 | 
			
		||||
 | 
			
		||||
Upgrading is strongly recommended to stay up to date with security fixes
 | 
			
		||||
and new features. For instructions on how to upgrade GNU social code,
 | 
			
		||||
please see the UPGRADE file.
 | 
			
		||||
 | 
			
		||||
Additional configuration
 | 
			
		||||
------------------------
 | 
			
		||||
 | 
			
		||||
Please refer to DOCUMENTATION/SYSTEM_ADMINISTRATORS/CONFIGURE for information.
 | 
			
		||||
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))
 | 
			
		||||
plugin_mo = $(patsubst %.po,%.mo,$(wildcard plugins/*/locale/*/LC_MESSAGES/*.po))
 | 
			
		||||
up: .PHONY
 | 
			
		||||
	docker-compose up -d
 | 
			
		||||
 | 
			
		||||
translations : $(core_mo) $(plugin_mo)
 | 
			
		||||
down: .PHONY
 | 
			
		||||
	docker-compose down
 | 
			
		||||
 | 
			
		||||
clean :
 | 
			
		||||
	rm -f $(core_mo) $(plugin_mo)
 | 
			
		||||
redis-shell:
 | 
			
		||||
	docker exec -it $(strip $(DIR))_redis_1 sh -c 'redis-cli'
 | 
			
		||||
 | 
			
		||||
updatepo :
 | 
			
		||||
	php scripts/update_po_templates.php --all
 | 
			
		||||
php-repl: .PHONY
 | 
			
		||||
	docker exec -it $(strip $(DIR))_php_1 sh -c '/var/www/social/bin/console psysh'
 | 
			
		||||
 | 
			
		||||
%.mo : %.po
 | 
			
		||||
	msgfmt -o $@ $<
 | 
			
		||||
php-shell: .PHONY
 | 
			
		||||
	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
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										157
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										157
									
								
								README.md
									
									
									
									
									
								
							@@ -1,157 +0,0 @@
 | 
			
		||||
# GNU social 1.20.x
 | 
			
		||||
(c) 2010-2019 Free Software Foundation, 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.
 | 
			
		||||
 | 
			
		||||
The file INSTALL.md has useful instructions on how to
 | 
			
		||||
install this software.
 | 
			
		||||
 | 
			
		||||
System administrators may find the `DOCUMENTATION/SYSTEM_ADMINISTRATORS`
 | 
			
		||||
directory useful, namely:
 | 
			
		||||
 | 
			
		||||
- upgrade_from: upgrading from different software
 | 
			
		||||
- CONFIGURE.md: configuration options in gruesome detail.
 | 
			
		||||
- PLUGINS.md: how to install and configure plugins.
 | 
			
		||||
 | 
			
		||||
Developers may find the `DOCUMENTATION/DEVELOPERS` directory useful.
 | 
			
		||||
 | 
			
		||||
## 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 proprietary social network sites,
 | 
			
		||||
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 open standards (such as 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.
 | 
			
		||||
 | 
			
		||||
Refer to COPYING.md for full text of the software license..
 | 
			
		||||
 | 
			
		||||
### 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@notabug.org:diogo/gnu-social.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.20.x    "oldstable", few updates, well tested coded
 | 
			
		||||
* master    "stable", usually working well
 | 
			
		||||
* nightly   "testing", most updates, not always working as expected
 | 
			
		||||
 | 
			
		||||
To keep it up-to-date, use `git pull`. Watch for conflicts!
 | 
			
		||||
 | 
			
		||||
As in any upgrade, do __not__ forget to run `/scripts/upgrade.php`.
 | 
			
		||||
 | 
			
		||||
## 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/>
 | 
			
		||||
 | 
			
		||||
* GNU social has a bug tracker for any defects you may find, or ideas for
 | 
			
		||||
  making things better. <https://notabug.org/diogo/gnu-social/issues>
 | 
			
		||||
* Patches are welcome, preferrably to our repository on notabug.org. <https://notabug.org/diogo/gnu-social>
 | 
			
		||||
 | 
			
		||||
## Credits
 | 
			
		||||
 | 
			
		||||
An incomplete list of developers who've worked on GNU social,
 | 
			
		||||
or its predecessors StatusNet and Free Social has been made available
 | 
			
		||||
in `CREDITS.md`.
 | 
			
		||||
 | 
			
		||||
### Current team
 | 
			
		||||
 | 
			
		||||
* Matt Lee
 | 
			
		||||
* Mikael Nordfeldth
 | 
			
		||||
* Diogo Cordeiro
 | 
			
		||||
* Bruno Casteleiro
 | 
			
		||||
* Miguel Dantas
 | 
			
		||||
* Alexei Sorokin
 | 
			
		||||
@@ -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(array $args = array())
 | 
			
		||||
    {
 | 
			
		||||
        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()
 | 
			
		||||
    {
 | 
			
		||||
        // 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);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										182
									
								
								actions/all.php
									
									
									
									
									
								
							
							
						
						
									
										182
									
								
								actions/all.php
									
									
									
									
									
								
							@@ -1,182 +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')) { exit(1); }
 | 
			
		||||
 | 
			
		||||
class AllAction extends ShowstreamAction
 | 
			
		||||
{
 | 
			
		||||
    public function getStream()
 | 
			
		||||
    {
 | 
			
		||||
        if ($this->scoped instanceof Profile && $this->scoped->isLocal() && $this->scoped->getUser()->streamModeOnly()) {
 | 
			
		||||
            $stream = new InboxNoticeStream($this->target, $this->scoped);
 | 
			
		||||
        } else {
 | 
			
		||||
            $stream = new ThreadingInboxNoticeStream($this->target, $this->scoped);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $stream;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function title()
 | 
			
		||||
    {
 | 
			
		||||
        if (!empty($this->scoped) && $this->scoped->sameAs($this->target)) {
 | 
			
		||||
            // 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->getNickname()
 | 
			
		||||
                    )
 | 
			
		||||
                ),
 | 
			
		||||
                // TRANS: %s is user nickname.
 | 
			
		||||
                sprintf(_('Feed for friends of %s (Activity Streams JSON)'), $this->target->getNickname())),
 | 
			
		||||
            new Feed(Feed::RSS1,
 | 
			
		||||
                common_local_url(
 | 
			
		||||
                    'allrss', array(
 | 
			
		||||
                        'nickname' =>
 | 
			
		||||
                        $this->target->getNickname())
 | 
			
		||||
                ),
 | 
			
		||||
                // TRANS: %s is user nickname.
 | 
			
		||||
                sprintf(_('Feed for friends of %s (RSS 1.0)'), $this->target->getNickname())),
 | 
			
		||||
            new Feed(Feed::RSS2,
 | 
			
		||||
                common_local_url(
 | 
			
		||||
                    'ApiTimelineFriends', array(
 | 
			
		||||
                        'format' => 'rss',
 | 
			
		||||
                        'id' => $this->target->getNickname()
 | 
			
		||||
                    )
 | 
			
		||||
                ),
 | 
			
		||||
                // TRANS: %s is user nickname.
 | 
			
		||||
                sprintf(_('Feed for friends of %s (RSS 2.0)'), $this->target->getNickname())),
 | 
			
		||||
            new Feed(Feed::ATOM,
 | 
			
		||||
                common_local_url(
 | 
			
		||||
                    'ApiTimelineFriends', array(
 | 
			
		||||
                        'format' => 'atom',
 | 
			
		||||
                        'id' => $this->target->getNickname()
 | 
			
		||||
                    )
 | 
			
		||||
                ),
 | 
			
		||||
                // TRANS: %s is user nickname.
 | 
			
		||||
                sprintf(_('Feed for friends of %s (Atom)'), $this->target->getNickname()))
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    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->getNickname()) . ' ';
 | 
			
		||||
 | 
			
		||||
        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->getNickname(), $this->target->getNickname(), '@' . $this->target->getNickname());
 | 
			
		||||
            }
 | 
			
		||||
        } 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->getNickname());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $this->elementStart('div', 'guide');
 | 
			
		||||
        $this->raw(common_markup_to_html($message));
 | 
			
		||||
        $this->elementEnd('div');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function showContent()
 | 
			
		||||
    {
 | 
			
		||||
        if (Event::handle('StartShowAllContent', array($this))) {
 | 
			
		||||
            if ($this->scoped instanceof Profile && $this->scoped->isLocal() && $this->scoped->getUser()->streamModeOnly()) {
 | 
			
		||||
                $nl = new PrimaryNoticeList($this->notice, $this, array('show_n'=>NOTICES_PER_PAGE));
 | 
			
		||||
            } else {
 | 
			
		||||
                $nl = new ThreadedNoticeList($this->notice, $this, $this->scoped);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            $cnt = $nl->show();
 | 
			
		||||
 | 
			
		||||
            if (0 == $cnt) {
 | 
			
		||||
                $this->showEmptyListMessage();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            $this->pagination(
 | 
			
		||||
                $this->page > 1, $cnt > NOTICES_PER_PAGE,
 | 
			
		||||
                $this->page, 'all', array('nickname' => $this->target->getNickname())
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            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();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class ThreadingInboxNoticeStream extends ThreadingNoticeStream
 | 
			
		||||
{
 | 
			
		||||
    function __construct(Profile $target, Profile $scoped=null)
 | 
			
		||||
    {
 | 
			
		||||
        parent::__construct(new InboxNoticeStream($target, $scoped));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,73 +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('GNUSOCIAL')) { exit(1); }
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 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 TargetedRss10Action
 | 
			
		||||
{
 | 
			
		||||
    protected function getNotices()
 | 
			
		||||
    {
 | 
			
		||||
        $stream = new InboxNoticeStream($this->target, $this->scoped);
 | 
			
		||||
        return $stream->getNotices(0, $this->limit)->fetchAll();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
     /**
 | 
			
		||||
     * Get channel.
 | 
			
		||||
     *
 | 
			
		||||
     * @return array associative array on channel information
 | 
			
		||||
     */
 | 
			
		||||
    function getChannel()
 | 
			
		||||
    {
 | 
			
		||||
        $c    = array('url' => common_local_url('allrss',
 | 
			
		||||
                                             array('nickname' =>
 | 
			
		||||
                                                   $this->target->getNickname())),
 | 
			
		||||
                   // TRANS: Message is used as link title. %s is a user nickname.
 | 
			
		||||
                   'title' => sprintf(_('%s and friends'), $this->target->getNickname()),
 | 
			
		||||
                   'link' => common_local_url('all',
 | 
			
		||||
                                             array('nickname' =>
 | 
			
		||||
                                                   $this->target->getNickname())),
 | 
			
		||||
                   // 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!'),
 | 
			
		||||
                                            $this->target->getNickname(), common_config('site', 'name')));
 | 
			
		||||
        return $c;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,121 +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('GNUSOCIAL')) {
 | 
			
		||||
    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
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * Return true if read only.
 | 
			
		||||
     *
 | 
			
		||||
     * MAY override
 | 
			
		||||
     *
 | 
			
		||||
     * @param array $args other arguments
 | 
			
		||||
     *
 | 
			
		||||
     * @return boolean is read only action?
 | 
			
		||||
     */
 | 
			
		||||
    public function isReadOnly($args)
 | 
			
		||||
    {
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Handle the request
 | 
			
		||||
     *
 | 
			
		||||
     * Return some Twitter-ish data about API limits
 | 
			
		||||
     *
 | 
			
		||||
     * @return void
 | 
			
		||||
     * @throws ClientException
 | 
			
		||||
     */
 | 
			
		||||
    protected function handle()
 | 
			
		||||
    {
 | 
			
		||||
        parent::handle();
 | 
			
		||||
 | 
			
		||||
        if (!in_array($this->format, ['xml', 'json'])) {
 | 
			
		||||
            $this->clientError(
 | 
			
		||||
            // TRANS: Client error displayed when coming across a non-supported API method.
 | 
			
		||||
                _('API method not found.'),
 | 
			
		||||
                404,
 | 
			
		||||
                $this->format
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $reset = new DateTime();
 | 
			
		||||
        $reset->modify('+1 hour');
 | 
			
		||||
 | 
			
		||||
        $this->initDocument($this->format);
 | 
			
		||||
 | 
			
		||||
        if ($this->format == 'xml') {
 | 
			
		||||
            $this->elementStart('hash');
 | 
			
		||||
            $this->element('remaining-hits', ['type' => 'integer'], "150");
 | 
			
		||||
            $this->element('hourly-limit', ['type' => 'integer'], "150");
 | 
			
		||||
            $this->element(
 | 
			
		||||
                'reset-time',
 | 
			
		||||
                ['type' => 'datetime'],
 | 
			
		||||
                common_date_iso8601($reset->format('r'))
 | 
			
		||||
            );
 | 
			
		||||
            $this->element(
 | 
			
		||||
                'reset_time_in_seconds',
 | 
			
		||||
                ['type' => 'integer'],
 | 
			
		||||
                strtotime('+1 hour')
 | 
			
		||||
            );
 | 
			
		||||
            $this->elementEnd('hash');
 | 
			
		||||
        } elseif ($this->format == 'json') {
 | 
			
		||||
            $out = [
 | 
			
		||||
                '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);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,194 +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 (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 (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 (Event::handle('APIStartRegistrationTry', array($this))) { 
 | 
			
		||||
				try {
 | 
			
		||||
					$user = User::register(array('nickname' => $nickname,
 | 
			
		||||
														'password' => $password,
 | 
			
		||||
														'email' => $email,
 | 
			
		||||
														'fullname' => $fullname,
 | 
			
		||||
														'homepage' => $homepage,
 | 
			
		||||
														'bio' => $bio,
 | 
			
		||||
														'location' => $location,
 | 
			
		||||
														'code' => $this->code));
 | 
			
		||||
					Event::handle('EndRegistrationTry', array($this));
 | 
			
		||||
 | 
			
		||||
					$this->initDocument('json');
 | 
			
		||||
					$this->showJsonObjects($this->twitterUserArray($user->getProfile()));
 | 
			
		||||
					$this->endDocument('json');
 | 
			
		||||
 | 
			
		||||
				} catch (Exception $e) {
 | 
			
		||||
					$this->clientError($e->getMessage(), 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(array $args = array())
 | 
			
		||||
    {
 | 
			
		||||
        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()
 | 
			
		||||
    {
 | 
			
		||||
        parent::handle();
 | 
			
		||||
 | 
			
		||||
        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,141 +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);
 | 
			
		||||
 | 
			
		||||
        $profile->fullname = $this->name;
 | 
			
		||||
        $profile->homepage = $this->url;
 | 
			
		||||
        $profile->bio = $this->description;
 | 
			
		||||
        $profile->location = $this->location;
 | 
			
		||||
 | 
			
		||||
        if (!empty($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;
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            // location is empty so reset the extrapolated information too
 | 
			
		||||
            $profile->lat = '';
 | 
			
		||||
            $profile->lon = '';
 | 
			
		||||
            $profile->location_id = '';
 | 
			
		||||
            $profile->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(array $args = array())
 | 
			
		||||
    {
 | 
			
		||||
        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()
 | 
			
		||||
    {
 | 
			
		||||
        parent::handle();
 | 
			
		||||
 | 
			
		||||
        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,227 +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;
 | 
			
		||||
 | 
			
		||||
    protected function prepare(array $args=array())
 | 
			
		||||
    {
 | 
			
		||||
        parent::prepare($args);
 | 
			
		||||
 | 
			
		||||
        $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,111 +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('GNUSOCIAL')) { 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->scoped->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->scoped, $this->other);
 | 
			
		||||
        } catch (AlreadyFulfilledException $e) {
 | 
			
		||||
            $this->clientError($e->getMessage(), 409);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $this->initDocument($this->format);
 | 
			
		||||
        $this->showProfile($this->other, $this->format);
 | 
			
		||||
        $this->endDocument($this->format);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,114 +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('GNUSOCIAL')) { 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
 | 
			
		||||
{
 | 
			
		||||
    protected $needPost = true;
 | 
			
		||||
 | 
			
		||||
    protected $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'))) {
 | 
			
		||||
            $this->clientError(
 | 
			
		||||
                // TRANS: Client error displayed when coming across a non-supported API method.
 | 
			
		||||
                _('API method not found.'),
 | 
			
		||||
                404
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!$this->other instanceof Profile) {
 | 
			
		||||
            $this->clientError(
 | 
			
		||||
                // TRANS: Client error displayed when trying to unfollow a user that cannot be found.
 | 
			
		||||
                _('Could not unfollow user: User not found.'),
 | 
			
		||||
                403
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Don't allow unsubscribing from yourself!
 | 
			
		||||
 | 
			
		||||
        if ($this->scoped->id == $this->other->id) {
 | 
			
		||||
            $this->clientError(
 | 
			
		||||
                // TRANS: Client error displayed when trying to unfollow self.
 | 
			
		||||
                _("You cannot unfollow yourself."),
 | 
			
		||||
                403
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // throws an exception on error
 | 
			
		||||
        Subscription::cancel($this->scoped, $this->other);
 | 
			
		||||
 | 
			
		||||
        $this->initDocument($this->format);
 | 
			
		||||
        $this->showProfile($this->other, $this->format);
 | 
			
		||||
        $this->endDocument($this->format);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,118 +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('GNUSOCIAL')) { 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
 | 
			
		||||
     */
 | 
			
		||||
    protected function prepare(array $args=array())
 | 
			
		||||
    {
 | 
			
		||||
        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
 | 
			
		||||
     *
 | 
			
		||||
     * @return void
 | 
			
		||||
     */
 | 
			
		||||
    protected function handle()
 | 
			
		||||
    {
 | 
			
		||||
        parent::handle();
 | 
			
		||||
 | 
			
		||||
        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
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $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,169 +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('GNUSOCIAL')) { 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
 | 
			
		||||
     */
 | 
			
		||||
    protected function prepare(array $args=array())
 | 
			
		||||
    {
 | 
			
		||||
        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
 | 
			
		||||
     *
 | 
			
		||||
     * @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->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(array $args = array())
 | 
			
		||||
    {
 | 
			
		||||
        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()
 | 
			
		||||
    {
 | 
			
		||||
        parent::handle();
 | 
			
		||||
 | 
			
		||||
        $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,76 +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('GNUSOCIAL')) { 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
 | 
			
		||||
{
 | 
			
		||||
    protected function handle()
 | 
			
		||||
    {
 | 
			
		||||
        parent::handle();
 | 
			
		||||
 | 
			
		||||
        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 {
 | 
			
		||||
            // TRANS: Client error displayed when coming across a non-supported API method.
 | 
			
		||||
            throw new ClientException(_('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,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,124 +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()
 | 
			
		||||
    {
 | 
			
		||||
        $fn = array($this->target, 'getOtherTags');
 | 
			
		||||
 | 
			
		||||
        # 20 lists
 | 
			
		||||
        list($this->lists, $this->next_cursor, $this->prev_cursor) =
 | 
			
		||||
                Profile_list::getAtCursor($fn, array($this->scoped), $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->scoped), $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(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 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()
 | 
			
		||||
    {
 | 
			
		||||
        parent::handle();
 | 
			
		||||
 | 
			
		||||
        $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,195 +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. Apparently modelled after a former Twitpic API.
 | 
			
		||||
 *
 | 
			
		||||
 * @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;
 | 
			
		||||
 | 
			
		||||
    protected function prepare(array $args=array())
 | 
			
		||||
    {
 | 
			
		||||
        parent::prepare($args);
 | 
			
		||||
 | 
			
		||||
        // fallback to xml for older clients etc
 | 
			
		||||
        if (empty($this->format)) {
 | 
			
		||||
            $this->format = 'xml';
 | 
			
		||||
        }
 | 
			
		||||
        if (!in_array($this->format, ['json', 'xml'])) {
 | 
			
		||||
            throw new ClientException('This API call does not support the format '._ve($this->format));
 | 
			
		||||
        }
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    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']));
 | 
			
		||||
            throw new ClientException(sprintf($msg, $_SERVER['CONTENT_LENGTH']));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        try {
 | 
			
		||||
            $upload = MediaFile::fromUpload('media', $this->scoped);
 | 
			
		||||
        } catch (NoUploadedMediaException $e) {
 | 
			
		||||
            common_debug('No media file was uploaded to the _FILES array');
 | 
			
		||||
            $fh = tmpfile();
 | 
			
		||||
            if ($this->arg('media')) {
 | 
			
		||||
                common_debug('Found media parameter which we hope contains a media file!');
 | 
			
		||||
                fwrite($fh, $this->arg('media'));
 | 
			
		||||
            } elseif ($this->arg('media_data')) {
 | 
			
		||||
                common_debug('Found media_data parameter which we hope contains a base64-encoded media file!');
 | 
			
		||||
                fwrite($fh, base64_decode($this->arg('media_data')));
 | 
			
		||||
            } else {
 | 
			
		||||
                common_debug('No media|media_data POST parameter was supplied');
 | 
			
		||||
                fclose($fh);
 | 
			
		||||
                throw $e;
 | 
			
		||||
            }
 | 
			
		||||
            common_debug('MediaFile importing the uploaded file with fromFilehandle');
 | 
			
		||||
            $upload = MediaFile::fromFilehandle($fh, $this->scoped);
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        common_debug('MediaFile completed and saved us fileRecord with id=='._ve($upload->fileRecord->id));
 | 
			
		||||
        // 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
 | 
			
		||||
     */
 | 
			
		||||
    protected function showResponse(MediaFile $upload)
 | 
			
		||||
    {
 | 
			
		||||
        $this->initDocument($this->format);
 | 
			
		||||
        switch ($this->format) {
 | 
			
		||||
        case 'json':
 | 
			
		||||
            return $this->showResponseJson($upload);
 | 
			
		||||
        case 'xml':
 | 
			
		||||
            return $this->showResponseXml($upload);
 | 
			
		||||
        default:
 | 
			
		||||
            throw new ClientException('This API call does not support the format '._ve($this->format));
 | 
			
		||||
        }
 | 
			
		||||
        $this->endDocument($this->format);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected function showResponseJson(MediaFile $upload)
 | 
			
		||||
    {
 | 
			
		||||
        $enc = $upload->fileRecord->getEnclosure();
 | 
			
		||||
 | 
			
		||||
        // note that we use media_id instead of mediaid which XML users might've gotten used to (nowadays we service media_id in both!)
 | 
			
		||||
        $output = [
 | 
			
		||||
                'media_id' => $upload->fileRecord->id,
 | 
			
		||||
                'media_id_string' => (string)$upload->fileRecord->id,
 | 
			
		||||
                'media_url' => $upload->shortUrl(),
 | 
			
		||||
                'size' => $upload->fileRecord->size,
 | 
			
		||||
                ];
 | 
			
		||||
        if (common_get_mime_media($enc->mimetype) === 'image') {
 | 
			
		||||
            $output['image'] = [
 | 
			
		||||
                                'w' => $enc->width,
 | 
			
		||||
                                'h' => $enc->height,
 | 
			
		||||
                                'image_type' => $enc->mimetype,
 | 
			
		||||
                                ];
 | 
			
		||||
        }
 | 
			
		||||
        print json_encode($output);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected function showResponseXml(MediaFile $upload)
 | 
			
		||||
    {
 | 
			
		||||
        $this->elementStart('rsp', array('stat' => 'ok', 'xmlns:atom'=>Activity::ATOM));
 | 
			
		||||
        $this->element('mediaid', null, $upload->fileRecord->id);
 | 
			
		||||
        $this->element('mediaurl', null, $upload->shortUrl());
 | 
			
		||||
        $this->element('media_url', null, $upload->shortUrl());
 | 
			
		||||
        $this->element('size', null, $upload->fileRecord->size);
 | 
			
		||||
 | 
			
		||||
        $enclosure = $upload->fileRecord->getEnclosure();
 | 
			
		||||
        $this->element('atom:link', array('rel'  => 'enclosure',
 | 
			
		||||
                                          'href' => $enclosure->url,
 | 
			
		||||
                                          'type' => $enclosure->mimetype));
 | 
			
		||||
 | 
			
		||||
        // Twitter specific metadata expected in response since Twitter's Media upload API v1.1 (even though Twitter doesn't use XML)
 | 
			
		||||
        $this->element('media_id', null, $upload->fileRecord->id);
 | 
			
		||||
        $this->element('media_id_string', null, (string)$upload->fileRecord->id);
 | 
			
		||||
        if (common_get_mime_media($enclosure->mimetype) === 'image') {
 | 
			
		||||
            $this->element('image', ['w'=>$enclosure->width, 'h'=>$enclosure->height, 'image_type'=>$enclosure->mimetype]);
 | 
			
		||||
        }
 | 
			
		||||
        $this->elementEnd('rsp');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Overrided clientError to show a more Twitpic-like error
 | 
			
		||||
     *
 | 
			
		||||
     * @param String $msg an error message
 | 
			
		||||
     */
 | 
			
		||||
    function clientError($msg, $code=400, $format=null)
 | 
			
		||||
    {
 | 
			
		||||
        $this->initDocument($this->format);
 | 
			
		||||
        switch ($this->format) {
 | 
			
		||||
        case 'json':
 | 
			
		||||
            $error = ['errors' => array()];
 | 
			
		||||
            $error['errors'][] = ['message'=>$msg, 'code'=>131];
 | 
			
		||||
            print json_encode($error);
 | 
			
		||||
            break;
 | 
			
		||||
        case 'xml':
 | 
			
		||||
            $this->elementStart('rsp', array('stat' => 'fail'));
 | 
			
		||||
 | 
			
		||||
            // @todo add in error code
 | 
			
		||||
            $errAttr = array('msg' => $msg);
 | 
			
		||||
 | 
			
		||||
            $this->element('err', $errAttr, null);
 | 
			
		||||
            $this->elementEnd('rsp');
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        $this->endDocument($this->format);
 | 
			
		||||
        exit;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -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()
 | 
			
		||||
    {
 | 
			
		||||
        parent::handle();
 | 
			
		||||
 | 
			
		||||
        $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(array $args = array())
 | 
			
		||||
    {
 | 
			
		||||
        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()
 | 
			
		||||
    {
 | 
			
		||||
        parent::handle();
 | 
			
		||||
 | 
			
		||||
        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(array $args = array())
 | 
			
		||||
    {
 | 
			
		||||
        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()
 | 
			
		||||
    {
 | 
			
		||||
        parent::handle();
 | 
			
		||||
 | 
			
		||||
        $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(array $args = array())
 | 
			
		||||
    {
 | 
			
		||||
        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()
 | 
			
		||||
    {
 | 
			
		||||
        parent::handle();
 | 
			
		||||
        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->getRendered());
 | 
			
		||||
        $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;
 | 
			
		||||
        $source_link = null;
 | 
			
		||||
 | 
			
		||||
        $ns = $notice->getSource();
 | 
			
		||||
        if ($ns instanceof Notice_source) {
 | 
			
		||||
            $source = $ns->code;
 | 
			
		||||
            if (!empty($ns->url)) {
 | 
			
		||||
                $source_link = $ns->url;
 | 
			
		||||
                if (!empty($ns->name)) {
 | 
			
		||||
                    $source = $ns->name;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $this->element("twitter:source", null, $source);
 | 
			
		||||
        $this->element("twitter:source_link", null, $source_link);
 | 
			
		||||
 | 
			
		||||
        $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(array $args = array())
 | 
			
		||||
    {
 | 
			
		||||
        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()
 | 
			
		||||
    {
 | 
			
		||||
        parent::handle();
 | 
			
		||||
        $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,113 +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('GNUSOCIAL')) { 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
 | 
			
		||||
{
 | 
			
		||||
    protected function prepare(array $args=array())
 | 
			
		||||
    {
 | 
			
		||||
        parent::prepare($args);
 | 
			
		||||
 | 
			
		||||
        if (!in_array($_SERVER['REQUEST_METHOD'], array('POST', 'DELETE'))) {
 | 
			
		||||
            // TRANS: Client error displayed trying to delete a status not using POST or DELETE.
 | 
			
		||||
            // TRANS: POST and DELETE should not be translated.
 | 
			
		||||
            throw new ClientException(_('This method requires a POST or DELETE.'));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // FIXME: Return with a Not Acceptable status code?
 | 
			
		||||
        if (!in_array($this->format, array('xml', 'json'))) {
 | 
			
		||||
            // TRANS: Client error displayed when coming across a non-supported API method.
 | 
			
		||||
            throw new ClientException(_('API method not found.'), 404);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        try {
 | 
			
		||||
            $this->notice = Notice::getByID($this->trimmed('id'));
 | 
			
		||||
        } catch (NoResultException $e) {
 | 
			
		||||
            // TRANS: Client error displayed trying to delete a status with an invalid ID.
 | 
			
		||||
            throw new ClientException(_('No status found with that ID.'), 404);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return true;
 | 
			
		||||
     }
 | 
			
		||||
 | 
			
		||||
    protected function handle()
 | 
			
		||||
    {
 | 
			
		||||
        parent::handle();
 | 
			
		||||
 | 
			
		||||
        if (!$this->scoped->sameAs($this->notice->getProfile()) && !$this->scoped->hasRight(Right::DELETEOTHERSNOTICE)) {
 | 
			
		||||
            // TRANS: Client error displayed trying to delete a status of another user.
 | 
			
		||||
            throw new AuthorizationException(_('You may not delete another user\'s status.'));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (Event::handle('StartDeleteOwnNotice', array($this->scoped->getUser(), $this->notice))) {
 | 
			
		||||
            $this->notice->deleteAs($this->scoped);
 | 
			
		||||
            Event::handle('EndDeleteOwnNotice', array($this->scoped->getUser(), $this->notice));
 | 
			
		||||
        }
 | 
			
		||||
        $this->showNotice();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 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,224 +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 = null;
 | 
			
		||||
        try {
 | 
			
		||||
            $this->notice = Notice::getByID($this->notice_id);
 | 
			
		||||
        } catch (NoResultException $e) {
 | 
			
		||||
            // No such notice was found, maybe it was deleted?
 | 
			
		||||
            $deleted = null;
 | 
			
		||||
            Event::handle('IsNoticeDeleted', array($this->notice_id, &$deleted));
 | 
			
		||||
            if ($deleted === true) {
 | 
			
		||||
                // TRANS: Client error displayed trying to show a deleted notice.
 | 
			
		||||
                throw new ClientException(_('Notice deleted.'), 410);
 | 
			
		||||
            }
 | 
			
		||||
            // TRANS: Client error displayed trying to show a non-existing notice.
 | 
			
		||||
            throw new ClientException(_('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()
 | 
			
		||||
    {
 | 
			
		||||
        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));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 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()
 | 
			
		||||
    {
 | 
			
		||||
        return strtotime($this->notice->created);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 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()
 | 
			
		||||
    {
 | 
			
		||||
        return '"' . implode(
 | 
			
		||||
            ':',
 | 
			
		||||
            array($this->arg('action'),
 | 
			
		||||
                  common_user_cache_hash($this->auth_user),
 | 
			
		||||
                  common_language(),
 | 
			
		||||
                  $this->notice->id,
 | 
			
		||||
                  strtotime($this->notice->created))
 | 
			
		||||
        )
 | 
			
		||||
        . '"';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    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->deleteAs($this->scoped);
 | 
			
		||||
            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,368 +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, atom
 | 
			
		||||
 | 
			
		||||
    @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;
 | 
			
		||||
    var $media_ids             = array();   // file_id in the keys
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 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');
 | 
			
		||||
        $matches = array();
 | 
			
		||||
        common_debug(get_called_class().': media_ids=='._ve($this->trimmed('media_ids')));
 | 
			
		||||
        if (preg_match_all('/\d+/', $this->trimmed('media_ids'), $matches) !== false) {
 | 
			
		||||
            foreach (array_unique($matches[0]) as $match) {
 | 
			
		||||
                try {
 | 
			
		||||
                    $this->media_ids[$match] = File::getByID($match);
 | 
			
		||||
                } catch (EmptyPkeyValueException $e) {
 | 
			
		||||
                    // got a zero from the client, at least Twidere does this on occasion
 | 
			
		||||
                } catch (NoResultException $e) {
 | 
			
		||||
                    // File ID was not found. Do we abort and report to the client?
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $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);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            foreach(array_keys($this->media_ids) as $media_id) {
 | 
			
		||||
                // FIXME: Validation on this... Worst case is that if someone sends bad media_ids then
 | 
			
		||||
                // we'll fill the notice with non-working links, so no real harm, done, but let's fix.
 | 
			
		||||
                // The File objects are in the array, so we could get URLs from them directly.
 | 
			
		||||
                $this->status .= ' ' . common_local_url('attachment', array('attachment' => $media_id));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            $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);
 | 
			
		||||
            } elseif ($this->format == 'atom') {
 | 
			
		||||
                $this->showSingleAtomStatus($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://somesourcecode.net/microblog/">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,228 +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;
 | 
			
		||||
 | 
			
		||||
    protected function prepare(array $args=array())
 | 
			
		||||
    {
 | 
			
		||||
        parent::prepare($args);
 | 
			
		||||
 | 
			
		||||
        $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
 | 
			
		||||
     */
 | 
			
		||||
    protected function handle()
 | 
			
		||||
    {
 | 
			
		||||
        parent::handle();
 | 
			
		||||
        $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()
 | 
			
		||||
    {
 | 
			
		||||
        $notice = Notice_tag::getStream($this->tag)->getNotices(($this->page - 1) * $this->count,
 | 
			
		||||
                                                                 $this->count + 1,
 | 
			
		||||
                                                                 $this->since_id,
 | 
			
		||||
                                                                 $this->max_id);
 | 
			
		||||
 | 
			
		||||
        return $notice->fetchAll();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 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,409 +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('GNUSOCIAL')) {
 | 
			
		||||
    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
 | 
			
		||||
{
 | 
			
		||||
    public $notices = null;
 | 
			
		||||
 | 
			
		||||
    public $next_id = null;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * We expose AtomPub here, so non-GET/HEAD reqs must be read/write.
 | 
			
		||||
     *
 | 
			
		||||
     * @param array $args other arguments
 | 
			
		||||
     *
 | 
			
		||||
     * @return boolean true
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
    public 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
 | 
			
		||||
     */
 | 
			
		||||
    public 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
 | 
			
		||||
     */
 | 
			
		||||
    public 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->scoped),
 | 
			
		||||
                        common_language(),
 | 
			
		||||
                        $this->target->getID(),
 | 
			
		||||
                        strtotime($this->notices[0]->created),
 | 
			
		||||
                        strtotime($this->notices[$last]->created))
 | 
			
		||||
                )
 | 
			
		||||
                . '"';
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Take arguments for running
 | 
			
		||||
     *
 | 
			
		||||
     * @param array $args $_REQUEST args
 | 
			
		||||
     *
 | 
			
		||||
     * @return boolean success flag
 | 
			
		||||
     * @throws AuthorizationException
 | 
			
		||||
     * @throws ClientException
 | 
			
		||||
     */
 | 
			
		||||
    protected function prepare(array $args = [])
 | 
			
		||||
    {
 | 
			
		||||
        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);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!$this->target->isLocal()) {
 | 
			
		||||
            $this->serverError(_('Remote user timelines are not available here yet.'), 501);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $this->notices = $this->getNotices();
 | 
			
		||||
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get notices
 | 
			
		||||
     *
 | 
			
		||||
     * @return array notices
 | 
			
		||||
     */
 | 
			
		||||
    public function getNotices()
 | 
			
		||||
    {
 | 
			
		||||
        $notices = [];
 | 
			
		||||
 | 
			
		||||
        $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;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Handle the request
 | 
			
		||||
     *
 | 
			
		||||
     * Just show the notices
 | 
			
		||||
     *
 | 
			
		||||
     * @return void
 | 
			
		||||
     * @throws ClientException
 | 
			
		||||
     * @throws ServerException
 | 
			
		||||
     */
 | 
			
		||||
    protected function handle()
 | 
			
		||||
    {
 | 
			
		||||
        parent::handle();
 | 
			
		||||
 | 
			
		||||
        if ($this->isPost()) {
 | 
			
		||||
            $this->handlePost();
 | 
			
		||||
        } else {
 | 
			
		||||
            $this->showTimeline();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function handlePost()
 | 
			
		||||
    {
 | 
			
		||||
        if (!$this->scoped instanceof Profile ||
 | 
			
		||||
            !$this->target->sameAs($this->scoped)) {
 | 
			
		||||
            // 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.'), 403);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // 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);
 | 
			
		||||
 | 
			
		||||
        common_debug('AtomPub: Ignoring right now, but this POST was made to collection: ' . $activity->id);
 | 
			
		||||
 | 
			
		||||
        // Reset activity data so we can handle it in the same functions as with OStatus
 | 
			
		||||
        // because we don't let clients set their own UUIDs... Not sure what AtomPub thinks
 | 
			
		||||
        // about that though.
 | 
			
		||||
        $activity->id = null;
 | 
			
		||||
        $activity->actor = null;    // not used anyway, we use $this->target
 | 
			
		||||
        $activity->objects[0]->id = null;
 | 
			
		||||
 | 
			
		||||
        $stored = null;
 | 
			
		||||
        if (Event::handle('StartAtomPubNewActivity', array($activity, $this->target, &$stored))) {
 | 
			
		||||
            // TRANS: Client error displayed when not using the POST verb. Do not translate POST.
 | 
			
		||||
            throw new ClientException(_('Could not handle this Atom Activity.'));
 | 
			
		||||
        }
 | 
			
		||||
        if (!$stored instanceof Notice) {
 | 
			
		||||
            throw new ServerException('Server did not create a Notice object from handled AtomPub activity.');
 | 
			
		||||
        }
 | 
			
		||||
        Event::handle('EndAtomPubNewActivity', array($activity, $this->target, $stored));
 | 
			
		||||
 | 
			
		||||
        header('HTTP/1.1 201 Created');
 | 
			
		||||
        header("Location: " . common_local_url('ApiStatusesShow', array('id' => $stored->getID(),
 | 
			
		||||
                'format' => 'atom')));
 | 
			
		||||
        $this->showSingleAtomStatus($stored);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Show the timeline of notices
 | 
			
		||||
     *
 | 
			
		||||
     * @return void
 | 
			
		||||
     * @throws ClientException
 | 
			
		||||
     * @throws ServerException
 | 
			
		||||
     * @throws UserNoProfileException
 | 
			
		||||
     */
 | 
			
		||||
    public function showTimeline()
 | 
			
		||||
    {
 | 
			
		||||
        // We'll use the shared params from the Atom stub
 | 
			
		||||
        // for other feed types.
 | 
			
		||||
        $atom = new AtomUserNoticeFeed($this->target->getUser(), $this->scoped);
 | 
			
		||||
 | 
			
		||||
        $link = common_local_url(
 | 
			
		||||
            'showstream',
 | 
			
		||||
            array('nickname' => $this->target->getNickname())
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        $self = $this->getSelfUri();
 | 
			
		||||
 | 
			
		||||
        // FriendFeed's SUP protocol
 | 
			
		||||
        // Also added RSS and Atom feeds
 | 
			
		||||
 | 
			
		||||
        $suplink = common_local_url('sup', null, null, $this->target->getID());
 | 
			
		||||
        header('X-SUP-ID: ' . $suplink);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        // paging links
 | 
			
		||||
        $nextUrl = !empty($this->next_id)
 | 
			
		||||
            ? common_local_url(
 | 
			
		||||
                'ApiTimelineUser',
 | 
			
		||||
                array('format' => $this->format,
 | 
			
		||||
                    'id' => $this->target->getID()),
 | 
			
		||||
                array('max_id' => $this->next_id)
 | 
			
		||||
            )
 | 
			
		||||
            : null;
 | 
			
		||||
 | 
			
		||||
        $prevExtra = [];
 | 
			
		||||
        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->getID()),
 | 
			
		||||
            $prevExtra
 | 
			
		||||
        );
 | 
			
		||||
        $firstUrl = common_local_url(
 | 
			
		||||
            'ApiTimelineUser',
 | 
			
		||||
            array('format' => $this->format,
 | 
			
		||||
                'id' => $this->target->getID())
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        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->scoped);
 | 
			
		||||
                $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);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -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(array $args = array())
 | 
			
		||||
    {
 | 
			
		||||
        parent::prepare($args);
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Handle a request
 | 
			
		||||
     *
 | 
			
		||||
     * @param array $args Arguments from $_REQUEST
 | 
			
		||||
     *
 | 
			
		||||
     * @return void
 | 
			
		||||
     */
 | 
			
		||||
    function handle()
 | 
			
		||||
    {
 | 
			
		||||
        parent::handle();
 | 
			
		||||
        $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(array $args = array())
 | 
			
		||||
    {
 | 
			
		||||
        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()
 | 
			
		||||
    {
 | 
			
		||||
        parent::handle();
 | 
			
		||||
 | 
			
		||||
        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);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user