Comparar commits
582 Commits
new_data_handler
...
v3
| Autor | SHA1 | Data | |
|---|---|---|---|
| 0bb44602b2 | |||
| d313d088b2 | |||
| 0621c9fe85 | |||
| a08748fe77 | |||
| 3a397ec8b3 | |||
| c920be93f9 | |||
| 63aa46d8f3 | |||
| 5020243326 | |||
| 4ec5928ef3 | |||
| 361934e6c4 | |||
| 035a8c90b6 | |||
| e27142f20c | |||
| 39a4a4ba99 | |||
| dcc6881253 | |||
| 8fd96abf3c | |||
| bfd1c60d61 | |||
| 8a929a20b8 | |||
| b53ef8cbff | |||
| e4e68d048b | |||
| ae181ff6b4 | |||
| e19ee25660 | |||
| c95a7e36f9 | |||
| 04a5744b9f | |||
| 583b28b65d | |||
| 06356d10b0 | |||
| 58b212e463 | |||
| b2c2988e96 | |||
| 796b77ba6f | |||
| 088568fcde | |||
| 8675782ae0 | |||
| 0919bc4902 | |||
| 17ccee08d1 | |||
| f6a750165f | |||
| 1b006a1405 | |||
| 92e4cd2abc | |||
| 2b4ef43979 | |||
| 1b01c32383 | |||
| 24027a884f | |||
| 8b5b9cfd4f | |||
| 34b2a1ad53 | |||
| 0134a75934 | |||
| 908cae3af6 | |||
| 1ccc41b244 | |||
| cc89d4fa83 | |||
| f61635e181 | |||
| ddc7834069 | |||
| 71f50d7f48 | |||
| b254a7efeb | |||
| 51ae3909a1 | |||
| 01bd7f9d51 | |||
| 76638fc62e | |||
| 3e0dc1c70c | |||
| 66d4f323f0 | |||
| 7368e888f3 | |||
| bae43c9e7d | |||
| 33a22f9604 | |||
| b7296c682e | |||
| fba1cd1d26 | |||
| fb7114c373 | |||
| f99d3d2be5 | |||
| f70ee98e19 | |||
| 77b9e3ed78 | |||
| c2ac90157e | |||
| 5d80d80e72 | |||
| 18b05baf61 | |||
| 1b8ff83acb | |||
| 9c050f189f | |||
| a1d374644f | |||
| 9ed9065f1b | |||
| 6e1fc64b53 | |||
| 3c362c543e | |||
| 0ced7e27a8 | |||
| 84e958a574 | |||
| c8a60b683f | |||
| 7c5570e4f5 | |||
| 8fd7d5e314 | |||
| 8db080fc07 | |||
| 6173dff860 | |||
| 6e62dcee46 | |||
| 2df6b90c4c | |||
| dd64ec33b5 | |||
| 8b163eaf25 | |||
| 15a3989a63 | |||
| c0de943975 | |||
| 53b1b79140 | |||
| da4c8b4a7f | |||
| 367878e096 | |||
| 544495797b | |||
| 3925a69228 | |||
| 82fd3586bc | |||
| e3bb0afb3b | |||
| af94469fec | |||
| e11cc30ceb | |||
| 941ded7c0c | |||
| 7c4b891694 | |||
| ff50aa716f | |||
| eb7393a190 | |||
| 5674c4a355 | |||
| 3554a99b86 | |||
| da57dc7485 | |||
| 7a5ad40f95 | |||
| e575e30144 | |||
| 8b7e6c9606 | |||
| fe790a444d | |||
| e901da1629 | |||
| f3b2f5bed5 | |||
| 984192164f | |||
| 06cbcc480e | |||
| cfb689f477 | |||
| 9af77c0408 | |||
| d6f0426883 | |||
| bd211ba737 | |||
| e376c66bd5 | |||
| 8d8a4b56e3 | |||
| bf4b7bd51b | |||
| f025cafac1 | |||
| 16d76dad5d | |||
| d1a04601a0 | |||
| ce7058eb28 | |||
| 5d2eff4af6 | |||
| 2fa82c9e6f | |||
| caf40c1067 | |||
| 4ea62dbf7a | |||
| c314e3e6d4 | |||
| ca79b7a0cd | |||
| b53565cba5 | |||
| f877850e31 | |||
| dbf940bfe6 | |||
| c8cd0523cc | |||
| d8f7f2431b | |||
| 229bff8c21 | |||
| bb1089a80a | |||
| 3ce611cbe7 | |||
| 35e1b7cd16 | |||
| 98c6513bfd | |||
| f96b494be7 | |||
| 919a21a9cf | |||
| e55afd3e8f | |||
| 0e0c45d35e | |||
| c60a53a638 | |||
| c59ea15a0f | |||
| e921306cb3 | |||
| d2b36d6115 | |||
| 9956714af3 | |||
| 2254a4d639 | |||
| 1084d9926e | |||
| dd5b610a12 | |||
| a1e6179752 | |||
| 2e34f5727e | |||
| db788dcff7 | |||
| 02060e20a5 | |||
| 1d6bfa1e5d | |||
| 7e9d4b896a | |||
| ce5892c68d | |||
| 223c10b6cf | |||
| 3509feaba2 | |||
| 34f4b92e34 | |||
| 9e24b120fc | |||
| 8b05adb72c | |||
| 9f1ea4b417 | |||
| ded109dc92 | |||
| 517541aeb6 | |||
| ff0973b746 | |||
| 2608da6167 | |||
| d45e170401 | |||
| a2fa0595ca | |||
| 3544e0108a | |||
| ad5aca94b1 | |||
| b1e40180c4 | |||
| 397f02d88c | |||
| a5ca98f711 | |||
| c017c132cb | |||
| 0df2bc464e | |||
| 585b1478a9 | |||
| 04064621dc | |||
| af0145c303 | |||
| abaa5839a8 | |||
| 9e66eb347f | |||
| 207e24aba8 | |||
| bae80ebd70 | |||
| b3327040f2 | |||
| d7f8793580 | |||
| fd13e4fe7a | |||
| 7c6d429d24 | |||
| 287d74ea57 | |||
| e6736507ad | |||
| 79094ec2a0 | |||
| 2ebcb9212e | |||
| ab950f07f5 | |||
| d8580692c0 | |||
| 9f572c0caa | |||
| f4f4989945 | |||
| 3ef284cd51 | |||
| 7c6e3ed864 | |||
| e6b5c83ca1 | |||
| 5eb59cebc3 | |||
| 828c00a789 | |||
| 355d94c70c | |||
| 629dc7b3ac | |||
| dfa47f5ee2 | |||
| b195646635 | |||
| a43d97f0c0 | |||
| d4de595cad | |||
| 27c61a203e | |||
| d2b7c5efbc | |||
| eb29dc6305 | |||
| faba609bfd | |||
| 490daef73b | |||
| 18d8484fad | |||
| 5b7778ab1d | |||
| 11dc95cf66 | |||
| 45bd7ad3a0 | |||
| e72dde7b4b | |||
| 178742e09a | |||
| 9fcbaf2b94 | |||
| b1f6e40dde | |||
| 760e892952 | |||
| ea9042be52 | |||
| 8903d21a27 | |||
| c307ec8ffa | |||
| 3cea097fee | |||
| ef996f91be | |||
| efbbf84549 | |||
| 56bff81534 | |||
| 82b41ffffb | |||
| 3bd13005c4 | |||
| c35fbf6280 | |||
| fe9109b9fe | |||
| 8a9ef01010 | |||
| 022adb0b20 | |||
| e11ba5efc8 | |||
| 09516621d7 | |||
| cc8481eb8d | |||
| ebb5b81210 | |||
| a04f2a2424 | |||
| 1a125c5f36 | |||
| 7062924993 | |||
| d6a73be313 | |||
| 7e9d650909 | |||
| 985bfef507 | |||
| 4d3d556cd0 | |||
| 74c0414d36 | |||
| 3779a5d9e1 | |||
| 251d7870d2 | |||
| d2022f6efd | |||
| c3f7fabb19 | |||
| 1edb12d68b | |||
| cd8d699888 | |||
| 3a6f4b0c6b | |||
| 522480989a | |||
| 683611b9bf | |||
| 7e350c96bc | |||
| 17cd375947 | |||
| b91ac960ca | |||
| 6ceccae177 | |||
| 875c87ab2f | |||
| a0458057cf | |||
| 26d3748c78 | |||
| 9a515b9234 | |||
| b924c180ae | |||
| 737f3eb553 | |||
| 6e3954f3bb | |||
| 4544f29832 | |||
| 477c357f11 | |||
| 7869a7c1b0 | |||
| edc7159ef6 | |||
| 1db6943702 | |||
| e8dff6c4a0 | |||
| 23ed816035 | |||
| 324b7f38a9 | |||
| aa7aff3f6b | |||
| 236929a166 | |||
| 953e243639 | |||
| 338d53c982 | |||
| 37ebcc509b | |||
| f9be6f9a85 | |||
| 2cc2b5b856 | |||
| 194976135f | |||
| ef17f3ea7d | |||
| 0eec6fcfb6 | |||
| 09a772419a | |||
| 6c035d01d4 | |||
| 97bddc4537 | |||
| 684675bd84 | |||
| b8c0fa9fa0 | |||
| 9e7794cd66 | |||
| 92ad44abf9 | |||
| 7e83ddf80e | |||
| a9be720f09 | |||
| d7906f113e | |||
| 01dcaefcfb | |||
| cfba91ea43 | |||
| 134b6f6478 | |||
| 64104cb182 | |||
| 9aedcc7997 | |||
| 35547e28ea | |||
| c6543e1f95 | |||
| 2183875e9e | |||
| e5ee069f4a | |||
| 6c844315aa | |||
| 872bb1388d | |||
| 42aa255152 | |||
| e58188d136 | |||
| bb32c0af3b | |||
| 63fd2c7037 | |||
| 520a2ba202 | |||
| 13e8445083 | |||
| d1c70cb13b | |||
| 6898cff623 | |||
| f4558e3c41 | |||
| d24075b1c5 | |||
| a8c2a9da3a | |||
| 8041df7d41 | |||
| 073a181778 | |||
| bec6fdc66a | |||
| 6833c9f1c2 | |||
| 18ade30185 | |||
| e7ab305335 | |||
| 110d3a453a | |||
| f5aeab39b4 | |||
| e7738895ce | |||
| 60446dfc20 | |||
| dc211c9c44 | |||
| 27babac6dc | |||
| 3e2b7cddc8 | |||
| 80ba2b3ccc | |||
| b730582336 | |||
| 1b429dd2e5 | |||
| 448404e45c | |||
| 562d84c375 | |||
| f09e3362aa | |||
| 51b5b1c08c | |||
| ca2dde9a41 | |||
| 6674d1ed0f | |||
| 2a10dffff8 | |||
| e0b17fc97d | |||
| 52800c3a65 | |||
| 9124617055 | |||
| b312712d1b | |||
| 5bc1b8695e | |||
| d921f3dadb | |||
| c154712012 | |||
| 3634af3fdc | |||
| 1df9ec9f0f | |||
| ae54a94d41 | |||
| 69add504e6 | |||
| a0d30b6872 | |||
| a06b33be66 | |||
| fe3e33e702 | |||
| 3f56459734 | |||
| 4903241e4b | |||
| 85be003cf5 | |||
| bddc1c0f9d | |||
| 01f6d83b86 | |||
| aa994ee4fb | |||
| d058a70557 | |||
| 7298468df7 | |||
| 63caa5044d | |||
| 2ae93dbec6 | |||
| b434bead2c | |||
| 6284b155b8 | |||
| b12c2d17d5 | |||
| 5fb1e26a4c | |||
| 6423750250 | |||
| d9b5ef1cee | |||
| f1717bde51 | |||
| c6f4f40bba | |||
| 65f1b1e1e3 | |||
| ad91ef66bd | |||
| 6bfa593988 | |||
| 3ea580b537 | |||
| 87b0b493eb | |||
| 4eb4a2de00 | |||
| 1f2f57b03b | |||
| 4afaad3df5 | |||
| c3ba2e0f94 | |||
| 693c3168da | |||
| 8f309bc768 | |||
| 1a0d6a90c2 | |||
| 7f2019b4af | |||
| ee7f0a2016 | |||
| 644b417f6c | |||
| 471576d6e8 | |||
| 7ee8aa7838 | |||
| af63e9a7ad | |||
| 95c7344557 | |||
| 0c936e54ba | |||
| 62b90c29db | |||
| 6911b499d3 | |||
| 44f4c9374d | |||
| 11dabbe44d | |||
| 0a5a3845db | |||
| 5b797328f2 | |||
| b89f1ad7d8 | |||
| b0104d9992 | |||
| 9d8f4c774f | |||
| 8b7a22ecd9 | |||
| a4e6db8d76 | |||
| 78506d5249 | |||
| 6747b18b75 | |||
| 544f13c52a | |||
| 4644f6e96b | |||
| a3b228399b | |||
| 100a557c7c | |||
| 6acc75ccff | |||
| b41f9620fa | |||
| 58bde08425 | |||
| 7d6c6edab3 | |||
| d209964718 | |||
| c03f659efb | |||
| 2e66cbeb60 | |||
| 19409cb999 | |||
| c06182c38f | |||
| f79cd8cee3 | |||
| c130739de0 | |||
| 1a4a1583d5 | |||
| 3633ca04eb | |||
| e61c0c45aa | |||
| 6d81848f25 | |||
| 10b3b343dd | |||
| f6fd025be2 | |||
| b5897687a6 | |||
| ebeae261de | |||
| 9733f3c02c | |||
| 217c8a3933 | |||
| 7188d81ad4 | |||
| 48cacd6d9d | |||
| 1e378a514d | |||
| 92ab5e18ee | |||
| b42af10905 | |||
| afe8158cb7 | |||
| a05bea0af5 | |||
| e1514a151c | |||
| 2a82cfdb2a | |||
| 49da433879 | |||
| 92388e1734 | |||
| 3860c25dc0 | |||
| 25ee5ed1f9 | |||
| 566214ac62 | |||
| 1459f10803 | |||
| 0795a39459 | |||
| e5831d6807 | |||
| 88bdb5114f | |||
| 90bd9088bb | |||
| 01cf8ab82c | |||
| aee5506f00 | |||
| b6183f2de1 | |||
| 452e0fe553 | |||
| 2f341a3369 | |||
| 66e55d1a1f | |||
| 63fac32bc0 | |||
| aaeaeba57c | |||
| d3c56897a3 | |||
| 0c2c3ec862 | |||
| b6e7b18c7b | |||
| 55d049b1e8 | |||
| 8c0601816f | |||
| 350cde08d8 | |||
| db5a29fd9a | |||
| 0716605e94 | |||
| c802480d75 | |||
| 2519431f02 | |||
| b38e71e544 | |||
| c981afcf31 | |||
| eccb8a4faf | |||
| 7fa5ddfc44 | |||
| 054f4e77f5 | |||
| 1398d6cc21 | |||
| b902b019fb | |||
| 5e589aba3c | |||
| c28cee88b7 | |||
| 14a45dc546 | |||
| 883621ba34 | |||
| 067cc81ebb | |||
| b19ee7b894 | |||
| 1b356d3bf2 | |||
| 94a4059b4a | |||
| 735a0023cc | |||
| 2ad4fa99ed | |||
| c0950c5fc6 | |||
| afbbbbd4f2 | |||
| 32812c9482 | |||
| c70e806d74 | |||
| 05be2e7386 | |||
| e2e8885ce3 | |||
| b214d8b6ee | |||
| ba98bb9334 | |||
| 630a578e1d | |||
| 0bb35d7e7f | |||
| 357296baeb | |||
| bff525d26f | |||
| e4bdb21a54 | |||
| c0ac7f0ac8 | |||
| eba2fe1624 | |||
| 0030fe3aeb | |||
| aaabf82eff | |||
| de91d28f6f | |||
| 24d5d200b8 | |||
| 573ba2ee43 | |||
| b4fced4bd7 | |||
| 52310a8ad8 | |||
| 11d203c54a | |||
| 723f12923c | |||
| 8b106dbc6c | |||
| 955d5a136f | |||
| 2db3825940 | |||
| db3253e5d2 | |||
| dbde8383c9 | |||
| 6d552f15b6 | |||
| ba15724a62 | |||
| 938d286fb6 | |||
| 2e6c7b1bb8 | |||
| 5be705ca2a | |||
| 07b4cfaeae | |||
| c9379b3608 | |||
| 22c8c96249 | |||
| d66828c2bf | |||
| a244f3ba4d | |||
| 0c20d35206 | |||
| 462ea26303 | |||
| b25632ebc4 | |||
| 2a2b3f72fb | |||
| 52819d39d9 | |||
| 1d41ff16d6 | |||
| 36dd245ee3 | |||
| e0bc35b975 | |||
| 893bafa14b | |||
| 7d262ad50b | |||
| d9e7862cea | |||
| 9f30c299ee | |||
| 39845444cc | |||
| ec32db2dd6 | |||
| 411e8ed79d | |||
| c1c2a9f1a1 | |||
| 2850e56f30 | |||
| 9c0354bbf1 | |||
| c09f1c2443 | |||
| 912f2c3567 | |||
| ad51998d67 | |||
| 1049080df5 | |||
| 966b00617e | |||
| b408208e4c | |||
| a1edc2c6a9 | |||
| 2a06261f75 | |||
| 0b58465fb9 | |||
| f67a93eddc | |||
| 7044f0e2cf | |||
| ed7a88ce66 | |||
| e392160435 | |||
| 5c0a3102ff | |||
| 2032c7c1f7 | |||
| d295d8b43c | |||
| ee8bac9ad7 | |||
| 4863bd30d7 | |||
| 7070a14480 | |||
| a38f25f7cd | |||
| a5259073df | |||
| 3e5ce46e98 | |||
| f746866b65 | |||
| 8f31a1a820 | |||
| 4187568522 | |||
| da82048d77 | |||
| 04d1caff78 | |||
| bea06da531 | |||
| 7643f3cf7b | |||
| aa5c6bbf08 | |||
| 9536f2a909 | |||
| c7475d78b4 | |||
| 3c9a07677e | |||
| b669f57068 | |||
| ccebe536b3 | |||
| b9a0733062 | |||
| 5961b45140 | |||
| 5f53738376 | |||
| 5eb4a7d711 | |||
| f717081893 | |||
| 01b5118c6f | |||
| d705bcbd98 | |||
| f0f5ecb756 | |||
| c0342b1482 | |||
| d1fc7c0774 | |||
| 46be9b76ef |
+43
@@ -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 ###
|
||||
@@ -0,0 +1,5 @@
|
||||
# define your env variables for the test env here
|
||||
KERNEL_CLASS='App\Kernel'
|
||||
APP_SECRET='$ecretf0rt3st'
|
||||
SYMFONY_DEPRECATIONS_HELPER=999999
|
||||
PANTHER_APP_ENV=panther
|
||||
+41
-17
@@ -1,18 +1,42 @@
|
||||
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
|
||||
docker/*/*.env
|
||||
|
||||
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
|
||||
|
||||
+278
@@ -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."
|
||||
@@ -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
@@ -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/>.
|
||||
+58
-58
@@ -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.
|
||||
Diferenças do arquivo suprimidas por serem muito extensas
Carregar 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;
|
||||
}
|
||||
```
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
### Entrypoint
|
||||
|
||||
GNU social's entrypoint is the `public/index.php` script, which gets
|
||||
called by the webserver for all requests. This is handled by the
|
||||
webserver itself, which translates a `GET /foo` to `GET
|
||||
/index.php?p=foo`. This feature is called 'fancy URLs', as it was in V2.
|
||||
|
||||
The `index` script handles all the initialization of the Symfony
|
||||
framework and social itself. It reads configuration from `.env` or any
|
||||
`.env.*` file at the project root. The `index` script creates a
|
||||
`Kernel` object, which is defined on the `src/Kernel.php` file. This
|
||||
is the part where the code we control starts; the `Kernel` constructor
|
||||
creates the needed constants, sets the timezone to UTC and the string
|
||||
encoding to UTF8. The other functions in this class get called by the
|
||||
Symfony framework at the appropriate times. We will come back to this
|
||||
file.
|
||||
|
||||
### Registering services
|
||||
|
||||
Next, the `src/Util/GNUsocial.php` class is instantiated by the
|
||||
Symfony framework, on the `'onKernelRequest'` or `'onCommand'` events. The
|
||||
former event, as described in the docs:
|
||||
|
||||
> This event is dispatched very early in Symfony, before the
|
||||
> controller is determined. It's useful to add information to the
|
||||
> Request or return a Response early to stop the handling of the
|
||||
> request.
|
||||
|
||||
The latter, is launched on the `bin/console` script is used.
|
||||
|
||||
In both cases, these events call the `register` function, which
|
||||
creates static references for the logging, event and translation
|
||||
services. This is done so these services can be used via static
|
||||
function calls, which is much less verbose and more accessible than
|
||||
the way the framework recommends. This function also loads all the
|
||||
Modules and Plugins, which like in V2, are components that aren't
|
||||
directly connected to the core code, being used to implement internal
|
||||
and optional functionality respectively, by handling events launched
|
||||
by various parts of the code.
|
||||
|
||||
### Database definitions
|
||||
|
||||
Going back to the `Kernel`, the `build` function gets called by the
|
||||
Symfony framework and allows us to register a 'Compiler Pass'.
|
||||
Specifically, we register the `SchemaDefPass` from the
|
||||
`src/DependencyInjection/Compiler/SchemaDefPass.php` file, which adds
|
||||
a new 'metadata driver' to Doctrine. The metadata driver is
|
||||
responsible for loading database definitions. We keep the same method
|
||||
as in V2, which was that each 'Entity' has a `schemaDef` static
|
||||
function which returns an array describing the database.
|
||||
|
||||
This definition is handled by the `SchemaDefDriver` class from
|
||||
`src/Util/SchemaDefDriver.php` file, which extends `StaticPHPDriver`
|
||||
and replaces the methods `loadMetadata` with `schemaDef`. The function
|
||||
`loadMetadataForClass` function is called by the Symfony framework for
|
||||
each file in `src/Entity/`. It allows us to call the `schemaDef`
|
||||
function and translate the array definition to Doctrine's internal
|
||||
representation.
|
||||
|
||||
### Routing
|
||||
|
||||
Next, we'll look at the `RouteLoader`, defined in
|
||||
`src/Util/RoutLoader.php`, which loads all the files from
|
||||
`src/Routes/*.php` and calls the static `load` method, which defines
|
||||
routes with an interface similar to V2's `connect`, except it requires
|
||||
an extra identifier as the first argument. This identifier is used,
|
||||
for instance, to generate URLs for each route. Each route connects an
|
||||
URL path to a Controller, with the possibility of taking arguments,
|
||||
which are passed to the `__invoke` method of the respective
|
||||
controller. The controllers are defined in `src/Controller/` and are
|
||||
responsible for handling a request and return a Symfony `Response`
|
||||
object (subject to change, in order to abstract HTML vs JSON output).
|
||||
|
||||
### End to end
|
||||
|
||||
The next steps are handled by the Symfony framework which creates a
|
||||
`Request` object from the HTTP request, and then a corresponding
|
||||
`Response` is created by calling the `Kernel::handle` method, which
|
||||
matches the appropriate route and thus calls it's controller.
|
||||
|
||||
### Performance
|
||||
|
||||
All this happens on each request, which seems like a lot to handle,
|
||||
and would be too slow. Fortunately, Symfony has a 'compiler' which
|
||||
caches and optimizes the code paths. In production mode, this can be
|
||||
done through a command, while in development mode, it's handled on
|
||||
each request if the file changed, which has a performance impact, but
|
||||
obviously makes development easier.
|
||||
Arquivo binário não exibido.
@@ -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
|
||||
Link simbólico
+1
@@ -0,0 +1 @@
|
||||
../../INSTALL.md
|
||||
Diferenças do arquivo suprimidas por serem muito extensas
Carregar 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.
|
||||
Link simbólico
+1
@@ -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>
|
||||
-35
@@ -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>
|
||||
-43
@@ -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,88 +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.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;
|
||||
# }
|
||||
}
|
||||
+121
-40
@@ -1,34 +1,128 @@
|
||||
|
||||
GNU social
|
||||
=====
|
||||
|
||||
GNU social is a federated social network.
|
||||
|
||||
TABLE OF CONTENTS
|
||||
=================
|
||||
* Prerequisites
|
||||
* Installation with docker
|
||||
+ Prerequisites
|
||||
+ With TLS/SSL
|
||||
+ Without TLS/SSL
|
||||
+ Configuration
|
||||
+ Installing/running
|
||||
|
||||
* Installation without docker
|
||||
+ Prerequisites
|
||||
- PHP modules
|
||||
- Better performance
|
||||
* Installation
|
||||
+ Installation
|
||||
- Getting it up and running
|
||||
- Fancy URLs
|
||||
- Themes
|
||||
- Private
|
||||
* Extra features
|
||||
+ Extra features
|
||||
- Sphinx
|
||||
- SMS
|
||||
- Translation
|
||||
- Queues and daemons
|
||||
* After installation
|
||||
+ After installation
|
||||
- Backups
|
||||
- Upgrading
|
||||
* Additional configuration
|
||||
+ Additional configuration
|
||||
|
||||
Installation with docker
|
||||
================
|
||||
|
||||
Installation can be done in multiple ways, but the simplest is using
|
||||
`docker` and `docker-compose`. The compose file currently includes all
|
||||
the necessary services for running the app. Running the database and
|
||||
webserver outside of `docker` containers is currently not supported,
|
||||
unless the app is installed without `docker`.
|
||||
|
||||
Prerequisites
|
||||
=============
|
||||
-----
|
||||
|
||||
PHP modules
|
||||
In order to host your GNU social instance, you'll need a domain, a
|
||||
server with a constant IP and both `docker` and `docker-compose`
|
||||
installed on your system.
|
||||
|
||||
Alternatively, for local hosting or development, behind a NAT, use a
|
||||
dynamic DNS solutions. I recommend you go to
|
||||
https://gnudip.datasystems24.net or another GnuDIP host and register.
|
||||
Then clone https://notabug.org/someonewithpc/gnudip.git, inspect and
|
||||
run the `./install.sh` script. This allows you to have a domain that
|
||||
dynamically points to your IP address.
|
||||
|
||||
With TLS/SSL
|
||||
----
|
||||
|
||||
Next, if you want to setup SSL (which you should in most cases,
|
||||
exceptions being wanting to use the Tor network), you'll need a
|
||||
certificate. There are multiple approaches to achieve this, among
|
||||
which are using a proxy server capable of either proxying an HTTP
|
||||
connection to HTTPS or an HTTPS connection to HTTPS, or creating a
|
||||
certificate signed by Let's Encrypt. For the former, follow the
|
||||
instructions of your proxy provider.
|
||||
|
||||
If you're not using a proxy, you can use the
|
||||
`bin/bootstrap_certificates` script to generate and install
|
||||
certificates signed by Let's Encrypt. To do this, you should add the
|
||||
server's IP, if it's static, as an `A` DNS record with your DNS
|
||||
provider (normally, your domain registrar); the `A` record doesn't
|
||||
need to be at the root of your domain, meaning it's name can be a
|
||||
subdomain. For dynamic IPs, create a `CNAME` record pointing to the
|
||||
hostname you created with the GnuDIP host, above. A `CNAME` cannot be
|
||||
created for a domain root, so you must use a subdomain. Then, run the
|
||||
aforementioned script and fill in the details.
|
||||
|
||||
Without TLS/SSL
|
||||
----
|
||||
|
||||
Edit the `docker-compose.yaml` file and comment the `certbot` service
|
||||
to disable it. In the future, this will be handled by the
|
||||
`bin/configure` script.
|
||||
|
||||
Configuration
|
||||
----
|
||||
|
||||
Run the `bin/configure` script and enter the information as asked.
|
||||
This will generate all the required `.env` files used by
|
||||
`docker-compose` to configure the application.
|
||||
|
||||
Installation/Running
|
||||
-----
|
||||
|
||||
Simply run `docker-compose up` from the root of the project (the
|
||||
folder where the `.git` folder is). In this form, the application can
|
||||
be stopped by pressing `C-c` (`CTRL` + `C`); pressing it again will
|
||||
force the containers to stop immediately. However, this form will show
|
||||
you all logs, but in most cases, you won't want to see those all the
|
||||
time. For that, run `docker-compose up -d` from the same directory;
|
||||
The application can then be stopped with `docker-compose down`.
|
||||
|
||||
|
||||
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
|
||||
Installation without docker
|
||||
================
|
||||
|
||||
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.
|
||||
- PHP 7.3+
|
||||
- MariaDB 10.3+
|
||||
- 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)
|
||||
@@ -50,12 +144,10 @@ functional setup of GNU social:
|
||||
- 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
|
||||
------------------
|
||||
### Better performance
|
||||
|
||||
For some functionality, you will also need the following extensions:
|
||||
|
||||
@@ -70,17 +162,15 @@ For some functionality, you will also need the following extensions:
|
||||
- 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
|
||||
-------------------------
|
||||
### Getting it up and running
|
||||
|
||||
Installing the basic GNU Social web component is relatively easy,
|
||||
especially if you've previously installed PHP/MariaDB packages.
|
||||
@@ -163,8 +253,7 @@ especially if you've previously installed PHP/MariaDB packages.
|
||||
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
|
||||
----------
|
||||
### 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
|
||||
@@ -204,8 +293,7 @@ like:
|
||||
|
||||
https://social.example.net/main/register
|
||||
|
||||
Themes
|
||||
------
|
||||
### 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,
|
||||
@@ -229,8 +317,7 @@ listing on profile pages.
|
||||
You may want to start by copying the files from the default theme to
|
||||
your own directory.
|
||||
|
||||
Private
|
||||
-------
|
||||
### 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
|
||||
@@ -262,10 +349,9 @@ Access to file attachments can also be restricted to logged-in users only:
|
||||
$config['attachments']['dir'] = '/var/www/gnusocial-files';
|
||||
|
||||
Extra features
|
||||
==============
|
||||
---------
|
||||
|
||||
Sphinx
|
||||
------
|
||||
### Sphinx
|
||||
|
||||
To use a Sphinx server to search users and notices, you'll need to
|
||||
enable the SphinxSearch plugin. Add to your config.php:
|
||||
@@ -278,8 +364,7 @@ php on the client side, which itself depends on the sphinx development files.
|
||||
|
||||
See plugins/SphinxSearch/README for more details and server setup.
|
||||
|
||||
SMS
|
||||
---
|
||||
### SMS
|
||||
|
||||
StatusNet supports a cheap-and-dirty system for sending update messages
|
||||
to mobile phones and for receiving updates from the mobile. Instead of
|
||||
@@ -327,8 +412,7 @@ For this to work, there *must* be a domain or sub-domain for which all
|
||||
|
||||
$config['mail']['domain'] = 'yourdomain.example.net';
|
||||
|
||||
Translations
|
||||
------------
|
||||
### Translations
|
||||
|
||||
For info on helping with translations, see the platform currently in use
|
||||
for translations: https://www.transifex.com/projects/p/gnu-social/
|
||||
@@ -343,8 +427,7 @@ tracking the git repo, you will need to install at least 'gettext' on
|
||||
your system and then run:
|
||||
$ make translations
|
||||
|
||||
Queues and daemons
|
||||
------------------
|
||||
### 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
|
||||
@@ -355,7 +438,7 @@ 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
|
||||
#### 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.
|
||||
@@ -375,7 +458,7 @@ 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
|
||||
#### 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
|
||||
@@ -440,24 +523,22 @@ home-grown DB-based queue solution. This is strongly recommended for
|
||||
best response time, especially when using XMPP.
|
||||
|
||||
After installation
|
||||
==================
|
||||
----------
|
||||
|
||||
Backups
|
||||
-------
|
||||
### 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
|
||||
|
||||
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
|
||||
------------------------
|
||||
### Additional configuration
|
||||
|
||||
Please refer to DOCUMENTATION/SYSTEM_ADMINISTRATORS/CONFIGURE for information.
|
||||
----
|
||||
|
||||
-18
@@ -1,18 +0,0 @@
|
||||
# Warning: do not transform tabs to spaces in this file.
|
||||
|
||||
all : translations
|
||||
|
||||
core_mo = $(patsubst %.po,%.mo,$(wildcard locale/*/LC_MESSAGES/statusnet.po))
|
||||
plugin_mo = $(patsubst %.po,%.mo,$(wildcard plugins/*/locale/*/LC_MESSAGES/*.po))
|
||||
|
||||
translations : $(core_mo) $(plugin_mo)
|
||||
|
||||
clean :
|
||||
rm -f $(core_mo) $(plugin_mo)
|
||||
|
||||
updatepo :
|
||||
php scripts/update_po_templates.php --all
|
||||
|
||||
%.mo : %.po
|
||||
msgfmt -o $@ $<
|
||||
|
||||
-157
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
Alguns arquivos não foram exibidos porque demasiados arquivos foram alterados neste diff Mostrar Mais
Referência em uma Nova Issue
Bloquear um usuário