X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=lib%2Fapiaction.php;h=b6e8f87b6de0337b71feafce6f44291d5b3ee620;hb=ec93184d7b71f3a1a20a0a599d8e8d3f74c077a9;hp=479a86ad8046f8a324fb39b2798a47b3cca1de14;hpb=77a96e3d7cecd5fd61ad72b698a15a8a3c7b0940;p=quix0rs-gnu-social.git diff --git a/lib/apiaction.php b/lib/apiaction.php index 479a86ad80..b6e8f87b6d 100644 --- a/lib/apiaction.php +++ b/lib/apiaction.php @@ -112,7 +112,6 @@ if (!defined('STATUSNET')) { * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @link http://status.net/ */ - class ApiAction extends Action { const READ_ONLY = 1; @@ -139,7 +138,6 @@ class ApiAction extends Action * * @return boolean false if user doesn't exist */ - function prepare($args) { StatusNet::setApi(true); // reduce exception reports to aid in debugging @@ -172,7 +170,6 @@ class ApiAction extends Action * * @return void */ - function handle($args) { header('Access-Control-Allow-Origin: *'); @@ -301,7 +298,7 @@ class ApiAction extends Action // StatusNet-specific - $twitter_user['statusnet:profile_url'] = $profile->profileurl; + $twitter_user['statusnet_profile_url'] = $profile->profileurl; return $twitter_user; } @@ -406,7 +403,7 @@ class ApiAction extends Action // StatusNet-specific - $twitter_status['statusnet:html'] = $notice->rendered; + $twitter_status['statusnet_html'] = $notice->rendered; return $twitter_status; } @@ -415,7 +412,7 @@ class ApiAction extends Action { $twitter_group = array(); - $twitter_group['id'] = $group->id; + $twitter_group['id'] = intval($group->id); $twitter_group['url'] = $group->permalink(); $twitter_group['nickname'] = $group->nickname; $twitter_group['fullname'] = $group->fullname; @@ -462,66 +459,70 @@ class ApiAction extends Action function twitterRssEntryArray($notice) { - $profile = $notice->getProfile(); - $entry = array(); - // We trim() to avoid extraneous whitespace in the output + if (Event::handle('StartRssEntryArray', array($notice, &$entry))) { + $profile = $notice->getProfile(); - $entry['content'] = common_xml_safe_str(trim($notice->rendered)); - $entry['title'] = $profile->nickname . ': ' . common_xml_safe_str(trim($notice->content)); - $entry['link'] = common_local_url('shownotice', array('notice' => $notice->id)); - $entry['published'] = common_date_iso8601($notice->created); + // We trim() to avoid extraneous whitespace in the output - $taguribase = TagURI::base(); - $entry['id'] = "tag:$taguribase:$entry[link]"; + $entry['content'] = common_xml_safe_str(trim($notice->rendered)); + $entry['title'] = $profile->nickname . ': ' . common_xml_safe_str(trim($notice->content)); + $entry['link'] = common_local_url('shownotice', array('notice' => $notice->id)); + $entry['published'] = common_date_iso8601($notice->created); - $entry['updated'] = $entry['published']; - $entry['author'] = $profile->getBestName(); + $taguribase = TagURI::base(); + $entry['id'] = "tag:$taguribase:$entry[link]"; - // Enclosures - $attachments = $notice->attachments(); - $enclosures = array(); - - foreach ($attachments as $attachment) { - $enclosure_o=$attachment->getEnclosure(); - if ($enclosure_o) { - $enclosure = array(); - $enclosure['url'] = $enclosure_o->url; - $enclosure['mimetype'] = $enclosure_o->mimetype; - $enclosure['size'] = $enclosure_o->size; - $enclosures[] = $enclosure; - } - } + $entry['updated'] = $entry['published']; + $entry['author'] = $profile->getBestName(); - if (!empty($enclosures)) { - $entry['enclosures'] = $enclosures; - } + // Enclosures + $attachments = $notice->attachments(); + $enclosures = array(); - // Tags/Categories - $tag = new Notice_tag(); - $tag->notice_id = $notice->id; - if ($tag->find()) { - $entry['tags']=array(); - while ($tag->fetch()) { - $entry['tags'][]=$tag->tag; + foreach ($attachments as $attachment) { + $enclosure_o=$attachment->getEnclosure(); + if ($enclosure_o) { + $enclosure = array(); + $enclosure['url'] = $enclosure_o->url; + $enclosure['mimetype'] = $enclosure_o->mimetype; + $enclosure['size'] = $enclosure_o->size; + $enclosures[] = $enclosure; + } } - } - $tag->free(); - // RSS Item specific - $entry['description'] = $entry['content']; - $entry['pubDate'] = common_date_rfc2822($notice->created); - $entry['guid'] = $entry['link']; + if (!empty($enclosures)) { + $entry['enclosures'] = $enclosures; + } - if (isset($notice->lat) && isset($notice->lon)) { - // This is the format that GeoJSON expects stuff to be in. - // showGeoRSS() below uses it for XML output, so we reuse it - $entry['geo'] = array('type' => 'Point', - 'coordinates' => array((float) $notice->lat, - (float) $notice->lon)); - } else { - $entry['geo'] = null; + // Tags/Categories + $tag = new Notice_tag(); + $tag->notice_id = $notice->id; + if ($tag->find()) { + $entry['tags']=array(); + while ($tag->fetch()) { + $entry['tags'][]=$tag->tag; + } + } + $tag->free(); + + // RSS Item specific + $entry['description'] = $entry['content']; + $entry['pubDate'] = common_date_rfc2822($notice->created); + $entry['guid'] = $entry['link']; + + if (isset($notice->lat) && isset($notice->lon)) { + // This is the format that GeoJSON expects stuff to be in. + // showGeoRSS() below uses it for XML output, so we reuse it + $entry['geo'] = array('type' => 'Point', + 'coordinates' => array((float) $notice->lat, + (float) $notice->lon)); + } else { + $entry['geo'] = null; + } + + Event::handle('EndRssEntryArray', array($notice, &$entry)); } return $entry; @@ -550,7 +551,6 @@ class ApiAction extends Action $notifications = false; if ($source->isSubscribed($target)) { - $sub = Subscription::pkeyGet(array('subscriber' => $source->id, 'subscribed' => $target->id)); @@ -561,7 +561,7 @@ class ApiAction extends Action $details['notifications_enabled'] = $notifications; $details['blocking'] = $source->hasBlocked($target); - $details['id'] = $source->id; + $details['id'] = intval($source->id); return $details; } @@ -613,7 +613,11 @@ class ApiAction extends Action $this->showTwitterXmlStatus($value, 'retweeted_status'); break; default: - $this->element($element, null, $value); + if (strncmp($element, 'statusnet_', 10) == 0) { + $this->element('statusnet:'.substr($element, 10), null, $value); + } else { + $this->element($element, null, $value); + } } } $this->elementEnd($tag); @@ -638,6 +642,8 @@ class ApiAction extends Action foreach($twitter_user as $element => $value) { if ($element == 'status') { $this->showTwitterXmlStatus($twitter_user['status']); + } else if (strncmp($element, 'statusnet_', 10) == 0) { + $this->element('statusnet:'.substr($element, 10), null, $value); } else { $this->element($element, null, $value); } @@ -720,6 +726,12 @@ class ApiAction extends Action $this->endDocument('xml'); } + function showSingleAtomStatus($notice) + { + header('Content-Type: application/atom+xml; charset=utf-8'); + print $notice->asAtomEntry(true, true, true, $this->auth_user); + } + function show_single_json_status($notice) { $this->initDocument('json'); @@ -730,7 +742,6 @@ class ApiAction extends Action function showXmlTimeline($notice) { - $this->initDocument('xml'); $this->elementStart('statuses', array('type' => 'array', 'xmlns:statusnet' => 'http://status.net/schema/api/1/')); @@ -755,7 +766,6 @@ class ApiAction extends Action function showRssTimeline($notice, $title, $link, $subtitle, $suplink = null, $logo = null, $self = null) { - $this->initDocument('rss'); $this->element('title', null, $title); @@ -811,7 +821,6 @@ class ApiAction extends Action function showAtomTimeline($notice, $title, $id, $link, $subtitle=null, $suplink=null, $selfuri=null, $logo=null) { - $this->initDocument('atom'); $this->element('title', null, $title); @@ -851,12 +860,10 @@ class ApiAction extends Action } $this->endDocument('atom'); - } function showRssGroups($group, $title, $link, $subtitle) { - $this->initDocument('rss'); $this->element('title', null, $title); @@ -938,10 +945,10 @@ class ApiAction extends Action $from_profile = $message->getFrom(); $to_profile = $message->getTo(); - $dmsg['id'] = $message->id; - $dmsg['sender_id'] = $message->from_profile; + $dmsg['id'] = intval($message->id); + $dmsg['sender_id'] = intval($from_profile); $dmsg['text'] = trim($message->content); - $dmsg['recipient_id'] = $message->to_profile; + $dmsg['recipient_id'] = intval($to_profile); $dmsg['created_at'] = $this->dateTwitter($message->created); $dmsg['sender_screen_name'] = $from_profile->nickname; $dmsg['recipient_screen_name'] = $to_profile->nickname; @@ -1004,7 +1011,6 @@ class ApiAction extends Action function showAtomGroups($group, $title, $id, $link, $subtitle=null, $selfuri=null) { - $this->initDocument('atom'); $this->element('title', null, common_xml_safe_str($title)); @@ -1035,7 +1041,6 @@ class ApiAction extends Action function showJsonTimeline($notice) { - $this->initDocument('json'); $statuses = array(); @@ -1061,7 +1066,6 @@ class ApiAction extends Action function showJsonGroups($group) { - $this->initDocument('json'); $groups = array(); @@ -1107,7 +1111,6 @@ class ApiAction extends Action function showTwitterXmlUsers($user) { - $this->initDocument('xml'); $this->elementStart('users', array('type' => 'array', 'xmlns:statusnet' => 'http://status.net/schema/api/1/')); @@ -1130,7 +1133,6 @@ class ApiAction extends Action function showJsonUsers($user) { - $this->initDocument('json'); $users = array(); @@ -1215,7 +1217,6 @@ class ApiAction extends Action $this->endXML(); break; case 'json': - // Check for JSONP callback if (isset($this->callback)) { print ')'; @@ -1235,9 +1236,12 @@ class ApiAction extends Action return; } - function clientError($msg, $code = 400, $format = 'xml') + function clientError($msg, $code = 400, $format = null) { $action = $this->trimmed('action'); + if ($format === null) { + $format = $this->format; + } common_debug("User error '$code' on '$action': $msg", __FILE__); @@ -1249,31 +1253,40 @@ class ApiAction extends Action // Do not emit error header for JSONP if (!isset($this->callback)) { - header('HTTP/1.1 '.$code.' '.$status_string); + header('HTTP/1.1 ' . $code . ' ' . $status_string); } - if ($format == 'xml') { + switch($format) { + case 'xml': $this->initDocument('xml'); $this->elementStart('hash'); $this->element('error', null, $msg); $this->element('request', null, $_SERVER['REQUEST_URI']); $this->elementEnd('hash'); $this->endDocument('xml'); - } elseif ($format == 'json'){ + break; + case 'json': $this->initDocument('json'); $error_array = array('error' => $msg, 'request' => $_SERVER['REQUEST_URI']); print(json_encode($error_array)); $this->endDocument('json'); - } else { - + break; + case 'text': + header('Content-Type: text/plain; charset=utf-8'); + print $msg; + break; + default: // If user didn't request a useful format, throw a regular client error throw new ClientException($msg, $code); } } - function serverError($msg, $code = 500, $content_type = 'xml') + function serverError($msg, $code = 500, $content_type = null) { $action = $this->trimmed('action'); + if ($content_type === null) { + $content_type = $this->format; + } common_debug("Server error '$code' on '$action': $msg", __FILE__); @@ -1358,12 +1371,16 @@ class ApiAction extends Action return; } + private static function is_decimal($str) + { + return preg_match('/^[0-9]+$/', $str); + } + function getTargetUser($id) { if (empty($id)) { - // Twitter supports these other ways of passing the user ID - if (is_numeric($this->arg('id'))) { + if (self::is_decimal($this->arg('id'))) { return User::staticGet($this->arg('id')); } else if ($this->arg('id')) { $nickname = common_canonical_nickname($this->arg('id')); @@ -1371,7 +1388,7 @@ class ApiAction extends Action } else if ($this->arg('user_id')) { // This is to ensure that a non-numeric user_id still // overrides screen_name even if it doesn't get used - if (is_numeric($this->arg('user_id'))) { + if (self::is_decimal($this->arg('user_id'))) { return User::staticGet('id', $this->arg('user_id')); } } else if ($this->arg('screen_name')) { @@ -1382,7 +1399,7 @@ class ApiAction extends Action return $this->auth_user; } - } else if (is_numeric($id)) { + } else if (self::is_decimal($id)) { return User::staticGet($id); } else { $nickname = common_canonical_nickname($id); @@ -1395,68 +1412,54 @@ class ApiAction extends Action if (empty($id)) { // Twitter supports these other ways of passing the user ID - if (is_numeric($this->arg('id'))) { + if (self::is_decimal($this->arg('id'))) { return Profile::staticGet($this->arg('id')); } else if ($this->arg('id')) { + // Screen names currently can only uniquely identify a local user. $nickname = common_canonical_nickname($this->arg('id')); - return Profile::staticGet('nickname', $nickname); + $user = User::staticGet('nickname', $nickname); + return $user ? $user->getProfile() : null; } else if ($this->arg('user_id')) { // This is to ensure that a non-numeric user_id still // overrides screen_name even if it doesn't get used - if (is_numeric($this->arg('user_id'))) { + if (self::is_decimal($this->arg('user_id'))) { return Profile::staticGet('id', $this->arg('user_id')); } } else if ($this->arg('screen_name')) { $nickname = common_canonical_nickname($this->arg('screen_name')); - return Profile::staticGet('nickname', $nickname); + $user = User::staticGet('nickname', $nickname); + return $user ? $user->getProfile() : null; } - } else if (is_numeric($id)) { + } else if (self::is_decimal($id)) { return Profile::staticGet($id); } else { $nickname = common_canonical_nickname($id); - return Profile::staticGet('nickname', $nickname); + $user = User::staticGet('nickname', $nickname); + return $user ? $user->getProfile() : null; } } function getTargetGroup($id) { if (empty($id)) { - if (is_numeric($this->arg('id'))) { - return User_group::staticGet($this->arg('id')); + if (self::is_decimal($this->arg('id'))) { + return User_group::staticGet('id', $this->arg('id')); } else if ($this->arg('id')) { - $nickname = common_canonical_nickname($this->arg('id')); - $local = Local_group::staticGet('nickname', $nickname); - if (empty($local)) { - return null; - } else { - return User_group::staticGet('id', $local->id); - } + return User_group::getForNickname($this->arg('id')); } else if ($this->arg('group_id')) { - // This is to ensure that a non-numeric user_id still - // overrides screen_name even if it doesn't get used - if (is_numeric($this->arg('group_id'))) { + // This is to ensure that a non-numeric group_id still + // overrides group_name even if it doesn't get used + if (self::is_decimal($this->arg('group_id'))) { return User_group::staticGet('id', $this->arg('group_id')); } } else if ($this->arg('group_name')) { - $nickname = common_canonical_nickname($this->arg('group_name')); - $local = Local_group::staticGet('nickname', $nickname); - if (empty($local)) { - return null; - } else { - return User_group::staticGet('id', $local->group_id); - } + return User_group::getForNickname($this->arg('group_name')); } - } else if (is_numeric($id)) { - return User_group::staticGet($id); + } else if (self::is_decimal($id)) { + return User_group::staticGet('id', $id); } else { - $nickname = common_canonical_nickname($id); - $local = Local_group::staticGet('nickname', $nickname); - if (empty($local)) { - return null; - } else { - return User_group::staticGet('id', $local->group_id); - } + return User_group::getForNickname($id); } } @@ -1472,7 +1475,6 @@ class ApiAction extends Action */ function arg($key, $def=null) { - // XXX: Do even more input validation/scrubbing? if (array_key_exists($key, $this->args)) { @@ -1539,5 +1541,4 @@ class ApiAction extends Action return $uri; } - }