summaryrefslogtreecommitdiff
path: root/extlib/libomb/service_provider.php
diff options
context:
space:
mode:
authorZach Copley <zach@status.net>2009-11-19 20:12:46 -0800
committerZach Copley <zach@status.net>2009-11-19 20:12:46 -0800
commit4b98edf75f4e255f8c61087bd1525d89653a521f (patch)
treeb2a7eb6d77429eadb1beabe2d5e6ae1c1a2831d6 /extlib/libomb/service_provider.php
parentf92574dbcb1f2d7cd0aaf3c9362db46fa066e888 (diff)
parentc213477081afefb1720c8ae729d1965e7a1dac63 (diff)
Merge branch '0.9-release'
* 0.9-release: (874 commits) Removed call to NewDirectMessage() until IE return is fixed i.e., Don't show flag user button your own profile Fixed HXR response for flag user Using the right form class name Using common_redirect Left a form_data class of a <ul> in the user admin panel Added validation to fields in user admin panel Added a user admin panel Added mobile logos for default and identica themes Changed gif to png Changed this to action. THANKS zach! Doing content negotiation only once Add execute bit to pingqueuehandler Localisation updates for !StatusNet from !translatewiki.net Use the browser's geolocation API to set the location on the notice form Add geometa library, and include it. Add location form elements to the noticeform, and save their values on submission Use the $user object nickname, as login name doesnt have to == nickname anymore with plugins such as ldap/etc Revert "Re added NICKNAME_FMT constant to router.php." Moved most path and server settings to a new paths admin panel ... Conflicts: js/util.js locale/it_IT/LC_MESSAGES/statusnet.mo locale/mk_MK/LC_MESSAGES/statusnet.mo locale/mk_MK/LC_MESSAGES/statusnet.po locale/pt_BR/LC_MESSAGES/statusnet.mo locale/vi_VN/LC_MESSAGES/statusnet.mo plugins/InfiniteScroll/infinitescroll.js plugins/Realtime/realtimeupdate.js
Diffstat (limited to 'extlib/libomb/service_provider.php')
-rwxr-xr-xextlib/libomb/service_provider.php425
1 files changed, 425 insertions, 0 deletions
diff --git a/extlib/libomb/service_provider.php b/extlib/libomb/service_provider.php
new file mode 100755
index 000000000..753152713
--- /dev/null
+++ b/extlib/libomb/service_provider.php
@@ -0,0 +1,425 @@
+<?php
+
+require_once 'constants.php';
+require_once 'remoteserviceexception.php';
+require_once 'helper.php';
+
+/**
+ * OMB service realization
+ *
+ * This class realizes a complete, simple OMB service.
+ *
+ * PHP version 5
+ *
+ * LICENSE: This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * 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_Provider {
+ protected $user; /* An OMB_Profile representing the user */
+ protected $datastore; /* AN OMB_Datastore */
+
+ protected $remote_user; /* An OMB_Profile representing the remote user during
+ the authorization process */
+
+ protected $oauth_server; /* An OAuthServer; should only be accessed via
+ getOAuthServer. */
+
+ /**
+ * Initialize an OMB_Service_Provider object
+ *
+ * Constructs an OMB_Service_Provider instance that provides OMB services
+ * referring to a particular user.
+ *
+ * @param OMB_Profile $user An OMB_Profile; mandatory for XRDS
+ * output, user auth handling and OMB
+ * action performing
+ * @param OMB_Datastore $datastore An OMB_Datastore; mandatory for
+ * everything but XRDS output
+ * @param OAuthServer $oauth_server An OAuthServer; used for token writing
+ * and OMB action handling; will use
+ * default value if not set
+ *
+ * @access public
+ **/
+ public function __construct ($user = null, $datastore = null, $oauth_server = null) {
+ $this->user = $user;
+ $this->datastore = $datastore;
+ $this->oauth_server = $oauth_server;
+ }
+
+ public function getRemoteUser() {
+ return $this->remote_user;
+ }
+
+ /**
+ * Write a XRDS document
+ *
+ * Writes a XRDS document specifying the OMB service. Optionally uses a
+ * given object of a class implementing OMB_XRDS_Writer for output. Else
+ * OMB_Plain_XRDS_Writer is used.
+ *
+ * @param OMB_XRDS_Mapper $xrds_mapper An object mapping actions to URLs
+ * @param OMB_XRDS_Writer $xrds_writer Optional; The OMB_XRDS_Writer used to
+ * write the XRDS document
+ *
+ * @access public
+ *
+ * @return mixed Depends on the used OMB_XRDS_Writer; OMB_Plain_XRDS_Writer
+ * returns nothing.
+ **/
+ public function writeXRDS($xrds_mapper, $xrds_writer = null) {
+ if ($xrds_writer == null) {
+ require_once 'plain_xrds_writer.php';
+ $xrds_writer = new OMB_Plain_XRDS_Writer();
+ }
+ return $xrds_writer->writeXRDS($this->user, $xrds_mapper);
+ }
+
+ /**
+ * Echo a request token
+ *
+ * Outputs an unauthorized request token for the query found in $_GET or
+ * $_POST.
+ *
+ * @access public
+ **/
+ public function writeRequestToken() {
+ OMB_Helper::removeMagicQuotesFromRequest();
+ echo $this->getOAuthServer()->fetch_request_token(OAuthRequest::from_request());
+ }
+
+ /**
+ * Handle an user authorization request.
+ *
+ * Parses an authorization request. This includes OAuth and OMB verification.
+ * Throws exceptions on failures. Returns an OMB_Profile object representing
+ * 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
+ *
+ * @return OMB_Profile The profile of the soon-to-be subscribed, i. e. remote
+ * user
+ **/
+ public function handleUserAuth() {
+ OMB_Helper::removeMagicQuotesFromRequest();
+
+ /* Verify the request token. */
+
+ $this->token = $this->datastore->lookup_token(null, "request", $_GET['oauth_token']);
+ if (is_null($this->token)) {
+ throw new OAuthException('The given request token has not been issued ' .
+ 'by this service.');
+ }
+
+ /* Verify the OMB part. */
+
+ if ($_GET['omb_version'] !== OMB_VERSION) {
+ throw OMB_RemoteServiceException::forRequest(OAUTH_ENDPOINT_AUTHORIZE,
+ 'Wrong OMB version ' . $_GET['omb_version']);
+ }
+
+ if ($_GET['omb_listener'] !== $this->user->getIdentifierURI()) {
+ throw OMB_RemoteServiceException::forRequest(OAUTH_ENDPOINT_AUTHORIZE,
+ 'Wrong OMB listener ' . $_GET['omb_listener']);
+ }
+
+ foreach (array('omb_listenee', 'omb_listenee_profile',
+ 'omb_listenee_nickname', 'omb_listenee_license') as $param) {
+ if (!isset($_GET[$param]) || is_null($_GET[$param])) {
+ throw OMB_RemoteServiceException::forRequest(OAUTH_ENDPOINT_AUTHORIZE,
+ "Required parameter '$param' not found");
+ }
+ }
+
+ /* Store given callback for later use. */
+ if (isset($_GET['oauth_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');
+
+ return $this->remote_user;
+ }
+
+ /**
+ * Continue the OAuth dance after user authorization
+ *
+ * Performs the appropriate actions after user answered the authorization
+ * request.
+ *
+ * @param bool $accepted Whether the user granted authorization
+ *
+ * @access public
+ *
+ * @return array A two-component array with the values:
+ * - callback The callback URL or null if none given
+ * - token The authorized request token or null if not
+ * authorized.
+ **/
+ public function continueUserAuth($accepted) {
+ $callback = $this->callback;
+ if (!$accepted) {
+ $this->datastore->revoke_token($this->token->key);
+ $this->token = null;
+ /* TODO: The handling is probably wrong in terms of OAuth 1.0 but the way
+ laconica works. Moreover I don’t know the right way either. */
+
+ } else {
+ $this->datastore->authorize_token($this->token->key);
+ $this->datastore->saveProfile($this->remote_user);
+ $this->datastore->saveSubscription($this->user->getIdentifierURI(),
+ $this->remote_user->getIdentifierURI(), $this->token);
+
+ if (!is_null($this->callback)) {
+ /* Callback wants to get some informations as well. */
+ $params = $this->user->asParameters('omb_listener', false);
+
+ $params['oauth_token'] = $this->token->key;
+ $params['omb_version'] = OMB_VERSION;
+
+ $callback .= (parse_url($this->callback, PHP_URL_QUERY) ? '&' : '?');
+ foreach ($params as $k => $v) {
+ $callback .= OAuthUtil::urlencode_rfc3986($k) . '=' .
+ OAuthUtil::urlencode_rfc3986($v) . '&';
+ }
+ }
+ }
+ return array($callback, $this->token);
+ }
+
+ /**
+ * Echo an access token
+ *
+ * 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
+ **/
+ public function writeAccessToken() {
+ OMB_Helper::removeMagicQuotesFromRequest();
+ echo $this->getOAuthServer()->fetch_access_token(
+ OAuthRequest::from_request('POST'));
+ }
+
+ /**
+ * Handle an updateprofile request
+ *
+ * Handles an updateprofile request posted to this service. Updates the
+ * profile through the OMB_Datastore.
+ *
+ * @access public
+ *
+ * @return OMB_Profile The updated profile
+ **/
+ public function handleUpdateProfile() {
+ list($req, $profile) = $this->handleOMBRequest(OMB_ENDPOINT_UPDATEPROFILE);
+ $profile->updateFromParameters($req->get_parameters(), 'omb_listenee');
+ $this->datastore->saveProfile($profile);
+ $this->finishOMBRequest();
+ return $profile;
+ }
+
+ /**
+ * Handle a postnotice request
+ *
+ * Handles a postnotice request posted to this service. Saves the notice
+ * through the OMB_Datastore.
+ *
+ * @access public
+ *
+ * @return OMB_Notice The received notice
+ **/
+ public function handlePostNotice() {
+ list($req, $profile) = $this->handleOMBRequest(OMB_ENDPOINT_POSTNOTICE);
+ require_once 'notice.php';
+ $notice = OMB_Notice::fromParameters($profile, $req->get_parameters());
+ $this->datastore->saveNotice($notice);
+ $this->finishOMBRequest();
+ return $notice;
+ }
+
+ /**
+ * Handle an OMB request
+ *
+ * Performs common OMB request handling.
+ *
+ * @param string $uri The URI defining the OMB endpoint being served
+ *
+ * @access protected
+ *
+ * @return array(OAuthRequest, OMB_Profile)
+ **/
+ protected function handleOMBRequest($uri) {
+
+ OMB_Helper::removeMagicQuotesFromRequest();
+ $req = OAuthRequest::from_request('POST');
+ $listenee = $req->get_parameter('omb_listenee');
+
+ try {
+ list($consumer, $token) = $this->getOAuthServer()->verify_request($req);
+ } catch (OAuthException $e) {
+ header('HTTP/1.1 403 Forbidden');
+ throw OMB_RemoteServiceException::forRequest($uri,
+ 'Revoked accesstoken for ' . $listenee);
+ }
+
+ $version = $req->get_parameter('omb_version');
+ if ($version !== OMB_VERSION) {
+ header('HTTP/1.1 400 Bad Request');
+ throw OMB_RemoteServiceException::forRequest($uri,
+ 'Wrong OMB version ' . $version);
+ }
+
+ $profile = $this->datastore->getProfile($listenee);
+ if (is_null($profile)) {
+ header('HTTP/1.1 400 Bad Request');
+ throw OMB_RemoteServiceException::forRequest($uri,
+ 'Unknown remote profile ' . $listenee);
+ }
+
+ $subscribers = $this->datastore->getSubscriptions($listenee);
+ if (count($subscribers) === 0) {
+ header('HTTP/1.1 403 Forbidden');
+ throw OMB_RemoteServiceException::forRequest($uri,
+ 'No subscriber for ' . $listenee);
+ }
+
+ return array($req, $profile);
+ }
+
+ /**
+ * Finishes an OMB request handling
+ *
+ * Performs common OMB request handling finishing.
+ *
+ * @access protected
+ **/
+ protected function finishOMBRequest() {
+ header('HTTP/1.1 200 OK');
+ header('Content-type: text/plain');
+ /* There should be no clutter but the version. */
+ echo "omb_version=" . OMB_VERSION;
+ }
+
+ /**
+ * Return an OAuthServer
+ *
+ * Checks whether the OAuthServer is null. If so, initializes it with a
+ * default value. Returns the OAuth server.
+ *
+ * @access protected
+ **/
+ protected function getOAuthServer() {
+ if (is_null($this->oauth_server)) {
+ $this->oauth_server = new OAuthServer($this->datastore);
+ $this->oauth_server->add_signature_method(
+ new OAuthSignatureMethod_HMAC_SHA1());
+ }
+ return $this->oauth_server;
+ }
+
+ /**
+ * Publish a notice
+ *
+ * Posts an OMB notice. This includes storing the notice and posting it to
+ * subscribed users.
+ *
+ * @param OMB_Notice $notice The new notice
+ *
+ * @access public
+ *
+ * @return array An array mapping subscriber URIs to the exception posting to
+ * them has raised; Empty array if no exception occured
+ **/
+ public function postNotice($notice) {
+ $uri = $this->user->getIdentifierURI();
+
+ /* $notice is passed by reference and may change. */
+ $this->datastore->saveNotice($notice);
+ $subscribers = $this->datastore->getSubscriptions($uri);
+
+ /* No one to post to. */
+ if (is_null($subscribers)) {
+ return array();
+ }
+
+ require_once 'service_consumer.php';
+
+ $err = array();
+ foreach($subscribers as $subscriber) {
+ try {
+ $service = new OMB_Service_Consumer($subscriber['uri'], $uri, $this->datastore);
+ $service->setToken($subscriber['token'], $subscriber['secret']);
+ $service->postNotice($notice);
+ } catch (Exception $e) {
+ $err[$subscriber['uri']] = $e;
+ continue;
+ }
+ }
+ return $err;
+ }
+
+ /**
+ * Publish a profile update
+ *
+ * Posts the current profile as an OMB profile update. This includes updating
+ * the stored profile and posting it to subscribed users.
+ *
+ * @access public
+ *
+ * @return array An array mapping subscriber URIs to the exception posting to
+ * them has raised; Empty array if no exception occured
+ **/
+ public function updateProfile() {
+ $uri = $this->user->getIdentifierURI();
+
+ $this->datastore->saveProfile($this->user);
+ $subscribers = $this->datastore->getSubscriptions($uri);
+
+ /* No one to post to. */
+ if (is_null($subscribers)) {
+ return array();
+ }
+
+ require_once 'service_consumer.php';
+
+ $err = array();
+ foreach($subscribers as $subscriber) {
+ try {
+ $service = new OMB_Service_Consumer($subscriber['uri'], $uri, $this->datastore);
+ $service->setToken($subscriber['token'], $subscriber['secret']);
+ $service->updateProfile($this->user);
+ } catch (Exception $e) {
+ $err[$subscriber['uri']] = $e;
+ continue;
+ }
+ }
+ return $err;
+ }
+}