var $api_arg;
var $api_method;
var $api_action;
-
+
function handle($args) {
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 = $cmdext[0];
$this->content_type = strtolower($cmdext[1]);
}
-
+
# XXX Maybe check to see if the command actually exists first?
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();
+ $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();
- }
+ $this->show_basic_auth_error();
+ }
}
} else {
$this->process_command();
- }
+ }
}
-
- function process_command() {
+
+ function process_command() {
$action = "twitapi$this->api_action";
- $actionfile = INSTALLDIR."/actions/$action.php";
+ $actionfile = INSTALLDIR."/actions/$action.php";
if (file_exists($actionfile)) {
require_once($actionfile);
$action_class = ucfirst($action)."Action";
$action_obj = new $action_class();
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);
- # all API methods should exit()
}
+ } else {
+ common_user_error("API method not found!", $code=404);
}
- common_user_error("API method not found!", $code=404);
}
-
# Whitelist of API methods that don't need authentication
function requires_auth() {
static $noauth = array( 'statuses/public_timeline',
'statuses/show',
'users/show',
- 'help/test',
+ 'help/test',
'help/downtime_schedule');
-
+
static $bareauth = array('statuses/user_timeline',
- 'statuses/friends',
+ 'statuses/friends',
'statuses/followers');
$fullname = "$this->api_action/$this->api_method";
-
+
if (in_array($fullname, $bareauth)) {
# bareauth: only needs auth if without an argument
if ($this->api_arg) {
return true;
}
}
-
+
function show_basic_auth_error() {
header('HTTP/1.1 401 Unauthorized');
header('Content-type: text/plain');
print("Could not authenticate you."); # exactly what Twitter says - no \n
- exit();
}
-
+
}
class TwitapiaccountAction extends TwitterapiAction {
function is_readonly() {
-
+
static $write_methods = array( 'update_location',
'update_delivery_device');
-
- $cmdtext = explode('.', $this->arg('method'));
-
- if (in_array($cmdtext[0], $write_methods)) {
+
+ $cmdtext = explode('.', $this->arg('method'));
+
+ if (in_array($cmdtext[0], $write_methods)) {
return false;
}
-
+
return true;
}
function verify_credentials($args, $apidata) {
if ($apidata['content-type'] == 'xml') {
- header('Content-Type: application/xml; charset=utf-8');
+ header('Content-Type: application/xml; charset=utf-8');
print '<authorized>true</authorized>';
} elseif ($apidata['content-type'] == 'json') {
- header('Content-Type: application/json; charset=utf-8');
+ header('Content-Type: application/json; charset=utf-8');
print '{"authorized":true}';
} else {
common_user_error(_('API method not found!'), $code=404);
}
-
- exit();
+
}
-
+
function end_session($args, $apidata) {
parent::handle($args);
common_server_error(_('API method under construction.'), $code=501);
- exit();
}
-
+
function update_location($args, $apidata) {
parent::handle($args);
- if (!in_array($apidata['content-type'], array('xml', 'json'))) {
- common_user_error(_('API method not found!'), $code = 404);
- exit;
- }
-
if ($_SERVER['REQUEST_METHOD'] != 'POST') {
$this->client_error(_('This method requires a POST.'), 400, $apidata['content-type']);
- exit();
+ return;
}
$location = trim($this->arg('location'));
if (!is_null($location) && strlen($location) > 255) {
-
- // XXX: But Twitter just truncates and runs with it. -- Zach
+
+ // XXX: But Twitter just truncates and runs with it. -- Zach
$this->client_error(_('That\'s too long. Max notice size is 255 chars.'), 406, $apidate['content-type']);
- exit();
+ return;
}
-
+
$user = $apidata['user'];
$profile = $user->getProfile();
-
+
if (!$profile) {
common_server_error(_('User has no profile.'));
- exit();
+ return;
}
-
+
$orig_profile = clone($profile);
$profile->location = $location;
-
+
common_debug('Old profile: ' . common_log_objstring($orig_profile), __FILE__);
common_debug('New profile: ' . common_log_objstring($profile), __FILE__);
if (!$result) {
common_log_db_error($profile, 'UPDATE', __FILE__);
common_server_error(_('Couldn\'t save profile.'));
- exit();
+ return;
}
common_broadcast_profile($profile);
$type = $apidata['content-type'];
-
+
$this->init_document($type);
$this->show_profile($profile, $type);
$this->end_document($type);
-
- exit();
}
function update_delivery_device($args, $apidata) {
parent::handle($args);
common_server_error(_('API method under construction.'), $code=501);
- exit();
}
-
+
function rate_limit_status($args, $apidata) {
parent::handle($args);
common_server_error(_('API method under construction.'), $code=501);
- exit();
}
}
\ No newline at end of file
function create($args, $apidata) {
parent::handle($args);
common_server_error(_('API method under construction.'), $code=501);
- exit();
}
-
+
function destroy($args, $apidata) {
parent::handle($args);
common_server_error(_('API method under construction.'), $code=501);
- exit();
}
-
+
}
\ No newline at end of file
common_user_error(_('API method not found!'), $code = 404);
}
- exit();
}
// had to change this from "new" to "create" to avoid PHP reserved word
if ($_SERVER['REQUEST_METHOD'] != 'POST') {
$this->client_error(_('This method requires a POST.'), 400, $apidata['content-type']);
- exit();
+ return;
}
$user = $apidata['user'];
} else if (mb_strlen($status) > 140) {
$this->client_error(_('That\'s too long. Max message size is 140 chars.'),
$code = 406, $apidata['content-type']);
- exit();
+ return;
}
$other = $this->get_user($this->trimmed('user'));
if (!$other) {
$this->client_error(_('Recipient user not found.'), $code = 403, $apidata['content-type']);
- exit();
+ return;
} else if (!$user->mutuallySubscribed($other)) {
$this->client_error(_('Can\'t send direct messages to users who aren\'t your friend.'),
$code = 403, $apidata['content-type']);
- exit();
+ return;
} else if ($user->id == $other->id) {
// Sending msgs to yourself is allowed by Twitter
$this->client_error(_('Don\'t send a message to yourself; just say it to yourself quietly instead.'),
$code = 403, $apidata['content-type']);
- exit();
+ return;
}
$message = Message::saveNew($user->id, $other->id, $content, $source);
if (is_string($message)) {
$this->server_error($message);
- exit();
+ return;
}
$this->notify($user, $other, $message);
$this->show_single_json_dmsg($message);
}
- exit();
}
function destroy($args, $apidata) {
parent::handle($args);
common_server_error(_('API method under construction.'), $code=501);
- exit();
}
function show_xml_dmsgs($message) {
if (!$profile) {
common_server_error(_('User has no profile.'));
- exit();
+ return;
}
$page = $this->arg('page');
if (!$notice) {
common_server_error(_('Could not retrieve favorite notices.'));
- exit();
+ return;
}
$sitename = common_config('site', 'name');
common_user_error(_('API method not found!'), $code = 404);
}
- exit();
}
function create($args, $apidata) {
if (!in_array($apidata['content-type'], array('xml', 'json'))) {
common_user_error(_('API method not found!'), $code = 404);
- exit;
+ return;
}
// Check for RESTfulness
if (!in_array($_SERVER['REQUEST_METHOD'], array('POST', 'DELETE'))) {
// XXX: Twitter just prints the err msg, no XML / JSON.
$this->client_error(_('This method requires a POST or DELETE.'), 400, $apidata['content-type']);
- exit();
+ return;
}
$user = $apidata['user'];
if (!$notice) {
$this->client_error(_('No status found with that ID.'), 404, $apidata['content-type']);
- exit();
+ return;
}
// XXX: Twitter lets you fave things repeatedly via api.
if ($user->hasFave($notice)) {
$this->client_error(_('This notice is already a favorite!'), 403, $apidata['content-type']);
- exit();
+ return;
}
common_debug("notice: " . $apidata['api_arg']);
if (!$fave) {
common_server_error(_('Could not create favorite.'));
- exit();
+ return;
}
$this->notify($fave, $notice, $user);
$this->show_single_json_status($notice);
}
- exit();
}
function destroy($args, $apidata) {
parent::handle($args);
common_server_error(_('API method under construction.'), $code=501);
- exit();
}
// XXX: these two funcs swiped from faves. Maybe put in util.php, or some common base class?
if ($_SERVER['REQUEST_METHOD'] != 'POST') {
$this->client_error(_('This method requires a POST.'), 400, $apidata['content-type']);
- exit();
+ return;
}
$id = $apidata['api_arg'];
if (!$other) {
$this->client_error(_('Could not follow user: User not found.'), 403, $apidata['content-type']);
- exit();
+ return;
}
$user = $apidata['user'];
if ($user->isSubscribed($other)) {
$errmsg = sprintf(_('Could not follow user: %s is already on your list.'), $other->nickname);
$this->client_error($errmsg, 403, $apidata['content-type']);
- exit();
+ return;
}
$sub = new Subscription();
if (!$result) {
$errmsg = sprintf(_('Could not follow user: %s is already on your list.'), $other->nickname);
$this->client_error($errmsg, 400, $apidata['content-type']);
- exit();
+ return;
}
$sub->query('COMMIT');
$this->init_document($type);
$this->show_profile($other, $type);
$this->end_document($type);
- exit();
+
}
//destroy
if (!in_array($_SERVER['REQUEST_METHOD'], array('POST', 'DELETE'))) {
$this->client_error(_('This method requires a POST or DELETE.'), 400, $apidata['content-type']);
- exit();
+ return;
}
$id = $apidata['api_arg'];
$sub->query('COMMIT');
} else {
$this->client_error(_('You are not friends with the specified user.'), 403, $apidata['content-type']);
- exit();
+ return;
}
$type = $apidata['content-type'];
$this->init_document($type);
$this->show_profile($other, $type);
$this->end_document($type);
- exit();
+
}
// Tests if a friendship exists between two users.
if (!in_array($apidata['content-type'], array('xml', 'json'))) {
common_user_error(_('API method not found!'), $code = 404);
- exit;
+ return;
}
$user_a_id = $this->trimmed('user_a');
if (!$user_a || !$user_b) {
$this->client_error(_('Two user ids or screen_names must be supplied.'), 400, $apidata['content-type']);
- exit();
+ return;
}
if ($user_a->isSubscribed($user_b)) {
break;
}
- exit();
}
}
\ No newline at end of file
} else {
common_user_error(_('API method not found!'), $code=404);
}
- exit();
+
}
function downtime_schedule($args, $apidata) {
parent::handle($args);
common_server_error(_('API method under construction.'), $code=501);
- exit();
}
}
\ No newline at end of file
function follow($args, $apidata) {
parent::handle($args);
common_server_error(_('API method under construction.'), $code=501);
- exit();
}
-
+
function leave($args, $apidata) {
parent::handle($args);
common_server_error(_('API method under construction.'), $code=501);
- exit();
}
-
+
}
\ No newline at end of file
common_server_error(_('Couldn\'t find any statuses.'), $code = 503);
}
- exit();
}
/*
common_user_error(_('API method not found!'), $code = 404);
}
- exit();
}
/*
if (!$profile) {
common_server_error(_('User has no profile.'));
- exit();
+ return;
}
$count = $this->arg('count');
common_user_error(_('API method not found!'), $code = 404);
}
- exit();
}
function update($args, $apidata) {
if (!in_array($apidata['content-type'], array('xml', 'json'))) {
common_user_error(_('API method not found!'), $code = 404);
- exit;
+ return;
}
if ($_SERVER['REQUEST_METHOD'] != 'POST') {
$this->client_error(_('This method requires a POST.'), 400, $apidata['content-type']);
- exit();
+ return;
}
$user = $apidata['user'];
// No error is given, but the status is not posted to the
// user's timeline. Seems bad. Shouldn't we throw an
// errror? -- Zach
- exit();
+ return;
} else if (mb_strlen($status) > 140) {
// that assume Twitter will truncate for them. Should we just
// truncate too? -- Zach
$this->client_error(_('That\'s too long. Max notice size is 140 chars.'), $code = 406, $apidata['content-type']);
- exit();
+ return;
}
$reply_to = NULL;
$reply_to = $in_reply_to_status_id;
} else {
$this->client_error(_('Not found'), $code = 404, $apidata['content-type']);
- exit();
+ return;
}
}
if (is_string($notice)) {
$this->server_error($notice);
- exit();
+ return;
}
common_broadcast_notice($notice);
$apidata['api_arg'] = $notice->id;
$this->show($args, $apidata);
- exit();
}
/*
common_user_error(_('API method not found!'), $code = 404);
}
- exit();
}
function show($args, $apidata) {
if (!in_array($apidata['content-type'], array('xml', 'json'))) {
common_user_error(_('API method not found!'), $code = 404);
- exit;
+ return;
}
$notice_id = $apidata['api_arg'];
$this->client_error(_('No status with that ID found.'), 404, $apidata['content-type']);
}
- exit();
}
if (!in_array($apidata['content-type'], array('xml', 'json'))) {
common_user_error(_('API method not found!'), $code = 404);
- exit;
+ return;
}
// Check for RESTfulness
if (!in_array($_SERVER['REQUEST_METHOD'], array('POST', 'DELETE'))) {
// XXX: Twitter just prints the err msg, no XML / JSON.
$this->client_error(_('This method requires a POST or DELETE.'), 400, $apidata['content-type']);
- exit();
+ return;
}
$user = $apidata['user'];
if (!$notice) {
$this->client_error(_('No status found with that ID.'), 404, $apidata['content-type']);
- exit();
+ return;
}
if ($user->id == $notice->profile_id) {
$this->client_error(_('You may not delete another user\'s status.'), 403, $apidata['content-type']);
}
- exit();
}
# User Methods
$this->init_document($type);
$this->show_profiles($others, $type);
$this->end_document($type);
- exit();
}
function get_subs_user($apidata) {
break;
default:
$this->client_error(_('unsupported file type'));
- exit();
}
}
class TwitapiusersAction extends TwitterapiAction {
- function is_readonly() {
+ function is_readonly() {
return true;
}
-/*
+/*
Returns extended information of a given user, specified by ID or
screen name as per the required id parameter below. This information
includes design settings, so third party developers can theme their
* email. Optional. The email address of a user. Ex:
http://twitter.com/users/show.xml?email=test@example.com
-*/
+*/
function show($args, $apidata) {
parent::handle($args);
-
+
if (!in_array($apidata['content-type'], array('xml', 'json'))) {
common_user_error(_('API method not found!'), $code = 404);
- exit;
+ return;
}
-
+
$user = null;
$email = $this->arg('email');
-
+
if (isset($apidata['api_arg'])) {
if (is_numeric($apidata['api_arg'])) {
// by user id
- $user = User::staticGet($apidata['api_arg']);
+ $user = User::staticGet($apidata['api_arg']);
} else {
// by nickname
$nickname = common_canonical_nickname($apidata['api_arg']);
$user = User::staticGet('nickname', $nickname);
- }
+ }
} elseif ($email) {
// or, find user by email address
// XXX: The Twitter API spec say an id is *required*, but you can actually
// pull up a user with just an email address. -- Zach
- $user = User::staticGet('email', $email);
- }
+ $user = User::staticGet('email', $email);
+ }
if (!$user) {
// XXX: Twitter returns a random(?) user instead of throwing and err! -- Zach
$this->client_error(_('User not found.'), 404, $apidata['content-type']);
- exit();
+ return;
}
-
+
$profile = $user->getProfile();
if (!$profile) {
common_server_error(_('User has no profile.'));
- exit();
+ return;
}
$twitter_user = $this->twitter_user_array($profile, true);
$twitter_user['following'] = '';
$twitter_user['notifications'] = '';
- if ($apidata['content-type'] == 'xml') {
+ if ($apidata['content-type'] == 'xml') {
$this->init_document('xml');
$this->show_twitter_xml_user($twitter_user);
$this->end_document('xml');
$this->init_document('json');
$this->show_json_objects($twitter_user);
$this->end_document('json');
- }
-
- exit();
+ }
+
}
}
$twitter_status = $this->twitter_status_array($notice);
$this->show_twitter_xml_status($twitter_status);
$this->end_document('xml');
- exit();
}
function show_single_json_status($notice) {
$status = $this->twitter_status_array($notice);
$this->show_json_objects($status);
$this->end_document('json');
- exit();
}
function show_single_xml_dmsg($message) {
$this->end_document('json');
}
- exit();
}
function init_twitter_rss() {