588 Commits

Autor SHA1 Mensagem Data
Hugo Sales 0bb44602b2 [SECURITY] Ensure ARGON2 constants are defined, or throw exception 2020-07-29 18:10:44 +00:00
Hugo Sales d313d088b2 [DEPENDENCY] Update dependencies 2020-07-29 18:10:44 +00:00
Hugo Sales 0621c9fe85 [UI][CONTROLLER] Refactor UserPanel to use the new Form::handle method and add placeholders in the password fields 2020-07-29 18:10:44 +00:00
Hugo Sales a08748fe77 [DATABASE] Remove DATABASE::flush from Profile::setSelfTags 2020-07-29 18:10:44 +00:00
Hugo Sales 3a397ec8b3 [FORMATTING] Add option to split a string to array by both a comma and a space 2020-07-29 18:10:44 +00:00
Hugo Sales c920be93f9 [FORM] Add DataTransformer to and from array 2020-07-29 18:10:44 +00:00
Hugo Sales 63aa46d8f3 [FORM] Add Form::handle which automagically creates a form, handles a request, and writes the data to the given entity and update Form::create to do some more magic as well 2020-07-29 18:10:44 +00:00
Hugo Sales 5020243326 [DATABASE][TOOLS] Update local_user to return the proper PhoneNumber type 2020-07-29 18:10:44 +00:00
Hugo Sales 4ec5928ef3 [CORE][SECURITY][UX] Save previous url on /register and /logout 2020-07-29 18:10:44 +00:00
rainydaysavings 361934e6c4 [CONTROLLER][UI] Fixing controller display errors, Settings CSS fixes 2020-07-29 18:10:44 +00:00
rainydaysavings 035a8c90b6 [UI][ROUTES][CONTROLLER] Fixing Settings navs and templates 2020-07-29 18:10:44 +00:00
rainydaysavings e27142f20c [UI] Register and Login rework 2020-07-29 18:10:44 +00:00
rainydaysavings 39a4a4ba99 [UI] Left panel fix 2020-07-29 18:10:44 +00:00
Hugo Sales dcc6881253 [Controller] Update settings/avatar 2020-07-29 18:10:44 +00:00
Hugo Sales 8fd96abf3c [DATABASE][TOOLS] Update local_user, SchemaDefDriver and bin/generate_entity_fields to use the phone_number type (which maps to a varchar 35 and does validation) 2020-07-29 18:10:44 +00:00
Hugo Sales bfd1c60d61 [UI] Update settings/account to reflect the current values 2020-07-29 18:10:44 +00:00
Hugo Sales 8a929a20b8 [UI][ROUTES] s%settings/profile%settings/personal_info% 2020-07-29 18:10:44 +00:00
Hugo Sales b53ef8cbff [CORE][UX] Save previous url to redirect back after registering 2020-07-29 18:10:44 +00:00
Hugo Sales e4e68d048b [DEPENDENCY] Add odolbeau/phone-number-bundle 2020-07-29 18:10:44 +00:00
Hugo Sales ae181ff6b4 [UTIL][NICKNAME][FIX] Add self to constant 2020-07-29 18:10:44 +00:00
Hugo Sales e19ee25660 [UI][USERPANEL] Add prefilled fields, mark some as optional and handle self tags in the profile settings page 2020-07-29 18:10:44 +00:00
Hugo Sales c95a7e36f9 [SELFTAGS] Add Profile::{set,get}SelfTags 2020-07-29 18:10:44 +00:00
Hugo Sales 04a5744b9f [FORM] Add Form::isRequired 2020-07-29 18:10:44 +00:00
Hugo Sales 583b28b65d [DATABASE] Refactor DB.php and make findBy always return an array, instead of a doctrine collection 2020-07-29 18:10:28 +00:00
Hugo Sales 06356d10b0 [UTIL] Update Formatting::{toString,toArray} to allow spliting by either space or comma 2020-07-29 17:58:07 +01:00
Alexei Sorokin 58b212e463 [SECURITY] Update way passwords are checked and update 2020-07-29 17:58:07 +01:00
rainydaysavings b2c2988e96 a marca mark[UI][ROUTES] Footer links and pages done 2020-07-29 17:57:42 +01:00
rainydaysavings 796b77ba6f [UI][ROUTES] Footer links added 2020-07-29 17:57:23 +01:00
rainydaysavings 088568fcde [UI] Fixing problem due to Firefox's autofill filter 2020-07-29 17:57:16 +01:00
rainydaysavings 8675782ae0 [UI] Login template small fix 2020-07-29 17:57:11 +01:00
rainydaysavings 0919bc4902 [UI] Left panel template and Login page CSS work done 2020-07-29 17:57:07 +01:00
Hugo Sales 17ccee08d1 [SECURITY][CONTROLLER] Remove unreachable code from the Security controller 2020-07-29 17:56:42 +01:00
Hugo Sales f6a750165f [CONTROLLER][ADMIN][CONFIG] Fix form to use static strings as keys and add labels seperately; convert input from string to appropriate type 2020-07-29 17:56:42 +01:00
Hugo Sales 1b006a1405 [LIB][Util] Update Common::setConfig to throw an exception if appropriate, add Formatting::{toString,toArray} 2020-07-29 17:56:28 +01:00
Hugo Sales 92e4cd2abc [I18N] Remove incomplete autogenerated translation file, to be fixed later 2020-07-29 17:56:28 +01:00
Hugo Sales 2b4ef43979 [AUTOGENERATED] Update all entity fields 2020-07-29 17:56:28 +01:00
Hugo Sales 1b01c32383 [SECURITY] Small refactor in Authenticator.php, to remove unused services 2020-07-29 17:56:15 +01:00
Hugo Sales 24027a884f [USER][UI][AUTHENTICATION] Add registration form 2020-07-29 17:56:15 +01:00
Hugo Sales 8b5b9cfd4f [UTIL][NICKNAME] Small refactor and remove the check between user nickname and group_alias, as these will have different semantics 2020-07-29 17:56:15 +01:00
Hugo Sales 34b2a1ad53 [DATABASE] Fix typos in user_notification_prefs 2020-07-29 17:56:15 +01:00
Hugo Sales 0134a75934 [DATABASE] Fix typo in profile table and add a constructor 2020-07-29 17:56:15 +01:00
Hugo Sales 908cae3af6 [FORM][WRAPPER] Merge argument options, not replace 2020-07-29 17:56:15 +01:00
Hugo Sales 1ccc41b244 [DATABASE] Update LocalUser table to not have a numerical id, add is_email_verified and fix getProfile accordingly 2020-07-29 17:56:15 +01:00
Hugo Sales cc89d4fa83 [MAILER][WRAPPER] Add mailer wrapper that respects the configuration 2020-07-29 17:56:15 +01:00
Hugo Sales f61635e181 [FIX] Fix bug in DATABASE.php, since findBy can return different types 2020-07-29 17:56:15 +01:00
Hugo Sales ddc7834069 [TOOLS] Update generate fields script to output default values 2020-07-29 17:56:15 +01:00
Hugo Sales 71f50d7f48 [DEPENDENCY] Add symfonycasts/verify-email-bundle 2020-07-29 17:56:15 +01:00
Hugo Sales b254a7efeb [COMMON][SECURITY][WRAPPER] Added security service static wrapper and Common::getUser 2020-07-29 17:56:15 +01:00
Hugo Sales 51ae3909a1 [CORE][ROUTES] Small refactor on entrypoint and RouteLoader 2020-07-29 17:55:58 +01:00
Hugo Sales 01bd7f9d51 [TWIG] Add twig function to output the active tag if the current route matches a given one 2020-07-29 17:55:58 +01:00
Hugo Sales 76638fc62e [CONTROLLER][ROUTES] Refactor the base Controller to not reinvent the wheel too much and rely on Symfony's events 2020-07-29 17:55:45 +01:00
Hugo Sales 3e0dc1c70c [ROUTES] Change name of admin and settings routes and refactor the way they're specified 2020-07-29 17:55:27 +01:00
Hugo Sales 66d4f323f0 [CONTROLLER][ROUTES] Refactor controllers to use the new base class and remove controller from the class name 2020-07-29 17:55:11 +01:00
Hugo Sales 7368e888f3 [NOTIFICATION][DATABASE] Update user notification prefs table, implementation of Notification and define a base class for notification transport 2020-07-29 17:55:11 +01:00
Hugo Sales bae43c9e7d [CONTROLLER] Remove example enqueue 2020-07-29 17:55:11 +01:00
Hugo Sales 33a22f9604 [DEFAULTS] Add password hashing algorithm default settings 2020-07-29 17:55:11 +01:00
Hugo Sales b7296c682e [LOGIN] Implement password checking and related systems 2020-07-29 17:55:11 +01:00
Hugo Sales fba1cd1d26 [USER] Add UserRoles 2020-07-29 17:55:11 +01:00
Hugo Sales fb7114c373 [DATABASE] Add role collumn to profile table 2020-07-29 17:55:11 +01:00
Hugo Sales f99d3d2be5 [UTIL] Update Common::config to ensure the values queried exist 2020-07-29 17:55:11 +01:00
Hugo Sales f70ee98e19 [DEFAULTS][FIX] Fix logic error that kept reloading the table when the file wasn't modified 2020-07-29 17:55:11 +01:00
Hugo Sales 77b9e3ed78 [UI][SESSION] Add login and logout pages 2020-07-29 17:55:11 +01:00
Hugo Sales c2ac90157e [LIB][Util] Remove Functional::arity as it got merged upstream as Functional\ary 2020-07-29 17:54:55 +01:00
Hugo Sales 5d80d80e72 [LIB][Util] Make Common::config return the unserialized value instead of the entity 2020-07-29 17:54:36 +01:00
Hugo Sales 18b05baf61 [CORE] Refactor GNUsocial.php so it initializes itself as a service 2020-07-29 17:54:22 +01:00
Hugo Sales 1b8ff83acb [I18N] Remove support for context until it proves necessary, as it broke the code 2020-07-29 17:54:22 +01:00
Hugo Sales 9c050f189f [TOOLS] Update shebang on scripts to use the correct php executable 2020-07-29 17:54:22 +01:00
Hugo Sales a1d374644f [AUTOGENERATED] Update autogenerated code 2020-07-29 17:54:22 +01:00
Hugo Sales 9ed9065f1b [DATABASE] Rename user table to local_user, since doctrine shits itself otherwise ._. 2020-07-29 17:54:22 +01:00
Hugo Sales 6e1fc64b53 [DEPENDENCY] Add symfony/config as a dependency 2020-07-29 17:54:22 +01:00
Hugo Sales 3c362c543e [CONFIG] Change way configuration is done to use Symfony's system instead of environment vars 2020-07-29 17:54:22 +01:00
Hugo Sales 0ced7e27a8 [CORE][I18n][DEFAULTS] Remove I18nHelper 2020-07-29 17:53:30 +01:00
Hugo Sales 84e958a574 [LIB][Util] Change methods in the Common class to camelCase, add isSystemPath (previously in Nickname.php) 2020-07-29 17:53:10 +01:00
Hugo Sales c8a60b683f [UTIL][NICKNAME] Import nickname utilities and exceptions from v2 2020-07-29 17:53:10 +01:00
Hugo Sales 7c5570e4f5 [DEFAULTS] Update default reserved usernames 2020-07-29 17:53:10 +01:00
Hugo Sales 8fd7d5e314 [DATABASE][WRAPPER] Add findBy method which allows finding entities with a complex expression 2020-07-29 17:53:10 +01:00
Hugo Sales 8db080fc07 [DATABASE] Re-import the local_group table, as it'll be used as per the new group semantics 2020-07-29 17:53:10 +01:00
rainydaysavings 6173dff860 [UI] Settings routes refactor, avatar and misc settings added. 2020-07-29 17:52:59 +01:00
rainydaysavings 6e62dcee46 [UI][CONTROLLER][ROUTES] UserPanel account page form added, account page CSS work 2020-07-29 17:52:39 +01:00
rainydaysavings 2df6b90c4c [UI] Fixed top header spacing issue, hamburger menu weird rendering 2020-07-29 17:52:33 +01:00
rainydaysavings dd64ec33b5 [UI] FAQ pages markdown fixes 2020-07-29 17:52:30 +01:00
rainydaysavings 8b163eaf25 [UI][CONTROLLER] Form help messages added, fixed checkbox trick hitbox 2020-07-29 17:52:14 +01:00
rainydaysavings 15a3989a63 [UI] Reset CSS added, small fixes all around 2020-07-29 17:52:08 +01:00
rainydaysavings c0de943975 [UI] Settings page CSS redesign port completed 2020-07-29 17:52:01 +01:00
rainydaysavings 53b1b79140 [UI][CONTROLLER][ROUTES] Corrected core action name, UserPanel CSS work 2020-07-29 17:51:28 +01:00
rainydaysavings da4c8b4a7f [UI] Fixed FAQ template issues 2020-07-29 17:51:24 +01:00
rainydaysavings 367878e096 [UI] Side panel animation added 2020-07-29 17:51:21 +01:00
rainydaysavings 544495797b [UI] Redesign responsiveness work done 2020-07-29 17:51:17 +01:00
rainydaysavings 3925a69228 [UI] Further work into new side panel design 2020-07-29 17:51:13 +01:00
rainydaysavings 82fd3586bc [UI] Basic implementation of the new base design 2020-07-29 17:51:07 +01:00
rainydaysavings e3bb0afb3b [UI] Polishing FAQ CSS 2020-07-29 17:51:02 +01:00
rainydaysavings af94469fec [UI] Standardization of sizes and variable usage for faster theming 2020-07-29 17:50:51 +01:00
rainydaysavings e11cc30ceb [UI][CONTROLLER] Profile settings action functionality working 2020-07-29 17:50:27 +01:00
Hugo Sales 941ded7c0c [DATABASE][WRAPPER] Update DATABASE wrapper so entity names are provided without the namespace 2020-07-29 17:50:27 +01:00
Hugo Sales 7c4b891694 [DOCKER] Add redis to the docker image 2020-07-29 17:50:27 +01:00
Hugo Sales ff50aa716f [CACHE] Fix usage of the redis extension 2020-07-29 17:50:27 +01:00
Hugo Sales eb7393a190 [DOCKER] Fix redis extension build process to use LZ4 and add APCu 2020-07-29 17:50:27 +01:00
Hugo Sales 5674c4a355 [DEPENDENCY] Add mock polyfill implementations of the redis and memcached extension 2020-07-29 17:50:27 +01:00
Hugo Sales 3554a99b86 [CACHE][Redis] Add special support for redis (fixed size lists), set method and general fixes 2020-07-29 17:49:55 +01:00
Hugo Sales da57dc7485 [LIB][Util] Refactor and implement array indexing methods on RingBuffer 2020-07-29 17:49:21 +01:00
Hugo Sales 7a5ad40f95 [DOCKER] Updated php image so redis is compiled with LZ4 compression available, as it's the fastest at decompressing and really fast at compressing. Read performance is more important, with this being used as a cache 2020-07-29 17:49:21 +01:00
Hugo Sales e575e30144 [CACHE] Add support for multiple pools with the syntax (as an example) SOCIAL_CACHE_ADAPTER='default=redis://localhost:6379,memcached://localhost:11211;db.config=apcu://' 2020-07-29 17:49:21 +01:00
Hugo Sales 8b7e6c9606 [DOCKER] Add msgpack and redis extensions to docker image 2020-07-29 17:49:21 +01:00
Hugo Sales fe790a444d [DEFAULTS] Add modified time to config table (as value) and only reload the defaults if the file is newer 2020-07-29 17:49:21 +01:00
Hugo Sales e901da1629 [CACHE] Extend the static wrapper to support working with lists in caches that don't natively support them 2020-07-29 17:49:21 +01:00
Hugo Sales f3b2f5bed5 [LIB][Util] Add Ring Buffer data structure 2020-07-29 17:46:55 +01:00
Hugo Sales 984192164f [DOCKER] Move certbot files to hidden folder, so it's ignored by GNU global 2020-07-29 17:46:55 +01:00
Hugo Sales 06cbcc480e [DEFAULTS][FIX] Fix defaults to use value from environment 2020-07-29 17:46:55 +01:00
Hugo Sales cfb689f477 [PHP][EXTENSION][POLYFILL] Add php-ds polyfill, which is used if the native extension is not available 2020-07-29 17:46:55 +01:00
Hugo Sales 9af77c0408 [DOCKER][PHP][EXTENSION] Add PHP ds extension to docker PHP image 2020-07-29 17:46:55 +01:00
Hugo Sales d6f0426883 [TOOLS][configure] Fix to use quotation marks properly 2020-07-29 17:46:06 +01:00
Hugo Sales bd211ba737 [CACHE][WRAPPER] Fix cache wrapper 2020-07-29 17:45:53 +01:00
Hugo Sales e376c66bd5 [FORMATTING][DEFAULTS] Fix formatting and remove redundant config defaults 2020-07-29 17:45:53 +01:00
Hugo Sales 8d8a4b56e3 [CACHE][HTTP] Configure simple HTTP cache 2020-07-29 17:45:53 +01:00
Hugo Sales bf4b7bd51b [CACHE] Add a static wrapper around symfony/cache 2020-07-29 17:45:53 +01:00
Hugo Sales f025cafac1 [DEPENDENCY] Add symfony/cache as a dependency 2020-07-29 17:45:53 +01:00
Hugo Sales 16d76dad5d [LOG][WRAPPER] Refactor log wrapper 2020-07-29 17:45:02 +01:00
Hugo Sales d1a04601a0 [QUEUE] Add queueing wrapper, default configuration and example usage 2020-07-29 17:45:02 +01:00
Hugo Sales ce7058eb28 [DEPENDENCY] Add symfony/messenger as a dependency 2020-07-29 17:45:02 +01:00
Hugo Sales 5d2eff4af6 [DATABASE] Delete queue_item table, as queueing will be handled by messenger 2020-07-29 17:45:02 +01:00
Hugo Sales 2fa82c9e6f [CONTROLLER] Show dummy notices in main/all 2020-07-29 17:45:02 +01:00
Hugo Sales caf40c1067 [MODULES] Make ModulesManager check if file exists 2020-07-29 17:40:59 +01:00
Hugo Sales 4ea62dbf7a [CONTROLLER] Add Controller base class, which handles rendering templates if requested HTML or json, accordingly 2020-07-29 17:40:59 +01:00
Hugo Sales c314e3e6d4 [ROUTE] Fix routes, config_admin got deleted 2020-07-29 17:40:59 +01:00
Hugo Sales ca79b7a0cd [COMMAND][DEPRECATION][FIX] Fix app:events's deprecation 2020-07-29 17:40:59 +01:00
Hugo Sales b53565cba5 [GIT] Update gitignore to ignore composer.local.json, where plugin settings will be placed 2020-07-29 17:40:59 +01:00
Hugo Sales f877850e31 [DEPENDENCY] Update all dependencies 2020-07-29 17:40:59 +01:00
Hugo Sales dbf940bfe6 [DEPENDENCY] Add wikimedia/composer-merge-plugin as a dependency, to allow managing plugins 2020-07-29 17:40:59 +01:00
rainydaysavings c8cd0523cc [DEPENDENCY] Add erusev/parsedown and twig/markdown-extra as dependencies 2020-07-29 17:40:59 +01:00
rainydaysavings d8f7f2431b [TWIG][CONFIG] Change default_path and add public_path 2020-07-29 17:40:59 +01:00
rainydaysavings 229bff8c21 eliseu bruh mark[UI][CONTROLLER][ROUTES] Small CSS fixes. 2020-07-29 17:40:24 +01:00
rainydaysavings bb1089a80a eliseu hope mark[UI][Mobile] Settings page responsive css work. 2020-07-29 17:39:53 +01:00
rainydaysavings 3ce611cbe7 [UI][CONTROLLER] Settings page styling almost done. 2020-07-29 17:39:25 +01:00
rainydaysavings 35e1b7cd16 eliseu shady mark[UI] Routes fixed, base template fix. 2020-07-29 17:38:45 +01:00
rainydaysavings 98c6513bfd eliseu nonsense mark[UI] Better use of icons, fixing static pages routing. 2020-07-29 17:37:42 +01:00
rainydaysavings f96b494be7 [FAQ] Removing unnecessary categories. 2020-07-29 17:37:03 +01:00
rainydaysavings 919a21a9cf [UI][FAQ] FAQ polish, better use of twig, responsive css. 2020-07-29 17:36:53 +01:00
rainydaysavings e55afd3e8f [UI][Mobile][FAQ][ROUTES] FAQ sub pages and routing added, small screen css work started. 2020-07-29 17:36:17 +01:00
rainydaysavings 0e0c45d35e eliseu split mark[UI] Header completed, FAQ almost done. 2020-07-29 17:36:01 +01:00
rainydaysavings c60a53a638 eliseu split mark[UI][FAQ] FAQ page progress, assets folder and assets added 2020-07-29 17:35:22 +01:00
rainydaysavings c59ea15a0f [UI][ROUTES][CONTROLLER] Settings pages routes and styling done. 2020-07-29 17:35:05 +01:00
rainydaysavings e921306cb3 [UI] Work started on profile settings page. 2020-07-29 17:31:07 +01:00
rainydaysavings d2b36d6115 [UI][Header] New header implemented. 2020-07-29 17:30:53 +01:00
rainydaysavings 9956714af3 Eliseu split mark[UI] CSS refactoring to better reflect blocks, work begun on profile settings page. 2020-07-29 17:29:22 +01:00
rainydaysavings 2254a4d639 Eliseu split mark [UI] Routes fixed, base template fix. 2020-07-29 17:28:55 +01:00
rainydaysavings 1084d9926e [UI][ROUTES] Better use of icons, fixing static pages routing. 2020-07-29 17:28:06 +01:00
rainydaysavings dd5b610a12 [UI][FAQ] Better FAQ organization, removing unnecessary categories. 2020-07-29 17:27:31 +01:00
rainydaysavings a1e6179752 [UI][Mobile][FAQ] FAQ polish, better use of twig, responsive css. 2020-07-29 17:26:58 +01:00
rainydaysavings 2e34f5727e [UI][Mobile][FAQ] FAQ sub pages and routing added, small screen css work started. 2020-07-29 17:25:54 +01:00
rainydaysavings db788dcff7 Eliseu split mark [UI] Header completed, FAQ almost done. 2020-07-29 17:25:00 +01:00
rainydaysavings 02060e20a5 [UI][FAQ] FAQ page progress, assets folder and assets added 2020-07-29 17:24:44 +01:00
rainydaysavings 1d6bfa1e5d [UI][FAQ] Controller and Route for FAQ page created as well as basic template structure 2020-07-29 17:23:58 +01:00
Hugo Sales 7e9d4b896a [TOOLS] Fix bootstrap and pre-commit scripts 2020-07-29 17:23:58 +01:00
Hugo Sales ce5892c68d [MODULE] Move 'foreign' entities from core to a module 2020-07-29 17:23:58 +01:00
Hugo Sales 223c10b6cf [AUTOGENERATED] Update autogenerated code 2020-07-29 17:23:58 +01:00
Hugo Sales 3509feaba2 [TOOLS] Update bin/generate_entity_fields script 2020-07-29 17:23:58 +01:00
Hugo Sales 34f4b92e34 [CORE][DATABASE] Replace zero dates with CURRENT_TIMESTAMP and add defaults to all 'created' or 'modified'
This commit is a port from v2's 9a515b9234 ([SCHEMA] Improve timestamp storage) to v3.

