diff options
Diffstat (limited to 'extlib/libomb/service_consumer.php')
-rwxr-xr-x | extlib/libomb/service_consumer.php | 815 |
1 files changed, 423 insertions, 392 deletions
diff --git a/extlib/libomb/service_consumer.php b/extlib/libomb/service_consumer.php index 273fd052e..33ebccc65 100755 --- a/extlib/libomb/service_consumer.php +++ b/extlib/libomb/service_consumer.php @@ -1,19 +1,6 @@ <?php - -require_once 'constants.php'; -require_once 'Validate.php'; -require_once 'Auth/Yadis/Yadis.php'; -require_once 'OAuth.php'; -require_once 'unsupportedserviceexception.php'; -require_once 'remoteserviceexception.php'; -require_once 'omb_yadis_xrds.php'; -require_once 'helper.php'; - /** - * OMB service representation - * - * This class represents a complete remote OMB service. It provides discovery - * and execution of the service’s methods. + * This file is part of libomb * * PHP version 5 * @@ -30,401 +17,445 @@ require_once 'helper.php'; * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * - * @package OMB - * @author Adrian Lang <mail@adrianlang.de> - * @copyright 2009 Adrian Lang - * @license http://www.gnu.org/licenses/agpl.html GNU AGPL 3.0 - **/ - -class OMB_Service_Consumer { - protected $url; /* The service URL */ - protected $services; /* An array of strings mapping service URI to - service URL */ - - protected $token; /* An OAuthToken */ - - protected $listener_uri; /* The URI identifying the listener, i. e. the - remote user. */ - - protected $listenee_uri; /* The URI identifying the listenee, i. e. the - local user during an auth request. */ - - /** - * According to OAuth Core 1.0, an user authorization request is no full-blown - * OAuth request. nonce, timestamp, consumer_key and signature are not needed - * in this step. See http://laconi.ca/trac/ticket/827 for more informations. - * - * Since Laconica up to version 0.7.2 performs a full OAuth request check, a - * correct request would fail. - **/ - public $performLegacyAuthRequest = true; - - /* Helper stuff we are going to need. */ - protected $fetcher; - protected $oauth_consumer; - protected $datastore; - - /** - * Constructor for OMB_Service_Consumer - * - * Initializes an OMB_Service_Consumer object representing the OMB service - * specified by $service_url. Performs a complete service discovery using - * Yadis. - * Throws OMB_UnsupportedServiceException if XRDS file does not specify a - * complete OMB service. - * - * @param string $service_url The URL of the service - * @param string $consumer_url An URL representing the consumer - * @param OMB_Datastore $datastore An instance of a class implementing - * OMB_Datastore - * - * @access public - **/ - public function __construct ($service_url, $consumer_url, $datastore) { - $this->url = $service_url; - $this->fetcher = Auth_Yadis_Yadis::getHTTPFetcher(); - $this->datastore = $datastore; - $this->oauth_consumer = new OAuthConsumer($consumer_url, ''); - - $xrds = OMB_Yadis_XRDS::fromYadisURL($service_url, $this->fetcher); - - /* Detect our services. This performs a validation as well, since - getService und getXRD throw exceptions on failure. */ - $this->services = array(); - - foreach (array(OAUTH_DISCOVERY => OMB_Helper::$OAUTH_SERVICES, - OMB_VERSION => OMB_Helper::$OMB_SERVICES) - as $service_root => $targetservices) { - $uris = $xrds->getService($service_root)->getURIs(); - $xrd = $xrds->getXRD($uris[0]); - foreach ($targetservices as $targetservice) { - $yadis_service = $xrd->getService($targetservice); - if ($targetservice == OAUTH_ENDPOINT_REQUEST) { - $localid = $yadis_service->getElements('xrd:LocalID'); - $this->listener_uri = $yadis_service->parser->content($localid[0]); + * @package OMB + * @author Adrian Lang <mail@adrianlang.de> + * @license http://www.gnu.org/licenses/agpl.html GNU AGPL 3.0 + * @version 0.1a-20090828 + * @link http://adrianlang.de/libomb + */ + +require_once 'Validate.php'; +require_once 'Auth/Yadis/Yadis.php'; +require_once 'OAuth.php'; +require_once 'constants.php'; +require_once 'helper.php'; +require_once 'omb_yadis_xrds.php'; +require_once 'profile.php'; +require_once 'remoteserviceexception.php'; +require_once 'unsupportedserviceexception.php'; + +/** + * OMB service representation + * + * This class represents a complete remote OMB service. It provides discovery + * and execution of the service’s methods. + */ +class OMB_Service_Consumer +{ + protected $url; /* The service URL */ + protected $services; /* An array of strings mapping service URI to + service URL */ + + protected $token; /* An OAuthToken */ + + protected $listener_uri; /* The URI identifying the listener, i. e. the + remote user. */ + + protected $listenee_uri; /* The URI identifying the listenee, i. e. the + local user during an auth request. */ + + /** + * According to OAuth Core 1.0, an user authorization request is no + * full-blown OAuth request. nonce, timestamp, consumer_key and signature + * are not needed in this step. See http://laconi.ca/trac/ticket/827 for + * more informations. + * + * Since Laconica up to version 0.7.2 performs a full OAuth request check, a + * correct request would fail. + */ + public $performLegacyAuthRequest = true; + + /* Helper stuff we are going to need. */ + protected $fetcher; + protected $oauth_consumer; + protected $datastore; + + /** + * Constructor for OMB_Service_Consumer + * + * Initializes an OMB_Service_Consumer object representing the OMB service + * specified by $service_url. Performs a complete service discovery using + * Yadis. + * Throws OMB_UnsupportedServiceException if XRDS file does not specify a + * complete OMB service. + * + * @param string $service_url The URL of the service + * @param string $consumer_url An URL representing the consumer + * @param OMB_Datastore $datastore An instance of a class implementing + * OMB_Datastore + * + * @access public + */ + public function __construct ($service_url, $consumer_url, $datastore) + { + $this->url = $service_url; + $this->fetcher = Auth_Yadis_Yadis::getHTTPFetcher(); + $this->datastore = $datastore; + $this->oauth_consumer = new OAuthConsumer($consumer_url, ''); + + $xrds = OMB_Yadis_XRDS::fromYadisURL($service_url, $this->fetcher); + + /* Detect our services. This performs a validation as well, since + getService und getXRD throw exceptions on failure. */ + $this->services = array(); + + foreach (array(OAUTH_DISCOVERY => OMB_Helper::$OAUTH_SERVICES, + OMB_VERSION => OMB_Helper::$OMB_SERVICES) + as $service_root => $targetservices) { + $uris = $xrds->getService($service_root)->getURIs(); + $xrd = $xrds->getXRD($uris[0]); + foreach ($targetservices as $targetservice) { + $yadis_service = $xrd->getService($targetservice); + if ($targetservice == OAUTH_ENDPOINT_REQUEST) { + $localid = + $yadis_service->getElements('xrd:LocalID'); + $this->listener_uri = + $yadis_service->parser->content($localid[0]); + } + $uris = $yadis_service->getURIs(); + $this->services[$targetservice] = $uris[0]; + } } - $uris = $yadis_service->getURIs(); - $this->services[$targetservice] = $uris[0]; - } } - } - - /** - * Get the handler URI for a service - * - * Returns the URI the remote web service has specified for the given - * service. - * - * @param string $service The URI identifying the service - * - * @access public - * - * @return string The service handler URI - **/ - public function getServiceURI($service) { - return $this->services[$service]; - } - - /** - * Get the remote user’s URI - * - * Returns the URI of the remote user, i. e. the listener. - * - * @access public - * - * @return string The remote user’s URI - **/ - public function getRemoteUserURI() { - return $this->listener_uri; - } - - /** - * Get the listenee’s URI - * - * Returns the URI of the user being subscribed to, i. e. the local user. - * - * @access public - * - * @return string The local user’s URI - **/ - public function getListeneeURI() { - return $this->listenee_uri; - } - - /** - * Request a request token - * - * Performs a token request on the service. Returns an OAuthToken on success. - * Throws an exception if the request fails. - * - * @access public - * - * @return OAuthToken An unauthorized request token - **/ - public function requestToken() { - /* Set the token to null just in case the user called setToken. */ - $this->token = null; - - $result = $this->performAction(OAUTH_ENDPOINT_REQUEST, - array('omb_listener' => $this->listener_uri)); - if ($result->status != 200) { - throw OMB_RemoteServiceException::fromYadis(OAUTH_ENDPOINT_REQUEST, - $result); + + /** + * Get the handler URI for a service + * + * Returns the URI the remote web service has specified for the given + * service. + * + * @param string $service The URI identifying the service + * + * @access public + * + * @return string The service handler URI + */ + public function getServiceURI($service) + { + return $this->services[$service]; } - parse_str($result->body, $return); - if (!isset($return['oauth_token']) || !isset($return['oauth_token_secret'])) { - throw OMB_RemoteServiceException::fromYadis(OAUTH_ENDPOINT_REQUEST, - $result); + + /** + * Get the remote user’s URI + * + * Returns the URI of the remote user, i. e. the listener. + * + * @access public + * + * @return string The remote user’s URI + */ + public function getRemoteUserURI() + { + return $this->listener_uri; } - $this->setToken($return['oauth_token'], $return['oauth_token_secret']); - return $this->token; - } - - /** - * - * Request authorization - * - * Returns an URL which equals to an authorization request. The end user - * should be redirected to this location to perform authorization. - * The $finish_url should be a local resource which invokes - * OMB_Consumer::finishAuthorization on request. - * - * @param OMB_Profile $profile An OMB_Profile object representing the - * soon-to-be subscribed (i. e. local) user - * @param string $finish_url Target location after successful - * authorization - * - * @access public - * - * @return string An URL representing an authorization request - **/ - public function requestAuthorization($profile, $finish_url) { - if ($this->performLegacyAuthRequest) { - $params = $profile->asParameters('omb_listenee', false); - $params['omb_listener'] = $this->listener_uri; - $params['oauth_callback'] = $finish_url; - - $url = $this->prepareAction(OAUTH_ENDPOINT_AUTHORIZE, $params, 'GET')->to_url(); - } else { - - $params = array( - 'oauth_callback' => $finish_url, - 'oauth_token' => $this->token->key, - 'omb_version' => OMB_VERSION, - 'omb_listener' => $this->listener_uri); - - $params = array_merge($profile->asParameters('omb_listenee', false). $params); - - /* Build result URL. */ - $url = $this->services[OAUTH_ENDPOINT_AUTHORIZE]; - $url .= (strrpos($url, '?') === false ? '?' : '&'); - foreach ($params as $k => $v) { - $url .= OAuthUtil::urlencode_rfc3986($k) . '=' . OAuthUtil::urlencode_rfc3986($v) . '&'; - } + + /** + * Get the listenee’s URI + * + * Returns the URI of the user being subscribed to, i. e. the local user. + * + * @access public + * + * @return string The local user’s URI + */ + public function getListeneeURI() + { + return $this->listenee_uri; } - $this->listenee_uri = $profile->getIdentifierURI(); - - return $url; - } - - /** - * Finish authorization - * - * Finish the subscription process by converting the received and authorized - * request token into an access token. After that, the subscriber’s profile - * and the subscription are stored in the database. - * Expects an OAuthRequest in query parameters. - * Throws exceptions on failure. - * - * @access public - **/ - public function finishAuthorization() { - OMB_Helper::removeMagicQuotesFromRequest(); - $req = OAuthRequest::from_request(); - if ($req->get_parameter('oauth_token') != - $this->token->key) { - /* That’s not the token I wanted to get authorized. */ - throw new OAuthException('The authorized token does not equal the ' . - 'submitted token.'); + /** + * Request a request token + * + * Performs a token request on the service. Returns an OAuthToken on success. + * Throws an exception if the request fails. + * + * @access public + * + * @return OAuthToken An unauthorized request token + */ + public function requestToken() + { + /* Set the token to null just in case the user called setToken. */ + $this->token = null; + + $result = $this->performAction(OAUTH_ENDPOINT_REQUEST, + array('omb_listener' => $this->listener_uri)); + if ($result->status != 200) { + throw OMB_RemoteServiceException::fromYadis(OAUTH_ENDPOINT_REQUEST, + $result); + } + parse_str($result->body, $return); + if (!isset($return['oauth_token']) || + !isset($return['oauth_token_secret'])) { + throw OMB_RemoteServiceException::fromYadis(OAUTH_ENDPOINT_REQUEST, + $result); + } + $this->setToken($return['oauth_token'], $return['oauth_token_secret']); + return $this->token; } - if ($req->get_parameter('omb_version') != OMB_VERSION) { - throw new OMB_RemoteServiceException('The remote service uses an ' . - 'unsupported OMB version'); + /** + * Request authorization + * + * Returns an URL which equals to an authorization request. The end user + * should be redirected to this location to perform authorization. + * The $finish_url should be a local resource which invokes + * OMB_Consumer::finishAuthorization on request. + * + * @param OMB_Profile $profile An OMB_Profile object representing the + * soon-to-be subscribed (i. e. local) user + * @param string $finish_url Target location after successful + * authorization + * + * @access public + * + * @return string An URL representing an authorization request + */ + public function requestAuthorization($profile, $finish_url) + { + if ($this->performLegacyAuthRequest) { + $params = $profile->asParameters('omb_listenee', + false); + $params['omb_listener'] = $this->listener_uri; + $params['oauth_callback'] = $finish_url; + + $url = $this->prepareAction(OAUTH_ENDPOINT_AUTHORIZE, $params, + 'GET')->to_url(); + } else { + $params = array('oauth_callback' => $finish_url, + 'oauth_token' => $this->token->key, + 'omb_version' => OMB_VERSION, + 'omb_listener' => $this->listener_uri); + + $params = array_merge($profile->asParameters('omb_listenee', false), + $params); + + /* Build result URL. */ + $url = $this->services[OAUTH_ENDPOINT_AUTHORIZE] . + (strrpos($url, '?') === false ? '?' : '&'); + foreach ($params as $k => $v) { + $url .= OAuthUtil::urlencode_rfc3986($k) . '=' . + OAuthUtil::urlencode_rfc3986($v) . '&'; + } + } + + $this->listenee_uri = $profile->getIdentifierURI(); + + return $url; } - /* Construct the profile to validate it. */ + /** + * Finish authorization + * + * Finish the subscription process by converting the received and authorized + * request token into an access token. After that, the subscriber’s profile + * and the subscription are stored in the database. + * Expects an OAuthRequest in query parameters. + * Throws exceptions on failure. + * + * @access public + */ + public function finishAuthorization() + { + OMB_Helper::removeMagicQuotesFromRequest(); + $req = OAuthRequest::from_request(); + if ($req->get_parameter('oauth_token') != $this->token->key) { + /* That’s not the token I wanted to get authorized. */ + throw new OAuthException('The authorized token does not equal ' . + 'the submitted token.'); + } + + if ($req->get_parameter('omb_version') != OMB_VERSION) { + throw new OMB_RemoteServiceException('The remote service uses an ' . + 'unsupported OMB version'); + } + + /* Construct the profile to validate it. */ + + /* Fix OMB bug. Listener URI is not passed. */ + if ($_SERVER['REQUEST_METHOD'] == 'POST') { + $params = $_POST; + } else { + $params = $_GET; + } + $params['omb_listener'] = $this->listener_uri; + + $listener = OMB_Profile::fromParameters($params, 'omb_listener'); - /* Fix OMB bug. Listener URI is not passed. */ - if ($_SERVER['REQUEST_METHOD'] == 'POST') { - $params = $_POST; - } else { - $params = $_GET; + /* Ask the remote service to convert the authorized request token into + an access token. */ + + $result = $this->performAction(OAUTH_ENDPOINT_ACCESS, array()); + if ($result->status != 200) { + throw new OAuthException('Could not get access token'); + } + + parse_str($result->body, $return); + if (!isset($return['oauth_token']) || + !isset($return['oauth_token_secret'])) { + throw new OAuthException('Could not get access token'); + } + $this->setToken($return['oauth_token'], $return['oauth_token_secret']); + + /* Subscription is finished and valid. Now store the new subscriber and + the subscription in the database. */ + + $this->datastore->saveProfile($listener); + $this->datastore->saveSubscription($this->listener_uri, + $this->listenee_uri, + $this->token); + } + + /** + * Return the URI identifying the listener + * + * Returns the URI for the OMB user who tries to subscribe or already has + * subscribed our user. This method is a workaround for a serious OMB flaw: + * The Listener URI is not passed in the finishauthorization call. + * + * @access public + * + * @return string the listener’s URI + */ + public function getListenerURI() + { + return $this->listener_uri; } - $params['omb_listener'] = $this->listener_uri; - require_once 'profile.php'; - $listener = OMB_Profile::fromParameters($params, 'omb_listener'); + /** + * Inform the service about a profile update + * + * Sends an updated profile to the service. + * + * @param OMB_Profile $profile The profile that has changed + * + * @access public + */ + public function updateProfile($profile) + { + $params = $profile->asParameters('omb_listenee', true); + $this->performOMBAction(OMB_ENDPOINT_UPDATEPROFILE, $params, + $profile->getIdentifierURI()); + } - /* Ask the remote service to convert the authorized request token into an - access token. */ + /** + * Inform the service about a new notice + * + * Sends a notice to the service. + * + * @param OMB_Notice $notice The notice + * + * @access public + */ + public function postNotice($notice) + { + $params = $notice->asParameters(); + $params['omb_listenee'] = $notice->getAuthor()->getIdentifierURI(); + $this->performOMBAction(OMB_ENDPOINT_POSTNOTICE, $params, + $params['omb_listenee']); + } - $result = $this->performAction(OAUTH_ENDPOINT_ACCESS, array()); - if ($result->status != 200) { - throw new OAuthException('Could not get access token'); + /** + * Set the token member variable + * + * Initializes the token based on given token and secret token. + * + * @param string $token The token + * @param string $secret The secret token + * + * @access public + */ + public function setToken($token, $secret) + { + $this->token = new OAuthToken($token, $secret); } - parse_str($result->body, $return); - if (!isset($return['oauth_token']) || !isset($return['oauth_token_secret'])) { - throw new OAuthException('Could not get access token'); + /** + * Prepare an OAuthRequest object + * + * Creates an OAuthRequest object mapping the request specified by the + * parameters. + * + * @param string $action_uri The URI specifying the target service + * @param array $params Additional parameters for the service call + * @param string $method The HTTP method used to call the service + * ('POST' or 'GET', usually) + * + * @access protected + * + * @return OAuthRequest the prepared request + */ + protected function prepareAction($action_uri, $params, $method) + { + $url = $this->services[$action_uri]; + + $url_params = array(); + parse_str(parse_url($url, PHP_URL_QUERY), $url_params); + + /* Add OMB version. */ + $url_params['omb_version'] = OMB_VERSION; + + /* Add user-defined parameters. */ + $url_params = array_merge($url_params, $params); + + $req = OAuthRequest::from_consumer_and_token($this->oauth_consumer, + $this->token, $method, + $url, $url_params); + + /* Sign the request. */ + $req->sign_request(new OAuthSignatureMethod_HMAC_SHA1(), + $this->oauth_consumer, $this->token); + + return $req; } - $this->setToken($return['oauth_token'], $return['oauth_token_secret']); - - /* Subscription is finished and valid. Now store the new subscriber and the - subscription in the database. */ - - $this->datastore->saveProfile($listener); - $this->datastore->saveSubscription($this->listener_uri, - $this->listenee_uri, - $this->token); - } - - /** - * Return the URI identifying the listener - * - * Returns the URI for the OMB user who tries to subscribe or already has - * subscribed our user. This method is a workaround for a serious OMB flaw: - * The Listener URI is not passed in the finishauthorization call. - * - * @access public - * - * @return string the listener’s URI - **/ - public function getListenerURI() { - return $this->listener_uri; - } - - /** - * Inform the service about a profile update - * - * Sends an updated profile to the service. - * - * @param OMB_Profile $profile The profile that has changed - * - * @access public - **/ - public function updateProfile($profile) { - $params = $profile->asParameters('omb_listenee', true); - $this->performOMBAction(OMB_ENDPOINT_UPDATEPROFILE, $params, $profile->getIdentifierURI()); - } - - /** - * Inform the service about a new notice - * - * Sends a notice to the service. - * - * @param OMB_Notice $notice The notice - * - * @access public - **/ - public function postNotice($notice) { - $params = $notice->asParameters(); - $params['omb_listenee'] = $notice->getAuthor()->getIdentifierURI(); - $this->performOMBAction(OMB_ENDPOINT_POSTNOTICE, $params, $params['omb_listenee']); - } - - /** - * Set the token member variable - * - * Initializes the token based on given token and secret token. - * - * @param string $token The token - * @param string $secret The secret token - * - * @access public - **/ - public function setToken($token, $secret) { - $this->token = new OAuthToken($token, $secret); - } - - /** - * Prepare an OAuthRequest object - * - * Creates an OAuthRequest object mapping the request specified by the - * parameters. - * - * @param string $action_uri The URI specifying the target service - * @param array $params Additional parameters for the service call - * @param string $method The HTTP method used to call the service - * ('POST' or 'GET', usually) - * - * @access protected - * - * @return OAuthRequest the prepared request - **/ - protected function prepareAction($action_uri, $params, $method) { - $url = $this->services[$action_uri]; - - $url_params = array(); - parse_str(parse_url($url, PHP_URL_QUERY), $url_params); - - /* Add OMB version. */ - $url_params['omb_version'] = OMB_VERSION; - - /* Add user-defined parameters. */ - $url_params = array_merge($url_params, $params); - - $req = OAuthRequest::from_consumer_and_token($this->oauth_consumer, - $this->token, $method, $url, $url_params); - - /* Sign the request. */ - $req->sign_request(new OAuthSignatureMethod_HMAC_SHA1(), - $this->oauth_consumer, $this->token); - - return $req; - } - - /** - * Perform a service call - * - * Creates an OAuthRequest object and execute the mapped call as POST request. - * - * @param string $action_uri The URI specifying the target service - * @param array $params Additional parameters for the service call - * - * @access protected - * - * @return Auth_Yadis_HTTPResponse The POST request response - **/ - protected function performAction($action_uri, $params) { - $req = $this->prepareAction($action_uri, $params, 'POST'); - - /* Return result page. */ - return $this->fetcher->post($req->get_normalized_http_url(), $req->to_postdata(), array()); - } - - /** - * Perform an OMB action - * - * Executes an OMB action – to date, it’s one of updateProfile or postNotice. - * - * @param string $action_uri The URI specifying the target service - * @param array $params Additional parameters for the service call - * @param string $listenee_uri The URI identifying the local user for whom - * the action is performed - * - * @access protected - **/ - protected function performOMBAction($action_uri, $params, $listenee_uri) { - $result = $this->performAction($action_uri, $params); - if ($result->status == 403) { - /* The remote user unsubscribed us. */ - $this->datastore->deleteSubscription($this->listener_uri, $listenee_uri); - } else if ($result->status != 200 || - strpos($result->body, 'omb_version=' . OMB_VERSION) === false) { - /* The server signaled an error or sent an incorrect response. */ - throw OMB_RemoteServiceException::fromYadis($action_uri, $result); + + /** + * Perform a service call + * + * Creates an OAuthRequest object and execute the mapped call as POST + * request. + * + * @param string $action_uri The URI specifying the target service + * @param array $params Additional parameters for the service call + * + * @access protected + * + * @return Auth_Yadis_HTTPResponse The POST request response + */ + protected function performAction($action_uri, $params) + { + $req = $this->prepareAction($action_uri, $params, 'POST'); + + /* Return result page. */ + return $this->fetcher->post($req->get_normalized_http_url(), + $req->to_postdata(), array()); + } + + /** + * Perform an OMB action + * + * Executes an OMB action – as of OMB 0.1, it’s one of updateProfile and + * postNotice. + * + * @param string $action_uri The URI specifying the target service + * @param array $params Additional parameters for the service call + * @param string $listenee_uri The URI identifying the local user for whom + * the action is performed + * + * @access protected + */ + protected function performOMBAction($action_uri, $params, $listenee_uri) + { + $result = $this->performAction($action_uri, $params); + if ($result->status == 403) { + /* The remote user unsubscribed us. */ + $this->datastore->deleteSubscription($this->listener_uri, + $listenee_uri); + } else if ($result->status != 200 || + strpos($result->body, 'omb_version=' . OMB_VERSION) === false) { + /* The server signaled an error or sent an incorrect response. */ + throw OMB_RemoteServiceException::fromYadis($action_uri, $result); + } } - } } +?> |