From: Mikael Nordfeldth Date: Mon, 7 Oct 2013 17:56:57 +0000 (+0200) Subject: Let's not limit qvitter stuff to 'json' requests X-Git-Url: https://git.mxchange.org/?p=quix0rs-gnu-social.git;a=commitdiff_plain;h=1d8b19fe545e62370dc7c1810478021473d5357f Let's not limit qvitter stuff to 'json' requests Also, cleanup and report errors properly when we try unsupported media types. --- diff --git a/actions/apiaccountregister.php b/actions/apiaccountregister.php index 7d038b20dc..15a62d3971 100644 --- a/actions/apiaccountregister.php +++ b/actions/apiaccountregister.php @@ -1,5 +1,5 @@ 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)) { @@ -68,148 +98,93 @@ class ApiAccountRegisterAction extends ApiAction 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.'),404,'json'); - return false; + $this->clientError(_('Sorry, only invited people can register.'), 401); } if (!empty($this->code)) { $this->invite = Invitation::staticGet('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.'),404,'json'); - return false; + $this->clientError(_('Sorry, invalid invitation code.'), 401); } // Store this in case we need it common_ensure_session(); $_SESSION['invitecode'] = $this->code; } - return true; - } - - /** - * Handle the request - * - * @param array $args $_REQUEST data (unused) - * - * @return void - */ - function handle($args) - { - parent::handle($args); - - if ($_SERVER['REQUEST_METHOD'] != 'POST') { - $this->clientError( - _('This method requires a POST.'), - 400, $this->format - ); - return; + // Input scrubbing + try { + $nickname = Nickname::normalize($nickname); + } catch (NicknameException $e) { + // clientError handles Api exceptions with various formats and stuff + $this->clientError(_('Not a valid nickname.'), 400); + } + $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->nicknameExists($nickname)) { + // TRANS: Form validation error displayed when trying to register with an existing nickname. + $this->clientError(_('Nickname already in use. Try another one.'), 400); + } else if (!User::allowed_nickname($nickname)) { + // TRANS: Form validation error displayed when trying to register with an invalid nickname. + $this->clientError(_('Not a valid nickname.'), 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 (!is_null($fullname) && mb_strlen($fullname) > 255) { + // TRANS: Form validation error displayed when trying to register with a too long full name. + $this->clientError(_('Full name is too long (maximum 255 characters).'), 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 (!is_null($location) && mb_strlen($location) > 255) { + // TRANS: Form validation error displayed when trying to register with a too long location. + $this->clientError(_('Location is too long (maximum 255 characters).'), 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 { - - $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'); - - // invitation code, if any - $code = $this->trimmed('code'); - - if ($code) { - $invite = Invitation::staticGet($code); - } + + // annoy spammers + sleep(7); + + if ($user = User::register(array('nickname' => $nickname, + 'password' => $password, + 'email' => $email, + 'fullname' => $fullname, + 'homepage' => $homepage, + 'bio' => $bio, + 'location' => $location, + 'code' => $code))) { + if (!$user) { + // TRANS: Form validation error displayed when trying to register with an invalid username or password. + $this->clientError(_('Invalid username or password.'), 400); + } - if (common_config('site', 'inviteonly') && !($code && $invite)) { - // TRANS: Client error displayed when trying to register to an invite-only site without an invitation. - $this->clientError(_('Sorry, only invited people can register.'),404,'json'); - return; - } + Event::handle('EndRegistrationTry', array($this)); - // Input scrubbing - try { - $nickname = Nickname::normalize($nickname); - } catch (NicknameException $e) { - $this->showForm($e->getMessage()); - } - $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.'),404,'json'); - } else if ($this->nicknameExists($nickname)) { - // TRANS: Form validation error displayed when trying to register with an existing nickname. - $this->clientError(_('Nickname already in use. Try another one.'),404,'json'); - } else if (!User::allowed_nickname($nickname)) { - // TRANS: Form validation error displayed when trying to register with an invalid nickname. - $this->clientError(_('Not a valid nickname.'),404,'json'); - } 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.'),404,'json'); - } 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.'),404,'json'); - return; - } else if (!is_null($fullname) && mb_strlen($fullname) > 255) { - // TRANS: Form validation error displayed when trying to register with a too long full name. - $this->clientError(_('Full name is too long (maximum 255 characters).'),404,'json'); - return; - } 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()),404,'json'); - return; - } else if (!is_null($location) && mb_strlen($location) > 255) { - // TRANS: Form validation error displayed when trying to register with a too long location. - $this->clientError(_('Location is too long (maximum 255 characters).'),404,'json'); - return; - } 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.'),404,'json'); - return; - } else if ($password != $confirm) { - // TRANS: Form validation error displayed when trying to register with non-matching passwords. - $this->clientError(_('Passwords do not match.'),404,'json'); - } else { - - // annoy spammers - sleep(7); - - if ($user = User::register(array('nickname' => $nickname, - 'password' => $password, - 'email' => $email, - 'fullname' => $fullname, - 'homepage' => $homepage, - 'bio' => $bio, - 'location' => $location, - 'code' => $code))) { - if (!$user) { - // TRANS: Form validation error displayed when trying to register with an invalid username or password. - $this->clientError(_('Invalid username or password.'),404,'json'); - return; - } - - Event::handle('EndRegistrationTry', array($this)); - - $this->initDocument('json'); - $this->showJsonObjects($this->twitterUserArray($user->getProfile())); - $this->endDocument('json'); - - } else { - // TRANS: Form validation error displayed when trying to register with an invalid username or password. - $this->clientError(_('Invalid username or password.'),404,'json'); - } - } - } + $this->initDocument('json'); + $this->showJsonObjects($this->twitterUserArray($user->getProfile())); + $this->endDocument('json'); + + } else { + // TRANS: Form validation error displayed when trying to register with an invalid username or password. + $this->clientError(_('Invalid username or password.'), 400); + } + } } diff --git a/actions/apiaccountupdatebackgroundcolor.php b/actions/apiaccountupdatebackgroundcolor.php index 230ff5b585..8d2a97228c 100644 --- a/actions/apiaccountupdatebackgroundcolor.php +++ b/actions/apiaccountupdatebackgroundcolor.php @@ -32,6 +32,8 @@ class ApiAccountUpdateBackgroundColorAction extends ApiAuthAction { var $backgroundcolor = null; + protected $needPost = true; + /** * Take arguments for running * @@ -39,11 +41,13 @@ class ApiAccountUpdateBackgroundColorAction extends ApiAuthAction * * @return boolean success flag */ - function prepare($args) + protected function prepare($args) { parent::prepare($args); - $this->user = $this->auth_user; + if ($this->format !== 'json') { + $this->clientError('This method currently only serves JSON.', 415); + } $this->backgroundcolor = $this->trimmed('backgroundcolor'); return true; @@ -59,40 +63,23 @@ class ApiAccountUpdateBackgroundColorAction extends ApiAuthAction * * @return void */ - function handle($args) + protected function handle() { - parent::handle($args); - - if ($_SERVER['REQUEST_METHOD'] != 'POST') { - $this->clientError( - _('This method requires a POST.'), - 400, $this->format - ); - return; + 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); } - - $validhex = preg_match('/^[a-f0-9]{6}$/i',$this->backgroundcolor); - if($validhex === false || $validhex == 0) { - $this->clientError(_('Not a valid hex color.'),404,'json'); - return; - } - - // save the new color - $original = clone($this->user); - $this->user->backgroundcolor = $this->backgroundcolor; - if (!$this->user->update($original)) { - $this->clientError(_('Error updating user.'),404,'json'); - return; - } - - $profile = $this->user->getProfile(); - - if (empty($profile)) { - $this->clientError(_('User has no profile.'),'json'); - return; + + // 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($profile, true); + $twitter_user = $this->twitterUserArray($this->scoped, true); $this->initDocument('json'); $this->showJsonObjects($twitter_user); diff --git a/actions/apiaccountupdatelinkcolor.php b/actions/apiaccountupdatelinkcolor.php index 9416a32cb7..49c42204b4 100644 --- a/actions/apiaccountupdatelinkcolor.php +++ b/actions/apiaccountupdatelinkcolor.php @@ -32,6 +32,8 @@ class ApiAccountUpdateLinkColorAction extends ApiAuthAction { var $linkcolor = null; + protected $needPost = true; + /** * Take arguments for running * @@ -39,11 +41,13 @@ class ApiAccountUpdateLinkColorAction extends ApiAuthAction * * @return boolean success flag */ - function prepare($args) + protected function prepare($args) { parent::prepare($args); - $this->user = $this->auth_user; + if ($this->format !== 'json') { + $this->clientError('This method currently only serves JSON.', 415); + } $this->linkcolor = $this->trimmed('linkcolor'); @@ -60,45 +64,26 @@ class ApiAccountUpdateLinkColorAction extends ApiAuthAction * * @return void */ - function handle($args) + protected function handle() { - parent::handle($args); - - if ($_SERVER['REQUEST_METHOD'] != 'POST') { - $this->clientError( - _('This method requires a POST.'), - 400, $this->format - ); - return; + 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); } - - $validhex = preg_match('/^[a-f0-9]{6}$/i',$this->linkcolor); - if($validhex === false || $validhex == 0) { - $this->clientError(_('Not a valid hex color.'),404,'json'); - return; - } - - // save the new color - $original = clone($this->user); - $this->user->linkcolor = $this->linkcolor; - if (!$this->user->update($original)) { - $this->clientError(_('Error updating user.'),404,'json'); - return; - } - - $profile = $this->user->getProfile(); - - if (empty($profile)) { - $this->clientError(_('User has no profile.'),'json'); - return; + + // 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($profile, true); + $twitter_user = $this->twitterUserArray($this->scoped, true); $this->initDocument('json'); $this->showJsonObjects($twitter_user); $this->endDocument('json'); } - - } diff --git a/actions/apiattachment.php b/actions/apiattachment.php index 52cb570de3..b3d8cc80b9 100644 --- a/actions/apiattachment.php +++ b/actions/apiattachment.php @@ -46,10 +46,14 @@ class ApiAttachmentAction extends ApiAuthAction * * @return boolean success flag */ - function prepare($args) + protected function prepare($args) { parent::prepare($args); + if ($this->format !== 'json') { + $this->clientError('This method currently only serves JSON.', 415); + } + return true; } @@ -62,9 +66,10 @@ class ApiAttachmentAction extends ApiAuthAction * * @return void */ - function handle($args) + protected function handle() { - parent::handle($args); + parent::handle(); + $file = new File(); $file->selectAdd(); // clears it $file->selectAdd('url'); @@ -73,7 +78,7 @@ class ApiAttachmentAction extends ApiAuthAction $file_txt = ''; if(strstr($url[0],'.html')) { - $file_txt['txt'] = file_get_contents(str_replace('://quitter.se','://127.0.0.1',$url[0])); + $file_txt['txt'] = file_get_contents($url[0]); $file_txt['body_start'] = strpos($file_txt['txt'],'')+6; $file_txt['body_end'] = strpos($file_txt['txt'],''); $file_txt = substr($file_txt['txt'],$file_txt['body_start'],$file_txt['body_end']-$file_txt['body_start']); diff --git a/actions/apicheckhub.php b/actions/apicheckhub.php index 2650d367ae..ed7f39baec 100644 --- a/actions/apicheckhub.php +++ b/actions/apicheckhub.php @@ -34,6 +34,8 @@ if (!defined('GNUSOCIAL')) { exit(1); } */ class ApiCheckHubAction extends ApiAuthAction { + protected $url = null; + /** * Take arguments for running * @@ -45,16 +47,18 @@ class ApiCheckHubAction extends ApiAuthAction { 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, 'json'); - return; + $this->clientError(_('No URL.'), 403); } if (!common_valid_http_url($this->url)) { - $this->clientError(_('Invalid URL.'), 403, 'json'); - return; + $this->clientError(_('Invalid URL.'), 403); } return true; @@ -79,11 +83,9 @@ class ApiCheckHubAction extends ApiAuthAction $huburi = $discover->getHubLink(); } } catch (FeedSubNoFeedException $e) { - $this->clientError(_('No feed found'), 403, 'json'); - return; + $this->clientError(_('No feed found'), 403); } catch (FeedSubBadResponseException $e) { - $this->clientError(_('No hub found'), 403, 'json'); - return; + $this->clientError(_('No hub found'), 403); } $hub_status = array(); diff --git a/actions/apichecknickname.php b/actions/apichecknickname.php index 7aa1283739..9aa834ab26 100644 --- a/actions/apichecknickname.php +++ b/actions/apichecknickname.php @@ -34,16 +34,20 @@ if (!defined('GNUSOCIAL')) { exit(1); } class ApiCheckNicknameAction extends ApiAction { - function prepare($args) + protected function prepare($args) { parent::prepare($args); + + if ($this->format !== 'json') { + $this->clientError('This method currently only serves JSON.', 415); + } return true; } - function handle($args) + protected function handle() { - parent::handle($args); + parent::handle(); $nickname = $this->trimmed('nickname'); diff --git a/actions/apiexternalprofileshow.php b/actions/apiexternalprofileshow.php index 2acc97f48f..8a007e18b3 100644 --- a/actions/apiexternalprofileshow.php +++ b/actions/apiexternalprofileshow.php @@ -42,14 +42,24 @@ class ApiExternalProfileShowAction extends ApiPrivateAuthAction * @return boolean success flag * */ - function prepare($args) + protected function prepare($args) { 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::staticGet('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; } @@ -62,15 +72,9 @@ class ApiExternalProfileShowAction extends ApiPrivateAuthAction * * @return void */ - function handle($args) + protected function handle() { - parent::handle($args); - - if (empty($this->profile)) { - // TRANS: Client error displayed when requesting profile information for a non-existing profile. - $this->clientError(_('Profile not found.'), 404, 'json'); - return; - } + parent::handle(); $twitter_user = $this->twitterUserArray($this->profile, true); diff --git a/actions/apigroupadmins.php b/actions/apigroupadmins.php index 3ddff15480..cba9c08ab3 100644 --- a/actions/apigroupadmins.php +++ b/actions/apigroupadmins.php @@ -61,15 +61,14 @@ class ApiGroupAdminsAction extends ApiPrivateAuthAction * * @return boolean success flag */ - function prepare($args) + protected function prepare($args) { 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->format); - return false; + $this->clientError(_('Group not found.'), 404); } $this->profiles = $this->getProfiles(); @@ -86,9 +85,9 @@ class ApiGroupAdminsAction extends ApiPrivateAuthAction * * @return void */ - function handle($args) + protected function handle() { - parent::handle($args); + parent::handle(); // XXX: RSS and Atom diff --git a/actions/apistatusesfavs.php b/actions/apistatusesfavs.php index 9f3593593b..9a60028419 100644 --- a/actions/apistatusesfavs.php +++ b/actions/apistatusesfavs.php @@ -36,7 +36,7 @@ class ApiStatusesFavsAction extends ApiAuthAction { const MAXCOUNT = 100; - var $original = null; + var $original = null; // Notice object for which to retrieve favs var $cnt = self::MAXCOUNT; /** @@ -46,18 +46,21 @@ class ApiStatusesFavsAction extends ApiAuthAction * * @return boolean success flag */ - function prepare($args) + protected function prepare($args) { parent::prepare($args); + if ($this->format !== 'json') { + $this->clientError('This method currently only serves JSON.', 415); + } + $id = $this->trimmed('id'); $this->original = Notice::staticGet('id', $id); - if (empty($this->original)) { + if (!($this->original instanceof Notice)) { // TRANS: Client error displayed trying to display redents of a non-exiting notice. - $this->clientError(_('No such notice.'), 400, $this->format); - return false; + $this->clientError(_('No such notice.'), 400); } $cnt = $this->trimmed('count'); @@ -80,9 +83,9 @@ class ApiStatusesFavsAction extends ApiAuthAction * * @return void */ - function handle($args) + protected function handle() { - parent::handle($args); + parent::handle(); $fave = new Fave(); $fave->selectAdd(); diff --git a/lib/action.php b/lib/action.php index bcd6aab26d..26afd7bfbe 100644 --- a/lib/action.php +++ b/lib/action.php @@ -135,7 +135,7 @@ class Action extends HTMLOutputter // lawsuit protected function prepare(array $args=array()) { if ($this->needPost && !$this->isPost()) { - $this->clientError(_('This method requires a POST.'), 400, $this->format); + $this->clientError(_('This method requires a POST.'), 405); } $this->args = common_copy_args($args); diff --git a/lib/router.php b/lib/router.php index 0d38d44835..1cbbffd4df 100644 --- a/lib/router.php +++ b/lib/router.php @@ -462,36 +462,44 @@ class Router // START qvitter API additions - $m->connect('api/statuses/favs/:id.json', - array('action' => 'ApiStatusesFavs', - 'id' => '[0-9]+')); + $m->connect('api/statuses/favs/:id.:format', + array('action' => 'ApiStatusesFavs', + 'id' => '[0-9]+', + 'format' => '(xml|json)')); - $m->connect('api/attachment/:id.json', - array('action' => 'ApiAttachment', - 'id' => '[0-9]+')); + $m->connect('api/attachment/:id.:format', + array('action' => 'ApiAttachment', + 'id' => '[0-9]+', + 'format' => '(xml|json)')); - $m->connect('api/checkhub.json', - array('action' => 'ApiCheckHub')); + $m->connect('api/checkhub.:format', + array('action' => 'ApiCheckHub', + 'format' => '(xml|json)')); - $m->connect('api/externalprofile/show.json', - array('action' => 'ApiExternalProfileShow')); + $m->connect('api/externalprofile/show.:format', + array('action' => 'ApiExternalProfileShow', + 'format' => '(xml|json)')); $m->connect('api/statusnet/groups/admins/:id.:format', - array('action' => 'ApiGroupAdmins', - 'id' => Nickname::INPUT_FMT, - 'format' => '(xml|json)')); + array('action' => 'ApiGroupAdmins', + 'id' => Nickname::INPUT_FMT, + 'format' => '(xml|json)')); - $m->connect('api/account/update_link_color.json', - array('action' => 'ApiAccountUpdateLinkColor')); + $m->connect('api/account/update_link_color.:format', + array('action' => 'ApiAccountUpdateLinkColor', + 'format' => '(xml|json)')); - $m->connect('api/account/update_background_color.json', - array('action' => 'ApiAccountUpdateBackgroundColor')); + $m->connect('api/account/update_background_color.:format', + array('action' => 'ApiAccountUpdateBackgroundColor', + 'format' => '(xml|json)')); - $m->connect('api/account/register.json', - array('action' => 'ApiAccountRegister')); + $m->connect('api/account/register.:format', + array('action' => 'ApiAccountRegister', + 'format' => '(xml|json)')); - $m->connect('api/check_nickname.json', - array('action' => 'ApiCheckNickname')); + $m->connect('api/check_nickname.:format', + array('action' => 'ApiCheckNickname', + 'format' => '(xml|json)')); // END qvitter API additions