As explained by Alexei Sorokin:

Avoid the use of deprecated MariaDATABASE "zero dates" globally. If they're present
as attribute defaults somewhere, they will be replaced with NULL implicitly.
The existing "zero dates" in MariaDATABASE storage will be left intact and this
should not present any issues.

The "timestamp" type in table definitions now corresponds to DATETIME in
MariaDATABASE with "DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP", which
should be close enough to the original behaviour for compatibility purposes.
It is now the recommended type for "modified" attributes, because of the
update trigger on MariaDATABASE. But there is no such trigger implemented on
PostgreSQL as of this moment.
2020-07-29 17:19:35 +01:00
Hugo Sales 9e24b120fc [CORE][DATABASE] Restructure the database 2020-07-29 17:19:10 +01:00
Hugo Sales 8b05adb72c [ROUTE][ADMIN][CONFIG] Add route to update values in the config table 2020-07-29 17:19:10 +01:00
Hugo Sales 9f1ea4b417 [DEFAULTS] Small fixes and add check of SOCIAL_NO_RELOAD_DEFAULTS from the environment, to override the reloading of default values 2020-07-29 17:19:10 +01:00
Hugo Sales ded109dc92 [DOCUMENTATION] Fixed type annotations and documentation of Common::size_str_to_int 2020-07-29 17:19:10 +01:00
Hugo Sales 517541aeb6 [CORE][Event] Move GSEvent to Event, no longer a name collision 2020-07-29 17:18:51 +01:00
Hugo Sales ff0973b746 [FORM] Added Symfony Form wrapper 2020-07-29 17:18:51 +01:00
Hugo Sales 2608da6167 [CORE][Symfony] Fixed deprecation resultant from Symfony 5.1 upgrade
User Deprecated: Since symfony/framework-bundle 5.1: Using type
"Symfony\Component\Routing\RouteCollectionBuilder" for argument 1 of
method "App\Kernel:configureRoutes()" is deprecated, use
"Symfony\Component\Routing\Loader\Configurator\RoutingConfigurator"
instead.
2020-07-29 17:17:33 +01:00
Hugo Sales d45e170401 [TESTS][I18N] Added test for I18n::_m and I18nHelper::formatICU 2020-07-29 17:17:33 +01:00
Hugo Sales a2fa0595ca [I18N] Fix implementation of I18nHelper::formatICU 2020-07-29 17:17:33 +01:00
Hugo Sales 3544e0108a [ROUTES] Add easier support for using TemplateController and improved documentation 2020-07-29 17:17:33 +01:00
Hugo Sales ad5aca94b1 [I18N] Small fixes. Still broken, though :') 2020-07-29 17:17:33 +01:00
Hugo Sales b1e40180c4 [AUTOLOAD] Always autoload _m file 2020-07-29 17:17:33 +01:00
Hugo Sales 397f02d88c [DEPENDENCY] Upgrade Symfony framework from 5.0 to 5.1 2020-07-29 17:17:33 +01:00
Hugo Sales a5ca98f711 [DEPENDENCY][DEV] Added Symfony Bridge PHPUnit 2020-07-29 17:17:33 +01:00
Hugo Sales c017c132cb [GIT] Updated gitignore 2020-07-29 17:17:33 +01:00
Hugo Sales 0df2bc464e [I18N] Overhaul _m() implementation to support ICU message formats 2020-07-29 17:17:33 +01:00
Hugo Sales 585b1478a9 [I18N] Dumped english translation files 2020-07-29 17:17:33 +01:00
Hugo Sales 04064621dc [TOOLS] Small fix to composer install hook 2020-07-29 17:17:33 +01:00
Hugo Sales af0145c303 [I18N] Added ability to call _m_dynamic from any class, allowing it to define translations for dynamic-valued calls to _m 2020-07-29 17:17:33 +01:00
Hugo Sales abaa5839a8 [TOOLS] Improve configure script to disallow reserved database names 2020-07-29 17:17:33 +01:00
Hugo Sales 9e66eb347f [I18N] Custom translation extractor based on Symfony's PhpExtractor, since we use instead of 2020-07-29 17:17:33 +01:00
Hugo Sales 207e24aba8 [I18N] Refactor since rfc/use-static-function is not implemented
As the above mentioned RFC is not implemented, `_m` needs to be
outside of the I18n class, otherwise it would have to always be called
with `I18n::_m`.
2020-07-29 17:17:33 +01:00
Hugo Sales bae80ebd70 [ROUTES] Add static wrapper around Symfony's router 2020-07-29 17:17:33 +01:00
Hugo Sales b3327040f2 [CORE] Refactoring core 2020-07-29 17:17:33 +01:00
Hugo Sales d7f8793580 [UI][CONFIG] Added admin configuration form 2020-07-29 17:17:33 +01:00
Hugo Sales fd13e4fe7a [I18N] Fix i18n and add default domain 'Core' 2020-07-29 17:17:33 +01:00
Hugo Sales 7c6d429d24 [DEFAULTS] Fix default config loading logic 2020-07-29 17:17:33 +01:00
Hugo Sales 287d74ea57 [TOOLS] Fixed all licence blocks, to use the same, foldable, format 2020-07-29 17:17:33 +01:00
Hugo Sales e6736507ad [DEPENDENCY] Added alchemy/zippy, which adds support for multiple archive formats. Used to allow theme uploads in zip, tar, gz, or other formats 2020-07-29 17:17:33 +01:00
Hugo Sales 79094ec2a0 [DOCUMENTATION][DEFAULTS] Documented all defaults and updated some. Restructured other documentation. 2020-07-29 17:17:33 +01:00
Hugo Sales 2ebcb9212e [DEFAULTS] Remove deprecated defaults and convert them to snake_case 2020-07-29 17:17:33 +01:00
Hugo Sales ab950f07f5 [GIT] Added docker-compose to gitignore, in preparation for using a script to generate them 2020-07-29 17:17:33 +01:00
Hugo Sales d8580692c0 [DATABASE] Change the way defaults are loaded, bulk insert, reload everything in debug mode, only on http requests (not command line) 2020-07-29 17:17:33 +01:00
Hugo Sales 9f572c0caa [TOOLS] Update install scripts 2020-07-29 17:17:33 +01:00
Hugo Sales f4f4989945 [DATABASE] Fix 'relation config doesn't exist' 2020-07-29 17:17:33 +01:00
Hugo Sales 3ef284cd51 [DATABASE] Postgres doesn't understand '0000-00-00 00:00:00' for datetime, use '-infinity' 2020-07-29 17:17:33 +01:00
Hugo Sales 7c6e3ed864 [DOCKER] Change postgres data path to the correct one 2020-07-29 17:17:33 +01:00
Hugo Sales e6b5c83ca1 [DATABASE][CONFIG] Loading defaults into database, doctrine static wrapper 2020-07-29 17:17:33 +01:00
Hugo Sales 5eb59cebc3 [DATABASE][CONFIG] Bring default configs from V2 and implement DATABASE wrapper 2020-07-29 17:17:33 +01:00
Hugo Sales 828c00a789 [ASSETS] Import old favicon.ico 2020-07-29 17:17:33 +01:00
Hugo Sales 355d94c70c [CORE][UTIL] Moved classes from util to core
And splitted up Common
2020-07-29 17:17:33 +01:00
Hugo Sales 629dc7b3ac [FORMATTING] Cherry-pick of Diogo's 763ac735c0758624ebd5957993dc0676b865927a 2020-07-29 17:14:36 +01:00
Diogo Cordeiro dfa47f5ee2 [DOCKER][BOOTSTRAP] Add option to use a self signed cert 2020-07-29 17:14:36 +01:00
Diogo Cordeiro b195646635 [DOCUMENTATION][TOOL] Small bug fixes and docblock elaboration 2020-07-29 17:12:37 +01:00
Hugo Sales a43d97f0c0 [CORE] Rename GNU social constants 2020-07-29 17:12:36 +01:00
Hugo Sales d4de595cad [DOCUMENTATION] Updated INSTALL.md to reflect the fact that a CNAME record can be used directly 2020-07-29 17:12:36 +01:00
Hugo Sales 27c61a203e [DOCUMENTATION] Import installation instructions for installing without docker from V2 2020-07-29 17:12:36 +01:00
Hugo Sales d2b7c5efbc [DOCKER] Small fixes to docker setup, imported from V2 2020-07-29 17:12:36 +01:00
Hugo Sales eb29dc6305 [DOCUMENTATION] Added a code walkthrough document, which explains how the codebase works 2020-07-29 17:12:36 +01:00
Hugo Sales faba609bfd [DOCUMENTATION] Added install documentation 2020-07-29 17:12:36 +01:00
Hugo Sales 490daef73b [TOOLS] Updated install script to also support mariadb 2020-07-29 17:12:36 +01:00
Hugo Sales 18d8484fad [TOOLS][DOCKER] Further fixes in the docker environment and fixed the install script 2020-07-29 17:12:36 +01:00
Hugo Sales 5b7778ab1d [DOCKER] Fixed docker environment to properly configure the app environment 2020-07-29 17:12:36 +01:00
Hugo Sales 11dc95cf66 [TOOLS] Added script to configure the installation and to bootstrap certificate creation with Let's Encrypt 2020-07-29 17:12:36 +01:00
Hugo Sales 45bd7ad3a0 [TOOLS][SSL] Added bin/boostrap_certificates.sh, allowing for easy configuration of SSL certificates with Let's Encrypt 2020-07-29 17:12:36 +01:00
Hugo Sales e72dde7b4b [TOOLS][DOCUMENTATION] Improvements to entity generation script 2020-07-29 17:12:36 +01:00
Hugo Sales 178742e09a [DOCUMENTATION] Added generated diagram 2020-07-29 17:12:36 +01:00
Hugo Sales 9fcbaf2b94 [DOCUMENTATION][TOOLS] Wrote a tool to generate entity diagrams from the database definition 2020-07-29 17:12:36 +01:00
Hugo Sales b1f6e40dde [UTIL] Wrote HTML library to convert arrays to html 2020-07-29 17:12:11 +01:00
Hugo Sales 760e892952 [GITIGNORE] Add file folder to gitignore 2020-06-30 18:45:01 +00:00
Hugo Sales ea9042be52 [DATABASE] Changed the type of the 'id' field of the ProfileList table from serial to int, as doctrine complains otherwise 2020-06-30 18:45:01 +00:00
Hugo Sales 8903d21a27 [TOOLS][CS-FIX] Altered some php-cs-fix rules 2020-06-30 18:45:01 +00:00
Hugo Sales c307ec8ffa [DATABASE][AUTOCODE] Update autocode to use \DateTimeInterface instead of DateTime 2020-06-30 18:45:01 +00:00
Hugo Sales 3cea097fee [TOOLS] Fix the generate_entities_fields script 2020-06-30 18:45:01 +00:00
Hugo Sales ef996f91be [SCHEMADEF] Bug fixes 2020-06-30 18:45:01 +00:00
Hugo Sales efbbf84549 [DATABASE] Add missing table names 2020-06-30 18:45:01 +00:00
Hugo Sales 56bff81534 [MODULES] Fix small error in modules manager 2020-06-30 18:45:01 +00:00
Hugo Sales 82b41ffffb [DATABASE][AUTOCODE] Autogenerated fields, setters and getters for each entity 2020-06-30 18:45:01 +00:00
Hugo Sales 3bd13005c4 [TOOLS][AUTOCODE] Fixed generate_entities script 2020-06-30 18:45:00 +00:00
Hugo Sales c35fbf6280 [TOOLS] Change autocode tag to allow editor folding 2020-06-30 18:45:00 +00:00
Hugo Sales fe9109b9fe [DATABASE] Removed calls to common_config 2020-06-30 18:45:00 +00:00
Hugo Sales 8a9ef01010 [FORMATTING] Changed license block format to allow folding 2020-06-30 18:45:00 +00:00
Hugo Sales 022adb0b20 [DATABASE] Extracted schemaDef method from old files and refactored onto new files 2020-06-30 18:44:57 +00:00
Hugo Sales e11ba5efc8 [COMMON] Added toCamelCase and toSnakeCase functions 2020-06-30 18:35:43 +00:00
Hugo Sales 09516621d7 [TOOLS] Add script used to port from old class files to entities 2020-06-30 18:35:43 +00:00
Hugo Sales cc8481eb8d [CORE][DATABASE] Import old classes folder into src/Entity 2020-06-30 18:35:43 +00:00
Hugo Sales ebb5b81210 [DATABASE] Remove testing entity 2020-06-30 18:35:43 +00:00
Hugo Sales a04f2a2424 [TOOLS] Add command which imports a file with it's history 2020-06-30 18:35:43 +00:00
Hugo Sales 1a125c5f36 [MODULES] Rename extensions to modules, add example plugin, change plugin location 2020-06-30 18:35:43 +00:00
Hugo Sales 7062924993 [DOCUMENTATION] Document All The Things! 2020-06-30 18:35:43 +00:00
Hugo Sales d6a73be313 [CORE][ROUTES] Implemented custom router, with an interface similar to the old one, which allows routes to be seperated into files 2020-06-30 18:35:43 +00:00
Hugo Sales 7e9d650909 [COMMAND][EVENTS] Added command to list events and handlers, and search by regex 2020-06-30 18:35:43 +00:00
Hugo Sales 985bfef507 [CORE][COMMAND] Register internal structures on command event 2020-06-30 18:35:43 +00:00
Hugo Sales 4d3d556cd0 [CORE][EXTENSIONS] Added extension (modules, plugins) loading and test plugin, which is able to handle events 2020-06-30 18:35:43 +00:00
Hugo Sales 74c0414d36 [CORE][SCHEMADEF] Clean up SchemaDef compiler pass 2020-06-30 18:35:43 +00:00
Hugo Sales 3779a5d9e1 [CS-FIXER] Updated cs-fixer rules and added a temporary exception to the src/Entity folder (awaiting pr merge) 2020-06-30 18:35:43 +00:00
Hugo Sales 251d7870d2 [DOCTRINE][SCRIPT] Created a script to generate the class fields and accessors from the schema definition 2020-06-30 18:35:43 +00:00
Hugo Sales d2022f6efd [DOCTRINE][SCHEMADEF] Small refactoring 2020-06-30 18:35:43 +00:00
Hugo Sales c3f7fabb19 [CORE][DOCTRINE] Implement SchemaDefDriver, which transforms the old syntax from to doctrine's metadata 2020-06-30 18:35:43 +00:00
Hugo Sales 1edb12d68b [DOCTRINE] Configure cli-config for doctrine console and ensure DATABASE is set to UTF-8 2020-06-30 18:35:43 +00:00
Hugo Sales cd8d699888 [DOCTRINE][SCHEMADEF] Create a new metadata driver to allow us to continue using static schemaDef functions
This has the benefit of requiring fewer code changes, as well as providing a better isolation
between GNU social and symfony, useful in case the framework needs to be changed
2020-06-30 18:35:43 +00:00
Hugo Sales 3a6f4b0c6b [COMPOSER] Update composer dependencies 2020-06-30 18:35:43 +00:00
Hugo Sales 522480989a [CORE][I18N] Fix the translation system 2020-06-30 18:35:43 +00:00
Hugo Sales 683611b9bf [CORE][I18N] Port the translation system to rely on symfony's 2020-06-30 18:35:43 +00:00
Hugo Sales 7e350c96bc [CORE][EVENTS] Bring existing Events and Boostrapper back
- Adapt the existing event system to rely on Symfony's event dispatcher
2020-06-30 18:35:43 +00:00
Hugo Sales 17cd375947 [CORE][ROUTES] Example route 2020-06-30 18:35:43 +00:00
Hugo Sales b91ac960ca [DOCKER] Updated dockerfile to add memcached 2020-06-30 18:35:43 +00:00
Hugo Sales 6ceccae177 [DOCKER] Added preliminary docker container 2020-06-30 18:35:43 +00:00
Hugo Sales 875c87ab2f [COMPOSER] Update composer packages 2020-06-30 18:35:43 +00:00
Hugo Sales a0458057cf [V3] Big Bang
Beginning anew, this time with a modern framework: symfony
2020-06-30 18:35:43 +00:00
Hugo Sales 26d3748c78 [V3] Big Crunch
And so, just as it begins, so too must it end
One should not dwell and stall, for more is to come
2020-06-30 18:35:39 +00:00
Alexei Sorokin 9a515b9234 [SCHEMA] Improve timestamp storage
Avoid the use of deprecated MariaDB "zero dates" globally. If they're present
as attribute defaults somewhere, they will be replaced with NULL implicitly.
The existing "zero dates" in MariaDB storage will be left intact and this
should not present any issues.

