Update libomb, fix some omb handling stuff, improve error handling.

This commit is contained in:
Adrian Lang 2009-08-21 12:13:24 +02:00
parent b0bb1fff2e
commit 70235d7f05
7 changed files with 130 additions and 55 deletions

View File

@ -76,11 +76,10 @@ class FinishremotesubscribeAction extends Action
/* Create user objects for both users. Do it early for request /* Create user objects for both users. Do it early for request
validation. */ validation. */
$listenee = $service->getListeneeURI(); $user = User::staticGet('uri', $service->getListeneeURI());
$user = User::staticGet('uri', $listenee);
if (!$user) { if (!$user) {
$this->clientError(_('User being listened to doesn\'t exist.')); $this->clientError(_('User being listened to does not exist.'));
return; return;
} }
@ -91,21 +90,31 @@ class FinishremotesubscribeAction extends Action
return; return;
} }
$remote = Remote_profile::staticGet('uri', $service->getListenerURI());
$profile = Profile::staticGet($remote->id);
if ($user->hasBlocked($profile)) {
$this->clientError(_('That user has blocked you from subscribing.'));
return;
}
/* Perform the handling itself via libomb. */ /* Perform the handling itself via libomb. */
try { try {
$service->finishAuthorization($listenee); $service->finishAuthorization();
} catch (OAuthException $e) { } catch (OAuthException $e) {
if ($e->getMessage() == 'The authorized token does not equal the ' . if ($e->getMessage() == 'The authorized token does not equal the ' .
'submitted token.') { 'submitted token.') {
$this->clientError(_('Not authorized.')); $this->clientError(_('You are not authorized.'));
return; return;
} else { } else {
$this->clientError(_('Couldn\'t convert request token to ' . $this->clientError(_('Could not convert request token to ' .
'access token.')); 'access token.'));
return; return;
} }
} catch (OMB_RemoteServiceException $e) { } catch (OMB_RemoteServiceException $e) {
$this->clientError(_('Unknown version of OMB protocol.')); $this->clientError(_('Remote service uses unknown version of ' .
'OMB protocol.'));
return; return;
} catch (Exception $e) { } catch (Exception $e) {
common_debug('Got exception ' . print_r($e, true), __FILE__); common_debug('Got exception ' . print_r($e, true), __FILE__);
@ -115,8 +124,6 @@ class FinishremotesubscribeAction extends Action
/* The service URLs are not accessible from datastore, so setting them /* The service URLs are not accessible from datastore, so setting them
after insertion of the profile. */ after insertion of the profile. */
$remote = Remote_profile::staticGet('uri', $service->getListenerURI());
$orig_remote = clone($remote); $orig_remote = clone($remote);
$remote->postnoticeurl = $remote->postnoticeurl =

View File

@ -47,12 +47,28 @@ require_once INSTALLDIR.'/extlib/libomb/service_provider.php';
*/ */
class PostnoticeAction extends Action class PostnoticeAction extends Action
{ {
/**
* For initializing members of the class.
*
* @param array $argarray misc. arguments
*
* @return boolean true
*/
function prepare($argarray)
{
parent::prepare($argarray);
try {
$this->checkNotice();
} catch (Exception $e) {
$this->clientError($e->getMessage());
return false;
}
return true;
}
function handle($args) function handle($args)
{ {
parent::handle($args); parent::handle($args);
if (!$this->checkNotice()) {
return;
}
try { try {
$srv = new OMB_Service_Provider(null, omb_oauth_datastore(), $srv = new OMB_Service_Provider(null, omb_oauth_datastore(),
omb_oauth_server()); omb_oauth_server());
@ -67,10 +83,15 @@ class PostnoticeAction extends Action
{ {
$content = common_shorten_links($_POST['omb_notice_content']); $content = common_shorten_links($_POST['omb_notice_content']);
if (mb_strlen($content) > 140) { if (mb_strlen($content) > 140) {
$this->clientError(_('Invalid notice content'), 400); throw new Exception(_('The notice content is too long.'));
return false; }
$license = $_POST['omb_notice_license'];
$site_license = common_config('license', 'url');
if ($license && !common_compatible_license($license, $site_license)) {
throw new Exception(sprintf(_('Notice license %s is not ' .
'compatible with site license %s.'),
$license, $site_license));
} }
return true;
} }
} }
?> ?>

View File

@ -153,12 +153,11 @@ class RemotesubscribeAction extends Action
$this->profile_url = $this->trimmed('profile_url'); $this->profile_url = $this->trimmed('profile_url');
if (!$this->profile_url) { if (!$this->profile_url) {
$this->showForm(_('No such user.')); $this->showForm(_('No such user'));
return; return;
} }
if (!Validate::uri($this->profile_url, if (!common_valid_http_url($this->profile_url)) {
array('allowed_schemes' => array('http', 'https')))) {
$this->showForm(_('Invalid profile URL (bad format)')); $this->showForm(_('Invalid profile URL (bad format)'));
return; return;
} }
@ -176,14 +175,14 @@ class RemotesubscribeAction extends Action
if ($service->getServiceURI(OAUTH_ENDPOINT_REQUEST) == if ($service->getServiceURI(OAUTH_ENDPOINT_REQUEST) ==
common_local_url('requesttoken') || common_local_url('requesttoken') ||
User::staticGet('uri', $service->getRemoteUserURI())) { User::staticGet('uri', $service->getRemoteUserURI())) {
$this->showForm(_('That\'s a local profile! Login to subscribe.')); $this->showForm(_('Thats a local profile! Login to subscribe.'));
return; return;
} }
try { try {
$service->requestToken(); $service->requestToken();
} catch (OMB_RemoteServiceException $e) { } catch (OMB_RemoteServiceException $e) {
$this->showForm(_('Couldn\'t get a request token.')); $this->showForm(_('Couldnt get a request token.'));
return; return;
} }

View File

@ -48,9 +48,31 @@ require_once INSTALLDIR.'/extlib/libomb/service_provider.php';
class UpdateprofileAction extends Action class UpdateprofileAction extends Action
{ {
/**
* For initializing members of the class.
*
* @param array $argarray misc. arguments
*
* @return boolean true
*/
function prepare($argarray)
{
parent::prepare($argarray);
$license = $_POST['omb_listenee_license'];
$site_license = common_config('license', 'url');
if (!common_compatible_license($license, $site_license)) {
$this->clientError(sprintf(_('Listenee stream license %s is not '.
'compatible with site license %s.'),
$license, $site_license);
return false;
}
return true;
}
function handle($args) function handle($args)
{ {
parent::handle($args); parent::handle($args);
try { try {
$srv = new OMB_Service_Provider(null, omb_oauth_datastore(), $srv = new OMB_Service_Provider(null, omb_oauth_datastore(),
omb_oauth_server()); omb_oauth_server());

View File

@ -80,7 +80,7 @@ class UserauthorizationAction extends Action
try { try {
$this->validateOmb(); $this->validateOmb();
$srv = new OMB_Service_Provider( $srv = new OMB_Service_Provider(
profile_to_omb_profile($_GET['omb_listener'], $profile), profile_to_omb_profile($user->uri, $profile),
omb_oauth_datastore()); omb_oauth_datastore());
$remote_user = $srv->handleUserAuth(); $remote_user = $srv->handleUserAuth();
@ -111,8 +111,8 @@ class UserauthorizationAction extends Action
{ {
$this->element('p', null, _('Please check these details to make sure '. $this->element('p', null, _('Please check these details to make sure '.
'that you want to subscribe to this ' . 'that you want to subscribe to this ' .
'user\'s notices. If you didn\'t just ask ' . 'users notices. If you didnt just ask ' .
'to subscribe to someone\'s notices, '. 'to subscribe to someones notices, '.
'click “Reject”.')); 'click “Reject”.'));
} }
@ -249,7 +249,7 @@ class UserauthorizationAction extends Action
common_show_header(_('Subscription authorized')); common_show_header(_('Subscription authorized'));
$this->element('p', null, $this->element('p', null,
_('The subscription has been authorized, but no '. _('The subscription has been authorized, but no '.
'callback URL was passed. Check with the site\'s ' . 'callback URL was passed. Check with the sites ' .
'instructions for details on how to authorize the ' . 'instructions for details on how to authorize the ' .
'subscription. Your subscription token is:')); 'subscription. Your subscription token is:'));
$this->element('blockquote', 'token', $tok); $this->element('blockquote', 'token', $tok);
@ -261,7 +261,7 @@ class UserauthorizationAction extends Action
common_show_header(_('Subscription rejected')); common_show_header(_('Subscription rejected'));
$this->element('p', null, $this->element('p', null,
_('The subscription has been rejected, but no '. _('The subscription has been rejected, but no '.
'callback URL was passed. Check with the site\'s ' . 'callback URL was passed. Check with the sites ' .
'instructions for details on how to fully reject ' . 'instructions for details on how to fully reject ' .
'the subscription.')); 'the subscription.'));
common_show_footer(); common_show_footer();
@ -295,16 +295,19 @@ class UserauthorizationAction extends Action
$user = User::staticGet('uri', $listener); $user = User::staticGet('uri', $listener);
if (!$user) { if (!$user) {
throw new Exception("Listener URI '$listener' not found here"); throw new Exception(sprintf(_('Listener URI %s not found here'),
$listener));
} }
$cur = common_current_user();
if ($cur->id != $user->id) { if (strlen($listenee) > 255) {
throw new Exception('Can\'t subscribe for another user!'); throw new Exception(sprintf(_('Listenee URI %s is too long.'),
$listenee));
} }
$other = User::staticGet('uri', $listenee); $other = User::staticGet('uri', $listenee);
if ($other) { if ($other) {
throw new Exception("Listenee URI '$listenee' is local user"); throw new Exception(sprintf(_('Listenee URI %s is a local user.'),
$listenee));
} }
$remote = Remote_profile::staticGet('uri', $listenee); $remote = Remote_profile::staticGet('uri', $listenee);
@ -318,27 +321,34 @@ class UserauthorizationAction extends Action
} }
if ($profile == common_profile_url($nickname)) { if ($profile == common_profile_url($nickname)) {
throw new Exception("Profile URL '$profile' is for a local user."); throw new Exception(sprintf(_('Profile URL %s is for a local user.'),
$profile));
} }
$license = $_GET['omb_listenee_license']; $license = $_GET['omb_listenee_license'];
$site_license = common_config('license', 'url'); $site_license = common_config('license', 'url');
if (!common_compatible_license($license, $site_license)) { if (!common_compatible_license($license, $site_license)) {
throw new Exception("Listenee stream license '$license' is not " . throw new Exception(sprintf(_('Listenee stream license %s is not ' .
"compatible with site license '$site_license'."); 'compatible with site license %s.'),
$license, $site_license));
} }
$avatar = $_GET['omb_listenee_avatar']; $avatar = $_GET['omb_listenee_avatar'];
if ($avatar) { if ($avatar) {
if (!common_valid_http_url($avatar) || strlen($avatar) > 255) { if (!common_valid_http_url($avatar) || strlen($avatar) > 255) {
throw new Exception("Invalid avatar URL '$avatar'"); throw new Exception(sprintf(_('Avatar URL %s is not valid.'),
$avatar));
} }
$size = @getimagesize($avatar); $size = @getimagesize($avatar);
if (!$size) { if (!$size) {
throw new Exception("Can't read avatar URL '$avatar'."); throw new Exception(sprintf(_('Cant read avatar URL %s.'),
$avatar));
} }
if (!in_array($size[2], array(IMAGETYPE_GIF, IMAGETYPE_JPEG, if (!in_array($size[2], array(IMAGETYPE_GIF, IMAGETYPE_JPEG,
IMAGETYPE_PNG))) { IMAGETYPE_PNG))) {
throw new Exception("Wrong image type for '$avatar'"); throw new Exception(sprintf(_('Wrong image type for avatar URL '.
'%s.'), $avatar));
} }
} }
} }

View File

@ -5,26 +5,28 @@ require_once 'OAuth.php';
/** /**
* Data access interface * Data access interface
* *
* This interface specifies data access methods libomb needs. It * This interface specifies data access methods libomb needs. It should be
* should be implemented by libomb users. * implemented by libomb users. OMB_Datastore is libombs main interface to the
* OMB_Datastore is libombs main interface to the applications data. * applications data. Objects corresponding to this interface are used in
* OMB_Service_Provider and OMB_Service_Consumer.
*
* Note that its implemented as a class since OAuthDataStore is as well a
* class, though only declaring methods.
*
* OMB_Datastore extends OAuthDataStore with two OAuth-related methods for token
* revoking and authorizing and all OMB-related methods.
* Refer to OAuth.php for a complete specification of OAuth-related methods.
* *
* It is the users duty to signal and handle errors. libomb does not check * It is the users duty to signal and handle errors. libomb does not check
* return values nor handle exceptions. It is suggested to use exceptions. * return values nor handle exceptions. It is suggested to use exceptions.
* Note that lookup_token and getProfile return null if the requested object * Note that lookup_token and getProfile return null if the requested object
* is not available. This is NOT an error and should not raise an exception. * is not available. This is NOT an error and should not raise an exception.
* Same applies for lookup_nonce which returns a boolean value. These methods * Same applies for lookup_nonce which returns a boolean value. These methods
* may nevertheless throw an exception, for example in case of a storage error. * may nevertheless throw an exception, for example in case of a storage errors.
* *
* Objects corresponding to this interface are used in OMB_Service_Provider and * Most of the parameters passed to these methods are unescaped and unverified
* OMB_Service_Consumer. * user input. Therefore they should be handled with extra care to avoid
* * security problems like SQL injections.
* OMB_Datastore extends OAuthDataStore with two OAuth-related methods for token
* revoking and authorizing and all OMB-related methods.
* Refer to OAuth.php for a complete specification of OAuth-related methods.
*
* Note that its implemented as a class since OAuthDataStore is as well a
* class, though only declaring methods.
* *
* PHP version 5 * PHP version 5
* *
@ -59,7 +61,7 @@ class OMB_Datastore extends OAuthDataStore {
* Revokes the authorization token specified by $token_key. * Revokes the authorization token specified by $token_key.
* Throws exceptions in case of error. * Throws exceptions in case of error.
* *
* @param string $token_key The token to be revoked * @param string $token_key The key of the token to be revoked
* *
* @access public * @access public
**/ **/
@ -73,7 +75,7 @@ class OMB_Datastore extends OAuthDataStore {
* Authorizes the authorization token specified by $token_key. * Authorizes the authorization token specified by $token_key.
* Throws exceptions in case of error. * Throws exceptions in case of error.
* *
* @param string $token_key The token to be authorized * @param string $token_key The key of the token to be authorized
* *
* @access public * @access public
**/ **/

View File

@ -111,6 +111,12 @@ class OMB_Service_Provider {
* Throws exceptions on failures. Returns an OMB_Profile object representing * Throws exceptions on failures. Returns an OMB_Profile object representing
* the remote user. * the remote user.
* *
* The OMB_Profile passed to the constructor of OMB_Service_Provider should
* not represent the user specified in the authorization request, but the one
* currently logged in to the service. This condition being satisfied,
* handleUserAuth will check whether the listener specified in the request is
* identical to the logged in user.
*
* @access public * @access public
* *
* @return OMB_Profile The profile of the soon-to-be subscribed, i. e. remote * @return OMB_Profile The profile of the soon-to-be subscribed, i. e. remote
@ -150,6 +156,10 @@ class OMB_Service_Provider {
/* Store given callback for later use. */ /* Store given callback for later use. */
if (isset($_GET['oauth_callback']) && $_GET['oauth_callback'] !== '') { if (isset($_GET['oauth_callback']) && $_GET['oauth_callback'] !== '') {
$this->callback = $_GET['oauth_callback']; $this->callback = $_GET['oauth_callback'];
if (!OMB_Helper::validateURL($this->callback)) {
throw OMB_RemoteServiceException::forRequest(OAUTH_ENDPOINT_AUTHORIZE,
'Invalid callback URL specified');
}
} }
$this->remote_user = OMB_Profile::fromParameters($_GET, 'omb_listenee'); $this->remote_user = OMB_Profile::fromParameters($_GET, 'omb_listenee');
@ -205,13 +215,16 @@ class OMB_Service_Provider {
/** /**
* Echo an access token * Echo an access token
* *
* Outputs an access token for the query found in $_GET or $_POST. * Outputs an access token for the query found in $_POST. OMB 0.1 specifies
* that the access token request has to be a POST even if OAuth allows GET as
* well.
* *
* @access public * @access public
**/ **/
public function writeAccessToken() { public function writeAccessToken() {
OMB_Helper::removeMagicQuotesFromRequest(); OMB_Helper::removeMagicQuotesFromRequest();
echo $this->getOAuthServer()->fetch_access_token(OAuthRequest::from_request()); echo $this->getOAuthServer()->fetch_access_token(
OAuthRequest::from_request('POST'));
} }
/** /**
@ -235,7 +248,8 @@ class OMB_Service_Provider {
/** /**
* Handle a postnotice request * Handle a postnotice request
* *
* Handles a postnotice request posted to this service. * Handles a postnotice request posted to this service. Saves the notice
* through the OMB_Datastore.
* *
* @access public * @access public
* *
@ -264,7 +278,7 @@ class OMB_Service_Provider {
protected function handleOMBRequest($uri) { protected function handleOMBRequest($uri) {
OMB_Helper::removeMagicQuotesFromRequest(); OMB_Helper::removeMagicQuotesFromRequest();
$req = OAuthRequest::from_request(); $req = OAuthRequest::from_request('POST');
$listenee = $req->get_parameter('omb_listenee'); $listenee = $req->get_parameter('omb_listenee');
try { try {