| 
									
										
										
										
											2008-07-12 04:12:47 -04:00
										 |  |  | <?php | 
					
						
							|  |  |  | /* | 
					
						
							|  |  |  |  * Laconica - a distributed open-source microblogging tool | 
					
						
							|  |  |  |  * Copyright (C) 2008, Controlez-Vous, 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 | 
					
						
							| 
									
										
										
										
											2008-12-23 14:19:07 -05:00
										 |  |  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.     See the | 
					
						
							| 
									
										
										
										
											2008-07-12 04:12:47 -04:00
										 |  |  |  * GNU Affero General Public License for more details. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * You should have received a copy of the GNU Affero General Public License | 
					
						
							| 
									
										
										
										
											2008-12-23 14:19:07 -05:00
										 |  |  |  * along with this program.     If not, see <http://www.gnu.org/licenses/>. | 
					
						
							| 
									
										
										
										
											2008-07-12 04:12:47 -04:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | if (!defined('LACONICA')) { exit(1); } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-23 14:49:23 -05:00
										 |  |  | class ApiAction extends Action | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2008-07-12 04:12:47 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-23 14:19:07 -05:00
										 |  |  |     var $user; | 
					
						
							|  |  |  |     var $content_type; | 
					
						
							|  |  |  |     var $api_arg; | 
					
						
							|  |  |  |     var $api_method; | 
					
						
							|  |  |  |     var $api_action; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-23 14:33:23 -05:00
										 |  |  |     function handle($args) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2008-12-23 14:19:07 -05:00
										 |  |  |         parent::handle($args); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->api_action = $this->arg('apiaction'); | 
					
						
							|  |  |  |         $method = $this->arg('method'); | 
					
						
							|  |  |  |         $argument = $this->arg('argument'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (isset($argument)) { | 
					
						
							|  |  |  |             $cmdext = explode('.', $argument); | 
					
						
							|  |  |  |             $this->api_arg =  $cmdext[0]; | 
					
						
							|  |  |  |             $this->api_method = $method; | 
					
						
							|  |  |  |             $this->content_type = strtolower($cmdext[1]); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # Requested format / content-type will be an extension on the method
 | 
					
						
							|  |  |  |             $cmdext = explode('.', $method); | 
					
						
							|  |  |  |             $this->api_method = $cmdext[0]; | 
					
						
							|  |  |  |             $this->content_type = strtolower($cmdext[1]); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if ($this->requires_auth()) { | 
					
						
							|  |  |  |             if (!isset($_SERVER['PHP_AUTH_USER'])) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 # This header makes basic auth go
 | 
					
						
							|  |  |  |                 header('WWW-Authenticate: Basic realm="Laconica API"'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 # If the user hits cancel -- bam!
 | 
					
						
							|  |  |  |                 $this->show_basic_auth_error(); | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 $nickname = $_SERVER['PHP_AUTH_USER']; | 
					
						
							|  |  |  |                 $password = $_SERVER['PHP_AUTH_PW']; | 
					
						
							|  |  |  |                 $user = common_check_user($nickname, $password); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 if ($user) { | 
					
						
							|  |  |  |                     $this->user = $user; | 
					
						
							|  |  |  |                     $this->process_command(); | 
					
						
							|  |  |  |                 } else { | 
					
						
							|  |  |  |                     # basic authentication failed
 | 
					
						
							|  |  |  |                     $this->show_basic_auth_error(); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-08 16:15:08 -05:00
										 |  |  | 			# Caller might give us a username even if not required
 | 
					
						
							|  |  |  | 			if (isset($_SERVER['PHP_AUTH_USER'])) { | 
					
						
							|  |  |  | 				$user = User::staticGet('nickname', $_SERVER['PHP_AUTH_USER']); | 
					
						
							|  |  |  | 				if ($user) { | 
					
						
							|  |  |  | 					$this->user = $user; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				# Twitter doesn't throw an error if the user isn't found
 | 
					
						
							| 
									
										
										
										
											2008-10-16 22:36:38 -04:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2008-12-23 14:19:07 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |             $this->process_command(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-23 14:33:23 -05:00
										 |  |  |     function process_command() | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2008-12-23 14:19:07 -05:00
										 |  |  |         $action = "twitapi$this->api_action"; | 
					
						
							|  |  |  |         $actionfile = INSTALLDIR."/actions/$action.php"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (file_exists($actionfile)) { | 
					
						
							|  |  |  |             require_once($actionfile); | 
					
						
							|  |  |  |             $action_class = ucfirst($action)."Action"; | 
					
						
							|  |  |  |             $action_obj = new $action_class(); | 
					
						
							| 
									
										
										
										
											2008-07-12 04:12:47 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-03 16:03:58 -05:00
										 |  |  |             if (!$action_obj->prepare($this->args)) { | 
					
						
							|  |  |  |                 return; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-23 14:19:07 -05:00
										 |  |  |             if (method_exists($action_obj, $this->api_method)) { | 
					
						
							|  |  |  |                 $apidata = array(    'content-type' => $this->content_type, | 
					
						
							|  |  |  |                                     'api_method' => $this->api_method, | 
					
						
							|  |  |  |                                     'api_arg' => $this->api_arg, | 
					
						
							|  |  |  |                                     'user' => $this->user); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 call_user_func(array($action_obj, $this->api_method), $_REQUEST, $apidata); | 
					
						
							|  |  |  |             } else { | 
					
						
							| 
									
										
										
										
											2009-01-15 23:03:38 +00:00
										 |  |  |                 $this->clientError("API method not found!", $code=404); | 
					
						
							| 
									
										
										
										
											2008-12-23 14:19:07 -05:00
										 |  |  |             } | 
					
						
							|  |  |  |         } else { | 
					
						
							| 
									
										
										
										
											2009-01-15 23:03:38 +00:00
										 |  |  |             $this->clientError("API method not found!", $code=404); | 
					
						
							| 
									
										
										
										
											2008-12-23 14:19:07 -05:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Whitelist of API methods that don't need authentication
 | 
					
						
							| 
									
										
										
										
											2008-12-23 14:33:23 -05:00
										 |  |  |     function requires_auth() | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2008-12-23 14:19:07 -05:00
										 |  |  |         static $noauth = array( 'statuses/public_timeline', | 
					
						
							|  |  |  |                                 'statuses/show', | 
					
						
							|  |  |  |                                 'users/show', | 
					
						
							|  |  |  |                                 'help/test', | 
					
						
							| 
									
										
										
										
											2008-12-30 15:37:47 -05:00
										 |  |  |                                 'help/downtime_schedule', | 
					
						
							|  |  |  |                                 'laconica/version', | 
					
						
							|  |  |  |                                 'laconica/config', | 
					
						
							|  |  |  |                                 'laconica/wadl'); | 
					
						
							| 
									
										
										
										
											2008-12-23 14:19:07 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         static $bareauth = array('statuses/user_timeline', | 
					
						
							| 
									
										
										
										
											2009-03-07 13:52:52 +01:00
										 |  |  |                                  'statuses/friends_timeline', | 
					
						
							| 
									
										
										
										
											2008-12-23 14:19:07 -05:00
										 |  |  |                                  'statuses/friends', | 
					
						
							| 
									
										
										
										
											2009-03-07 13:52:52 +01:00
										 |  |  |                                  'statuses/replies', | 
					
						
							| 
									
										
										
										
											2008-12-23 14:19:07 -05:00
										 |  |  |                                  'statuses/followers', | 
					
						
							|  |  |  |                                  'favorites/favorites'); | 
					
						
							| 
									
										
										
										
											2008-07-19 11:55:26 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-18 15:33:52 -08:00
										 |  |  |         $fullname = "$this->api_action/$this->api_method"; | 
					
						
							| 
									
										
										
										
											2009-04-13 15:49:26 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |         // If the site is "private", all API methods except laconica/config
 | 
					
						
							| 
									
										
										
										
											2009-02-18 15:33:52 -08:00
										 |  |  |         // need authentication
 | 
					
						
							| 
									
										
										
										
											2008-12-03 13:34:32 -05:00
										 |  |  |         if (common_config('site', 'private')) { | 
					
						
							| 
									
										
										
										
											2009-02-18 15:33:52 -08:00
										 |  |  |             return $fullname != 'laconica/config' || false; | 
					
						
							| 
									
										
										
										
											2008-12-03 13:34:32 -05:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-23 14:19:07 -05:00
										 |  |  |         if (in_array($fullname, $bareauth)) { | 
					
						
							|  |  |  |             # bareauth: only needs auth if without an argument
 | 
					
						
							|  |  |  |             if ($this->api_arg) { | 
					
						
							|  |  |  |                 return false; | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 return true; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } else if (in_array($fullname, $noauth)) { | 
					
						
							|  |  |  |             # noauth: never needs auth
 | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             # everybody else needs auth
 | 
					
						
							|  |  |  |             return true; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-23 14:33:23 -05:00
										 |  |  |     function show_basic_auth_error() | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2008-12-23 14:19:07 -05:00
										 |  |  |         header('HTTP/1.1 401 Unauthorized'); | 
					
						
							|  |  |  |         $msg = 'Could not authenticate you.'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if ($this->content_type == 'xml') { | 
					
						
							|  |  |  |             header('Content-Type: application/xml; charset=utf-8'); | 
					
						
							| 
									
										
										
										
											2009-01-23 01:19:19 -08:00
										 |  |  |             $this->startXML(); | 
					
						
							| 
									
										
										
										
											2009-01-15 22:57:15 +00:00
										 |  |  |             $this->elementStart('hash'); | 
					
						
							|  |  |  |             $this->element('error', null, $msg); | 
					
						
							|  |  |  |             $this->element('request', null, $_SERVER['REQUEST_URI']); | 
					
						
							|  |  |  |             $this->elementEnd('hash'); | 
					
						
							| 
									
										
										
										
											2009-01-23 01:19:19 -08:00
										 |  |  |             $this->endXML(); | 
					
						
							| 
									
										
										
										
											2008-12-23 14:19:07 -05:00
										 |  |  |         } else if ($this->content_type == 'json')  { | 
					
						
							|  |  |  |             header('Content-Type: application/json; charset=utf-8'); | 
					
						
							|  |  |  |             $error_array = array('error' => $msg, 'request' => $_SERVER['REQUEST_URI']); | 
					
						
							|  |  |  |             print(json_encode($error_array)); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             header('Content-type: text/plain'); | 
					
						
							|  |  |  |             print "$msg\n"; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-13 15:52:15 -04:00
										 |  |  |     function isReadOnly($args) | 
					
						
							| 
									
										
										
										
											2008-12-23 14:33:23 -05:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2009-04-13 15:49:26 -04:00
										 |  |  |         $apiaction = $args['apiaction']; | 
					
						
							|  |  |  |         $method = $args['method']; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-23 14:19:07 -05:00
										 |  |  |         list($cmdtext, $fmt) = explode('.', $method); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         static $write_methods = array( | 
					
						
							|  |  |  |             'account' => array('update_location', 'update_delivery_device', 'end_session'), | 
					
						
							|  |  |  |             'blocks' => array('create', 'destroy'), | 
					
						
							|  |  |  |             'direct_messages' => array('create', 'destroy'), | 
					
						
							|  |  |  |             'favorites' => array('create', 'destroy'), | 
					
						
							|  |  |  |             'friendships' => array('create', 'destroy'), | 
					
						
							|  |  |  |             'help' => array(), | 
					
						
							|  |  |  |             'notifications' => array('follow', 'leave'), | 
					
						
							|  |  |  |             'statuses' => array('update', 'destroy'), | 
					
						
							|  |  |  |             'users' => array() | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (array_key_exists($apiaction, $write_methods)) { | 
					
						
							|  |  |  |             if (!in_array($cmdtext, $write_methods[$apiaction])) { | 
					
						
							|  |  |  |                 return true; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2008-07-12 04:12:47 -04:00
										 |  |  | } |