The "timestamp" type in table definitions now corresponds to DATETIME in
MariaDB with "DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP", which
should be close enough to the original behaviour for compatibility purposes.
It is now the recommended type for "modified" attributes, because of the
update trigger on MariaDB. But there is no such trigger implemented on
PostgreSQL as of this moment.
2020-06-29 01:41:46 +03:00
Alexei Sorokin b924c180ae [DATABASE] Fix MariaDB schema verification 2020-06-28 20:05:11 +03:00
Diogo Cordeiro 737f3eb553 [ActivityPub][HTTPSignatures] Fix verify 2020-06-28 00:58:16 +01:00
Diogo Cordeiro 6e3954f3bb [ActivityPub][Inbox] Signature verification after Actor update would always fail 2020-06-28 00:49:55 +01:00
Diogo Cordeiro 4544f29832 [AVATAR] Ensure this Action stays secure 2020-06-28 00:11:47 +01:00
Hugo Sales 477c357f11 [MEDIA] Move AttachmentAction::sendFile to common_send_file
This fixed the wrong content type and status code returned by the Avatar action
2020-06-27 23:23:10 +01:00
Diogo Cordeiro 7869a7c1b0 [ActivityPub][Inbox] With PHP 7.3 we don't need get_all_headers workaround anymore
Furthermore, it was broken on Apache2 because the actual function
doesn't put the resulting array's key in lowercase.
2020-06-27 20:43:43 +01:00
Alexei Sorokin edc7159ef6 [Memcached_DataObject] Check if it is possible to sort efficiently 2020-06-27 11:22:19 +03:00
Diogo Cordeiro 1db6943702 [ActivityPub][Inbox] get_all_headers was nginx only 2020-06-26 14:08:47 +01:00
Diogo Cordeiro e8dff6c4a0 [TESTS] Move AcceptHeader from ActivityPub plugin to Core
Delete temporary ActivityPub tests (they were to be deleted long ago)
2020-06-25 15:50:12 +01:00
Diogo Cordeiro 23ed816035 [ExtendedProfile] Fix XML type bug 2020-06-24 21:44:25 +01:00
Diogo Cordeiro 324b7f38a9 [FORMAT] Run php-cs-fixer on tests/ 2020-06-24 13:55:10 +01:00
Diogo Cordeiro aa7aff3f6b [TESTS] Fix CommandInterpreterTest
Also corrected a bad refactoring that affected Xmpp plugin test
2020-06-24 13:54:38 +01:00
Diogo Cordeiro 236929a166 [PEAR] I'm tired of this issue still popping up, this seems to silence it 2020-06-24 13:08:58 +01:00
Diogo Cordeiro 953e243639 [UI] Make neo-quitter default theme 2020-06-21 00:34:55 +01:00
Diogo Cordeiro 338d53c982 [XML] Inscrease types strictness 2020-06-21 00:34:54 +01:00
Diogo Cordeiro 37ebcc509b [AVATAR] Temporary ImageFile wasn't 2020-06-21 00:34:27 +01:00
Diogo Cordeiro f9be6f9a85 [AVATAR] Try to delete tmp avatar if something goes wrong during the process 2020-06-20 14:47:35 +01:00
Diogo Cordeiro 2cc2b5b856 [MEDIA] ImageFile fromUpload method wasn't ensuring uploaded file was an image 2020-06-20 14:47:33 +01:00
Alexei Sorokin 194976135f [DATABASE] Some query improvements
Make common_sql_weight employ standard SQL functions for the timestamp
difference in seconds.
Also replace UTC_TIMESTAMP in the MariaDB-specific part with CURRENT_TIMESTAMP
as it is the only occurence and GNU social sets UTC as a default timezone.

In a delete_orphan_files.php script simplify the main query considerably.

In clean_profiles.php stop using COUNT as if it is ANY, that is unnecessary
punishment for the database. Instead implement the anti-join with a
left outer join.

In Autocomplete and Activitypub_profile use joins instead of a WHERE OR
anti-pattern for the semi-joins.

In lib/ui/galleryaction.php replace a CROSS JOIN with an INNER JOIN.

In actions/sup.php remove a redundant subquery: WHERE is applied before
grouping either way.
2020-06-10 16:52:00 +03:00
Alexei Sorokin ef17f3ea7d [CORE][DATABASE] Another approach to semi-join in the inboxnoticestream query
Compared to the solution with INNER JOIN this seems to have better performance
as there is no need to deduplicate the subquery result before use.
2020-06-10 14:21:47 +03:00
Alexei Sorokin 0eec6fcfb6 [DATABASE] Replace NOW() with CURRENT_TIMESTAMP 2020-06-09 20:26:06 +03:00
Alexei Sorokin 09a772419a [DATABASE] Use "<>" as an SQL non-equality sign in more cases
A follow-up to commit 644b417f6c
2020-06-08 18:31:22 +03:00
Alexei Sorokin 6c035d01d4 [DATABASE] Start transactions with START TRANSACTION
"BEGIN" is non-standard and unnecessary.
2020-06-08 12:25:01 +03:00
susdiv 97bddc4537 [Autocomplete] Fix postgres incompatible query in AutocompleteAction 2020-06-05 19:14:37 +00:00
susdiv 684675bd84 [SCRIPTS] Fix postgres incompatible query in clean_profiles.php 2020-06-05 17:57:22 +00:00
susdiv b8c0fa9fa0 [ActivityPub] Fix Postgres incompatible query in Following and Followed collection 2020-06-05 17:48:21 +00:00
Diogo Cordeiro 9e7794cd66 Merge branch 'nightly' of rainydaysavings/gnu-social into nightly 2020-06-03 00:08:53 +00:00
rainydaysavings 92ad44abf9 [THEME][neo-quitter] Added icon for Network in navbar 2020-06-03 00:59:22 +01:00
Hugo Sales 7e83ddf80e [FIX] Fix 'Trying to access array offset on value of type null' in AntiBrutePlugin and SimpleCaptchaPlugin when using scripts 2020-05-24 16:55:37 +00:00
tenma a9be720f09 [OStatus] Remove TFN's deprecated Census event and fix small typo in the code 2020-05-09 11:50:26 +01:00
tenma d7906f113e [ActivityPub] Remove TFN's deprecated Census event 2020-05-09 11:50:26 +01:00
tenma 01dcaefcfb [TheFreeNetwork] Use config + module settings for initialization and online lookup
The Census event is now replaced with module settings for populating the
protocols array. With this we can shutdown some plugins and still make
them be checked by TFN.

The performance:high config is now added when deciding whether or not to
do online lookup after the offline lookup fails.

default:
- Add default values for the TFN protocol setting

EVENTS:
- Remove Cencus event

TheFreeNetworkModule
- Remove Census event handler, update protocols array to use module's settings
- Use performance:high config when deciding to do online lookup
2020-05-09 11:50:26 +01:00
tenma cfba91ea43 [OStatus] Add TheFreeNetwork module's support in handling profile insertion
Ostatus_profile:
- Update createActivityObjectProfile to trigger TFN's assistance in inserting the profile
2020-05-09 11:50:26 +01:00
tenma 134b6f6478 [ActivityPub] Add TheFreeNetwork module's support in handling profile insertion
Activitypub_profile:
- Update do_insert to trigger TFN's assistance in inserting the profile

explorer:
- Use the new LRDD's method for grabbing profile aliases
2020-05-09 11:50:25 +01:00
tenma 64104cb182 [TheFreeNetwork] Handle new StartTFNLookup and EndTFNLookup events
EVENTS:
- describe new events

TheFreeNetworkModule:
- add event handlers and necessary auxiliary methods
- minor comment updates
2020-05-09 11:50:25 +01:00
tenma 9aedcc7997 [OStatus] Update salmonaction to use the new LRDD's method for grabbing aliases 2020-05-09 11:50:25 +01:00
tenma 35547e28ea [LRDD] Add a new method for grabing profile aliases 2020-05-09 11:50:25 +01:00
tenma c6543e1f95 [ActivityPub] Autofix profile URIs through alias discovering
Activitypub_profile:
- Add updateUri method

explorer:
- Add grab_aliases method
- Update grab_local_user's online course to grab and test aliases
2020-05-09 11:50:25 +01:00
Alexei Sorokin 2183875e9e [UI] Fix group member pages showing up twice 2020-05-05 16:49:21 +03:00
Alexei Sorokin e5ee069f4a [UI] Order groups in join descending order in profiles 2020-05-05 16:25:02 +03:00
Hugo Sales 6c844315aa [CORE] Fix 'Array and string offset access syntax with curly braces is deprecated' in AuthCryptModule and DirectionDetectorPlugin 2020-05-04 10:47:23 +00:00
Alexei Sorokin 872bb1388d [Nodeinfo] Count active users for full days and without silenced 2020-04-17 18:13:05 +03:00
Alexei Sorokin 42aa255152 [CORE] Re-format the inboxnoticestream query 2020-04-08 15:25:30 +03:00
Diogo Cordeiro e58188d136 [UI] Small improvement on attachment's visual 2020-04-07 13:28:34 +01:00
Diogo Cordeiro bb32c0af3b [SensitiveContent] Fix plugin settings
Also reformatted the code and minor bug fixed it
2020-04-07 13:28:29 +01:00
nee 63fd2c7037 [SensitiveContent] Add option to activate for not-logged-in visitors
Remove redundant setting retrival code.

An example config.php entry to activate the new config:
$config['site']['sensitivecontent']['hideforvisitors'] = true;
2020-04-07 02:59:35 +01:00
nee 520a2ba202 [SensitiveContent] Don't crash in GNU social classic
When an attachment has no thumbnail (for example when it's a video).
2020-04-07 02:59:30 +01:00
Hugo Sales 13e8445083 [SensitiveContent] Fix bug where having this plugin activated would not size thumbnails correctly 2020-04-07 02:59:24 +01:00
Hugo Sales d1c70cb13b [CORE] Make avatars be served with the same mechanism as attachments 2020-04-06 21:14:11 +00:00
Diogo Cordeiro 6898cff623 [PLUGINS] Remove VideoThumbnails not useful anymore 2020-04-03 12:20:27 +01:00
Diogo Cordeiro f4558e3c41 [ActivityPub] Fix profile url handling 2020-03-28 03:16:24 +00:00
tenma d24075b1c5 [INSTALL] Allow the setup of sslproxy during install time
install.php:
installer.php:
- add option field and handle logic

display.css:
- hardcode ssl's label margin-top value so all options are correctly displayed
2020-03-15 21:37:37 +00:00
tenma a8c2a9da3a [DOCUMENTATION] Add further notes to the nginx sample config 2020-03-12 18:03:48 +00:00
tenma 8041df7d41 [DATABASE] Fix deprecated call to implode() 2020-03-12 17:44:50 +00:00
Diogo Cordeiro 073a181778 [ActivityPub] Fix undefined tag index 'type' in Activitypub_notice 2020-02-14 17:25:26 +00:00
Diogo Cordeiro bec6fdc66a [NOTICES] Add data-nosnippet attribute for notices by remote profiles 2020-01-09 19:49:49 +00:00
Diogo Cordeiro 6833c9f1c2 [SHOWSTREAM] Add robots meta-tag for remote profiles 2020-01-09 17:02:26 +00:00
Diogo Cordeiro 18ade30185 [FORMAT] Ran php-cs-fixer on the handlers of notice items and streams
This was to keep the following two commits readable
- actions/showstream.php
- actions/userbyid.php
- lib/modules/ActivityHandlerModule.php
- lib/modules/ActivityHandlerPlugin.php
- lib/notices/conversationnoticestream.php
- lib/notices/noticelistitem.php
- lib/notices/noticestream.php
- lib/notices/threadednoticelistitem.php
2020-01-09 21:41:34 +00:00
Alexei Sorokin e7ab305335 [CORE] Use monotonic time via hrtime() where applicable
The realtime clock is not reliable when calculating elapsed time.
2020-01-07 19:48:13 +03:00
Alexei Sorokin 110d3a453a [Embed][CORE] Validate the hexadecimal for hex2bin properly 2020-01-07 17:30:18 +03:00
Alexei Sorokin f5aeab39b4 [PEAR DB_DataObject] Make static methods in Cast actually static 2020-01-07 17:16:07 +03:00
Diogo Cordeiro e7738895ce [DOCUMENTATION] Updated TODO and branches info 2019-12-23 15:39:26 +00:00
Diogo Cordeiro 60446dfc20 [CORE] Better queues defaults 2019-12-11 02:23:37 +00:00
Diogo Cordeiro dc211c9c44 [ActivityPub][Postman] Fix not sending notices to self 2019-12-11 01:30:25 +00:00
Diogo Cordeiro 27babac6dc [Ostatus] Partially revert 69add504e6
updateuris isn't needed after alll, we should solve this with TFNM and existing infrastructure.
2019-12-11 01:30:15 +00:00
Diogo Cordeiro 3e2b7cddc8 [ActivityPub][RSA] Revision, increase type scrictness and improve docs 2019-12-10 23:51:40 +00:00
Diogo Cordeiro 80ba2b3ccc [ActivityPub] Properly handle Actor URIs by using events correctly
This should fix nulls on explorer lookups inputed by postman after generate_followers/getSubscribers, that I think were caused by calling common_profile_uri that, curiously, only handles local profiles
2019-12-10 23:50:56 +00:00
Diogo Cordeiro b730582336 [CORE] Add GNUSOCIAL_ENGINE_REPO_URL and increase usage of GNUSOCIAL_ENGINE_URL 2019-11-21 00:21:22 +00:00
Alexei Sorokin 1b429dd2e5 [API] Show a nicer no such user error on statusnet/groups/list_all 2019-11-16 22:12:42 +03:00
Alexei Sorokin 448404e45c [SCRIPTS] Fix resend_confirm_address.php
Fix a regression from 6ec72b2978,
check if an address is set when using --email.
2019-11-16 21:22:46 +03:00
Alexei Sorokin 562d84c375 [Xmpp] Adjust type declarations for changes in XMPPHP 2019-11-16 20:44:18 +03:00
Diogo Cordeiro f09e3362aa [COMPOSER] update 2019-11-16 16:51:01 +00:00
Diogo Cordeiro 51b5b1c08c [ActivityPub][RSA] Fix types of generate_keys 2019-11-16 15:32:49 +00:00
Diogo Cordeiro ca2dde9a41 [ExtendedProfile] Fix updates and allow to delete values 2019-11-03 19:49:10 +03:00
Alexei Sorokin 6674d1ed0f [NodeInfo][DATABASE] Adjust indices of the "notice" and "user" tables
On big databases these queries from the Nodeinfo plugin choked up:

SELECT profile_id FROM notice
  WHERE notice.created >= (CURRENT_DATE - INTERVAL '180' DAY)
  AND notice.is_local = 1;
SELECT id FROM "user"
  WHERE "user".created >= (CURRENT_DATE - INTERVAL '180' DAY);
2019-11-03 18:57:03 +03:00
Diogo Cordeiro 2a10dffff8 [UI] Fix a small typo 2019-11-03 15:53:11 +00:00
Diogo Cordeiro e0b17fc97d [REALTIME] Reviewed both the superclass and its dist plugins 2019-11-03 15:37:49 +00:00
Alexei Sorokin 52800c3a65 [DATABASE] Remove profile_tag_tag_fkey
profile_list.tag is not supposed to be unique,
this also reverts the addition of profile_list_tag_key.
2019-11-02 14:32:48 +03:00
Alexei Sorokin 9124617055 [Xmpp] Latin-1 space characters are not forbidden for XMPP resources
Also use mb_strlen() with the 8bit encoding to count octets, strlen() is not as
reliable (mbstring.func_overload).
2019-11-02 13:54:26 +03:00
Alexei Sorokin b312712d1b [Xmpp] Use UnexpectedValueException in splitJid, a bit narrower 2019-11-02 13:29:00 +03:00
Alexei Sorokin 5bc1b8695e [DATABASE] Disable 'NULL' strings evaluation as SQL NULLs
Use $object->sqlValue('NULL') (identical to DataObject_Cast'ing) instead and
fix related issues like (email|sms)settings considering these NULLs as a
false positive for the E-Mail address still being set when it's been removed.

There could also be security implications to the now-disabled approach of
considering 'NULL' strings as SQL NULLs.
2019-11-02 12:21:43 +03:00
Diogo Cordeiro d921f3dadb [ActivityPub] New URI system 2019-11-10 17:47:51 +00:00
Diogo Cordeiro c154712012 [PEAR DB_DataObject] Removed DB_DATAOBJECT_NO_OVERLOAD as we don't have support for either PHP 4 or 5 2019-11-03 00:43:21 +00:00
tenma 3634af3fdc [TheFreeNetwork] First code: Module class and census event 2019-11-03 00:43:21 +00:00
tenma 1df9ec9f0f [SCRIPTS] Add updateuris script
To fix user URIs to their non-fancy version
2019-11-03 00:43:21 +00:00
tenma ae54a94d41 [CORE] Update common_user_uri
To be consistent between federated-protocols and maintain non-fancy URIs
2019-11-03 00:43:21 +00:00
tenma 69add504e6 [OStatus] Add script for profile deduplication and URI fixing 2019-11-03 00:43:21 +00:00
tenma a0d30b6872 [ActivityPub] Fix some small known problems
ActivityPubPlugin:
- Rework onProfileDeleteRelated to account for the tables _rsa and _pending_follow_requests
- Update onEndShowAccountProfileBlock to stop creating the ap_profile if it doesn't exist (we'll handle this in a different manner)

Activitypub_profile:
- Remove unnecessary code from from_profile method and add return type information

Explorer:
- Update travel_collection to call itself instead of _lookup, that was wrong
2019-11-03 00:43:21 +00:00
Alexei Sorokin a06b33be66 [AnonymousFave][DATABASE] Set the created timestamp on INSERT 2019-11-01 16:09:09 +03:00
Alexei Sorokin fe3e33e702 [DAEMONS][TwitterBridge] Set PUBLICDIR 2019-11-01 15:27:36 +03:00
Alexei Sorokin 3f56459734 [COMPOSER] Remove some pre-composer remnants from the code 2019-11-01 14:19:42 +03:00
Alexei Sorokin 4903241e4b [DOCUMENTATION][NGINX conf] snippets/fastcgi-php.conf is Debian-specific 2019-11-01 08:52:21 +03:00
Alexei Sorokin 85be003cf5 [Embed][CORE] hex2bin should always get an even amount of symbols 2019-11-01 08:29:52 +03:00
tenma bddc1c0f9d [ActivityPub] Fix successive "Cannot use object of type stdClass as array" errors in the postman 2019-11-01 02:23:39 +00:00
tenma 01f6d83b86 [MODULES] Fix VERSION constant to MODULE_VERSION in various modules 2019-10-30 23:52:14 +00:00
Diogo Cordeiro aa994ee4fb [CORE] Allow to force non-fancy URLs
Essential to allow toggling fancy urls later. In some cases it is
critical to keep the URL an unique URI.
2019-10-27 17:40:37 +00:00
Diogo Cordeiro d058a70557 [MEDIA] Simplify Attachment actions 2019-10-19 02:57:32 +01:00
Diogo Cordeiro 7298468df7 [FILE] Fix Return value of File::getFileOrThumbnailSize() must be of the type int, null returned 2019-10-19 01:16:37 +01:00
Diogo Cordeiro 63caa5044d [LIB_REFACTOR] Fix minor issues 2019-10-19 00:51:52 +01:00
tenma 2ae93dbec6 [ActivityPub] Revert usage of bitwise-operator & in the inbox_handler class. 2019-10-17 20:25:00 +01:00
Diogo Cordeiro b434bead2c [ActivityPub] The protocol allows content to be null, GNU social doesn't, we'll reject silentiously
Reported by kaniini
2019-10-11 19:09:12 +01:00
Diogo Cordeiro 6284b155b8 [ActivityPub] attributedTo itself is not required, if not present then it should be inferred from the actor
Reported by kaniini
2019-10-11 17:51:20 +01:00
Diogo Cordeiro b12c2d17d5 [ActivityPub] Fix security issue concerning remote profile deletes
Reported by kaniini
2019-10-11 17:41:43 +01:00
Diogo Cordeiro 5fb1e26a4c [ActivityPub] Inbox Handler: Remove old guzzle import
Improve exception information in doc blocks
2019-10-11 17:18:50 +01:00
Diogo Cordeiro 6423750250 [ActivityPub] Slightly increase robustness on exception handling
Also ported Activitypub_rsa to PHP7
Minor indentation fixes
2019-10-11 17:08:41 +01:00
Diogo Cordeiro d9b5ef1cee [ActivityPub] Consistent headers in explorer requests
Minor indentation fixes
2019-10-11 16:00:14 +01:00
Miguel Dantas f1717bde51 Fix 'Call to a member function getPayload() on null'
Trying to enable the RedisCache with the latest nightly, getting this with the daemon:

sep 25 11:40:18 friedrich startdaemons.sh[21428]: PHP Fatal error:  Uncaught Error: Call to a member function getPayload() on null in /var/www/social/plugins/RedisCache/RedisCachePlugin.php:96
sep 25 11:40:18 friedrich startdaemons.sh[21428]: Stack trace:
sep 25 11:40:18 friedrich startdaemons.sh[21428]: #0 /var/www/social/lib/util/event.php(89): RedisCachePlugin->onStartCacheSet('gnusocial:herds...', Object(HubSub), NULL, 86400, false)
sep 25 11:40:18 friedrich startdaemons.sh[21428]: #1 /var/www/social/lib/cache/cache.php(202): Event::handle('StartCacheSet', Array)
sep 25 11:40:18 friedrich startdaemons.sh[21428]: #2 /var/www/social/classes/Memcached_DataObject.php(520): Cache->set('gnusocial:herds...', Object(HubSub))
sep 25 11:40:18 friedrich startdaemons.sh[21428]: #3 /var/www/social/classes/Memcached_DataObject.php(52): Memcached_DataObject->encache()
sep 25 11:40:18 friedrich startdaemons.sh[21428]: #4 /var/www/social/classes/Managed_DataObject.php(50): Memcached_DataObject::getClassKV('HubSub', 'hashkey', 'a38b9dc516371af...')
sep 25 11:40:18 friedrich startdaemons.sh[21428]: #5 /var/www/social/plugins/OStatus/classes/HubSub.php(47): Managed_DataObject::getKV('hashkey', 'a38b9dc516371af...')
sep 25 11:40:18 friedrich startdaemons.sh[21428]: #6 /var/www/social/plugins/OStatus/lib/hubprepqueuehandler.php(68): HubSub::getByHashkey('https://herds.e...', 'https://raki.so...')
sep 25 11:40:18 friedrich startdaemons.sh[21428]: #7 /var/www/social/plugins/RedisQueue/classes/RedisQueueManager.php(58): HubPrepQueueHandl in /var/www/social/plugins/RedisCache/RedisCachePlugin.php on line 96
Sign in to j
2019-09-26 11:29:31 +01:00
Miguel Dantas c6f4f40bba [Embed][CORE] Fixes 'Invalid Filename' on Embed. Regex didn't get updated 2019-09-26 11:29:31 +01:00
Alexei Sorokin 65f1b1e1e3 Fix minor git merge resolving issues 2019-09-18 17:43:00 +03:00
Alexei Sorokin ad91ef66bd [SCRIPTS] Set PUBLICDIR in plugin scripts as well 2019-09-18 17:15:00 +03:00
Alexei Sorokin 6bfa593988 [DAEMONS] Move resetDb to the Daemon class
As it is used inside the Daemon class now, it should always be available.
2019-09-13 22:08:42 +03:00
Diogo Cordeiro 3ea580b537 [ActivityPub] Add missing parenthesis in class instantiation
Fixed some issues related to thrown exceptions in the doblocks; also boolean -> bool
2019-09-13 18:58:41 +01:00
Alexei Sorokin 87b0b493eb [ActivityPub] Fix an unhandled error in onStartGetProfileFromURI 2019-09-13 20:55:23 +03:00
Diogo Cordeiro 4eb4a2de00 [ActivityPub] Fix some bugs with onStartNoticeSearch
Refactored Activitypub_profile::ensure_web_finger to Activitypub_profile::ensure_webfinger
Do not throw exceptions in the handling of this event because we don't
want to stop the regular search just because we were unable to find
ActivityPub actors or notes.
2019-09-13 18:10:20 +01:00
Alexei Sorokin 1f2f57b03b [CORE] Fix logging of very early failures 2019-09-13 12:11:43 +03:00
Alexei Sorokin 4afaad3df5 [DATABASE][MariaDB] Properly account for foreign keys 2019-09-13 10:34:48 +03:00
Diogo Cordeiro c3ba2e0f94 [BugFix] Plugins ExtendedProfile and OverwriteThemeBackground - admin is identical to system path names. 2019-09-12 23:18:50 +01:00
Alexei Sorokin 693c3168da [OStatus] The unsubscribe state also needs a label 2019-09-12 14:19:21 +03:00
Alexei Sorokin 8f309bc768 Merge branch 'pgsql_support' into nightly 2019-09-12 12:01:50 +03:00
Alexei Sorokin 1a0d6a90c2 [INSTALL] Fix lib/util/installer.php import path 2019-09-12 11:52:04 +03:00
Diogo Cordeiro 7f2019b4af [MODULES] Make disable in admin panel effective 2019-09-12 04:50:46 +01:00
Alexei Sorokin ee7f0a2016 [DATABASE] Re-introduce PostgreSQL support 2019-09-11 14:14:40 +03:00
Alexei Sorokin 644b417f6c [DATABASE] Use "<>" as an SQL non-equality sign
"!=" is not SQL compliant.
2019-09-11 13:27:36 +03:00
Alexei Sorokin 471576d6e8 [DATABASE] Columns not in GROUP BY must not be queried 2019-09-11 13:12:41 +03:00
Alexei Sorokin 7ee8aa7838 [DATABASE] Re-introduce the enum type abstraction 2019-09-11 12:48:28 +03:00
Alexei Sorokin af63e9a7ad [DATABASE] Set all primary keys as "not null" explicitly 2019-09-11 12:27:40 +03:00
Alexei Sorokin 95c7344557 [DATABASE] Various table schema related fixes 2019-09-11 12:07:54 +03:00
Alexei Sorokin 0c936e54ba [DATABASE] Re-order tables to be created
Foreign keys need to be created after the respective tables are already in
place. This order makes sure this is the case.
2019-09-11 11:56:36 +03:00
Alexei Sorokin 62b90c29db [DATABASE] Introduce a bool type in schema
PostgreSQL has a clear distinction between integers and booleans, so it makes
sense to draw a clear line.
2019-09-11 11:25:39 +03:00
Alexei Sorokin 6911b499d3 [DATABASE] Consistently use the "LIMIT $limit OFFSET $offset" syntax
The "LIMIT $offset, $limit" syntax is only supported by MySQL and MariaDB.
2019-09-11 10:12:49 +03:00
Alexei Sorokin 44f4c9374d [DATABASE] Use time intervals in a SQL standard compliant way 2019-09-11 09:58:13 +03:00
Alexei Sorokin 11dabbe44d [DATABASE] Only use single quotation marks for SQL strings
Double quotation marks are only used for identifiers in the SQL standard.
2019-09-11 09:46:30 +03:00
Alexei Sorokin 0a5a3845db [DATABASE] Set NULL in DB_DataObject in a more reliable manner
Also stop assuming that FeedSub::sub_state (enum) and FeedSub::sub_end
(datetime) can possibly be set to an empty string.
2019-09-11 08:32:19 +03:00
Alexei Sorokin 5b797328f2 [DATABASE] Always quote identifiers
The code used to operate under the assumption that MariaDB doesn't support
quoting identifiers. Not only is that not exactly true, but MariaDB has
reserved keywords that cannot be used as table or column names unquoted.
2019-09-11 08:15:16 +03:00
Alexei Sorokin b89f1ad7d8 [CORE] Another inboxnoticestream improvement 2019-09-10 22:25:45 +03:00
Alexei Sorokin b0104d9992 [DAEMONS] Switch daemons to double-forking for daemonisation 2019-09-10 21:14:27 +03:00
Alexei Sorokin 9d8f4c774f [DAEMONS] Properly disconnect daemons from the database 2019-09-10 20:25:28 +03:00
Diogo Cordeiro 8b7a22ecd9 Merge branch 'nightly' of biodantas/gnu-social into nightly 2019-09-10 17:11:00 +00:00
Miguel Dantas a4e6db8d76 [OpportunisticQM] Revamped plugin to be able to use other poll based queuemanagers, no just the DB 2019-09-05 01:39:00 +02:00
Miguel Dantas 78506d5249 [StompQueue] Changed StompQueueManager to use polling rather than sockets 2019-09-05 01:39:00 +02:00
Miguel Dantas 6747b18b75 [PLUGINS] Added UnQueue, a new default plugin which does all actions immediately 2019-09-05 01:39:00 +02:00
Miguel Dantas 544f13c52a [PLUGINS] Added DBQueue plugin 2019-09-05 01:38:59 +02:00
Miguel Dantas 4644f6e96b [PLUGINS] Added StompQueue plugin, based on the implementation in lib/queue/stompqueuemanager. Updated to new STOMP library version. Dropped liberalstomp.php and stompqueuemanager.php 2019-09-05 01:38:40 +02:00
Miguel Dantas a3b228399b [PLUGINS] Added RedisQueue 2019-09-03 14:01:27 +01:00
Miguel Dantas 100a557c7c [CORE][AUTOLOAD] Fix class OAuthRequest not found
Issue description as reported by aab:

2019-08-28 17:34:48 LOG_ERR: [khp.ignorelist.com:61055.f5f7f51c GET /api/statuses/show/178372.atom] ServerErrorAction: 500 Class 'OAuthRequest' not found
2019-08-28 17:39:50 LOG_ERR: [khp.ignorelist.com:65390.4483ff85 GET /api/statusnet/conversation/104672.rss] Handled serverError (500) but cannot output into desired format ('rss'): 'Class \'OAuthRequest\' not found'
2019-08-28 17:39:50 LOG_ERR: [khp.ignorelist.com:65390.4483ff85 GET /api/statusnet/conversation/104672.rss] ServerErrorAction: 500 Class 'OAuthRequest' not found
2019-08-28 17:40:49 LOG_ERR: [khp.ignorelist.com:65390.4c745f68 GET /api/statuses/show/18132.atom] Handled serverError (500) but cannot output into desired format ('atom'): 'Class \'OAuthRequest\' not found'
2019-08-28 17:40:49 LOG_ERR: [khp.ignorelist.com:65390.4c745f68 GET /api/statuses/show/18132.atom] ServerErrorAction: 500 Class 'OAuthRequest' not found
2019-08-28 17:47:41 LOG_ERR: [khp.ignorelist.com:65390.42ee9fd4 GET /api/statusnet/conversation/133023.as] Handled serverError (500) but cannot output into desired format ('as'): 'Class \'OAuthRequest\' not found'
2019-09-03 03:33:14 +01:00
Miguel Dantas 6acc75ccff [FRAMEWORK][AUTOLOAD] Fix autoloads 2019-09-03 03:33:14 +01:00
Miguel Dantas b41f9620fa [LIB_REFACTOR] Fix requires 2019-09-03 03:33:13 +01:00
Miguel Dantas 58bde08425 [LIB_REFACTOR] Moving files into separate semantic categories 2019-09-03 03:33:13 +01:00
Miguel Dantas 7d6c6edab3 [RedisCache] Fix call to getPayload on int. The library is badly documented, but seems to return the TTL instead of the normal redis response
Issue description as reported by aab:

About one day after enabling redis plugin:

PHP Fatal error:  Uncaught Error: Call to a member function getPayload() on int in /var/www/html/plugins/RedisCache/RedisCachePlugin.php:96
Stack trace:
0 /var/www/html/lib/event.php(89): RedisCachePlugin->onStartCacheSet('gnusocial:gatea...', Object(Queue_item), NULL, 86400, false)
1 /var/www/html/lib/cache.php(202): Event::handle('StartCacheSet', Array)
2 /var/www/html/classes/Memcached_DataObject.php(496): Cache->set('gnusocial:gatea...', Object(Queue_item))
3 /var/www/html/classes/Memcached_DataObject.php(416): Memcached_DataObject->encache()
4 /var/www/html/classes/Managed_DataObject.php(620): Memcached_DataObject->update(Object(Queue_item))
5 /var/www/html/classes/Queue_item.php(74): Managed_DataObject->update(Object(Queue_item))
6 /var/www/html/lib/dbqueuemanager.php(75): Queue_item::top(Array, Array)
7 /var/www/html/lib/iomaster.php(287): DBQueueManager->poll()
8 /var/www/html/lib/iomaster.php(161): IoMaster->poll()
9 /var/www/html/scripts/queuedaemon.php(112): IoMaster->service()
10 /var/www/html/lib/spawni in /var/www/html/plugins/RedisCache/RedisCachePlugin.php on line 96
2019-09-03 03:31:59 +01:00
Miguel Dantas d209964718 [Memcached] Fix call to undefined method close
Issue description as reported by aab:

Memcached config in config.php:

    addPlugin('Memcached', [ 'servers' => ['127.0.0.1', 11211],
                             'defaultExpiry' => 86400 // 24h
                           ]);

Memcached and php-memchached installed.

The error appears when executing startdaemons.

Log:

    PHP Fatal error:  Uncaught Error: Call to undefined method Memcached::close() in /var/www/html/plugins/Memcached/MemcachedPlugin.php:202
    Stack trace:
    #0 /var/www/html/lib/event.php(89): MemcachedPlugin->onStartCacheReconnect(false)
    #1 /var/www/html/lib/cache.php(273): Event::handle('StartCacheRecon...', Array)
    #2 /var/www/html/lib/spawningdaemon.php(209): Cache->reconnect()
    #3 /var/www/html/lib/spawningdaemon.php(188): SpawningDaemon->resetDb()
    #4 /var/www/html/lib/spawningdaemon.php(118): SpawningDaemon->initAndRunChild(3)
    #5 /var/www/html/lib/daemon.php(168): SpawningDaemon->run()
    #6 /var/www/html/scripts/queuedaemon.php(186): Daemon->runOnce()
    #7 {main}
      thrown in /var/www/html/plugins/Memcached/MemcachedPlugin.php on line 202
2019-09-03 03:30:07 +01:00
Miguel Dantas c03f659efb [Embed] Fix use of undefined img_data
Got error 'PHP message: PHP Notice: Undefined variable: img_data in /var/www/html/plugins/Embed/EmbedPlugin.php on line 544'
2019-09-03 03:29:32 +01:00
tenma 2e66cbeb60 [CORE] Fix undefined offset warnings in different files
This problem was presentend in the following issue:
https://notabug.org/diogo/gnu-social/issues/60

AcceptHeader/util:
- Perform isset before using the required array values
2019-09-03 03:26:35 +01:00
tenma 19409cb999 [ActivityPub] Add support fox search-box profile/notice grabbing
NoticeSearchAction:
- Add new event before finding query matches

ActivityPubPlugin:
- Subscribe new searchNotice event
- Bump minor version number

Activitypub_explorer:
- Update lookup to make remote-grabbing optional
2019-09-03 03:26:35 +01:00
tenma c06182c38f [ActivityPub] Handle DELETE-Person activity
ActivityPubPlugin:
- update grab_notice_from_url to make online grab optional
- subscribe events of user and profile deletion
- bump minor version number

Activitypub_inbox_handler:
- separate handle_delete for delete-note and delete-person

Activitypub_postman:
- add delete-person logic

Activitypub_delete:
- update validation method to check for the "Person" type
- update to_array method to target the activity
2019-09-03 03:26:35 +01:00
Miguel Dantas f79cd8cee3 [CORE] Fix small bug where Notice was sending a JSON representation to the queue, instead of sending itself 2019-09-03 03:26:35 +01:00
tenma c130739de0 [AP] Fix subscription events
Both StartSubscribe and StartUnsubscribe had a wrong initial if-condition.
Furthermore, this events were calling Activitypub_profile::from_profile()
which is wrong because it creates the Activitypub_profile object when
the goal is only to check if it exists already.
2019-09-03 03:26:35 +01:00
tenma 1a4a1583d5 [AP] Subscribe RemoteFollow plugin events for allowing following with the remote-follow button 2019-09-03 03:26:35 +01:00
tenma 3633ca04eb [OStatus] Port remote-follow to the RemoteFollow plugin
OStatusPlugin:
- Stop adding the remote-follow button
- Subscribe to required RemoteFollow plugin events
- Drop main/ostatussub route and update urls to the main/RemoteFollowSub route
- Bump plugin minor version number

actions/ostatusgroup,
actions/ostatuspeopletag:
- Update urls to the main/RemoteFollowSub route

lib/util:
- Port required functions from OStatusSubAction and adapt to be used with the new events
2019-09-03 03:26:35 +01:00
tenma e61c0c45aa [RemoteFollow] Initial work in the RemoteFollow plugin
lib/default.php
- Add RemoteFollow to the list of default plugins

RemoteFollowPlugin:
- Subscribe events to add the remote-follow button

RemoteFollowInitAction:
- Handles the remote-follow form and getting the redirection url for follow completion

RemoteFollowSubAction:
- Handles the remote profile pulling and actual following
2019-09-03 03:26:35 +01:00
Miguel Dantas 6d81848f25 [URLMAPPER] Fix small bug in URLMapper: a dynamic route might not exist even if a static one does 2019-09-03 03:26:35 +01:00
Miguel Dantas 10b3b343dd [DirectMessage] Fixed use of incorrect type which prevented posting notices with only one word 2019-09-03 03:26:35 +01:00
tenma f6fd025be2 [AP] Update version info 2019-09-03 03:26:35 +01:00
tenma b5897687a6 [AP] Prevent postman to include the actor's followers for every sent activity 2019-09-03 03:26:35 +01:00
tenma ebeae261de [AP] Support Private Messaging
ActivityPubPlugin:
- Subscribe DirectMessage events

Activitypub_inbox_handler:
- Update handle_create_note to create private messages

Activitypub_postman:
- Add create_direct_note for sending private messages

Activitypub_create:
- Update create_to_array to support the 'directMessage' attribute
- Add isPrivateNote to verify private activities

Activitypub_notice:
- Update create_note to support the 'directMessage' attribute
- Remove isPrivateNote

lib/models:
- Add Activitypub_message, the model in charge of private notes
2019-09-03 03:26:35 +01:00
tenma 9733f3c02c [AP] Fix Follow collections
Activitypub_profile:
- Fix subscription-counter getter functions, invalid profiles were being counted

apActorFollowingAction:
- Small rewrite of generate_following, didn't make sense to not use try-catch block

apActorFollowersAction:
- Small rewrite of generate_followers, didn't make sense to not use try-catch block
2019-09-03 03:26:35 +01:00
tenma 217c8a3933 [AP] Handle unlisted/followers-only notices
Note that this commit isn't intended to add support for sending such notes
in GS. Instead, we handle the reception, storage and direct reply to this
type of notices, in AP.

ActivityPubPlugin:
- Subscribe the event StartNoticeSave to hack answering non-public notes

Activitypub_create:
- Add 'directMessage' attribute to the Create activity, defaulting to false for now
- Update validation method: validate 'directMessage' and add debug

Activitypub_notice:
- Handle incoming unlisted/followers-only notes
- Add support for unlisted-replies
- Add method to verify private (direct) notices

inbox_handler:
- Add handler for CREATE Note
- Prepare logic for private-messaging
- Overall refactor: Class members were continuously being passed as function arguments without need

SharePlugin:
- Stop showing the announce button in non public posts
2019-09-03 03:26:35 +01:00
tenma 7188d81ad4 [AP] Properly target public notices
ActivityPubPlugin:
- Use TO as principal audience, CC as secondary
- Update note validation
2019-09-03 03:26:35 +01:00
Miguel Dantas 48cacd6d9d [RedisCache] Added plugin description, fixes 'empty msgid' error 2019-09-03 03:26:35 +01:00
Diogo Cordeiro 1e378a514d [OverwriteThemeBackground] This new plugin will let the admin set a custom background theme independent 2019-09-03 03:26:35 +01:00
Diogo Cordeiro 92ab5e18ee [ExtendedProfile] Fix Admin menu option 2019-08-24 01:59:42 +01:00
Diogo Cordeiro b42af10905 [MODULES] Allow to delete third party plugins 2019-08-24 01:59:42 +01:00
Diogo Cordeiro afe8158cb7 [MODULES] Allow to upload third party plugins
Fixed some bugs
2019-08-24 01:59:42 +01:00
Diogo Cordeiro a05bea0af5 [MODULES] List all available plugins and allow enabling them via UI
Yet another revision of the Admin Plugin Management tool
2019-08-24 01:59:41 +01:00
Diogo Cordeiro e1514a151c [DOCUMENTATION][DEVELOPERS][PLUGINS] Some updates to Plugins doc 2019-08-24 01:59:41 +01:00
Diogo Cordeiro 2a82cfdb2a [TagCloud] Add Readme 2019-08-24 01:59:40 +01:00
Diogo Cordeiro 49da433879 [SearchSub][README] No longer is a default plugin since 8614cd77 2019-08-24 01:59:40 +01:00
Diogo Cordeiro 92388e1734 [SamplePlugin] Review and update with the latest GNU social best practices 2019-08-24 01:59:40 +01:00
Diogo Cordeiro 3860c25dc0 [ConversationTree] Format the plugin, add strict typing and fix docblocks 2019-08-24 01:59:39 +01:00
Diogo Cordeiro 25ee5ed1f9 [OfflineBackup] Fix plugin 2019-08-24 01:59:39 +01:00
Diogo Cordeiro 566214ac62 [PLUGINS] Removed OpenX as the service doesn't exist anymore 2019-08-24 01:59:39 +01:00
Diogo Cordeiro 1459f10803 [GroupFavorited] Fix plugin 2019-08-24 01:59:38 +01:00
Diogo Cordeiro 0795a39459 [ExtendedProfile] Hide 'Extra fields' from profile when no field was created by the sysadmin 2019-08-24 01:59:38 +01:00
Diogo Cordeiro e5831d6807 [ExtendedProfile] Allow to delete custom profile field 2019-08-24 01:59:38 +01:00
Diogo Cordeiro 88bdb5114f [Plugins] Incorporated GNUsocialExtendedProfile as part of ExtendedProfile
Also improved a lot of the plugin and made things in a way it would make sense
2019-08-24 01:59:37 +01:00
Diogo Cordeiro 90bd9088bb [GNUsocialProfileExtensions] Fixed plugin 2019-08-24 01:59:37 +01:00
Diogo Cordeiro 01cf8ab82c [PLUGINS] Removed GNUsocial{Photo, Photos, Video} as we don't need them anymore 2019-08-24 01:59:36 +01:00
Diogo Cordeiro aee5506f00 [PLUGINS] Removed GeoURL as the service doesn't exist anymore 2019-08-24 01:59:36 +01:00
Diogo Cordeiro b6183f2de1 [ForceGroup] Modernized plugin and improved documentation 2019-08-24 01:59:36 +01:00
Diogo Cordeiro 452e0fe553 [DEFAULT] Add 'DirectionDetector' as a default plugin 2019-08-24 01:59:35 +01:00
Diogo Cordeiro 2f341a3369 [ChooseTheme] Fixed plugin 2019-08-24 01:59:35 +01:00
Diogo Cordeiro 66e55d1a1f [BlankAd] Fixed plugin 2019-08-24 01:59:34 +01:00
Diogo Cordeiro 63fac32bc0 [Awesomeness] Fixed plugin 2019-08-24 01:59:34 +01:00
Diogo Cordeiro aaeaeba57c [DEFAULT] Add 'AccountManager' as a default plugin 2019-08-24 01:59:34 +01:00
Diogo Cordeiro d3c56897a3 [CORE] Core modules shouldn't show up in version action 2019-08-24 01:59:33 +01:00
Diogo Cordeiro 0c2c3ec862 [CORE] Plugin API now extends a new Module API 2019-08-24 01:59:33 +01:00
Diogo Cordeiro b6e7b18c7b [PLUGIN API] Bug fixes and improvements 2019-08-24 01:59:32 +01:00
Diogo Cordeiro 55d049b1e8 [CORE] Move plugin superclasses from /lib/ to /lib/modules/ 2019-08-22 03:13:58 +01:00
Diogo Cordeiro 8c0601816f [CORE] Move core plugins to a new modules directory
For reference (raised by rozzin in IRC):

* http://foldoc.org/module
* http://foldoc.org/library
* http://foldoc.org/plugin

As noted by XRevan86, modules are not necessarily non-essential.
As we will keep the modules directory in GS root [therefore, near to
plugins/], it is evidenced the difference between both.

This is a simple yet fundamental structural change. It doesn't change
functionality but makes clearer the way we understand GNU social's
internals.
2019-08-22 03:13:58 +01:00
Miguel Dantas 350cde08d8 [Embed] Added support for inline images 2019-08-22 03:13:58 +01:00
tenma db5a29fd9a [DirectMessage] Major plugin rework
This commit does the necessary rework to store private messages
as Notices and to support Federation. The plugin's README presents
some more detail about the changes and future work that is still
required to do.
2019-08-22 03:13:58 +01:00
tenma 0716605e94 [CORE][ROUTES] Update urlmapper to search dynamic routes before static ones when generating URLs.
This solves the problem of routes that differ only in having
or not $_GET params. The ones not having params (static) were
being matched first during URL generation.

The way this problem was solved was by separating the $reverse
array in both $reverse_statics and $reverse_dynamics and explicitly
traversing this last one first in the generation function. Note that
maintaining the $reverse array and unshifting dynamic routes to its
head ( and therefore to the front of the static ones ) doesn't work
since even among dynamic routes the order of arrival should be kept.
2019-08-22 03:13:58 +01:00
tenma c802480d75 [CORE] Add new Notice scope for private messaging
Notice:
- Add MESSAGE_SCOPE scope

lib/*.stream:
- Filter out notices with MESSAGE_SCOPE scope
2019-08-21 16:54:47 +01:00
Miguel Dantas 2519431f02 [Embed] Added support for inline images 2019-08-21 16:54:46 +01:00
Miguel Dantas b38e71e544 [Embed] Only resize thumbnail if it's bigger than the desired size 2019-08-21 16:54:46 +01:00
Diogo Cordeiro c981afcf31 [DOCUMENTATION] Add release notes
Update INSTALL requirements
Update CHANGELOG
Update TODO
2019-08-21 16:54:09 +01:00
Diogo Cordeiro eccb8a4faf [ActivityPub] Move models from 'classes' to 'lib/models' 2019-08-21 16:46:39 +01:00
tenma 7fa5ddfc44 [ActivityPub] Fix WebFinger event subscription
ActivityPubPlugin:
- remove reference to the first argument of onEndWebFingerProfileLinks, no need
as it is an object
2019-08-21 16:46:39 +01:00
tenma 054f4e77f5 [ActivityPub] Fix handling of Delete Activity
inbox_handler:
- Call stronger validation method for Delete Activity objects
- Take into account mixed object in handle_delete

Activitypub_delete:
- Add validation method for Delete Activity objects
2019-08-21 16:46:39 +01:00
Diogo Cordeiro 1398d6cc21 [ActivityPub] This is the first release of the plugin 2019-08-21 16:46:38 +01:00
tenma b902b019fb [ActivityPub] Use queues for notice distribution
ActivityPubPlugin:
- Change event-based notice distribution to queues logic

ActivityPub/lib:
- Add queue handler class activitypubqueuehandler.php

Misc:
- Add documentation for the (Start/End)InitializeQueueManager events
2019-08-21 16:46:38 +01:00
tenma 5e589aba3c [OStatus] Fix notice enqueue
OStatusPlugin:
- Enqueue in the last position, as it should be. No need to worry about
the OMB comment, this protocol no longer have queue handlers that could
cause a conflict.
2019-08-21 16:46:38 +01:00
tenma c28cee88b7 [ActivityPub] Ensuring federation with other software
ActivityPubPlugin:
- Prevent sending a Delete for an Announce

Activitypub_announce:
- Update announce_to_array to add id, to and cc information to the retrieved object

Activitypub_follow:
- Add id to the arguments of follow_to_array, useful for Accept-Follow activities

Activitypub_notice:
- Fix notice validation, url isn't a MUST

Activitypub_inbox_handler:
- Make handle_follow use the received activity id for the later Accept-Follow

Activitypub_postman:
- Fix call to the updated announce_to_array
- Fix successive unnecessary calls to ActivityPubPlugin::actor_uri()
2019-08-21 16:46:37 +01:00
brunoccast 14a45dc546 [ActivityPub] Fix notice creation
Activitypub_notice:
- Perform url test, use id when missing.
2019-08-21 16:46:37 +01:00
brunoccast 883621ba34 [ActivityPub] Routes
ActivityPubPlugin:
- Update routes to properly use the updated URLMapper
2019-08-21 16:46:37 +01:00
brunoccast 067cc81ebb [ActivityPub] Ensuring notice deletion
ActivityPubPlugin:
- Minor onDeleteOwnNotice rewrite

Activitypub_inbox_handler:
- Add deletion check to incoming notice

Activitypub_postman:
- Call the correct getUrl function
2019-08-21 16:46:37 +01:00
brunoccast b19ee7b894 [ActivityPub] Ensuring Notice Favor/Disfavor
ActivityPubPlugin:
- Minor re-write of favor/disfavor event handlers

Activitypub_postman:
like/undo-like:
- fix proper getUrl() call
misc:
- make all activities accumulate errors (may be needed later) and log some information about it
2019-08-21 16:46:36 +01:00
brunoccast 1b356d3bf2 [ActivityPub] Ensuring notice distribution
ActivityPubPlugin:
- Fix of accepted activity verbs to include SHARES
- Add attention profiles to delivery when announcing

Activitypub_notice:
- New local function to retrieve original URL
- Removal of unnecessary 'Atom*' attributes
- Small fix to the ensuring of actor profile

Activitypub_profile:
- New local function to fetch AP profiles from a collection

Activitypub_postman:
- Fix url passed in the announce activity
2019-08-21 16:46:36 +01:00
brunoccast 94a4059b4a [ActivityPub] Caching of Following/Followers interactions and collections
Follow interaction:
- Fixed mini-bug where the subscriber profile was being used as the subscribed
- Updated cache subscription-related values in both instances
- Tested and working with local GS instances

Unfollow interaction:
- Updated cache subscription-related values in both instances
- Tested and working with local GS instances

Followers/Following collections:
- Now returning ActivityPub profiles only
- Stored collections in cache

Misc:
- Fix bug concerning the retrieval of public/private-key after in-function generation
2019-08-21 16:46:36 +01:00
brunoccast 735a0023cc [ActivityPub] Routes
ActivityPubPlugin:
- Update routes to properly use URLMapper
- Minor updates
2019-08-21 16:46:36 +01:00
Diogo Cordeiro 2ad4fa99ed [CORE] Add ActivityPub plugin
This is not the same as the one in https://notabug.org/diogo/gnu-social-activitypub-plugin
Differences to the first "release"
-> Doesn't use guzzle nor has any composer dependencies
-> Supports HTTP Signatures
-> Has basic l10n/i18n
-> Some minor bug fixes
2019-08-21 16:46:35 +01:00
Miguel Dantas c0950c5fc6 [PLUGINS] Dropped Memcache in favor of Memcached. The difference between these is that they use a similarly php library to interact with memcache, but memcached is more modern 2019-08-15 22:33:38 +01:00
Miguel Dantas afbbbbd4f2 [Memcached] Merged useful features from Memcache 2019-08-15 22:33:37 +01:00
Miguel Dantas 32812c9482 [PLUGINS] Updated and reviewed the Memcached plugin 2019-08-15 22:33:37 +01:00
Miguel Dantas c70e806d74 [RedisCache] Added README with configuration instructions 2019-08-15 22:33:36 +01:00
Miguel Dantas 05be2e7386 [RedisCache] Fix use of undefined variable 2019-08-14 15:32:36 +01:00
Miguel Dantas e2e8885ce3 [PLUGINS] Removed direct call of EndCache events on all plugins, as it is now handled by the library 2019-08-14 15:32:35 +01:00
Miguel Dantas b214d8b6ee [CACHING] Imported Chimo's RedisCache plugin and fixed some small parts 2019-08-14 15:32:35 +01:00
Miguel Dantas ba98bb9334 [CORE] Fixed small anti-pattern on cache code. Plugins had to throw EndCache events, when this should be done by the library 2019-08-14 15:32:35 +01:00
Miguel Dantas 630a578e1d [COMPOSER] Added predis/predis and updated packages 2019-08-14 15:32:34 +01:00
Miguel Dantas 0bb35d7e7f [LinkPreview] Fix 'no candidate for action "embedproxy"' 2019-08-14 15:32:34 +01:00
tenma 357296baeb [CORE] Fix subscription-related functions from the Profile class
The undifined variable $private_stream, from the User class, was causing
undifined behavior from calling requiresSubscriptionApproval. The is_null
test was added to fix this problem.
2019-08-13 03:01:24 +01:00
Miguel Dantas bff525d26f [DOCUMENTATION][SYSADMIN][CONFIGURE] x-static-delivery was in the wrong section 2019-08-13 03:00:19 +01:00
Diogo Cordeiro e4bdb21a54 [NodeInfo] New endpoint and formula for computing active users
Seriously improved documentation
Now NodeInfo 2.0 is available at /api/nodeinfo/2.0.json
For active users we now also consider favourites and recently created accounts
Some further minor bug fixes and full review of the implementation
2019-08-12 05:35:27 +01:00
Diogo Cordeiro c0ac7f0ac8 [DOCUMENTATION] Late update of CHANGELOG and TODO list 2019-08-12 05:35:26 +01:00
Diogo Cordeiro eba2fe1624 [DOCUMENTATION][SYSADMIN][CONFIG][profile] Fix default of backup and restore options 2019-08-11 01:11:41 +01:00
Miguel Dantas 0030fe3aeb [REFACTOR] Added explicit return type to all instances of QueueHandler::handle 2019-08-11 01:11:41 +01:00
Miguel Dantas aaabf82eff [CORE][QUEUE] Error checking and type declaration on handling notice queue events
Patch submitted by XRevan86
2019-08-08 02:44:14 +01:00
Diogo Cordeiro de91d28f6f [PEAR][DB] Import some new commits
Patch submitted by XRevan86

[DB/pgsql.php] Change pg_exec to pg_query
Encouraged by http://php.net/manual/en/function.pg-query.php and enables
improved monitoring by New Relic (https://newrelic.com)
[DB.php] changed count to empty for php7.2
[DB/common.php] change to array cast for php72

From: https://github.com/pear/DB/
Commits: 7d0ddaff, d04a42a5 and ea9fff4a, respectively
2019-08-08 02:44:14 +01:00
Diogo Cordeiro 24d5d200b8 [EXTLIB][VALIDATE] Fix some types 2019-08-08 02:44:13 +01:00
Miguel Dantas 573ba2ee43 [DOCUMENTATION] Added X-Sendfile/X-Accel-Redirect to the sample nginx and apache config files 2019-08-08 02:44:13 +01:00
Diogo Cordeiro b4fced4bd7 [DOCUMENTATION] Add versioning information
Some other minor improvements and a bug fix in the boilerplate
2019-08-08 02:44:07 +01:00
Miguel Dantas 52310a8ad8 [Embed] Fixed error related to oembed action 2019-08-07 23:57:40 +01:00
Diogo Cordeiro 11d203c54a [DOCUMENTATION] Fix nginx location rule's regex for install and index 2019-08-07 23:57:36 +01:00
biodantas 723f12923c Merge branch 'master' of biodantas/gnu-social into master 2019-08-03 20:04:14 +00:00
Miguel Dantas 8b106dbc6c [MEDIA] Fixed wrong image cropping 2019-08-03 21:02:21 +01:00
Miguel Dantas 955d5a136f [MEDIA] Replaced internal image handling with intervention/image, which is capable of using both GD and ImageMagik 2019-08-03 17:49:37 +01:00
Miguel Dantas 2db3825940 [CORE][COMPOSER] Added intervention/image 2019-08-03 17:49:37 +01:00
Diogo Cordeiro db3253e5d2 [CORE] Bump PHP requirement to PHP7.3+ 2019-08-03 17:49:36 +01:00
Miguel Dantas dbde8383c9 [Embed] Fixed use of undefined variable in fixup_files script 2019-08-03 17:49:36 +01:00
Miguel Dantas 6d552f15b6 [Embed] Resize thumbnails fetched by Embed to avoid keeping original images when we need only 128x128. Size configurable in config.php 2019-08-03 17:49:36 +01:00
Miguel Dantas ba15724a62 [FORMAT][Embed] Ran php-cs-fixer on Embed's files and small style fixes 2019-08-03 17:49:33 +01:00
Diogo Cordeiro 938d286fb6 [DOCUMENTATION] Add a CHANGELOG that includes a TODO list to reach alpha in v2 2019-08-03 17:49:11 +01:00
Diogo Cordeiro 2e6c7b1bb8 [SCRIPTS] Make them work in v2 by setting PUBLICDIR 2019-08-03 17:49:11 +01:00
Miguel Dantas 5be705ca2a [Embed] Updated fixup_files.php script to be able to fix broken oEmbedinfo using the --broken-oembed flag 2019-08-03 17:49:10 +01:00
Miguel Dantas 07b4cfaeae [Embed] Hide error from the UI and just don't display an image if the remote image is not valid 2019-08-03 17:49:10 +01:00
Miguel Dantas c9379b3608 [Embed] Fix bug where we we're losing track of a file, in case the image needed to be reencoded 2019-08-03 17:49:10 +01:00
Miguel Dantas 22c8c96249 [Embed] Fixed Embed tests 2019-08-03 17:49:10 +01:00
Miguel Dantas d66828c2bf [Embed] Fixed bug where sometimes images were written outside the site root 2019-08-03 17:49:09 +01:00
Miguel Dantas a244f3ba4d [Embed] Removed old oEmbed and OpenGraph implementation 2019-08-03 17:49:09 +01:00
Miguel Dantas 0c20d35206 [Embed] Refactoring and bug fixing 2019-08-03 17:49:09 +01:00
Miguel Dantas 462ea26303 [Embed] Using oscarotero/Embed as first attempt to get oEmbed/OpenGraph data, fallback
to previous implementation otherwise.
2019-08-03 17:49:09 +01:00
Miguel Dantas b25632ebc4 [PLUGINS] Fixed oEmbed dependents to use Embed 2019-08-03 17:49:06 +01:00
Miguel Dantas 2a2b3f72fb [Embed][DB] Renaming the 'file_oembed' table to 'file_embed' on upgrade 2019-08-03 17:48:28 +01:00
Miguel Dantas 52819d39d9 [OEmbed][Embed] Renamed OEmbed plugin to Embed 2019-08-03 17:48:26 +01:00
Miguel Dantas 1d41ff16d6 [COMPOSER] Added embed/embed 2019-08-03 17:47:29 +01:00
Diogo Cordeiro 36dd245ee3 [DOCUMENTATION] New socialfy solution 2019-08-03 17:47:28 +01:00
Diogo Cordeiro e0bc35b975 [CORE] Avatars are in PUBLICDIR in v2
Fixed a bug in the Installer
2019-08-03 17:47:28 +01:00
Diogo Cordeiro 893bafa14b [INSTALL] Minor reformatting and modernization. Shouldn't change functionality significatively. 2019-08-03 17:47:28 +01:00
Diogo Cordeiro 7d262ad50b [CORE] Fixed some small issues with PEAR 2019-08-03 17:47:28 +01:00
Diogo Cordeiro d9e7862cea [CORE][COMPOSER] Ensure we are compatible with PHP 7.0.0 2019-08-03 17:47:27 +01:00
Diogo Cordeiro 9f30c299ee [CORE] Make tests great gain 2019-08-03 17:47:27 +01:00
Diogo Cordeiro 39845444cc [DOCUMENTATION] Update description of extlib and vendor directories 2019-08-03 17:47:27 +01:00
Diogo Cordeiro ec32db2dd6 [CORE][COMPOSER] Add hoa/consistency
Renamed curry to callable_left_curry
2019-08-03 17:47:27 +01:00
Diogo Cordeiro 411e8ed79d [CORE] Downgrade phpseclib to a working state 2019-08-03 17:47:26 +01:00
Daniel Supernault c1c2a9f1a1 [DEVTOOL] Add a robust and modern REPL 2019-08-03 17:47:26 +01:00
Daniel Supernault 2850e56f30 [CORE] Add custom favicon configuration support
Adds support for custom favicons defined in config.php that override theme favicons.
2019-08-03 17:47:26 +01:00
Daniel Supernault 9c0354bbf1 [CORE] Remove function_exists() calls and add up default bcrypt cost to 12. 2019-08-03 17:47:26 +01:00
Daniel Supernault c09f1c2443 [CORE] Add Argon2I support
Add Argon2I support, disabled by default.
2019-08-03 17:47:25 +01:00
Daniel Supernault 912f2c3567 [CORE] Update AuthCryptPlugin
Added password_hash() (bcrypt) support with fallback to crypt() for older PHP versions.
2019-08-03 17:47:25 +01:00
Daniel Supernault ad51998d67 [CORE] Add timing safe backwards compatible password_verify 2019-08-03 17:47:25 +01:00
Diogo Cordeiro 1049080df5 [CORE] Move public resources to a /public directory
Advantages:
* Increases security by preventing direct access to file/
* We are careful and have a defined('GNUSOCIAL') || die() to prevent
  direct access to GS files, but we may miss one or a vendor/extlib may
  not be as careful
* Improves directory structure - It's more natural to physically
  separate what is public from what are GNU social resources
2019-08-03 17:47:25 +01:00
Diogo Cordeiro 966b00617e [CORE] Remove PEAR Command as it is not used 2019-08-03 17:47:25 +01:00
Diogo Cordeiro b408208e4c [FORMAT] Run php-cs-fixer in php-gettext 2019-08-03 17:47:24 +01:00
Diogo Cordeiro a1edc2c6a9 [CORE][COMPOSER] Move plugins extlibs to composer (where appropriate) 2019-08-03 17:47:24 +01:00
Diogo Cordeiro 2a06261f75 [CORE][COMPOSER] Move extlib packages with immediate composer correspondent to composer dependencies
This adds a composer.json for all dependencies that are available
2019-08-03 17:47:24 +01:00
brunoccast 0b58465fb9 [CORE] Fix notice delete-form
DeletenoticeAction:
- Added tombstone check before deletion

NoticeListItem:
- Added tombstone check before showing delete-form

ActivityVerb:
- The plugin was overwriting the deletenotice route. Added stronger
regexp to the connected routes.
2019-08-03 17:47:23 +01:00
Diogo Cordeiro f67a93eddc [CORE] Bump Database requirement to MariaDB 10.3+ 2019-08-03 17:47:23 +01:00
Diogo Cordeiro 7044f0e2cf [Media] Fix undefined variable box in imagefile.php 2019-08-03 17:47:23 +01:00
Miguel Dantas ed7a88ce66 [StoreRemoteMedia] Added documentation for feature which limits the maximum filesize which is kept locally 2019-08-03 17:47:22 +01:00
Miguel Dantas e392160435 [ROUTES] Fixed attachment routes, broken by channges in fa378462f4 2019-08-03 17:47:17 +01:00
brunoccast 5c0a3102ff [ROUTES] Allow accept-header specification during router creation
Router:
- Fix calls to connect, most of them were misusing the function's params

URLMapper:
- Minor fixes
- Documentation
- Add support for accept-header specification

Plugins/*:
- Fix calls to connect
2019-08-03 17:47:16 +01:00
brunoccast 2032c7c1f7 [ROUTES] PSR2-format 2019-08-03 17:31:44 +01:00
Miguel Dantas d295d8b43c [CORE] Added documentation and fixed typo in attachments action 2019-08-03 17:31:44 +01:00
Miguel Dantas ee8bac9ad7 [CORE] Fix bug where we we're losing track of a file, in case the image needed to be reencoded 2019-08-03 17:31:44 +01:00
Miguel Dantas 4863bd30d7 [CORE] Fixed Media tests 2019-08-03 17:31:43 +01:00
Miguel Dantas 7070a14480 [CORE][StoreRemoteMedia] Fixed bug where sometimes images were written outside the site root 2019-08-03 17:31:43 +01:00
Diogo Cordeiro a38f25f7cd [PEAR] Modernize Validate code
Upgraded IDNA to IDNA2
Added PEAR Date
> fixed: The each function is deprecated
2019-08-03 17:31:43 +01:00
Miguel Dantas a5259073df [CORE] Fix X-Sendfile for nginx, using the X-Accel-Redirect header 2019-08-03 17:31:43 +01:00
Miguel Dantas 3e5ce46e98 [CORE] Fixed bug where the http connection was using the wrong size for thumbnails, and returning the wrong one 2019-08-03 17:31:42 +01:00
Miguel Dantas f746866b65 [StoreRemoteMedia] StoreRemoteMedia now uses the new filename format, which allows it to display correctly in the UI. Formatting fixes 2019-08-03 17:31:42 +01:00
Miguel Dantas 8f31a1a820 [MEDIA][OEMBED] Fixed regression in OEmbed, because it relied on accessing the files directly, which previous commits broke. The File table really should have a bool... 2019-08-03 17:31:42 +01:00
Miguel Dantas 4187568522 [OEMBED][UI] Skip adding an image thumbnail for oembed results if we
don't have a file locally to generate it, which can happen, for
instance, if StoreRemoteMedia is disabled
2019-08-03 17:31:42 +01:00
Miguel Dantas da82048d77 [MEDIA] Fix trying to display file wich is not available locally 2019-08-03 17:31:41 +01:00
Miguel Dantas 04d1caff78 [CORE] Fixed bug where all thumbnails were using the original file 2019-08-03 17:31:41 +01:00
Miguel Dantas bea06da531 [INSTALL] Fixed issue in installing where default.php needs util.php but it's not loaded 2019-08-03 17:31:41 +01:00
Miguel Dantas 7643f3cf7b [CORE][ACTION] Removed getfile action. Superseded by attachment/*/download, which additionally uses a file hash as oposed to a filename.
Additionally, added etag and last modified HTTP headers to attachments, to more effectively take advantage of caching
2019-08-03 17:31:41 +01:00
Miguel Dantas aa5c6bbf08 [CORE][UI] Made attachment actions and its subactions be able to identify attachments by id and by filehash. Changed the url stored in the DB to be attachment//view 2019-08-03 17:31:41 +01:00
Miguel Dantas 9536f2a909 [CORE] Refactored attachement actions to remove duplicate code 2019-08-03 17:31:40 +01:00
Miguel Dantas c7475d78b4 [CORE][UI][ROUTER] Added view action, which inlines images and videos but downloads everything else. Fixed File url to get an URL fromthe view action, so when a making a remote notice, the correct URL is used, not accessing directly to the file 2019-08-03 17:31:40 +01:00
Miguel Dantas 3c9a07677e [CORE] Attachments and thumbnails aren't accessed directly by the file under the file storage folder, but indirectly from PHP, so that access to the file folder can be blocked in the server config 2019-08-03 17:31:40 +01:00
Miguel Dantas b669f57068 [CORE] Fixed common_get_preferred_php_upload_limit, because some values in php.ini can be -1 or 0 for unlimited 2019-08-03 17:31:40 +01:00
Miguel Dantas ccebe536b3 [MEDIA] Removed blacklisted extensions, "trusts" upload extension (doesn't affect anything) and updated sysadmin documentation
Fixes bug which broke the UI. Oops
2019-08-03 17:31:39 +01:00
Miguel Dantas b9a0733062 [MEDIA][CORE] Add common function for converting a string with a size unit to an int and MediaFile uses file_quota 2019-08-03 17:31:39 +01:00
Miguel Dantas 5961b45140 [MEDIA][UI] In case an attachment preview isn't possible, the name is displayed anyway 2019-08-03 17:31:39 +01:00
Miguel Dantas 5f53738376 [MEDIA][UI] Added preview support for BMP, WEBP and ICO, displaying the name underneath, centered 2019-08-03 17:31:38 +01:00
Miguel Dantas 5eb4a7d711 [MEDIA] File downloader now in PHP, added proper name in the UI and changed the format for new attachment file names
The file downloader was changed from a simple redirect to the file to one
implemented in PHP, which should make it safer, by making it possible disallow
direct access to the file, to prevent executing of atttachments

The filename has a new format:
  bin2hex("{$original_name}")."-{$filehash}"
This format should be respected. Notice the dash, which is important to distinguish it from the previous
format, which was "{$hash}.{$ext}"

This change was made to both make the experience more user friendly, by
providing a readable name for files, as opposed to it's hash. This name is taken
from the upload filename, but, clearly, as this wasn't done before, it's
impossible to have a proper name for older files, so those are displayed as
"untitled.{$ext}".

This new name is displayed in the UI, instead of the previous name.
2019-08-03 17:31:36 +01:00
Diogo Cordeiro f717081893 [OEmbed] Revert filename change introduced with 96ce758c 2019-08-03 17:30:52 +01:00
Diogo Cordeiro 01b5118c6f [Oembed] Refactoring and some improvements (namely documentation)
Imported some changes from postActiv
2019-08-03 17:30:52 +01:00
Diogo Cordeiro d705bcbd98 [CORE] Use random_bytes() if available and improve common_confirmation_code() randomness.
With PHP 7 comes the [random_bytes()](https://php.net/manual/en/function.random-bytes.php) and the [random_int()](https://www.php.net/manual/en/function.random-int.php) function which generates cryptographically secure pseudo-random bytes and integers, respectively.
2019-08-03 17:29:14 +01:00
Diogo Cordeiro f0f5ecb756 [SCRIPTS] Fix sessiongc by XRevan86 2019-08-01 14:38:04 +01:00
Diogo Cordeiro c0342b1482 [DOCUMENTATION] Allow install.php to be ran with sample nginx conf 2019-08-01 14:37:59 +01:00
Diogo Cordeiro d1fc7c0774 [CORE] MySQL 5.5 support fully restored 2019-07-25 15:35:24 +01:00
Diogo Cordeiro 46be9b76ef [CORE] Fix wrong Profile_list schema and set created in user_im_prefs properly - by XRevan86
This reverts 496ab8c9, which was a bad correction of user_im_prefs values
2019-07-24 22:28:06 +01:00
Diogo Cordeiro 6c8d2e159e [DOCUMENTATION] Plugin events should be declared in the plugin's directory not in the core 2019-07-15 03:25:16 +01:00
Diogo Cordeiro db9bb6b5a1 [OStatus] null being returned instead of an empty array
Fixes: "Invalid argument supplied for foreach" in onEndFindMentions
2019-07-10 00:34:46 +01:00
Diogo Cordeiro 5ea0d74a57 [UI] Long strings/words in dents weren't being wrapped 2019-07-10 00:33:19 +01:00
Diogo Cordeiro 30a1a460b7 Minor reformatting of upgrade.php, doesn't change functionality 2019-07-01 23:14:39 +01:00
Diogo Cordeiro 5eb61c17d4 Regression introduced in daa5f87f fixed by XRevan86
require_once(): Failed opening required 'Error.php' in extlib/DB/DataObject.php on line 562
2019-07-01 23:14:23 +01:00
Diogo Cordeiro 0a4eeb89da [CORE][ROUTER] Fix wrong parameter in all/:tag by XRevan86 2019-07-01 22:40:21 +01:00
9688 arquivos alterados com 27201 adições e 1821929 exclusões
+43
Ver Arquivo
@@ -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 ###
+5
Ver Arquivo
@@ -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
Ver Arquivo
@@ -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
Ver Arquivo
@@ -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__)
);
-95
Ver Arquivo
@@ -1,95 +0,0 @@
## Code of Conduct
### Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, gender identity and expression, level of experience,
nationality, personal appearance, race, religion, or sexual identity and
orientation.
### Our Standards
Examples of behavior that contributes to creating a positive environment
include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
### Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
### Scope
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.
### Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at mattl@gnu.org. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.
### Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at [http://contributor-covenant.org/version/1/4][version]
[homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/4/
## The Code of Conflict
GNU social has a high submission standard and we want to keep quality code in the
codebase and bad code out of it. As such your code will be closely scrutinized,
and you might take this criticism personally. Please understand that this is
meant to keep the standards of the codebase up, and isn't meant personally. All
the same, this isn't an excuse for poor behaviour, and a reviewer shouldn't be
misbehaving towards submitters.
If however, anyone feels personally abused, threatened, or otherwise
uncomfortable due to this process, that is not acceptable. If so, please
contact the project team at mattl@gnu.org, and they will work to resolve the issue
to the best of their ability.
As a reviewer of code, please strive to keep things civil and focused on the
technical issues involved. We are all humans, and frustrations can be high on
both sides of the process. Try to keep in mind the immortal words of Bill and
Ted, "Be excellent to each other."
-112
Ver Arquivo
@@ -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
Ver Arquivo
@@ -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
Ver Arquivo
@@ -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
-355
Ver Arquivo
@@ -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;
}
```
+88
Ver Arquivo
@@ -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.
+3
Ver Arquivo
@@ -0,0 +1,3 @@
In the `dev` environment, the default values for the config table are reloaded on each HTTP request
In case you want to override this, add `SOCIAL_NO_RELOAD_DEFAULTS=1` to your .env.local file
+1
Ver Arquivo
@@ -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.
+1
Ver Arquivo
@@ -0,0 +1 @@
../../INSTALL.md
@@ -1,56 +0,0 @@
Initial simple way to Webfinger enable your domain -- needs PHP.
================================================================
This guide needs some updating, since it will only guide you to present
XML data (while the curl command likely gives you JSON). The workaround
is to simply make curl get 'webfinger.xml' instead, and/or have another
file that contains JSON, but that requires editing the PHP file as well.
Step 1
======
Put the 'dot-well-known' on your website, so it loads at:
https://example.com/.well-known/
(Remember the . at the beginning of this one, which is common practice
for "hidden" files and why we have renamed it "dot-")
Step 2
======
Edit the .well-known/host-meta file and replace "example.com" with the
domain name you're hosting the .well-known directory on.
Using vim you can do this as a quick method:
$ vim .well-known/host-meta [ENTER]
:%s/example.com/domain.com/ [ENTER]
:wq [ENTER]
Step 3
======
For each user on your site, and this might only be you...
In the webfinger directory, make a copy of the example@example.com.xml file
so that it's called (replace username and example.com with appropriate
values, the domain name should be the same as you're "socialifying"):
username@example.com.xml
Then edit the file contents, replacing "social.example.com" with your
GNU social instance's base path, and change the user ID number (and
nickname for the FOAF link) to that of your account on your social
site. If you don't know your user ID number, you can see this on your
GNU social profile page by looking at the destination URLs in the
Feeds links.
PROTIP: You can get the bulk of the contents (note the <Subject> element though)
from curling down your real webfinger data:
$ curl https://social.example.com/.well-known/webfinger?resource=acct:username@social.example.com
Finally
=======
Using this method, though fiddly, you can now be @user@domain without
the need for any prefixes for subdomains, etc.
@@ -1,5 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0" xmlns:hm="http://host-meta.net/xrd/1.0">
<Link rel="lrdd" type="application/xrd+xml"
template="https://example.com/.well-known/webfinger?resource={uri}"/>
</XRD>
@@ -1,35 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0">
<Subject>acct:username@example.com</Subject>
<Alias>acct:username@social.example.com</Alias>
<Alias>https://social.example.com/user/1</Alias>
<Link rel="http://webfinger.net/rel/profile-page"
type="text/html"
href="https://social.example.com/user/1"/>
<Link rel="http://schemas.google.com/g/2010#updates-from"
type="application/atom+xml"
href="https://social.example.com/api/statuses/user_timeline/1.atom"/>
<!-- Is this/was this ever supported?
<Link rel="http://microformats.org/profile/hcard"
type="text/html"
href="https://social.example.com/hcard"/> -->
<Link rel="http://gmpg.org/xfn/11"
type="text/html"
href="https://social.example.com/user/1"/>
<Link rel="describedby"
type="application/rdf+xml"
href="https://social.example.com/username/foaf"/>
<Link rel="http://salmon-protocol.org/ns/salmon-replies"
href="https://social.example.com/main/salmon/user/1"/>
<Link rel="http://salmon-protocol.org/ns/salmon-mention"
href="https://social.example.com/main/salmon/user/1"/>
<Link rel="http://ostatus.org/schema/1.0/subscribe"
template="https://social.example.com/main/ostatussub?profile={uri}"/>
</XRD>
@@ -1,43 +0,0 @@
<?php
/*
* GNU social
* Copyright (C) 2010, Free Software Foundation, Inc
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// basename should make sure we can't escape this directory
$u = basename($_GET['resource']);
if (!strpos($u, '@')) {
throw new Exception('Bad resource');
exit(1);
}
if (mb_strpos($u, 'acct:')===0) {
$u = substr($u, 5);
}
// Just to be a little bit safer, you know, with all the unicode stuff going on
$u = filter_var($u, FILTER_SANITIZE_EMAIL);
$f = $u . ".xml";
if (file_exists($f)) {
header('Content-Disposition: attachment; filename="'.urlencode($f).'"');
header('Content-type: application/xrd+xml');
echo file_get_contents($f);
}
@@ -1,100 +0,0 @@
Upgrading
=========
GNU social 1.1.x to GNU social 1.2.x
------------------------------------
If you are tracking the GNU social git repository, we currently recommend
using the "master" branch (or nightly if you want to use latest features)
and follow this procedure:
0. Backup your data. The StatusNet upgrade discussions below have some
guidelines to back up the database and files (mysqldump and rsync).
MAKE SURE YOU ARE THE SAME USER THAT RUNS THE PHP FILES WHILE PERFORMING
THE COMMANDS BELOW (I usually prepend the commands with 'sudo -u social')
1. Stop your queue daemons (you can run this command even if you do not
use the queue daemons):
$ bash scripts/stopdaemons.sh
2. Run the command to fetch the latest sourcecode:
$ git pull
If you are not using git we recommend following the instructions below
for upgrading "StatusNet 1.1.x to GNU social 1.2.x" as they are similar.
3. Run the upgrade script:
$ php scripts/upgrade.php
The upgrade script will likely take a long time because it will
upgrade the tables to another character encoding and make other
automated upgrades. Make sure it ends without errors. If you get
errors, create a new task on https://git.gnu.io/gnu/gnu-social/issues
4. Start your queue daemons again (you can run this command even if you
do not use the queue daemons):
$ bash scripts/startdaemons.sh
5. Report any issues at https://git.gnu.io/gnu/gnu-social/issues
If you are using ssh keys to log in to your server, you can make this
procedure pretty painless (assuming you have automated backups already).
Make sure you "cd" into the correct directory (in this case "htdocs")
and use the correct login@hostname combo:
$ ssh social@domain.example 'cd htdocs
&& bash scripts/stopdaemons.sh
&& git pull
&& time php scripts/upgrade.php
&& bash scripts/startdaemons.sh'
StatusNet 1.1.x to GNU social 1.2.x
-----------------------------------
We cannot support migrating from any other version of StatusNet than
1.1.1. If you are running a StatusNet version lower than this, please
follow the upgrade procedures for each respective StatusNet version.
You are now running StatusNet 1.1.1 and want to migrate to GNU social
1.2.x. Beware there may be changes in minimum required version of PHP
and the modules required, so review the INSTALL file (php5-intl is a
newly added dependency for example).
* Before you begin: Make backups. Always make backups. Of your entire
directory structure and the database too. All tables. All data. Alles.
0. Make a backup of everything. To backup the database, you can use a
variant of this command (you will be prompted for the database password):
$ mysqldump -u dbuser -p dbname > social-backup.sql
1. Stop your queue daemons 'bash scripts/stopdaemons.sh' should do it.
Not everyone runs queue daemons, but the above command won't hurt.
2. Unpack your GNU social code to a fresh directory. You can do this
by cloning our git repository:
$ git clone https://git.gnu.io/gnu/gnu-social.git gnusocial
3. Synchronize your local files to the GNU social directory. These
will be the local files such as avatars, config and files:
avatar/*
file/*
local/*
.htaccess
config.php
This command will point you in the right direction on how to do it:
$ rsync -avP statusnet/{.htaccess,avatar,file,local,config.php} gnusocial/
4. Replace your old StatusNet directory with the new GNU social
directory in your webserver root.
5. Run the upgrade script: 'php scripts/upgrade.php'
The upgrade script will likely take a long time because it will
upgrade the tables to another character encoding and make other
automated upgrades. Make sure it ends without errors. If you get
errors, create a new task on https://git.gnu.io/gnu/gnu-social/issues
6. Start your queue daemons: 'bash scripts/startdaemons.sh'
7. Report any issues at https://git.gnu.io/gnu/gnu-social/issues
@@ -1,55 +0,0 @@
### GNU social "fancy URL" setup
#
# Change the "RewriteBase" in the new .htaccess file to be the URL path
# to your GNU Social installation on your server. Typically this will
# be the path to your GNU Social directory relative to your Web root.
# If you are installing it in the root directory, leave it as '/'.
#
# If it doesn't work, double-check that AllowOverride for the GNU Social
# directory is 'All' in your Apache configuration file. This can be
# * /etc/apache2/apache2.conf (generic)
# * /etc/apache2/sites-available/default(on Debian and Ubuntu)
# * ...many other variations depending on distribution...
#
# See the Apache documentation for .htaccess files for more details:
# https://httpd.apache.org/docs/2.4/howto/htaccess.html
#
# Also, check that mod_rewrite is installed and enabled:
# https://httpd.apache.org/docs/2.4/mod/mod_rewrite.html
<IfModule mod_rewrite.c>
RewriteEngine On
# NOTE: change this to your actual GNU social base URL path,
# minus the domain part:
#
# https://social.example.com/ => /
# https://example.com/social/ => /social/
#
RewriteBase /
#RewriteBase /mublog/
## Uncomment these if having trouble with API authentication
## when PHP is running in CGI or FastCGI mode.
#
#RewriteCond %{HTTP:Authorization} ^(.*)
#RewriteRule ^(.*) - [E=HTTP_AUTHORIZATION:%1]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) index.php?p=$1 [L,QSA]
## You can also use PATHINFO by using this RewriteRule instead:
# RewriteRule (.*) index.php/$1 [L,QSA]
</IfModule>
<FilesMatch "\.(ini)">
<IfVersion < 2.3>
Order allow,deny
Deny from all
</IfVersion>
<IfVersion >= 2.3>
Require all denied
</IfVersion>
</FilesMatch>
@@ -1,28 +0,0 @@
# This is completely optional, but if you're running a site with
# ssl="always" configured, then you might as well redirect any of
# your stray HTTP visitors to HTTPS.
#
#$HTTP["scheme"] == "http" {
# $HTTP["host"] =~ "^(social\.example\.com)$" {
# url.redirect = ( "^\/?(.*)" => "https://%1/$1" )
# server.name = "%1"
# }
#}
# If you're using vhosts, you should have per-vhost server.document-root
# settings too! Read how in the respective alternative vhost modules.
#$HTTP["host"] =~ "^social\.example\.com$" {
# NOTE: configure fastcgi/cgi/fpm here if you're using per-user cgi/fpm
# fastcgi.server += ( ".php" =>
# ( "localhost" => (
# "host" => "127.0.0.1",
# "port" => "9000"
# ))
# )
dir-listing.activate = "disable"
# Make sure "mod_rewrite" is enabled in server.modules
url.rewrite-if-not-file = ( "^/(.*)$" => "/index.php/$1" )
#}
@@ -1,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
Ver Arquivo
@@ -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
Ver Arquivo
@@ -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
Ver Arquivo
@@ -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
-214
Ver Arquivo
@@ -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);
}
}
-161
Ver Arquivo
@@ -1,161 +0,0 @@
<?php
/**
* StatusNet - the distributed open-source microblogging tool
* Copyright (C) 2008-2010, StatusNet, Inc.
*
* Action to add a people tag to a user.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* PHP version 5
*
* @category Action
* @package StatusNet
* @author Shashi Gowda <connect2shashi@gmail.com>
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPLv3
* @link http://status.net/
*/
if (!defined('STATUSNET')) {
exit(1);
}
require_once INSTALLDIR . '/lib/togglepeopletag.php';
/**
*
* Action to tag a profile with a single tag.
*
* Takes parameters:
*
* - tagged: the ID of the profile being tagged
* - token: session token to prevent CSRF attacks
* - ajax: boolean; whether to return Ajax or full-browser results
* - peopletag_id: the ID of the tag being used
*
* Only works if the current user is logged in.
*
* @category Action
* @package StatusNet
* @author Shashi Gowda <connect2shashi@gmail.com>
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPLv3
* @link http://status.net/
*/
class AddpeopletagAction extends Action
{
var $user;
var $tagged;
var $peopletag;
/**
* Check pre-requisites and instantiate attributes
*
* @param Array $args array of arguments (URL, GET, POST)
*
* @return boolean success flag
*/
function prepare(array $args = array())
{
parent::prepare($args);
// CSRF protection
$token = $this->trimmed('token');
if (!$token || $token != common_session_token()) {
// TRANS: Client error displayed when the session token does not match or is not given.
$this->clientError(_('There was a problem with your session token.'.
' Try again, please.'));
}
// Only for logged-in users
$this->user = common_current_user();
if (empty($this->user)) {
// TRANS: Error message displayed when trying to perform an action that requires a logged in user.
$this->clientError(_('Not logged in.'));
}
// Profile to subscribe to
$tagged_id = $this->arg('tagged');
$this->tagged = Profile::getKV('id', $tagged_id);
if (empty($this->tagged)) {
// TRANS: Client error displayed trying to perform an action related to a non-existing profile.
$this->clientError(_('No such profile.'));
}
$id = $this->arg('peopletag_id');
$this->peopletag = Profile_list::getKV('id', $id);
if (empty($this->peopletag)) {
// TRANS: Client error displayed trying to reference a non-existing list.
$this->clientError(_('No such list.'));
}
return true;
}
/**
* Handle request
*
* Does the tagging and returns results.
*
* @param Array $args unused.
*
* @return void
*/
function handle()
{
// Throws exception on error
$ptag = Profile_tag::setTag($this->user->id, $this->tagged->id,
$this->peopletag->tag);
if (!$ptag) {
$user = User::getKV('id', $id);
if ($user) {
$this->clientError(
// TRANS: Client error displayed when an unknown error occurs when adding a user to a list.
// TRANS: %s is a username.
sprintf(_('There was an unexpected error while listing %s.'),
$user->nickname));
} else {
// TRANS: Client error displayed when an unknown error occurs when adding a user to a list.
// TRANS: %s is a profile URL.
$this->clientError(sprintf(_('There was a problem listing %s. ' .
'The remote server is probably not responding correctly. ' .
'Please try retrying later.'), $this->profile->profileurl));
}
}
if ($this->boolean('ajax')) {
$this->startHTML('text/xml;charset=utf-8');
$this->elementStart('head');
// TRANS: Title after adding a user to a list.
$this->element('title', null, _m('TITLE','Listed'));
$this->elementEnd('head');
$this->elementStart('body');
$unsubscribe = new UntagButton($this, $this->tagged, $this->peopletag);
$unsubscribe->show();
$this->elementEnd('body');
$this->endHTML();
} else {
$url = common_local_url('subscriptions',
array('nickname' => $this->user->nickname));
common_redirect($url, 303);
}
}
}
-182
Ver Arquivo
@@ -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));
}
}
-73
Ver Arquivo
@@ -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;
}
}
-121
Ver Arquivo
@@ -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);
}
}
-194
Ver Arquivo
@@ -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);
}
}
-90
Ver Arquivo
@@ -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');
}
}
-147
Ver Arquivo
@@ -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');
}
}
}
-89
Ver Arquivo
@@ -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');
}
}
-141
Ver Arquivo
@@ -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');
}
}
}
-112
Ver Arquivo
@@ -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');
}
}
}
-85
Ver Arquivo
@@ -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;
}
}
-136
Ver Arquivo
@@ -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();
}
}
-106
Ver Arquivo
@@ -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;
}
}
-113
Ver Arquivo
@@ -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);
}
}
}
-102
Ver Arquivo
@@ -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.'));
}
}
}
-115
Ver Arquivo
@@ -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;
}
}
-69
Ver Arquivo
@@ -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');
}
}
-227
Ver Arquivo
@@ -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;
}
}
}
-99
Ver Arquivo
@@ -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;
}
}
-111
Ver Arquivo
@@ -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);
}
}
-114
Ver Arquivo
@@ -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);
}
}
-118
Ver Arquivo
@@ -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;
}
}
-169
Ver Arquivo
@@ -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;
}
}
-148
Ver Arquivo
@@ -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;
}
}
-82
Ver Arquivo
@@ -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;
}
}
-190
Ver Arquivo
@@ -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;
}
}
-181
Ver Arquivo
@@ -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;
}
}
-125
Ver Arquivo
@@ -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;
}
}
-124
Ver Arquivo
@@ -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);
}
}
}
-123
Ver Arquivo
@@ -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);
}
}
}
-211
Ver Arquivo
@@ -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;
}
}
-208
Ver Arquivo
@@ -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;
}
}
-181
Ver Arquivo
@@ -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;
}
}
-247
Ver Arquivo
@@ -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;
}
}
-163
Ver Arquivo
@@ -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;
}
}
-76
Ver Arquivo
@@ -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;
}
}
-240
Ver Arquivo
@@ -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;
}
}
-112
Ver Arquivo
@@ -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;
}
}
-131
Ver Arquivo
@@ -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);
}
}
-124
Ver Arquivo
@@ -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);
}
}
-232
Ver Arquivo
@@ -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;
}
}
-87
Ver Arquivo
@@ -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;
}
}
}
-102
Ver Arquivo
@@ -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);
}
}
-110
Ver Arquivo
@@ -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);
}
}
-195
Ver Arquivo
@@ -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;
}
}
-122
Ver Arquivo
@@ -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;
}
}
-707
Ver Arquivo
@@ -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);
}
}
}
-172
Ver Arquivo
@@ -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);
}
}
-152
Ver Arquivo
@@ -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);
}
}
}
-392
Ver Arquivo
@@ -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');
}
}
-136
Ver Arquivo
@@ -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;
}
}
-113
Ver Arquivo
@@ -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);
}
}
}
}
-224
Ver Arquivo
@@ -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");
}
}
-368
Ver Arquivo
@@ -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;
}
}
-254
Ver Arquivo
@@ -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;
}
}
}
-344
Ver Arquivo
@@ -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>&lt;a href="http://somesourcecode.net/microblog/"&gt;mbpidgin&lt;/a&gt;</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;
}
}
-221
Ver Arquivo
@@ -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;
}
}
-249
Ver Arquivo
@@ -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;
}
}
-248
Ver Arquivo
@@ -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;
}
}
-254
Ver Arquivo
@@ -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;
}
}
-19
Ver Arquivo
@@ -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);
}
}
-335
Ver Arquivo
@@ -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;
}
}
-228
Ver Arquivo
@@ -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;
}
}
-409
Ver Arquivo
@@ -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);
}
}
}
-85
Ver Arquivo
@@ -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);
}
}
-80
Ver Arquivo
@@ -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;
}
}
-80
Ver Arquivo
@@ -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;
}
}
-117
Ver Arquivo
@@ -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