forked from GNUsocial/gnu-social
		
	Merge branch '0.9.x' into 1.0.x
This commit is contained in:
		
							
								
								
									
										227
									
								
								EVENTS.txt
									
									
									
									
									
								
							
							
						
						
									
										227
									
								
								EVENTS.txt
									
									
									
									
									
								
							| @@ -836,3 +836,230 @@ EndDeleteUser: handling the post for deleting a user | ||||
| - $action: action being shown | ||||
| - $user: user being deleted | ||||
|  | ||||
| StartActivityStart: starting the output for a notice activity <event> | ||||
| - &$notice: notice being output | ||||
| - &$xs: XMLStringer for output | ||||
| - &$attrs: <entry> attributes (mostly namespace declarations, if any) | ||||
|  | ||||
| EndActivityStart: end the opening tag for an activity <event> | ||||
| - &$notice: notice being output | ||||
| - &$xs: XMLStringer for output | ||||
| - $attrs: <entry> attributes (mostly namespace declarations, if any) | ||||
|  | ||||
| StartActivitySource: before outputting the <source> element for a notice activity | ||||
| - &$notice: notice being output | ||||
| - &$xs: XMLStringer for output | ||||
|  | ||||
| EndActivitySource: after outputting the <source> element for a notice activity | ||||
| - &$notice: notice being output | ||||
| - &$xs: XMLStringer for output | ||||
|  | ||||
| StartActivityTitle: before outputting notice activity title | ||||
| - &$notice: notice being output | ||||
| - &$xs: XMLStringer for output | ||||
| - &$title: title of the notice, mutable | ||||
|  | ||||
| EndActivityTitle: after outputting notice activity title | ||||
| - $notice: notice being output | ||||
| - &$xs: XMLStringer for output | ||||
| - $title: title of the notice | ||||
|  | ||||
| StartActivityAuthor: before outputting atom author | ||||
| - &$notice: notice being output | ||||
| - &$xs: XMLStringer for output | ||||
| - &$atomAuthor: string for XML representing atom author | ||||
|  | ||||
| EndActivityAuthor: after outputting atom author | ||||
| - &$notice: notice being output | ||||
| - &$xs: XMLStringer for output | ||||
| - &$atomAuthor: string for XML representing atom author | ||||
|  | ||||
| StartActivityActor: before outputting activity actor element for a notice activity entry | ||||
| - &$notice: notice being output | ||||
| - &$xs: XMLStringer for output | ||||
| - &$actor: string for XML representing activity actor | ||||
|  | ||||
| EndActivityActor: after outputting activity actor element for a notice activity entry | ||||
| - &$notice: notice being output | ||||
| - &$xs: XMLStringer for output | ||||
| - &$actor: string for XML representing activity actor | ||||
|  | ||||
| StartActivityLink: before outputting activity HTML link element for a notice activity entry | ||||
| - &$notice: notice being output | ||||
| - &$xs: XMLStringer for output | ||||
| - &$url: URL for activity HTML link element for a notice activity entry | ||||
|  | ||||
| EndActivityLink: before outputting activity HTML link element for a notice activity entry | ||||
| - &$notice: notice being output | ||||
| - &$xs: XMLStringer for output | ||||
| - $url:  URL for activity HTML link element for a notice activity entry | ||||
|  | ||||
| StartActivityId: before outputting atom:id element for a notice activity entry | ||||
| - &$notice: notice being output | ||||
| - &$xs: XMLStringer for output | ||||
| - &$id: atom:id (notice URI by default) | ||||
|  | ||||
| EndActivityId: after outputting atom:id element for a notice activity entry | ||||
| - &$notice: notice being output | ||||
| - &$xs: XMLStringer for output | ||||
| - $id:  atom:id (notice URI by default) | ||||
|  | ||||
| StartActivityPublished: before outputting atom:published element for a notice activity entry | ||||
| - &$notice: notice being output | ||||
| - &$xs: XMLStringer for output | ||||
| - &$published: atom:published value (notice created by default) | ||||
|  | ||||
| EndActivityPublished: before outputting atom:published element for a notice activity entry | ||||
| - &$notice: notice being output | ||||
| - &$xs: XMLStringer for output | ||||
| - $published:  atom:published value (notice created by default) | ||||
|  | ||||
| StartActivityUpdated: before outputting atom:updated element for a notice activity entry | ||||
| - &$notice: notice being output | ||||
| - &$xs: XMLStringer for output | ||||
| - &$updated: atom:updated value (same as atom:published by default) | ||||
|  | ||||
| EndActivityUpdated: after outputting atom:updated element for a notice activity entry | ||||
| - &$notice: notice being output | ||||
| - &$xs: XMLStringer for output | ||||
| - $updated: atom:updated value (same as atom:published by default) | ||||
|  | ||||
| StartActivityContent: before outputting atom:content element for a notice activity entry | ||||
| - &$notice: notice being output | ||||
| - &$xs: XMLStringer for output | ||||
| - &$content: atom:content value (notice rendered HTML by default) | ||||
|  | ||||
| EndActivityContent: after outputting atom:content element for a notice activity entry | ||||
| - &$notice: notice being output | ||||
| - &$xs: XMLStringer for output | ||||
| - $content: atom:content value (notice rendered HTML by default) | ||||
|  | ||||
| StartActivityVerb: before outputting activity:verb element for a notice activity entry | ||||
| - &$notice: notice being output | ||||
| - &$xs: XMLStringer for output | ||||
| - &$verb: activity:verb URI ('http://activitystrea.ms/schema/1.0/post' by default) | ||||
|  | ||||
| EndActivityVerb: after outputting activity:verb element for a notice activity entry | ||||
| - &$notice: notice being output | ||||
| - &$xs: XMLStringer for output | ||||
| - $verb: activity:verb URI ('http://activitystrea.ms/schema/1.0/post' by default) | ||||
|  | ||||
| StartActivityDefaultObjectType: before outputting activity:object-type element for a notice activity entry | ||||
| - &$notice: notice being output | ||||
| - &$xs: XMLStringer for output | ||||
| - &$type: activity:object-type URI for default object ('http://activitystrea.ms/schema/1.0/note' by default) | ||||
|  | ||||
| EndActivityDefaultObjectType: after outputting activity:verb element for a notice activity entry | ||||
| - &$notice: notice being output | ||||
| - &$xs: XMLStringer for output | ||||
| - $type: activity:object-type URI for default object ('http://activitystrea.ms/schema/1.0/note' by default) | ||||
|  | ||||
| StartActivityObjects: before outputting activity:object elements for a notice activity entry | ||||
| - &$notice: notice being output | ||||
| - &$xs: XMLStringer for output | ||||
| - &$objects: array of ActivityObject objects to output (empty by default) | ||||
|  | ||||
| EndActivityObjects: after outputting activity:object elements for a notice activity entry | ||||
| - &$notice: notice being output | ||||
| - &$xs: XMLStringer for output | ||||
| - $objects: array of ActivityObject objects to output (empty by default) | ||||
|  | ||||
| StartActivityNoticeInfo: before outputting statusnet:notice-info element for a notice activity entry | ||||
| - &$notice: notice being output | ||||
| - &$xs: XMLStringer for output | ||||
| - &$noticeInfoAttr: array of attributes for notice info element | ||||
|  | ||||
| EndActivityNoticeInfo: after outputting statusnet:notice-info element for a notice activity entry | ||||
| - &$notice: notice being output | ||||
| - &$xs: XMLStringer for output | ||||
| - $noticeInfoAttr: array of attributes for notice info element | ||||
|  | ||||
| StartActivityInReplyTo: before outputting thr:in-reply-to element for a notice activity entry | ||||
| - &$notice: notice being output | ||||
| - &$xs: XMLStringer for output | ||||
| - &$replyNotice: Notice object the main notice is in-reply-to | ||||
|  | ||||
| EndActivityInReplyTo: after outputting thr:in-reply-to element for a notice activity entry | ||||
| - &$notice: notice being output | ||||
| - &$xs: XMLStringer for output | ||||
| - $replyNotice: Notice object the main notice is in-reply-to | ||||
|  | ||||
| StartActivityConversation: before outputting ostatus:conversation link element for a notice activity entry | ||||
| - &$notice: notice being output | ||||
| - &$xs: XMLStringer for output | ||||
| - &$conv: Conversation object | ||||
|  | ||||
| EndActivityConversation: after outputting ostatus:conversation link element for a notice activity entry | ||||
| - &$notice: notice being output | ||||
| - &$xs: XMLStringer for output | ||||
| - $conv: Conversation object | ||||
|  | ||||
| StartActivityAttentionProfiles: before outputting ostatus:attention link element for people in a notice activity entry | ||||
| - &$notice: notice being output | ||||
| - &$xs: XMLStringer for output | ||||
| - &$replyProfiles: array of profiles of people being replied to | ||||
|  | ||||
| EndActivityAttentionProfiles: after outputting ostatus:attention link element for people in a notice activity entry | ||||
| - &$notice: notice being output | ||||
| - &$xs: XMLStringer for output | ||||
| - $replyProfiles: array of Profile object of people being replied to | ||||
|  | ||||
| StartActivityAttentionGroups: before outputting ostatus:attention link element for groups in a notice activity entry | ||||
| - &$notice: notice being output | ||||
| - &$xs: XMLStringer for output | ||||
| - &$groups: array of Group objects of groups being addressed | ||||
|  | ||||
| EndActivityAttentionGroups: after outputting ostatus:attention link element for groups in a notice activity entry | ||||
| - &$notice: notice being output | ||||
| - &$xs: XMLStringer for output | ||||
| - $groups: array of Group objects of groups being addressed | ||||
|  | ||||
| StartActivityForward: before outputting ostatus:forward link element in a notice activity entry | ||||
| - &$notice: notice being output | ||||
| - &$xs: XMLStringer for output | ||||
| - &$repeat: Notice that was repeated | ||||
|  | ||||
| EndActivityForward: after outputting ostatus:forward link element in a notice activity entry | ||||
| - &$notice: notice being output | ||||
| - &$xs: XMLStringer for output | ||||
| - $repeat: Notice that was repeated | ||||
|  | ||||
| StartActivityCategories: before outputting atom:category elements in a notice activity entry | ||||
| - &$notice: notice being output | ||||
| - &$xs: XMLStringer for output | ||||
| - &$tags: array of strings for tags on the notice (used for categories) | ||||
|  | ||||
| EndActivityCategories: after outputting atom:category elements in a notice activity entry | ||||
| - &$notice: notice being output | ||||
| - &$xs: XMLStringer for output | ||||
| - $tags: array of strings for tags on the notice (used for categories) | ||||
|  | ||||
| StartActivityEnclosures: before outputting enclosure link elements in a notice activity entry | ||||
| - &$notice: notice being output | ||||
| - &$xs: XMLStringer for output | ||||
| - &$enclosures: array of enclosure objects (see File::getEnclosure() for details) | ||||
|  | ||||
| EndActivityEnclosures: after outputting enclosure link elements in a notice activity entry | ||||
| - &$notice: notice being output | ||||
| - &$xs: XMLStringer for output | ||||
| - $enclosures: array of enclosure objects (see File::getEnclosure() for details) | ||||
|  | ||||
| StartActivityGeo: before outputting geo:rss element in a notice activity entry | ||||
| - &$notice: notice being output | ||||
| - &$xs: XMLStringer for output | ||||
| - &$lat: latitude | ||||
| - &$lon: longitude | ||||
|  | ||||
| EndActivityGeo: after outputting geo:rss element in a notice activity entry | ||||
| - &$notice: notice being output | ||||
| - &$xs: XMLStringer for output | ||||
| - $lat: latitude | ||||
| - $lon: longitude | ||||
|  | ||||
| StartActivityEnd: before the closing </entry> in a notice activity entry (last chance for data!) | ||||
| - &$notice: notice being output | ||||
| - &$xs: XMLStringer for output | ||||
|  | ||||
| EndActivityEnd: after the closing </entry> in a notice activity entry | ||||
| - &$notice: notice being output | ||||
| - &$xs: XMLStringer for output | ||||
|   | ||||
							
								
								
									
										53
									
								
								README
									
									
									
									
									
								
							
							
						
						
									
										53
									
								
								README
									
									
									
									
									
								
							| @@ -2,8 +2,8 @@ | ||||
| README | ||||
| ------ | ||||
|  | ||||
| StatusNet 0.9.2 ("King of Birds") | ||||
| 3 May 2010 | ||||
| StatusNet 0.9.3 ("Half a World Away") | ||||
| 29 June 2010 | ||||
|  | ||||
| This is the README file for StatusNet, the Open Source microblogging | ||||
| platform. It includes installation instructions, descriptions of | ||||
| @@ -77,40 +77,27 @@ for additional terms. | ||||
| New this version | ||||
| ================ | ||||
|  | ||||
| This is a minor bug and feature release since version 0.9.1 released 28  | ||||
| March 2010. | ||||
| This is a minor bug and feature release since version 0.9.2 released on | ||||
| 4 May 2010. | ||||
|  | ||||
| Because of fixes to OStatus bugs, it is highly recommended that all | ||||
| public sites upgrade to the new version immediately. | ||||
| For best compatibility with client software and site federation, and a lot of | ||||
| bug fixes, it is highly recommended that all public sites upgrade to the new | ||||
| version. | ||||
|  | ||||
| Notable changes this version: | ||||
|  | ||||
| - Installer no longer fails with a PHP fatal error when trying to set up the | ||||
|   subscription to update@status.net | ||||
| - Fixed email notifications for @-replies that come in via OStatus | ||||
| - OStatus related Fixes to the cloudy theme | ||||
| - Pass geo locations over Twitter bridge (will only be used if enabled on the | ||||
|   Twitter side) | ||||
| - scripts/showplugins.php - script to dump the list of activated plugins and | ||||
|   their settings | ||||
| - scripts/fixup_blocks.php - script to finds any stray subscriptions in | ||||
|   violation of blocks, and removes them | ||||
| - Allow blocking someone who's not currently subscribed to you (prevents | ||||
|   seeing @-replies from them, or them subbing to you in future) | ||||
| - Default 2-second timeout on Geonames web service lookups | ||||
| - Improved localization for plugins | ||||
| - New anti-spam measures: added nofollow rels to group members list, | ||||
|   subscribers list | ||||
| - Shared cache key option for Geonames plugin (lets multi-instance sites | ||||
|   share their cached geoname lookups) | ||||
| - Stability fixes to the TwitterStatusFetcher | ||||
| - If user allows location sharing but turned off browser location use profile | ||||
|   location | ||||
| - Improved group listing via the API | ||||
| - Improved FOAF output | ||||
| - Several other bugfixes | ||||
| - Enhanced API output to aid StatusNet-specific clients | ||||
| - Many updates to user interface translation from TranslateWiki | ||||
| - OStatus now works subscribing to SSL-protected sites by default | ||||
| - OpenID now works on PHP 5.3, supports closer site integration. | ||||
| - Numerous API and FOAF output fixes. | ||||
| - Fixes to Facebook integration for FB API behavior changes | ||||
| - PostgreSQL support updates | ||||
| - Initial version of a custom theme uploader (disabled by default) | ||||
| - LDAP auth plugins cleanup | ||||
| - Many other bugfixes | ||||
|  | ||||
| A full changelog is available at http://status.net/wiki/StatusNet_0.9.2. | ||||
| A full changelog is available at http://status.net/wiki/StatusNet_0.9.3. | ||||
|  | ||||
| Prerequisites | ||||
| ============= | ||||
| @@ -121,8 +108,8 @@ run correctly. | ||||
| - PHP 5.2.3+. It may be possible to run this software on earlier | ||||
|   versions of PHP, but many of the functions used are only available | ||||
|   in PHP 5.2 or above. 5.2.6 or later is needed for XMPP background | ||||
|   daemons on 64-bit platforms. PHP 5.3.x should work but is known | ||||
|   to cause some failures for OpenID. | ||||
|   daemons on 64-bit platforms. PHP 5.3.x should work correctly in this | ||||
|   release, but problems with some plugins are possible. | ||||
| - MySQL 5.x. The StatusNet database is stored, by default, in a MySQL | ||||
|   server. It has been primarily tested on 5.x servers, although it may | ||||
|   be possible to install on earlier (or later!) versions. The server | ||||
|   | ||||
| @@ -143,10 +143,10 @@ class AllAction extends ProfileAction | ||||
|                 $message .= _('Try subscribing to more people, [join a group](%%action.groups%%) or post something yourself.'); | ||||
|             } else { | ||||
|                 // TRANS: %1$s is user nickname, %2$s is user nickname, %2$s is user nickname prefixed with "@" | ||||
|                 $message .= sprintf(_('You can try to [nudge %1$s](../%2$s) from his profile or [post something to his or her attention](%%%%action.newnotice%%%%?status_textarea=%3$s).'), $this->user->nickname, $this->user->nickname, '@' . $this->user->nickname); | ||||
|                 $message .= sprintf(_('You can try to [nudge %1$s](../%2$s) from their profile or [post something to them](%%%%action.newnotice%%%%?status_textarea=%3$s).'), $this->user->nickname, $this->user->nickname, '@' . $this->user->nickname); | ||||
|             } | ||||
|         } else { | ||||
|             $message .= sprintf(_('Why not [register an account](%%%%action.register%%%%) and then nudge %s or post a notice to his or her attention.'), $this->user->nickname); | ||||
|             $message .= sprintf(_('Why not [register an account](%%%%action.register%%%%) and then nudge %s or post a notice to them.'), $this->user->nickname); | ||||
|         } | ||||
|  | ||||
|         $this->elementStart('div', 'guide'); | ||||
|   | ||||
| @@ -22,7 +22,7 @@ | ||||
|  * @category  API | ||||
|  * @package   StatusNet | ||||
|  * @author    Zach Copley <zach@status.net> | ||||
|  * @copyright 2009 StatusNet, Inc. | ||||
|  * @copyright 2009-2010 StatusNet, Inc. | ||||
|  * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 | ||||
|  * @link      http://status.net/ | ||||
|  */ | ||||
| @@ -131,7 +131,7 @@ class ApiAccountUpdateProfileColorsAction extends ApiAuthAction | ||||
|             try { | ||||
|                 $this->setColors($design); | ||||
|             } catch (WebColorException $e) { | ||||
|                 $this->clientError($e->getMessage()); | ||||
|                 $this->clientError($e->getMessage(), 400, $this->format); | ||||
|                 return false; | ||||
|             } | ||||
|  | ||||
| @@ -153,7 +153,7 @@ class ApiAccountUpdateProfileColorsAction extends ApiAuthAction | ||||
|             try { | ||||
|                 $this->setColors($design); | ||||
|             } catch (WebColorException $e) { | ||||
|                 $this->clientError($e->getMessage()); | ||||
|                 $this->clientError($e->getMessage(), 400, $this->format); | ||||
|                 return false; | ||||
|             } | ||||
|  | ||||
|   | ||||
| @@ -23,7 +23,7 @@ | ||||
|  * @package   StatusNet | ||||
|  * @author    Evan Prodromou <evan@status.net> | ||||
|  * @author    Zach Copley <zach@status.net> | ||||
|  * @copyright 2009 StatusNet, Inc. | ||||
|  * @copyright 2009-2010 StatusNet, Inc. | ||||
|  * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 | ||||
|  * @link      http://status.net/ | ||||
|  */ | ||||
| @@ -65,7 +65,7 @@ class ApiBlockCreateAction extends ApiAuthAction | ||||
|         parent::prepare($args); | ||||
|  | ||||
|         $this->user   = $this->auth_user; | ||||
|         $this->other  = $this->getTargetUser($this->arg('id')); | ||||
|         $this->other  = $this->getTargetProfile($this->arg('id')); | ||||
|  | ||||
|         return true; | ||||
|     } | ||||
|   | ||||
| @@ -23,7 +23,7 @@ | ||||
|  * @package   StatusNet | ||||
|  * @author    Evan Prodromou <evan@status.net> | ||||
|  * @author    Zach Copley <zach@status.net> | ||||
|  * @copyright 2009 StatusNet, Inc. | ||||
|  * @copyright 2009-2010 StatusNet, Inc. | ||||
|  * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 | ||||
|  * @link      http://status.net/ | ||||
|  */ | ||||
| @@ -64,7 +64,7 @@ class ApiBlockDestroyAction extends ApiAuthAction | ||||
|         parent::prepare($args); | ||||
|  | ||||
|         $this->user   = $this->auth_user; | ||||
|         $this->other  = $this->getTargetUser($this->arg('id')); | ||||
|         $this->other  = $this->getTargetProfile($this->arg('id')); | ||||
|  | ||||
|         return true; | ||||
|     } | ||||
|   | ||||
| @@ -24,7 +24,7 @@ | ||||
|  * @author    Dan Moore <dan@moore.cx> | ||||
|  * @author    Evan Prodromou <evan@status.net> | ||||
|  * @author    Zach Copley <zach@status.net> | ||||
|  * @copyright 2009 StatusNet, Inc. | ||||
|  * @copyright 2009-2010 StatusNet, Inc. | ||||
|  * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 | ||||
|  * @link      http://status.net/ | ||||
|  */ | ||||
| @@ -67,7 +67,7 @@ class ApiFriendshipsCreateAction extends ApiAuthAction | ||||
|         parent::prepare($args); | ||||
|  | ||||
|         $this->user   = $this->auth_user; | ||||
|         $this->other  = $this->getTargetUser($id); | ||||
|         $this->other  = $this->getTargetProfile($this->arg('id')); | ||||
|  | ||||
|         return true; | ||||
|     } | ||||
| @@ -106,7 +106,7 @@ class ApiFriendshipsCreateAction extends ApiAuthAction | ||||
|  | ||||
|         if (empty($this->other)) { | ||||
|             $this->clientError( | ||||
|                 _('Could not follow user: User not found.'), | ||||
|                 _('Could not follow user: profile not found.'), | ||||
|                 403, | ||||
|                 $this->format | ||||
|             ); | ||||
|   | ||||
| @@ -24,7 +24,7 @@ | ||||
|  * @author    Dan Moore <dan@moore.cx> | ||||
|  * @author    Evan Prodromou <evan@status.net> | ||||
|  * @author    Zach Copley <zach@status.net> | ||||
|  * @copyright 2009 StatusNet, Inc. | ||||
|  * @copyright 2009-2010 StatusNet, Inc. | ||||
|  * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 | ||||
|  * @link      http://status.net/ | ||||
|  */ | ||||
| @@ -67,7 +67,7 @@ class ApiFriendshipsDestroyAction extends ApiAuthAction | ||||
|         parent::prepare($args); | ||||
|  | ||||
|         $this->user   = $this->auth_user; | ||||
|         $this->other  = $this->getTargetUser($id); | ||||
|         $this->other  = $this->getTargetProfile($this->arg('id')); | ||||
|  | ||||
|         return true; | ||||
|     } | ||||
| @@ -125,8 +125,7 @@ class ApiFriendshipsDestroyAction extends ApiAuthAction | ||||
|         } | ||||
|  | ||||
|         // throws an exception on error | ||||
|         Subscription::cancel($this->user->getProfile(), | ||||
|                              $this->other->getProfile()); | ||||
|         Subscription::cancel($this->user->getProfile(), $this->other); | ||||
|  | ||||
|         $this->initDocument($this->format); | ||||
|         $this->showProfile($this->other, $this->format); | ||||
|   | ||||
| @@ -24,7 +24,7 @@ | ||||
|  * @author    Dan Moore <dan@moore.cx> | ||||
|  * @author    Evan Prodromou <evan@status.net> | ||||
|  * @author    Zach Copley <zach@status.net> | ||||
|  * @copyright 2009 StatusNet, Inc. | ||||
|  * @copyright 2009-2010 StatusNet, Inc. | ||||
|  * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 | ||||
|  * @link      http://status.net/ | ||||
|  */ | ||||
| @@ -50,8 +50,8 @@ require_once INSTALLDIR . '/lib/apiprivateauth.php'; | ||||
|  | ||||
| class ApiFriendshipsExistsAction extends ApiPrivateAuthAction | ||||
| { | ||||
|     var $user_a = null; | ||||
|     var $user_b = null; | ||||
|     var $profile_a = null; | ||||
|     var $profile_b = null; | ||||
|  | ||||
|     /** | ||||
|      * Take arguments for running | ||||
| @@ -66,11 +66,8 @@ class ApiFriendshipsExistsAction extends ApiPrivateAuthAction | ||||
|     { | ||||
|         parent::prepare($args); | ||||
|  | ||||
|         $user_a_id = $this->trimmed('user_a'); | ||||
|         $user_b_id = $this->trimmed('user_b'); | ||||
|  | ||||
|         $this->user_a = $this->getTargetUser($user_a_id); | ||||
|         $this->user_b = $this->getTargetUser($user_b_id); | ||||
|         $this->profile_a = $this->getTargetProfile($this->trimmed('user_a')); | ||||
|         $this->profile_b = $this->getTargetProfile($this->trimmed('user_b')); | ||||
|  | ||||
|         return true; | ||||
|     } | ||||
| @@ -89,16 +86,16 @@ class ApiFriendshipsExistsAction extends ApiPrivateAuthAction | ||||
|     { | ||||
|         parent::handle($args); | ||||
|  | ||||
|         if (empty($this->user_a) || empty($this->user_b)) { | ||||
|         if (empty($this->profile_a) || empty($this->profile_b)) { | ||||
|             $this->clientError( | ||||
|                 _('Two user ids or screen_names must be supplied.'), | ||||
|                 _('Two valid IDs or screen_names must be supplied.'), | ||||
|                 400, | ||||
|                 $this->format | ||||
|             ); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         $result = $this->user_a->isSubscribed($this->user_b); | ||||
|         $result = Subscription::exists($this->profile_a, $this->profile_b); | ||||
|  | ||||
|         switch ($this->format) { | ||||
|         case 'xml': | ||||
|   | ||||
| @@ -88,15 +88,15 @@ class ApiMediaUploadAction extends ApiAuthAction | ||||
|  | ||||
|         try { | ||||
|             $upload = MediaFile::fromUpload('media', $this->auth_user); | ||||
|         } catch (ClientException $ce) { | ||||
|             $this->clientError($ce->getMessage()); | ||||
|         } catch (Exception $e) { | ||||
|             $this->clientError($e->getMessage(), $e->getCode()); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         if (isset($upload)) { | ||||
|             $this->showResponse($upload); | ||||
|         } else { | ||||
|             $this->clientError('Upload failed.'); | ||||
|             $this->clientError(_('Upload failed.')); | ||||
|             return; | ||||
|         } | ||||
|     } | ||||
|   | ||||
| @@ -196,7 +196,8 @@ class ApiStatusesUpdateAction extends ApiAuthAction | ||||
|         if ($_SERVER['REQUEST_METHOD'] != 'POST') { | ||||
|             $this->clientError( | ||||
|                 _('This method requires a POST.'), | ||||
|                 400, $this->format | ||||
|                 400, | ||||
|                 $this->format | ||||
|             ); | ||||
|             return; | ||||
|         } | ||||
| @@ -217,7 +218,7 @@ class ApiStatusesUpdateAction extends ApiAuthAction | ||||
|  | ||||
|         if (empty($this->status)) { | ||||
|             $this->clientError( | ||||
|                 'Client must provide a \'status\' parameter with a value.', | ||||
|                 _('Client must provide a \'status\' parameter with a value.'), | ||||
|                 400, | ||||
|                 $this->format | ||||
|             ); | ||||
| @@ -291,8 +292,8 @@ class ApiStatusesUpdateAction extends ApiAuthAction | ||||
|  | ||||
|             try { | ||||
|                 $upload = MediaFile::fromUpload('media', $this->auth_user); | ||||
|             } catch (ClientException $ce) { | ||||
|                 $this->clientError($ce->getMessage()); | ||||
|             } catch (Exception $e) { | ||||
|                 $this->clientError($e->getMessage(), $e->getCode(), $this->format); | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
| @@ -305,7 +306,11 @@ class ApiStatusesUpdateAction extends ApiAuthAction | ||||
|                         'Max notice size is %d chars, ' . | ||||
|                         'including attachment URL.' | ||||
|                     ); | ||||
|                     $this->clientError(sprintf($msg, Notice::maxContent())); | ||||
|                     $this->clientError( | ||||
|                         sprintf($msg, Notice::maxContent()), | ||||
|                         400, | ||||
|                         $this->format | ||||
|                     ); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
| @@ -332,7 +337,7 @@ class ApiStatusesUpdateAction extends ApiAuthAction | ||||
|                     $options | ||||
|                 ); | ||||
|             } catch (Exception $e) { | ||||
|                 $this->clientError($e->getMessage()); | ||||
|                 $this->clientError($e->getMessage(), $e->getCode(), $this->format); | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|   | ||||
| @@ -25,7 +25,7 @@ | ||||
|  * @author    Evan Prodromou <evan@status.net> | ||||
|  * @author    Jeffery To <jeffery.to@gmail.com> | ||||
|  * @author    Zach Copley <zach@status.net> | ||||
|  * @copyright 2009 StatusNet, Inc. | ||||
|  * @copyright 2009-2010 StatusNet, Inc. | ||||
|  * @copyright 2009 Free Software Foundation, Inc http://www.fsf.org | ||||
|  * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 | ||||
|  * @link      http://status.net/ | ||||
| @@ -138,7 +138,9 @@ class ApiTimelineGroupAction extends ApiPrivateAuthAction | ||||
|                 $this->raw($atom->getString()); | ||||
|             } catch (Atom10FeedException $e) { | ||||
|                 $this->serverError( | ||||
|                     'Could not generate feed for group - ' . $e->getMessage() | ||||
|                     'Could not generate feed for group - ' . $e->getMessage(), | ||||
| 		    400, | ||||
| 		    $this->format | ||||
|                 ); | ||||
|                 return; | ||||
|             } | ||||
|   | ||||
| @@ -104,7 +104,7 @@ class FavorAction extends Action | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Notifies a user when his notice is favorited. | ||||
|      * Notifies a user when their notice is favorited. | ||||
|      * | ||||
|      * @param class $notice favorited notice | ||||
|      * @param class $user   user declaring a favorite | ||||
|   | ||||
| @@ -37,7 +37,7 @@ require_once INSTALLDIR.'/lib/omb.php'; | ||||
|  * Handler for remote subscription finish callback | ||||
|  * | ||||
|  * When a remote user subscribes a local user, a redirect to this action is | ||||
|  * issued after the remote user authorized his service to subscribe. | ||||
|  * issued after the remote user authorized their service to subscribe. | ||||
|  * | ||||
|  * @category Action | ||||
|  * @package  Laconica | ||||
|   | ||||
| @@ -82,7 +82,7 @@ class NudgeAction extends Action | ||||
|         } | ||||
|  | ||||
|         if (!$other->email || !$other->emailnotifynudge) { | ||||
|             $this->clientError(_('This user doesn\'t allow nudges or hasn\'t confirmed or set his email yet.')); | ||||
|             $this->clientError(_('This user doesn\'t allow nudges or hasn\'t confirmed or set their email yet.')); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|   | ||||
| @@ -196,18 +196,18 @@ class RepliesAction extends OwnerDesignAction | ||||
|  | ||||
|     function showEmptyListMessage() | ||||
|     { | ||||
|         $message = sprintf(_('This is the timeline showing replies to %1$s but %2$s hasn\'t received a notice to his attention yet.'), $this->user->nickname, $this->user->nickname) . ' '; | ||||
|         $message = sprintf(_('This is the timeline showing replies to %1$s but %2$s hasn\'t received a notice to them yet.'), $this->user->nickname, $this->user->nickname) . ' '; | ||||
|  | ||||
|         if (common_logged_in()) { | ||||
|             $current_user = common_current_user(); | ||||
|             if ($this->user->id === $current_user->id) { | ||||
|                 $message .= _('You can engage other users in a conversation, subscribe to more people or [join groups](%%action.groups%%).'); | ||||
|             } else { | ||||
|                 $message .= sprintf(_('You can try to [nudge %1$s](../%2$s) or [post something to his or her attention](%%%%action.newnotice%%%%?status_textarea=%3$s).'), $this->user->nickname, $this->user->nickname, '@' . $this->user->nickname); | ||||
|                 $message .= sprintf(_('You can try to [nudge %1$s](../%2$s) or [post something to them](%%%%action.newnotice%%%%?status_textarea=%3$s).'), $this->user->nickname, $this->user->nickname, '@' . $this->user->nickname); | ||||
|             } | ||||
|         } | ||||
|         else { | ||||
|             $message .= sprintf(_('Why not [register an account](%%%%action.register%%%%) and then nudge %s or post a notice to his or her attention.'), $this->user->nickname); | ||||
|             $message .= sprintf(_('Why not [register an account](%%%%action.register%%%%) and then nudge %s or post a notice to them.'), $this->user->nickname); | ||||
|         } | ||||
|  | ||||
|         $this->elementStart('div', 'guide'); | ||||
|   | ||||
| @@ -119,7 +119,7 @@ class ShowfavoritesAction extends OwnerDesignAction | ||||
|         if (!empty($cur) && $cur->id == $this->user->id) { | ||||
|  | ||||
|             // Show imported/gateway notices as well as local if | ||||
|             // the user is looking at his own favorites | ||||
|             // the user is looking at their own favorites | ||||
|  | ||||
|             $this->notice = $this->user->favoriteNotices(true, ($this->page-1)*NOTICES_PER_PAGE, | ||||
|                                                    NOTICES_PER_PAGE + 1); | ||||
| @@ -205,11 +205,11 @@ class ShowfavoritesAction extends OwnerDesignAction | ||||
|             if ($this->user->id === $current_user->id) { | ||||
|                 $message = _('You haven\'t chosen any favorite notices yet. Click the fave button on notices you like to bookmark them for later or shed a spotlight on them.'); | ||||
|             } else { | ||||
|                 $message = sprintf(_('%s hasn\'t added any notices to his favorites yet. Post something interesting they would add to their favorites :)'), $this->user->nickname); | ||||
|                 $message = sprintf(_('%s hasn\'t added any favorite notices yet. Post something interesting they would add to their favorites :)'), $this->user->nickname); | ||||
|             } | ||||
|         } | ||||
|         else { | ||||
|             $message = sprintf(_('%s hasn\'t added any notices to his favorites yet. Why not [register an account](%%%%action.register%%%%) and then post something interesting they would add to their favorites :)'), $this->user->nickname); | ||||
|             $message = sprintf(_('%s hasn\'t added any favorite notices yet. Why not [register an account](%%%%action.register%%%%) and then post something interesting they would add to their favorites :)'), $this->user->nickname); | ||||
|         } | ||||
|  | ||||
|         $this->elementStart('div', 'guide'); | ||||
|   | ||||
| @@ -198,11 +198,11 @@ class ShowstreamAction extends ProfileAction | ||||
|             if ($this->user->id === $current_user->id) { | ||||
|                 $message .= _('Seen anything interesting recently? You haven\'t posted any notices yet, now would be a good time to start :)'); | ||||
|             } else { | ||||
|                 $message .= sprintf(_('You can try to nudge %1$s or [post something to his or her attention](%%%%action.newnotice%%%%?status_textarea=%2$s).'), $this->user->nickname, '@' . $this->user->nickname); | ||||
|                 $message .= sprintf(_('You can try to nudge %1$s or [post something to them](%%%%action.newnotice%%%%?status_textarea=%2$s).'), $this->user->nickname, '@' . $this->user->nickname); | ||||
|             } | ||||
|         } | ||||
|         else { | ||||
|             $message .= sprintf(_('Why not [register an account](%%%%action.register%%%%) and then nudge %s or post a notice to his or her attention.'), $this->user->nickname); | ||||
|             $message .= sprintf(_('Why not [register an account](%%%%action.register%%%%) and then nudge %s or post a notice to them.'), $this->user->nickname); | ||||
|         } | ||||
|  | ||||
|         $this->elementStart('div', 'guide'); | ||||
|   | ||||
| @@ -139,7 +139,8 @@ class File extends Memcached_DataObject | ||||
|                     $redir_url = $redir_data; | ||||
|                     $redir_data = array(); | ||||
|                 } else { | ||||
|                     throw new ServerException("Can't process url '$given_url'"); | ||||
|                     // TRANS: Server exception thrown when a URL cannot be processed. | ||||
|                     throw new ServerException(sprintf(_("Cannot process URL '%s'"), $given_url)); | ||||
|                 } | ||||
|                 // TODO: max field length | ||||
|                 if ($redir_url === $given_url || strlen($redir_url) > 255 || !$followRedirects) { | ||||
| @@ -169,7 +170,9 @@ class File extends Memcached_DataObject | ||||
|         if (empty($x)) { | ||||
|             $x = File::staticGet($file_id); | ||||
|             if (empty($x)) { | ||||
|                 throw new ServerException("Robin thinks something is impossible."); | ||||
|                 // FIXME: This could possibly be a clearer message :) | ||||
|                 // TRANS: Server exception thrown when... Robin thinks something is impossible! | ||||
|                 throw new ServerException(_("Robin thinks something is impossible.")); | ||||
|             } | ||||
|         } | ||||
|  | ||||
| @@ -182,8 +185,10 @@ class File extends Memcached_DataObject | ||||
|     function isRespectsQuota($user,$fileSize) { | ||||
|  | ||||
|         if ($fileSize > common_config('attachments', 'file_quota')) { | ||||
|             return sprintf(_('No file may be larger than %d bytes ' . | ||||
|                              'and the file you sent was %d bytes. Try to upload a smaller version.'), | ||||
|             // TRANS: Message given if an upload is larger than the configured maximum. | ||||
|             // TRANS: %1$d is the byte limit for uploads, %2$d is the byte count for the uploaded file. | ||||
|             return sprintf(_('No file may be larger than %1$d bytes ' . | ||||
|                              'and the file you sent was %2$d bytes. Try to upload a smaller version.'), | ||||
|                            common_config('attachments', 'file_quota'), $fileSize); | ||||
|         } | ||||
|  | ||||
| @@ -192,6 +197,8 @@ class File extends Memcached_DataObject | ||||
|         $this->fetch(); | ||||
|         $total = $this->total + $fileSize; | ||||
|         if ($total > common_config('attachments', 'user_quota')) { | ||||
|             // TRANS: Message given if an upload would exceed user quota. | ||||
|             // TRANS: %d (number) is the user quota in bytes. | ||||
|             return sprintf(_('A file this large would exceed your user quota of %d bytes.'), common_config('attachments', 'user_quota')); | ||||
|         } | ||||
|         $query .= ' AND EXTRACT(month FROM file.modified) = EXTRACT(month FROM now()) and EXTRACT(year FROM file.modified) = EXTRACT(year FROM now())'; | ||||
| @@ -199,6 +206,8 @@ class File extends Memcached_DataObject | ||||
|         $this->fetch(); | ||||
|         $total = $this->total + $fileSize; | ||||
|         if ($total > common_config('attachments', 'monthly_quota')) { | ||||
|             // TRANS: Message given id an upload would exceed a user's monthly quota. | ||||
|             // TRANS: $d (number) is the monthly user quota in bytes. | ||||
|             return sprintf(_('A file this large would exceed your monthly quota of %d bytes.'), common_config('attachments', 'monthly_quota')); | ||||
|         } | ||||
|         return true; | ||||
| @@ -235,7 +244,8 @@ class File extends Memcached_DataObject | ||||
|     static function path($filename) | ||||
|     { | ||||
|         if (!self::validFilename($filename)) { | ||||
|             throw new ClientException("Invalid filename"); | ||||
|             // TRANS: Client exception thrown if a file upload does not have a valid name. | ||||
|             throw new ClientException(_("Invalid filename.")); | ||||
|         } | ||||
|         $dir = common_config('attachments', 'dir'); | ||||
|  | ||||
| @@ -249,7 +259,8 @@ class File extends Memcached_DataObject | ||||
|     static function url($filename) | ||||
|     { | ||||
|         if (!self::validFilename($filename)) { | ||||
|             throw new ClientException("Invalid filename"); | ||||
|             // TRANS: Client exception thrown if a file upload does not have a valid name. | ||||
|             throw new ClientException(_("Invalid filename.")); | ||||
|         } | ||||
|         if(common_config('site','private')) { | ||||
|  | ||||
| @@ -302,6 +313,7 @@ class File extends Memcached_DataObject | ||||
|  | ||||
|         if(! isset($this->filename)){ | ||||
|             $notEnclosureMimeTypes = array(null,'text/html','application/xhtml+xml'); | ||||
|             $mimetype = $this->mimetype; | ||||
|             if($mimetype != null){ | ||||
|                 $mimetype = strtolower($this->mimetype); | ||||
|             } | ||||
| @@ -341,4 +353,3 @@ class File extends Memcached_DataObject | ||||
|         return !empty($enclosure); | ||||
|     } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -39,6 +39,22 @@ class Foreign_user extends Memcached_DataObject | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     static function getByNickname($nickname, $service) | ||||
|     { | ||||
|         if (empty($nickname) || empty($service)) { | ||||
|             return null; | ||||
|         } else { | ||||
|             $fuser = new Foreign_user(); | ||||
| 	    $fuser->service = $service; | ||||
| 	    $fuser->nickname = $nickname; | ||||
|             $fuser->limit(1); | ||||
|  | ||||
|             $result = $fuser->find(true); | ||||
|  | ||||
|             return empty($result) ? null : $fuser; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     function updateKeys(&$orig) | ||||
|     { | ||||
|         $this->_connect(); | ||||
|   | ||||
| @@ -38,6 +38,7 @@ class Group_member extends Memcached_DataObject | ||||
|  | ||||
|         if (!$result) { | ||||
|             common_log_db_error($member, 'INSERT', __FILE__); | ||||
|             // TRANS: Exception thrown when joining a group fails. | ||||
|             throw new Exception(_("Group join failed.")); | ||||
|         } | ||||
|  | ||||
| @@ -50,6 +51,7 @@ class Group_member extends Memcached_DataObject | ||||
|                                               'profile_id' => $profile_id)); | ||||
|  | ||||
|         if (empty($member)) { | ||||
|             // TRANS: Exception thrown when trying to leave a group the user is not a member of. | ||||
|             throw new Exception(_("Not part of group.")); | ||||
|         } | ||||
|  | ||||
| @@ -57,6 +59,7 @@ class Group_member extends Memcached_DataObject | ||||
|  | ||||
|         if (!$result) { | ||||
|             common_log_db_error($member, 'INSERT', __FILE__); | ||||
|             // TRANS: Exception thrown when trying to leave a group fails. | ||||
|             throw new Exception(_("Group leave failed.")); | ||||
|         } | ||||
|  | ||||
|   | ||||
| @@ -38,6 +38,7 @@ class Local_group extends Memcached_DataObject | ||||
|             $this->encache(); | ||||
|         } else { | ||||
|             common_log_db_error($local, 'UPDATE', __FILE__); | ||||
|             // TRANS: Server exception thrown when updating a local group fails. | ||||
|             throw new ServerException(_('Could not update local group.')); | ||||
|         } | ||||
|  | ||||
|   | ||||
| @@ -73,6 +73,8 @@ class Login_token extends Memcached_DataObject | ||||
|  | ||||
|         if (!$result) { | ||||
|             common_log_db_error($login_token, 'INSERT', __FILE__); | ||||
|             // TRANS: Exception thrown when trying creating a login token failed. | ||||
|             // TRANS: %s is the user nickname for which token creation failed. | ||||
|             throw new Exception(sprintf(_('Could not create login token for %s'), | ||||
|                                                  $user->nickname)); | ||||
|         } | ||||
|   | ||||
| @@ -235,6 +235,7 @@ class Memcached_DataObject extends Safe_DataObject | ||||
|                 $pkey[] = $key; | ||||
|                 $pval[] = self::valueString($this->$key); | ||||
|             } else { | ||||
|                 // Low level exception. No need for i18n as discussed with Brion. | ||||
|                 throw new Exception("Unknown key type $key => $type for " . $this->tableName()); | ||||
|             } | ||||
|         } | ||||
| @@ -282,6 +283,7 @@ class Memcached_DataObject extends Safe_DataObject | ||||
|                     } else if ($type == 'fulltext') { | ||||
|                         $search_engine = new MySQLSearch($this, $table); | ||||
|                     } else { | ||||
|                         // Low level exception. No need for i18n as discussed with Brion. | ||||
|                         throw new ServerException('Unknown search type: ' . $type); | ||||
|                     } | ||||
|                 } else { | ||||
| @@ -527,7 +529,8 @@ class Memcached_DataObject extends Safe_DataObject | ||||
|         } | ||||
|  | ||||
|         if (!$dsn) { | ||||
|             throw new Exception("No database name / dsn found anywhere"); | ||||
|             // TRANS: Exception thrown when database name or Data Source Name could not be found. | ||||
|             throw new Exception(_("No database name or DSN found anywhere.")); | ||||
|         } | ||||
|  | ||||
|         return $dsn; | ||||
| @@ -577,6 +580,7 @@ class Memcached_DataObject extends Safe_DataObject | ||||
|         if ($message instanceof PEAR_Error) { | ||||
|             $message = $message->getMessage(); | ||||
|         } | ||||
|         // Low level exception. No need for i18n as discussed with Brion. | ||||
|         throw new ServerException("[$id] DB_DataObject error [$type]: $message"); | ||||
|     } | ||||
|  | ||||
| @@ -593,7 +597,7 @@ class Memcached_DataObject extends Safe_DataObject | ||||
|         return $c->get($cacheKey); | ||||
|     } | ||||
|  | ||||
|     static function cacheSet($keyPart, $value) | ||||
|     static function cacheSet($keyPart, $value, $flag=null, $expiry=null) | ||||
|     { | ||||
|         $c = self::memcache(); | ||||
|  | ||||
| @@ -603,7 +607,7 @@ class Memcached_DataObject extends Safe_DataObject | ||||
|  | ||||
|         $cacheKey = common_cache_key($keyPart); | ||||
|  | ||||
|         return $c->set($cacheKey, $value); | ||||
|         return $c->set($cacheKey, $value, $flag, $expiry); | ||||
|     } | ||||
|  | ||||
|     static function valueString($v) | ||||
| @@ -619,9 +623,11 @@ class Memcached_DataObject extends Safe_DataObject | ||||
|             case 'sql': | ||||
|             case 'datetime': | ||||
|             case 'time': | ||||
|                 // Low level exception. No need for i18n as discussed with Brion. | ||||
|                 throw new ServerException("Unhandled DB_DataObject_Cast type passed as cacheKey value: '$v->type'"); | ||||
|                 break; | ||||
|             default: | ||||
|                 // Low level exception. No need for i18n as discussed with Brion. | ||||
|                 throw new ServerException("Unknown DB_DataObject_Cast type passed as cacheKey value: '$v->type'"); | ||||
|                 break; | ||||
|             } | ||||
|   | ||||
| @@ -42,6 +42,7 @@ class Message extends Memcached_DataObject | ||||
|         $sender = Profile::staticGet('id', $from); | ||||
|  | ||||
|         if (!$sender->hasRight(Right::NEWMESSAGE)) { | ||||
|             // TRANS: Client exception thrown when a user tries to send a direct message while being banned from sending them. | ||||
|             throw new ClientException(_('You are banned from sending direct messages.')); | ||||
|         } | ||||
|  | ||||
| @@ -58,6 +59,7 @@ class Message extends Memcached_DataObject | ||||
|  | ||||
|         if (!$result) { | ||||
|             common_log_db_error($msg, 'INSERT', __FILE__); | ||||
|             // TRANS: Message given when a message could not be stored on the server. | ||||
|             return _('Could not insert message.'); | ||||
|         } | ||||
|  | ||||
| @@ -68,6 +70,7 @@ class Message extends Memcached_DataObject | ||||
|  | ||||
|         if (!$result) { | ||||
|             common_log_db_error($msg, 'UPDATE', __FILE__); | ||||
|             // TRANS: Message given when a message could not be updated on the server. | ||||
|             return _('Could not update message with new URI.'); | ||||
|         } | ||||
|  | ||||
|   | ||||
| @@ -42,10 +42,10 @@ if (!defined('STATUSNET') && !defined('LACONICA')) { | ||||
|  */ | ||||
| require_once INSTALLDIR.'/classes/Memcached_DataObject.php'; | ||||
|  | ||||
| /* We keep the first three 20-notice pages, plus one for pagination check, | ||||
| /* We keep 200 notices, the max number of notices available per API request, | ||||
|  * in the memcached cache. */ | ||||
|  | ||||
| define('NOTICE_CACHE_WINDOW', 61); | ||||
| define('NOTICE_CACHE_WINDOW', 200); | ||||
|  | ||||
| define('MAX_BOXCARS', 128); | ||||
|  | ||||
| @@ -90,7 +90,15 @@ class Notice extends Memcached_DataObject | ||||
|  | ||||
|     function getProfile() | ||||
|     { | ||||
|         return Profile::staticGet('id', $this->profile_id); | ||||
|         $profile = Profile::staticGet('id', $this->profile_id); | ||||
|  | ||||
|         if (empty($profile)) { | ||||
|             // TRANS: Server exception thrown when a user profile for a notice cannot be found. | ||||
|             // TRANS: %1$d is a profile ID (number), %2$d is a notice ID (number). | ||||
|             throw new ServerException(sprintf(_('No such profile (%1$d) for notice (%2$d).'), $this->profile_id, $this->id)); | ||||
|         } | ||||
|  | ||||
|         return $profile; | ||||
|     } | ||||
|  | ||||
|     function delete() | ||||
| @@ -248,28 +256,34 @@ class Notice extends Memcached_DataObject | ||||
|         $final = common_shorten_links($content); | ||||
|  | ||||
|         if (Notice::contentTooLong($final)) { | ||||
|             // TRANS: Client exception thrown if a notice contains too many characters. | ||||
|             throw new ClientException(_('Problem saving notice. Too long.')); | ||||
|         } | ||||
|  | ||||
|         if (empty($profile)) { | ||||
|             // TRANS: Client exception thrown when trying to save a notice for an unknown user. | ||||
|             throw new ClientException(_('Problem saving notice. Unknown user.')); | ||||
|         } | ||||
|  | ||||
|         if (common_config('throttle', 'enabled') && !Notice::checkEditThrottle($profile_id)) { | ||||
|             common_log(LOG_WARNING, 'Excessive posting by profile #' . $profile_id . '; throttled.'); | ||||
|             // TRANS: Client exception thrown when a user tries to post too many notices in a given time frame. | ||||
|             throw new ClientException(_('Too many notices too fast; take a breather '. | ||||
|                                         'and post again in a few minutes.')); | ||||
|         } | ||||
|  | ||||
|         if (common_config('site', 'dupelimit') > 0 && !Notice::checkDupes($profile_id, $final)) { | ||||
|             common_log(LOG_WARNING, 'Dupe posting by profile #' . $profile_id . '; throttled.'); | ||||
|             // TRANS: Client exception thrown when a user tries to post too many duplicate notices in a given time frame. | ||||
|             throw new ClientException(_('Too many duplicate messages too quickly;'. | ||||
|                                         ' take a breather and post again in a few minutes.')); | ||||
|         } | ||||
|  | ||||
|         if (!$profile->hasRight(Right::NEWNOTICE)) { | ||||
|             common_log(LOG_WARNING, "Attempted post from user disallowed to post: " . $profile->nickname); | ||||
|             throw new ClientException(_('You are banned from posting notices on this site.')); | ||||
|  | ||||
|             // TRANS: Client exception thrown when a user tries to post while being banned. | ||||
|             throw new ClientException(_('You are banned from posting notices on this site.'), 403); | ||||
|         } | ||||
|  | ||||
|         $notice = new Notice(); | ||||
| @@ -335,6 +349,7 @@ class Notice extends Memcached_DataObject | ||||
|  | ||||
|             if (!$id) { | ||||
|                 common_log_db_error($notice, 'INSERT', __FILE__); | ||||
|                 // TRANS: Server exception thrown when a notice cannot be saved. | ||||
|                 throw new ServerException(_('Problem saving notice.')); | ||||
|             } | ||||
|  | ||||
| @@ -361,6 +376,7 @@ class Notice extends Memcached_DataObject | ||||
|             if ($changed) { | ||||
|                 if (!$notice->update($orig)) { | ||||
|                     common_log_db_error($notice, 'UPDATE', __FILE__); | ||||
|                     // TRANS: Server exception thrown when a notice cannot be updated. | ||||
|                     throw new ServerException(_('Problem saving notice.')); | ||||
|                 } | ||||
|             } | ||||
| @@ -872,7 +888,8 @@ class Notice extends Memcached_DataObject | ||||
|     function saveKnownGroups($group_ids) | ||||
|     { | ||||
|         if (!is_array($group_ids)) { | ||||
|             throw new ServerException("Bad type provided to saveKnownGroups"); | ||||
|             // TRANS: Server exception thrown when no array is provided to the method saveKnownGroups(). | ||||
|             throw new ServerException(_("Bad type provided to saveKnownGroups")); | ||||
|         } | ||||
|  | ||||
|         $groups = array(); | ||||
| @@ -970,6 +987,7 @@ class Notice extends Memcached_DataObject | ||||
|  | ||||
|             if (!$result) { | ||||
|                 common_log_db_error($gi, 'INSERT', __FILE__); | ||||
|                 // TRANS: Server exception thrown when an update for a group inbox fails. | ||||
|                 throw new ServerException(_('Problem saving group inbox.')); | ||||
|             } | ||||
|  | ||||
| @@ -1075,7 +1093,9 @@ class Notice extends Memcached_DataObject | ||||
|  | ||||
|                 if (!$id) { | ||||
|                     common_log_db_error($reply, 'INSERT', __FILE__); | ||||
|                     throw new ServerException("Couldn't save reply for {$this->id}, {$mentioned->id}"); | ||||
|                     // TRANS: Server exception thrown when a reply cannot be saved. | ||||
|                     // TRANS: %1$d is a notice ID, %2$d is the ID of the mentioned user. | ||||
|                     throw new ServerException(sprintf(_("Could not save reply for %1$d, %2$d."), $this->id, $mentioned->id)); | ||||
|                 } else { | ||||
|                     $replied[$mentioned->id] = 1; | ||||
|                     self::blow('reply:stream:%d', $mentioned->id); | ||||
| @@ -1178,6 +1198,9 @@ class Notice extends Memcached_DataObject | ||||
|         return $groups; | ||||
|     } | ||||
|  | ||||
|     // This has gotten way too long. Needs to be sliced up into functional bits | ||||
|     // or ideally exported to a utility class. | ||||
|  | ||||
|     function asAtomEntry($namespace=false, $source=false, $author=true, $cur=null) | ||||
|     { | ||||
|         $profile = $this->getProfile(); | ||||
| @@ -1197,74 +1220,176 @@ class Notice extends Memcached_DataObject | ||||
|             $attrs = array(); | ||||
|         } | ||||
|  | ||||
|         $xs->elementStart('entry', $attrs); | ||||
|         if (Event::handle('StartActivityStart', array(&$this, &$xs, &$attrs))) { | ||||
|             $xs->elementStart('entry', $attrs); | ||||
|             Event::handle('EndActivityStart', array(&$this, &$xs, &$attrs)); | ||||
|         } | ||||
|  | ||||
|         if ($source) { | ||||
|             $xs->elementStart('source'); | ||||
|             $xs->element('id', null, $profile->profileurl); | ||||
|             $xs->element('title', null, $profile->nickname . " - " . common_config('site', 'name')); | ||||
|             $xs->element('link', array('href' => $profile->profileurl)); | ||||
|             $user = User::staticGet('id', $profile->id); | ||||
|             if (!empty($user)) { | ||||
|                 $atom_feed = common_local_url('ApiTimelineUser', | ||||
|                                               array('format' => 'atom', | ||||
|                                                     'id' => $profile->nickname)); | ||||
|                 $xs->element('link', array('rel' => 'self', | ||||
|                                            'type' => 'application/atom+xml', | ||||
|                                            'href' => $profile->profileurl)); | ||||
|                 $xs->element('link', array('rel' => 'license', | ||||
|                                            'href' => common_config('license', 'url'))); | ||||
|         if (Event::handle('StartActivitySource', array(&$this, &$xs))) { | ||||
|  | ||||
|             if ($source) { | ||||
|  | ||||
|                 $atom_feed = $profile->getAtomFeed(); | ||||
|  | ||||
|                 if (!empty($atom_feed)) { | ||||
|  | ||||
|                     $xs->elementStart('source'); | ||||
|  | ||||
|                     // XXX: we should store the actual feed ID | ||||
|  | ||||
|                     $xs->element('id', null, $atom_feed); | ||||
|  | ||||
|                     // XXX: we should store the actual feed title | ||||
|  | ||||
|                     $xs->element('title', null, $profile->getBestName()); | ||||
|  | ||||
|                     $xs->element('link', array('rel' => 'alternate', | ||||
|                                                'type' => 'text/html', | ||||
|                                                'href' => $profile->profileurl)); | ||||
|  | ||||
|                     $xs->element('link', array('rel' => 'self', | ||||
|                                                'type' => 'application/atom+xml', | ||||
|                                                'href' => $atom_feed)); | ||||
|  | ||||
|                     $xs->element('icon', null, $profile->avatarUrl(AVATAR_PROFILE_SIZE)); | ||||
|  | ||||
|                     $notice = $profile->getCurrentNotice(); | ||||
|  | ||||
|                     if (!empty($notice)) { | ||||
|                         $xs->element('updated', null, self::utcDate($notice->created)); | ||||
|                     } | ||||
|  | ||||
|                     $user = User::staticGet('id', $profile->id); | ||||
|  | ||||
|                     if (!empty($user)) { | ||||
|                         $xs->element('link', array('rel' => 'license', | ||||
|                                                    'href' => common_config('license', 'url'))); | ||||
|                     } | ||||
|  | ||||
|                     $xs->elementEnd('source'); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             $xs->element('icon', null, $profile->avatarUrl(AVATAR_PROFILE_SIZE)); | ||||
|             $xs->element('updated', null, common_date_w3dtf($this->created)); | ||||
|             Event::handle('EndActivitySource', array(&$this, &$xs)); | ||||
|         } | ||||
|  | ||||
|         if ($source) { | ||||
|             $xs->elementEnd('source'); | ||||
|         $title = common_xml_safe_str($this->content); | ||||
|  | ||||
|         if (Event::handle('StartActivityTitle', array(&$this, &$xs, &$title))) { | ||||
|             $xs->element('title', null, $title); | ||||
|             Event::handle('EndActivityTitle', array($this, &$xs, $title)); | ||||
|         } | ||||
|  | ||||
|         $xs->element('title', null, common_xml_safe_str($this->content)); | ||||
|         $atomAuthor = ''; | ||||
|  | ||||
|         if ($author) { | ||||
|             $xs->raw($profile->asAtomAuthor($cur)); | ||||
|             $xs->raw($profile->asActivityActor()); | ||||
|             $atomAuthor = $profile->asAtomAuthor($cur); | ||||
|         } | ||||
|  | ||||
|         $xs->element('link', array('rel' => 'alternate', | ||||
|                                    'type' => 'text/html', | ||||
|                                    'href' => $this->bestUrl())); | ||||
|  | ||||
|         $xs->element('id', null, $this->uri); | ||||
|  | ||||
|         $xs->element('published', null, common_date_w3dtf($this->created)); | ||||
|         $xs->element('updated', null, common_date_w3dtf($this->created)); | ||||
|  | ||||
|         $source = null; | ||||
|  | ||||
|         $ns = $this->getSource(); | ||||
|  | ||||
|         if ($ns) { | ||||
|             if (!empty($ns->name) && !empty($ns->url)) { | ||||
|                 $source = '<a href="' | ||||
|                   . htmlspecialchars($ns->url) | ||||
|                   . '" rel="nofollow">' | ||||
|                   . htmlspecialchars($ns->name) | ||||
|                    . '</a>'; | ||||
|             } else { | ||||
|                 $source = $ns->code; | ||||
|         if (Event::handle('StartActivityAuthor', array(&$this, &$xs, &$atomAuthor))) { | ||||
|             if (!empty($atomAuthor)) { | ||||
|                 $xs->raw($atomAuthor); | ||||
|                 Event::handle('EndActivityAuthor', array(&$this, &$xs, &$atomAuthor)); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         $noticeInfoAttr = array( | ||||
|             'local_id'   => $this->id, // local notice ID (useful to clients for ordering) | ||||
|             'source'     => $source,   // the client name (source attribution) | ||||
|         ); | ||||
|         $actor = ''; | ||||
|  | ||||
|         if ($author) { | ||||
|             $actor = $profile->asActivityActor(); | ||||
|         } | ||||
|  | ||||
|         if (Event::handle('StartActivityActor', array(&$this, &$xs, &$actor))) { | ||||
|             if (!empty($actor)) { | ||||
|                 $xs->raw($actor); | ||||
|                 Event::handle('EndActivityActor', array(&$this, &$xs, &$actor)); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         $url = $this->bestUrl(); | ||||
|  | ||||
|         if (Event::handle('StartActivityLink', array(&$this, &$xs, &$url))) { | ||||
|             $xs->element('link', array('rel' => 'alternate', | ||||
|                                        'type' => 'text/html', | ||||
|                                        'href' => $url)); | ||||
|             Event::handle('EndActivityLink', array(&$this, &$xs, $url)); | ||||
|         } | ||||
|  | ||||
|         $id = $this->uri; | ||||
|  | ||||
|         if (Event::handle('StartActivityId', array(&$this, &$xs, &$id))) { | ||||
|             $xs->element('id', null, $id); | ||||
|             Event::handle('EndActivityId', array(&$this, &$xs, $id)); | ||||
|         } | ||||
|  | ||||
|         $published = self::utcDate($this->created); | ||||
|  | ||||
|         if (Event::handle('StartActivityPublished', array(&$this, &$xs, &$published))) { | ||||
|             $xs->element('published', null, $published); | ||||
|             Event::handle('EndActivityPublished', array(&$this, &$xs, $published)); | ||||
|         } | ||||
|  | ||||
|         $updated = $published; // XXX: notices are usually immutable | ||||
|  | ||||
|         if (Event::handle('StartActivityUpdated', array(&$this, &$xs, &$updated))) { | ||||
|             $xs->element('updated', null, $updated); | ||||
|             Event::handle('EndActivityUpdated', array(&$this, &$xs, $updated)); | ||||
|         } | ||||
|  | ||||
|         $content = common_xml_safe_str($this->rendered); | ||||
|  | ||||
|         if (Event::handle('StartActivityContent', array(&$this, &$xs, &$content))) { | ||||
|             $xs->element('content', array('type' => 'html'), $content); | ||||
|             Event::handle('EndActivityContent', array(&$this, &$xs, $content)); | ||||
|         } | ||||
|  | ||||
|         // Most of our notices represent POSTing a NOTE. This is the default verb | ||||
|         // for activity streams, so we normally just leave it out. | ||||
|  | ||||
|         $verb = ActivityVerb::POST; | ||||
|  | ||||
|         if (Event::handle('StartActivityVerb', array(&$this, &$xs, &$verb))) { | ||||
|             $xs->element('activity:verb', null, $verb); | ||||
|             Event::handle('EndActivityVerb', array(&$this, &$xs, $verb)); | ||||
|         } | ||||
|  | ||||
|         // We use the default behavior for activity streams: if there's no activity:object, | ||||
|         // then treat the entry itself as the object. Here, you can set the type of that object, | ||||
|         // which is normally a NOTE. | ||||
|  | ||||
|         $type = ActivityObject::NOTE; | ||||
|  | ||||
|         if (Event::handle('StartActivityDefaultObjectType', array(&$this, &$xs, &$type))) { | ||||
|             $xs->element('activity:object-type', null, $type); | ||||
|             Event::handle('EndActivityDefaultObjectType', array(&$this, &$xs, $type)); | ||||
|         } | ||||
|  | ||||
|         // Since we usually use the entry itself as an object, we don't have an explicit | ||||
|         // object. Some extensions may want to add them (for photo, event, music, etc.). | ||||
|  | ||||
|         $objects = array(); | ||||
|  | ||||
|         if (Event::handle('StartActivityObjects', array(&$this, &$xs, &$objects))) { | ||||
|             foreach ($objects as $object) { | ||||
|                 $xs->raw($object->asString()); | ||||
|             } | ||||
|             Event::handle('EndActivityObjects', array(&$this, &$xs, $objects)); | ||||
|         } | ||||
|  | ||||
|         $noticeInfoAttr = array('local_id' => $this->id); // local notice ID (useful to clients for ordering) | ||||
|  | ||||
|         $ns = $this->getSource(); | ||||
|         if ($ns) { | ||||
|  | ||||
|         if (!empty($ns)) { | ||||
|             $noticeInfoAttr['source'] =  $ns->code; | ||||
|             if (!empty($ns->url)) { | ||||
|                 $noticeInfoAttr['source_link'] = $ns->url; | ||||
|                 if (!empty($ns->name)) { | ||||
|                     $noticeInfoAttr['source'] =  '<a href="' | ||||
|                       . htmlspecialchars($ns->url) | ||||
|                         . '" rel="nofollow">' | ||||
|                       . htmlspecialchars($ns->name) | ||||
|                         . '</a>'; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
| @@ -1278,103 +1403,143 @@ class Notice extends Memcached_DataObject | ||||
|             $noticeInfoAttr['repeat_of'] = $this->repeat_of; | ||||
|         } | ||||
|  | ||||
|         $xs->element('statusnet:notice_info', $noticeInfoAttr, null); | ||||
|         if (Event::handle('StartActivityNoticeInfo', array(&$this, &$xs, &$noticeInfoAttr))) { | ||||
|             $xs->element('statusnet:notice_info', $noticeInfoAttr, null); | ||||
|             Event::handle('EndActivityNoticeInfo', array(&$this, &$xs, $noticeInfoAttr)); | ||||
|         } | ||||
|  | ||||
|         $replyNotice = null; | ||||
|  | ||||
|         if ($this->reply_to) { | ||||
|             $reply_notice = Notice::staticGet('id', $this->reply_to); | ||||
|             if (!empty($reply_notice)) { | ||||
|             $replyNotice = Notice::staticGet('id', $this->reply_to); | ||||
|         } | ||||
|  | ||||
|         if (Event::handle('StartActivityInReplyTo', array(&$this, &$xs, &$replyNotice))) { | ||||
|             if (!empty($replyNotice)) { | ||||
|                 $xs->element('link', array('rel' => 'related', | ||||
|                                            'href' => $reply_notice->bestUrl())); | ||||
|                                            'href' => $replyNotice->bestUrl())); | ||||
|                 $xs->element('thr:in-reply-to', | ||||
|                              array('ref' => $reply_notice->uri, | ||||
|                                    'href' => $reply_notice->bestUrl())); | ||||
|                              array('ref' => $replyNotice->uri, | ||||
|                                    'href' => $replyNotice->bestUrl())); | ||||
|                 Event::handle('EndActivityInReplyTo', array(&$this, &$xs, $replyNotice)); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         $conv = null; | ||||
|  | ||||
|         if (!empty($this->conversation)) { | ||||
|  | ||||
|             $conv = Conversation::staticGet('id', $this->conversation); | ||||
|  | ||||
|             if (!empty($conv)) { | ||||
|                 $xs->element( | ||||
|                     'link', array( | ||||
|                         'rel' => 'ostatus:conversation', | ||||
|                         'href' => $conv->uri | ||||
|                     ) | ||||
|                 ); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if (Event::handle('StartActivityConversation', array(&$this, &$xs, &$conv))) { | ||||
|             if (!empty($conv)) { | ||||
|                 $xs->element('link', array('rel' => 'ostatus:conversation', | ||||
|                                            'href' => $conv->uri)); | ||||
|             } | ||||
|             Event::handle('EndActivityConversation', array(&$this, &$xs, $conv)); | ||||
|         } | ||||
|  | ||||
|         $replyProfiles = array(); | ||||
|  | ||||
|         $reply_ids = $this->getReplies(); | ||||
|  | ||||
|         foreach ($reply_ids as $id) { | ||||
|             $profile = Profile::staticGet('id', $id); | ||||
|            if (!empty($profile)) { | ||||
|                 $xs->element( | ||||
|                     'link', array( | ||||
|                         'rel' => 'ostatus:attention', | ||||
|                         'href' => $profile->getUri() | ||||
|                     ) | ||||
|                 ); | ||||
|             if (!empty($profile)) { | ||||
|                 $replyProfiles[] = $profile; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if (Event::handle('StartActivityAttentionProfiles', array(&$this, &$xs, &$replyProfiles))) { | ||||
|             foreach ($replyProfiles as $profile) { | ||||
|                 $xs->element('link', array('rel' => 'ostatus:attention', | ||||
|                                            'href' => $profile->getUri())); | ||||
|                 $xs->element('link', array('rel' => 'mentioned', | ||||
|                                            'href' => $profile->getUri())); | ||||
|             } | ||||
|             Event::handle('EndActivityAttentionProfiles', array(&$this, &$xs, $replyProfiles)); | ||||
|         } | ||||
|  | ||||
|         $groups = $this->getGroups(); | ||||
|  | ||||
|         foreach ($groups as $group) { | ||||
|             $xs->element( | ||||
|                 'link', array( | ||||
|                     'rel' => 'ostatus:attention', | ||||
|                     'href' => $group->permalink() | ||||
|                 ) | ||||
|             ); | ||||
|         if (Event::handle('StartActivityAttentionGroups', array(&$this, &$xs, &$groups))) { | ||||
|             foreach ($groups as $group) { | ||||
|                 $xs->element('link', array('rel' => 'ostatus:attention', | ||||
|                                            'href' => $group->permalink())); | ||||
|                 $xs->element('link', array('rel' => 'mentioned', | ||||
|                                            'href' => $group->permalink())); | ||||
|             } | ||||
|             Event::handle('EndActivityAttentionGroups', array(&$this, &$xs, $groups)); | ||||
|         } | ||||
|  | ||||
|         $repeat = null; | ||||
|  | ||||
|         if (!empty($this->repeat_of)) { | ||||
|             $repeat = Notice::staticGet('id', $this->repeat_of); | ||||
|         } | ||||
|  | ||||
|         if (Event::handle('StartActivityForward', array(&$this, &$xs, &$repeat))) { | ||||
|             if (!empty($repeat)) { | ||||
|                 $xs->element( | ||||
|                     'ostatus:forward', | ||||
|                      array('ref' => $repeat->uri, 'href' => $repeat->bestUrl()) | ||||
|                 ); | ||||
|                 $xs->element('ostatus:forward', | ||||
|                              array('ref' => $repeat->uri, | ||||
|                                    'href' => $repeat->bestUrl())); | ||||
|             } | ||||
|  | ||||
|             Event::handle('EndActivityForward', array(&$this, &$xs, $repeat)); | ||||
|         } | ||||
|  | ||||
|         $xs->element( | ||||
|             'content', | ||||
|             array('type' => 'html'), | ||||
|             common_xml_safe_str($this->rendered) | ||||
|         ); | ||||
|         $tags = $this->getTags(); | ||||
|  | ||||
|         $tag = new Notice_tag(); | ||||
|         $tag->notice_id = $this->id; | ||||
|         if ($tag->find()) { | ||||
|             while ($tag->fetch()) { | ||||
|                 $xs->element('category', array('term' => $tag->tag)); | ||||
|         if (Event::handle('StartActivityCategories', array(&$this, &$xs, &$tags))) { | ||||
|             foreach ($tags as $tag) { | ||||
|                 $xs->element('category', array('term' => $tag)); | ||||
|             } | ||||
|             Event::handle('EndActivityCategories', array(&$this, &$xs, $tags)); | ||||
|         } | ||||
|         $tag->free(); | ||||
|  | ||||
|         # Enclosures | ||||
|         // Enclosures | ||||
|  | ||||
|         $enclosures = array(); | ||||
|  | ||||
|         $attachments = $this->attachments(); | ||||
|         if($attachments){ | ||||
|             foreach($attachments as $attachment){ | ||||
|                 $enclosure=$attachment->getEnclosure(); | ||||
|                 if ($enclosure) { | ||||
|                     $attributes = array('rel'=>'enclosure','href'=>$enclosure->url,'type'=>$enclosure->mimetype,'length'=>$enclosure->size); | ||||
|                     if($enclosure->title){ | ||||
|                         $attributes['title']=$enclosure->title; | ||||
|                     } | ||||
|                     $xs->element('link', $attributes, null); | ||||
|                 } | ||||
|  | ||||
|         foreach ($attachments as $attachment) { | ||||
|             $enclosure = $attachment->getEnclosure(); | ||||
|             if ($enclosure) { | ||||
|                 $enclosures[] = $enclosure; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if (!empty($this->lat) && !empty($this->lon)) { | ||||
|             $xs->element('georss:point', null, $this->lat . ' ' . $this->lon); | ||||
|         if (Event::handle('StartActivityEnclosures', array(&$this, &$xs, &$enclosures))) { | ||||
|             foreach ($enclosures as $enclosure) { | ||||
|                 $attributes = array('rel' => 'enclosure', | ||||
|                                     'href' => $enclosure->url, | ||||
|                                     'type' => $enclosure->mimetype, | ||||
|                                     'length' => $enclosure->size); | ||||
|  | ||||
|                 if ($enclosure->title) { | ||||
|                     $attributes['title'] = $enclosure->title; | ||||
|                 } | ||||
|  | ||||
|                 $xs->element('link', $attributes, null); | ||||
|             } | ||||
|             Event::handle('EndActivityEnclosures', array(&$this, &$xs, $enclosures)); | ||||
|         } | ||||
|  | ||||
|         $xs->elementEnd('entry'); | ||||
|         $lat = $this->lat; | ||||
|         $lon = $this->lon; | ||||
|  | ||||
|         if (Event::handle('StartActivityGeo', array(&$this, &$xs, &$lat, &$lon))) { | ||||
|             if (!empty($lat) && !empty($lon)) { | ||||
|                 $xs->element('georss:point', null, $lat . ' ' . $lon); | ||||
|             } | ||||
|             Event::handle('EndActivityGeo', array(&$this, &$xs, $lat, $lon)); | ||||
|         } | ||||
|  | ||||
|         if (Event::handle('StartActivityEnd', array(&$this, &$xs))) { | ||||
|             $xs->elementEnd('entry'); | ||||
|             Event::handle('EndActivityEnd', array(&$this, &$xs)); | ||||
|         } | ||||
|  | ||||
|         return $xs->getString(); | ||||
|     } | ||||
| @@ -1895,4 +2060,24 @@ class Notice extends Memcached_DataObject | ||||
|                 $this->is_local == Notice::LOCAL_NONPUBLIC); | ||||
|     } | ||||
|  | ||||
|     public function getTags() | ||||
|     { | ||||
|         $tags = array(); | ||||
|         $tag = new Notice_tag(); | ||||
|         $tag->notice_id = $this->id; | ||||
|         if ($tag->find()) { | ||||
|             while ($tag->fetch()) { | ||||
|                 $tags[] = $tag->tag; | ||||
|             } | ||||
|         } | ||||
|         $tag->free(); | ||||
|         return $tags; | ||||
|     } | ||||
|  | ||||
|     static private function utcDate($dt) | ||||
|     { | ||||
|         $dateStr = date('d F Y H:i:s', strtotime($dt)); | ||||
|         $d = new DateTime($dateStr, new DateTimeZone('UTC')); | ||||
|         return $d->format(DATE_W3C); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -152,17 +152,16 @@ class Profile extends Memcached_DataObject | ||||
|      * | ||||
|      * @return mixed Notice or null | ||||
|      */ | ||||
|  | ||||
|     function getCurrentNotice() | ||||
|     { | ||||
|         $notice = new Notice(); | ||||
|         $notice->profile_id = $this->id; | ||||
|         // @fixme change this to sort on notice.id only when indexes are updated | ||||
|         $notice->orderBy('created DESC, notice.id DESC'); | ||||
|         $notice->limit(1); | ||||
|         if ($notice->find(true)) { | ||||
|         $notice = $this->getNotices(0, 1); | ||||
|  | ||||
|         if ($notice->fetch()) { | ||||
|             return $notice; | ||||
|         } else { | ||||
|             return null; | ||||
|         } | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     function getTaggedNotices($tag, $offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $max_id=0) | ||||
| @@ -735,14 +734,18 @@ class Profile extends Memcached_DataObject | ||||
|                                             'role' => $name)); | ||||
|  | ||||
|         if (empty($role)) { | ||||
|             throw new Exception('Cannot revoke role "'.$name.'" for user #'.$this->id.'; does not exist.'); | ||||
|             // TRANS: Exception thrown when trying to revoke an existing role for a user that does not exist. | ||||
|             // TRANS: %1$s is the role name, %2$s is the user ID (number). | ||||
|             throw new Exception(sprintf(_('Cannot revoke role "%1$s" for user #%2$d; does not exist.'),$name, $this->id)); | ||||
|         } | ||||
|  | ||||
|         $result = $role->delete(); | ||||
|  | ||||
|         if (!$result) { | ||||
|             common_log_db_error($role, 'DELETE', __FILE__); | ||||
|             throw new Exception('Cannot revoke role "'.$name.'" for user #'.$this->id.'; database error.'); | ||||
|             // TRANS: Exception thrown when trying to revoke a role for a user with a failing database query. | ||||
|             // TRANS: %1$s is the role name, %2$s is the user ID (number). | ||||
|             throw new Exception(sprintf(_('Cannot revoke role "%1$s" for user #%2$d; database error.'),$name, $this->id)); | ||||
|         } | ||||
|  | ||||
|         return true; | ||||
| @@ -943,4 +946,20 @@ class Profile extends Memcached_DataObject | ||||
|  | ||||
|         return $result; | ||||
|     } | ||||
|  | ||||
|     function getAtomFeed() | ||||
|     { | ||||
|         $feed = null; | ||||
|  | ||||
|         if (Event::handle('StartProfileGetAtomFeed', array($this, &$feed))) { | ||||
|             $user = User::staticGet('id', $this->id); | ||||
|             if (!empty($user)) { | ||||
|                 $feed = common_local_url('ApiTimelineUser', array('id' => $user->id, | ||||
|                                                                   'format' => 'atom')); | ||||
|             } | ||||
|             Event::handle('EndProfileGetAtomFeed', array($this, $feed)); | ||||
|         } | ||||
|  | ||||
|         return $feed; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -50,7 +50,8 @@ class Remote_profile extends Memcached_DataObject | ||||
|         if ($profile) { | ||||
|             return $profile->hasright($right); | ||||
|         } else { | ||||
|             throw new Exception("Missing profile"); | ||||
|             // TRANS: Exception thrown when a right for a non-existing user profile is checked. | ||||
|             throw new Exception(_("Missing profile.")); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -116,6 +116,7 @@ class Safe_DataObject extends DB_DataObject | ||||
|         if ($this->_call($method, $params, $return)) { | ||||
|             return $return; | ||||
|         } else { | ||||
|             // Low level exception. No need for i18n as discussed with Brion. | ||||
|             throw new Exception('Call to undefined method ' . | ||||
|                 get_class($this) . '::' . $method); | ||||
|         } | ||||
| @@ -125,7 +126,7 @@ class Safe_DataObject extends DB_DataObject | ||||
|      * Work around memory-leak bugs... | ||||
|      * Had to copy-paste the whole function in order to patch a couple lines of it. | ||||
|      * Would be nice if this code was better factored. | ||||
|      *      | ||||
|      * | ||||
|      * @param optional string  name of database to assign / read | ||||
|      * @param optional array   structure of database, and keys | ||||
|      * @param optional array  table links | ||||
| @@ -136,108 +137,103 @@ class Safe_DataObject extends DB_DataObject | ||||
|      */ | ||||
|     function databaseStructure() | ||||
|     { | ||||
|  | ||||
|         global $_DB_DATAOBJECT; | ||||
|          | ||||
|         // Assignment code  | ||||
|          | ||||
|  | ||||
|         // Assignment code | ||||
|  | ||||
|         if ($args = func_get_args()) { | ||||
|          | ||||
|  | ||||
|             if (count($args) == 1) { | ||||
|                  | ||||
|  | ||||
|                 // this returns all the tables and their structure.. | ||||
|                 if (!empty($_DB_DATAOBJECT['CONFIG']['debug'])) { | ||||
|                     $this->debug("Loading Generator as databaseStructure called with args",1); | ||||
|                 } | ||||
|                  | ||||
|  | ||||
|                 $x = new DB_DataObject; | ||||
|                 $x->_database = $args[0]; | ||||
|                 $this->_connect(); | ||||
|                 $DB = &$_DB_DATAOBJECT['CONNECTIONS'][$this->_database_dsn_md5]; | ||||
|         | ||||
|  | ||||
|                 $tables = $DB->getListOf('tables'); | ||||
|                 class_exists('DB_DataObject_Generator') ? '' :  | ||||
|                 class_exists('DB_DataObject_Generator') ? '' : | ||||
|                     require_once 'DB/DataObject/Generator.php'; | ||||
|                      | ||||
|  | ||||
|                 foreach($tables as $table) { | ||||
|                     $y = new DB_DataObject_Generator; | ||||
|                     $y->fillTableSchema($x->_database,$table); | ||||
|                 } | ||||
|                 return $_DB_DATAOBJECT['INI'][$x->_database];             | ||||
|                 return $_DB_DATAOBJECT['INI'][$x->_database]; | ||||
|             } else { | ||||
|          | ||||
|  | ||||
|                 $_DB_DATAOBJECT['INI'][$args[0]] = isset($_DB_DATAOBJECT['INI'][$args[0]]) ? | ||||
|                     $_DB_DATAOBJECT['INI'][$args[0]] + $args[1] : $args[1]; | ||||
|                  | ||||
|  | ||||
|                 if (isset($args[1])) { | ||||
|                     $_DB_DATAOBJECT['LINKS'][$args[0]] = isset($_DB_DATAOBJECT['LINKS'][$args[0]]) ? | ||||
|                         $_DB_DATAOBJECT['LINKS'][$args[0]] + $args[2] : $args[2]; | ||||
|                 } | ||||
|                 return true; | ||||
|             } | ||||
|            | ||||
|  | ||||
|         } | ||||
|          | ||||
|          | ||||
|          | ||||
|  | ||||
|         if (!$this->_database) { | ||||
|             $this->_connect(); | ||||
|         } | ||||
|          | ||||
|  | ||||
|         // loaded already? | ||||
|         if (!empty($_DB_DATAOBJECT['INI'][$this->_database])) { | ||||
|              | ||||
|  | ||||
|             // database loaded - but this is table is not available.. | ||||
|             if ( | ||||
|                     empty($_DB_DATAOBJECT['INI'][$this->_database][$this->__table])  | ||||
|                     empty($_DB_DATAOBJECT['INI'][$this->_database][$this->__table]) | ||||
|                     && !empty($_DB_DATAOBJECT['CONFIG']['proxy']) | ||||
|                 ) { | ||||
|                 if (!empty($_DB_DATAOBJECT['CONFIG']['debug'])) { | ||||
|                     $this->debug("Loading Generator to fetch Schema",1); | ||||
|                 } | ||||
|                 class_exists('DB_DataObject_Generator') ? '' :  | ||||
|                 class_exists('DB_DataObject_Generator') ? '' : | ||||
|                     require_once 'DB/DataObject/Generator.php'; | ||||
|                      | ||||
|                  | ||||
|  | ||||
|  | ||||
|                 $x = new DB_DataObject_Generator; | ||||
|                 $x->fillTableSchema($this->_database,$this->__table); | ||||
|             } | ||||
|             return true; | ||||
|         } | ||||
|          | ||||
|          | ||||
|  | ||||
|         if (empty($_DB_DATAOBJECT['CONFIG'])) { | ||||
|             DB_DataObject::_loadConfig(); | ||||
|         } | ||||
|          | ||||
|  | ||||
|         // if you supply this with arguments, then it will take those | ||||
|         // as the database and links array... | ||||
|           | ||||
|  | ||||
|         $schemas = isset($_DB_DATAOBJECT['CONFIG']['schema_location']) ? | ||||
|             array("{$_DB_DATAOBJECT['CONFIG']['schema_location']}/{$this->_database}.ini") : | ||||
|             array() ; | ||||
|                   | ||||
|  | ||||
|         if (isset($_DB_DATAOBJECT['CONFIG']["ini_{$this->_database}"])) { | ||||
|             $schemas = is_array($_DB_DATAOBJECT['CONFIG']["ini_{$this->_database}"]) ? | ||||
|                 $_DB_DATAOBJECT['CONFIG']["ini_{$this->_database}"] : | ||||
|                 explode(PATH_SEPARATOR,$_DB_DATAOBJECT['CONFIG']["ini_{$this->_database}"]); | ||||
|         } | ||||
|                      | ||||
|           | ||||
|  | ||||
|         /* BEGIN CHANGED FROM UPSTREAM */ | ||||
|         $_DB_DATAOBJECT['INI'][$this->_database] = $this->parseIniFiles($schemas); | ||||
|         /* END CHANGED FROM UPSTREAM */ | ||||
|  | ||||
|         // now have we loaded the structure..  | ||||
|          | ||||
|         // now have we loaded the structure.. | ||||
|  | ||||
|         if (!empty($_DB_DATAOBJECT['INI'][$this->_database][$this->__table])) { | ||||
|             return true; | ||||
|         } | ||||
|         // - if not try building it.. | ||||
|         if (!empty($_DB_DATAOBJECT['CONFIG']['proxy'])) { | ||||
|             class_exists('DB_DataObject_Generator') ? '' :  | ||||
|             class_exists('DB_DataObject_Generator') ? '' : | ||||
|                 require_once 'DB/DataObject/Generator.php'; | ||||
|                  | ||||
|  | ||||
|             $x = new DB_DataObject_Generator; | ||||
|             $x->fillTableSchema($this->_database,$this->__table); | ||||
|             // should this fail!!!??? | ||||
| @@ -245,7 +241,8 @@ class Safe_DataObject extends DB_DataObject | ||||
|         } | ||||
|         $this->debug("Cant find database schema: {$this->_database}/{$this->__table} \n". | ||||
|                     "in links file data: " . print_r($_DB_DATAOBJECT['INI'],true),"databaseStructure",5); | ||||
|         // we have to die here!! - it causes chaos if we dont (including looping forever!) | ||||
|         // we have to die here!! - it causes chaos if we don't (including looping forever!) | ||||
|         // Low level exception. No need for i18n as discussed with Brion. | ||||
|         $this->raiseError( "Unable to load schema for database and table (turn debugging up to 5 for full error message)", DB_DATAOBJECT_ERROR_INVALIDARGS, PEAR_ERROR_DIE); | ||||
|         return false; | ||||
|     } | ||||
| @@ -271,7 +268,7 @@ class Safe_DataObject extends DB_DataObject | ||||
|                 if (file_exists($ini) && is_file($ini)) { | ||||
|                     $data = array_merge($data, parse_ini_file($ini, true)); | ||||
|  | ||||
|                     if (!empty($_DB_DATAOBJECT['CONFIG']['debug'])) {  | ||||
|                     if (!empty($_DB_DATAOBJECT['CONFIG']['debug'])) { | ||||
|                         if (!is_readable ($ini)) { | ||||
|                             $this->debug("ini file is not readable: $ini","databaseStructure",1); | ||||
|                         } else { | ||||
|   | ||||
| @@ -27,7 +27,8 @@ class Status_network extends Safe_DataObject | ||||
|     /* the code below is auto generated do not remove the above tag */ | ||||
|  | ||||
|     public $__table = 'status_network';                  // table name | ||||
|     public $nickname;                        // varchar(64)  primary_key not_null | ||||
|     public $site_id;                         // int(4) primary_key not_null | ||||
|     public $nickname;                        // varchar(64)   unique_key not_null | ||||
|     public $hostname;                        // varchar(255)  unique_key | ||||
|     public $pathname;                        // varchar(255)  unique_key | ||||
|     public $dbhost;                          // varchar(255) | ||||
| @@ -39,7 +40,6 @@ class Status_network extends Safe_DataObject | ||||
|     public $logo;                            // varchar(255) | ||||
|     public $created;                         // datetime()   not_null | ||||
|     public $modified;                        // timestamp()   not_null default_CURRENT_TIMESTAMP | ||||
|     public $tags;                            // text | ||||
|  | ||||
|     /* Static get */ | ||||
|     function staticGet($k,$v=NULL) { | ||||
| @@ -308,9 +308,63 @@ class Status_network extends Safe_DataObject | ||||
|      */ | ||||
|     function getTags() | ||||
|     { | ||||
|         return array_filter(explode("|", strval($this->tags))); | ||||
|         $result = array(); | ||||
|          | ||||
|         $tags = new Status_network_tag(); | ||||
|         $tags->site_id = $this->site_id; | ||||
|         if ($tags->find()) { | ||||
|             while ($tags->fetch()) { | ||||
|                 $result[] = $tags->tag; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         // XXX : for backwards compatibility | ||||
|         if (empty($result)) { | ||||
|             return explode('|', $this->tags); | ||||
|         } | ||||
|          | ||||
|         return $result; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Save a given set of tags | ||||
|      * @param array tags | ||||
|      */ | ||||
|     function setTags($tags) | ||||
|     { | ||||
|         $this->clearTags(); | ||||
|         foreach ($tags as $tag) { | ||||
|             if (!empty($tag)) { | ||||
|                 $snt = new Status_network_tag(); | ||||
|                 $snt->site_id = $this->site_id; | ||||
|                 $snt->tag = $tag; | ||||
|                 $snt->created = common_sql_now(); | ||||
|                  | ||||
|                 $id = $snt->insert(); | ||||
|                 if (!$id) { | ||||
|                     // TRANS: Exception thrown when a tag cannot be saved. | ||||
|                     throw new Exception(_("Unable to save tag.")); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     function clearTags() | ||||
|     { | ||||
|         $tag = new Status_network_tag(); | ||||
|         $tag->site_id = $this->site_id; | ||||
|  | ||||
|         if ($tag->find()) { | ||||
|             while($tag->fetch()) { | ||||
|                 $tag->delete(); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         $tag->free(); | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Check if this site record has a particular meta-info tag attached. | ||||
|      * @param string $tag | ||||
|   | ||||
							
								
								
									
										69
									
								
								classes/Status_network_tag.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								classes/Status_network_tag.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,69 @@ | ||||
| <?php | ||||
| /* | ||||
|  * StatusNet - the distributed open-source microblogging tool | ||||
|  * Copyright (C) 2008, 2009, 2010 StatusNet, Inc. | ||||
|  * | ||||
|  * 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/>. | ||||
|  */ | ||||
|  | ||||
| if (!defined('STATUSNET')) { exit(1); } | ||||
|  | ||||
| class Status_network_tag extends Safe_DataObject | ||||
| { | ||||
|     ###START_AUTOCODE | ||||
|     /* the code below is auto generated do not remove the above tag */ | ||||
|  | ||||
|     public $__table = 'status_network_tag';                      // table name | ||||
|     public $site_id;                  // int(4)  primary_key not_null | ||||
|     public $tag;                      // varchar(64)  primary_key not_null  | ||||
|     public $created;                 // datetime()   not_null | ||||
|  | ||||
|  | ||||
|     function __construct() | ||||
|     { | ||||
|         global $config; | ||||
|         global $_DB_DATAOBJECT; | ||||
|          | ||||
|         $sn = new Status_network(); | ||||
|         $sn->_connect(); | ||||
|  | ||||
|         $config['db']['table_'. $this->__table] = $sn->_database; | ||||
|  | ||||
|         $this->_connect(); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /* Static get */ | ||||
|     function staticGet($k,$v=null) | ||||
|     { | ||||
|         $i = DB_DataObject::staticGet('Status_network_tag',$k,$v); | ||||
|  | ||||
|         // Don't use local process cache; if we're fetching multiple | ||||
|         // times it's because we're reloading it in a long-running | ||||
|         // process; we need a fresh copy! | ||||
|         global $_DB_DATAOBJECT; | ||||
|         unset($_DB_DATAOBJECT['CACHE']['status_network_tag']); | ||||
|         return $i; | ||||
|     } | ||||
|  | ||||
|     /* the code above is auto generated do not remove the tag below */ | ||||
|     ###END_AUTOCODE | ||||
|  | ||||
|  | ||||
|  | ||||
|     function pkeyGet($kv) | ||||
|     { | ||||
|         return Memcached_DataObject::pkeyGet('Status_network_tag', $kv); | ||||
|     } | ||||
| } | ||||
| @@ -71,14 +71,17 @@ class Subscription extends Memcached_DataObject | ||||
|         } | ||||
|  | ||||
|         if (!$subscriber->hasRight(Right::SUBSCRIBE)) { | ||||
|             // TRANS: Exception thrown when trying to subscribe while being banned from subscribing. | ||||
|             throw new Exception(_('You have been banned from subscribing.')); | ||||
|         } | ||||
|  | ||||
|         if (self::exists($subscriber, $other)) { | ||||
|             // TRANS: Exception thrown when trying to subscribe while already subscribed. | ||||
|             throw new Exception(_('Already subscribed!')); | ||||
|         } | ||||
|  | ||||
|         if ($other->hasBlocked($subscriber)) { | ||||
|             // TRANS: Exception thrown when trying to subscribe to a user who has blocked the subscribing user. | ||||
|             throw new Exception(_('User has blocked you.')); | ||||
|         } | ||||
|  | ||||
| @@ -129,6 +132,7 @@ class Subscription extends Memcached_DataObject | ||||
|  | ||||
|         if (!$result) { | ||||
|             common_log_db_error($sub, 'INSERT', __FILE__); | ||||
|             // TRANS: Exception thrown when a subscription could not be stored on the server. | ||||
|             throw new Exception(_('Could not save subscription.')); | ||||
|         } | ||||
|  | ||||
| @@ -160,17 +164,18 @@ class Subscription extends Memcached_DataObject | ||||
|      * Cancel a subscription | ||||
|      * | ||||
|      */ | ||||
|  | ||||
|     function cancel($subscriber, $other) | ||||
|     { | ||||
|         if (!self::exists($subscriber, $other)) { | ||||
|             // TRANS: Exception thrown when trying to unsibscribe without a subscription. | ||||
|             throw new Exception(_('Not subscribed!')); | ||||
|         } | ||||
|  | ||||
|         // Don't allow deleting self subs | ||||
|  | ||||
|         if ($subscriber->id == $other->id) { | ||||
|             throw new Exception(_('Couldn\'t delete self-subscription.')); | ||||
|             // TRANS: Exception thrown when trying to unsubscribe a user from themselves. | ||||
|             throw new Exception(_('Could not delete self-subscription.')); | ||||
|         } | ||||
|  | ||||
|         if (Event::handle('StartUnsubscribe', array($subscriber, $other))) { | ||||
| @@ -197,7 +202,8 @@ class Subscription extends Memcached_DataObject | ||||
|  | ||||
|                     if (!$result) { | ||||
|                         common_log_db_error($token, 'DELETE', __FILE__); | ||||
|                         throw new Exception(_('Couldn\'t delete subscription OMB token.')); | ||||
|                         // TRANS: Exception thrown when the OMB token for a subscription could not deleted on the server. | ||||
|                         throw new Exception(_('Could not delete subscription OMB token.')); | ||||
|                     } | ||||
|                 } else { | ||||
|                     common_log(LOG_ERR, "Couldn't find credentials with token {$token->tok}"); | ||||
| @@ -208,7 +214,8 @@ class Subscription extends Memcached_DataObject | ||||
|  | ||||
|             if (!$result) { | ||||
|                 common_log_db_error($sub, 'DELETE', __FILE__); | ||||
|                 throw new Exception(_('Couldn\'t delete subscription.')); | ||||
|                 // TRANS: Exception thrown when a subscription could not be deleted on the server. | ||||
|                 throw new Exception(_('Could not delete subscription.')); | ||||
|             } | ||||
|  | ||||
|             self::blow('user:notices_with_friends:%d', $subscriber->id); | ||||
|   | ||||
| @@ -355,11 +355,12 @@ class User extends Memcached_DataObject | ||||
|                                __FILE__); | ||||
|                 } else { | ||||
|                     $notice = Notice::saveNew($welcomeuser->id, | ||||
|                                               // TRANS: Notice given on user registration. | ||||
|                                               // TRANS: %1$s is the sitename, $2$s is the registering user's nickname. | ||||
|                                               sprintf(_('Welcome to %1$s, @%2$s!'), | ||||
|                                                       common_config('site', 'name'), | ||||
|                                                       $user->nickname), | ||||
|                                               'system'); | ||||
|  | ||||
|                 } | ||||
|             } | ||||
|  | ||||
| @@ -370,7 +371,6 @@ class User extends Memcached_DataObject | ||||
|     } | ||||
|  | ||||
|     // Things we do when the email changes | ||||
|  | ||||
|     function emailChanged() | ||||
|     { | ||||
|  | ||||
| @@ -519,7 +519,7 @@ class User extends Memcached_DataObject | ||||
|         if ($this->id == $other->id) { | ||||
|             common_log(LOG_WARNING, | ||||
|                 sprintf( | ||||
|                     "Profile ID %d (%s) tried to block his or herself.", | ||||
|                     "Profile ID %d (%s) tried to block themself.", | ||||
|                     $this->id, | ||||
|                     $this->nickname | ||||
|                 ) | ||||
|   | ||||
| @@ -492,6 +492,7 @@ class User_group extends Memcached_DataObject | ||||
|  | ||||
|         if (!$result) { | ||||
|             common_log_db_error($group, 'INSERT', __FILE__); | ||||
|             // TRANS: Server exception thrown when creating a group failed. | ||||
|             throw new ServerException(_('Could not create group.')); | ||||
|         } | ||||
|  | ||||
| @@ -501,6 +502,7 @@ class User_group extends Memcached_DataObject | ||||
|             $result = $group->update($orig); | ||||
|             if (!$result) { | ||||
|                 common_log_db_error($group, 'UPDATE', __FILE__); | ||||
|                 // TRANS: Server exception thrown when updating a group URI failed. | ||||
|                 throw new ServerException(_('Could not set group URI.')); | ||||
|             } | ||||
|         } | ||||
| @@ -508,6 +510,7 @@ class User_group extends Memcached_DataObject | ||||
|         $result = $group->setAliases($aliases); | ||||
|  | ||||
|         if (!$result) { | ||||
|             // TRANS: Server exception thrown when creating group aliases failed. | ||||
|             throw new ServerException(_('Could not create aliases.')); | ||||
|         } | ||||
|  | ||||
| @@ -522,6 +525,7 @@ class User_group extends Memcached_DataObject | ||||
|  | ||||
|         if (!$result) { | ||||
|             common_log_db_error($member, 'INSERT', __FILE__); | ||||
|             // TRANS: Server exception thrown when setting group membership failed. | ||||
|             throw new ServerException(_('Could not set group membership.')); | ||||
|         } | ||||
|  | ||||
| @@ -536,6 +540,7 @@ class User_group extends Memcached_DataObject | ||||
|  | ||||
|             if (!$result) { | ||||
|                 common_log_db_error($local_group, 'INSERT', __FILE__); | ||||
|                 // TRANS: Server exception thrown when saving local group information failed. | ||||
|                 throw new ServerException(_('Could not save local group info.')); | ||||
|             } | ||||
|         } | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| [status_network] | ||||
| site_id = 129 | ||||
| nickname = 130 | ||||
| hostname = 2 | ||||
| pathname = 2 | ||||
| @@ -11,9 +12,19 @@ theme = 2 | ||||
| logo = 2 | ||||
| created = 142 | ||||
| modified = 384 | ||||
| tags = 34 | ||||
|  | ||||
| [status_network__keys] | ||||
| nickname = K | ||||
| site_id  = K | ||||
| nickname = U | ||||
| hostname = U | ||||
| pathname = U | ||||
|  | ||||
| [status_network_tag] | ||||
| site_id = 129 | ||||
| tag = 130 | ||||
| created = 142 | ||||
|  | ||||
| [status_network_tag__keys] | ||||
| site_id = K | ||||
| tag = K | ||||
|  | ||||
|   | ||||
| @@ -51,6 +51,7 @@ VALUES | ||||
|     ('smob','SMOB','http://smob.sioc-project.org/', now()), | ||||
|     ('socialoomphBfD4pMqz31', 'SocialOomph', 'http://www.socialoomph.com/', now()), | ||||
|     ('spaz','Spaz','http://funkatron.com/spaz', now()), | ||||
|     ('StatusNet Desktop', 'StatusNet Desktop', 'http://status.net/desktop', now()), | ||||
|     ('tarpipe','tarpipe','http://tarpipe.com/', now()), | ||||
|     ('tjunar','Tjunar','http://nederflash.nl/boek/titels/tjunar-air', now()), | ||||
|     ('tr.im','tr.im','http://tr.im/', now()), | ||||
|   | ||||
							
								
								
									
										14
									
								
								db/site.sql
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								db/site.sql
									
									
									
									
									
								
							| @@ -1,8 +1,9 @@ | ||||
| /* For managing multiple sites */ | ||||
|  | ||||
| create table status_network ( | ||||
|  | ||||
|     nickname varchar(64) primary key comment 'nickname', | ||||
|         | ||||
|     site_id  integer auto_increment primary key comment 'unique id', | ||||
|     nickname varchar(64)  unique key comment 'nickname', | ||||
|     hostname varchar(255) unique key comment 'alternate hostname if any', | ||||
|     pathname varchar(255) unique key comment 'alternate pathname if any', | ||||
|  | ||||
| @@ -21,3 +22,12 @@ create table status_network ( | ||||
|     modified timestamp comment 'date this record was modified' | ||||
|  | ||||
| ) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_general_ci; | ||||
|  | ||||
| create table status_network_tag ( | ||||
|     site_id integer  comment 'unique id', | ||||
|     tag varchar(64) comment 'tag name', | ||||
|     created datetime not null comment 'date the record was created', | ||||
|  | ||||
|     constraint primary key (site_id, tag) | ||||
| ) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_general_ci; | ||||
|  | ||||
|   | ||||
							
								
								
									
										13
									
								
								db/site_093to094.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								db/site_093to094.sql
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| alter table status_network  | ||||
|       drop primary key, | ||||
|       add column site_id integer auto_increment primary key first, | ||||
|       add unique key (nickname); | ||||
|  | ||||
| create table status_network_tag ( | ||||
|     site_id integer  comment 'unique id', | ||||
|     tag varchar(64) comment 'tag name', | ||||
|     created datetime not null comment 'date the record was created', | ||||
|  | ||||
|     constraint primary key (site_id, tag) | ||||
| ) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_general_ci; | ||||
|  | ||||
| @@ -20,7 +20,7 @@ | ||||
| /** | ||||
|  * The library version string | ||||
|  */ | ||||
| define('Auth_OpenID_VERSION', '2.1.3'); | ||||
| define('Auth_OpenID_VERSION', '2.2.2'); | ||||
|  | ||||
| /** | ||||
|  * Require the fetcher code. | ||||
| @@ -102,9 +102,7 @@ define('Auth_OpenID_digits', | ||||
| define('Auth_OpenID_punct', | ||||
|        "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~"); | ||||
|  | ||||
| if (Auth_OpenID_getMathLib() === null) { | ||||
|     Auth_OpenID_setNoMathSupport(); | ||||
| } | ||||
| Auth_OpenID_include_init(); | ||||
|  | ||||
| /** | ||||
|  * The OpenID utility function class. | ||||
| @@ -120,7 +118,7 @@ class Auth_OpenID { | ||||
|      * | ||||
|      * @access private | ||||
|      */ | ||||
|     function isFailure($thing) | ||||
|     static function isFailure($thing) | ||||
|     { | ||||
|         return is_a($thing, 'Auth_OpenID_FailureResponse'); | ||||
|     } | ||||
| @@ -139,9 +137,12 @@ class Auth_OpenID { | ||||
|      * Returns an empty array if neither GET nor POST was used, or if | ||||
|      * POST was used but php://input cannot be opened. | ||||
|      * | ||||
|      * See background: | ||||
|      * http://lists.openidenabled.com/pipermail/dev/2007-March/000395.html | ||||
|      * | ||||
|      * @access private | ||||
|      */ | ||||
|     function getQuery($query_str=null) | ||||
|     static function getQuery($query_str=null) | ||||
|     { | ||||
|         $data = array(); | ||||
|  | ||||
| @@ -177,7 +178,7 @@ class Auth_OpenID { | ||||
|         return $data; | ||||
|     } | ||||
|  | ||||
|     function params_from_string($str) | ||||
|     static function params_from_string($str) | ||||
|     { | ||||
|         $chunks = explode("&", $str); | ||||
|  | ||||
| @@ -190,7 +191,7 @@ class Auth_OpenID { | ||||
|             } | ||||
|  | ||||
|             list($k, $v) = $parts; | ||||
|             $data[$k] = urldecode($v); | ||||
|             $data[urldecode($k)] = urldecode($v); | ||||
|         } | ||||
|  | ||||
|         return $data; | ||||
| @@ -203,7 +204,7 @@ class Auth_OpenID { | ||||
|      * | ||||
|      * @access private | ||||
|      */ | ||||
|     function ensureDir($dir_name) | ||||
|     static function ensureDir($dir_name) | ||||
|     { | ||||
|         if (is_dir($dir_name) || @mkdir($dir_name)) { | ||||
|             return true; | ||||
| @@ -225,7 +226,7 @@ class Auth_OpenID { | ||||
|      * | ||||
|      * @access private | ||||
|      */ | ||||
|     function addPrefix($values, $prefix) | ||||
|     static function addPrefix($values, $prefix) | ||||
|     { | ||||
|         $new_values = array(); | ||||
|         foreach ($values as $s) { | ||||
| @@ -241,7 +242,7 @@ class Auth_OpenID { | ||||
|      * | ||||
|      * @access private | ||||
|      */ | ||||
|     function arrayGet($arr, $key, $fallback = null) | ||||
|     static function arrayGet($arr, $key, $fallback = null) | ||||
|     { | ||||
|         if (is_array($arr)) { | ||||
|             if (array_key_exists($key, $arr)) { | ||||
| @@ -261,7 +262,7 @@ class Auth_OpenID { | ||||
|     /** | ||||
|      * Replacement for PHP's broken parse_str. | ||||
|      */ | ||||
|     function parse_str($query) | ||||
|     static function parse_str($query) | ||||
|     { | ||||
|         if ($query === null) { | ||||
|             return null; | ||||
| @@ -278,7 +279,7 @@ class Auth_OpenID { | ||||
|             } | ||||
|  | ||||
|             list($key, $value) = $pair; | ||||
|             $new_parts[$key] = urldecode($value); | ||||
|             $new_parts[urldecode($key)] = urldecode($value); | ||||
|         } | ||||
|  | ||||
|         return $new_parts; | ||||
| @@ -295,7 +296,7 @@ class Auth_OpenID { | ||||
|      * pairs from $data into a URL query string | ||||
|      * (e.g. "username=bob&id=56"). | ||||
|      */ | ||||
|     function httpBuildQuery($data) | ||||
|     static function httpBuildQuery($data) | ||||
|     { | ||||
|         $pairs = array(); | ||||
|         foreach ($data as $key => $value) { | ||||
| @@ -323,7 +324,7 @@ class Auth_OpenID { | ||||
|      * @return string $url The original URL with the new parameters added. | ||||
|      * | ||||
|      */ | ||||
|     function appendArgs($url, $args) | ||||
|     static function appendArgs($url, $args) | ||||
|     { | ||||
|         if (count($args) == 0) { | ||||
|             return $url; | ||||
| @@ -367,7 +368,7 @@ class Auth_OpenID { | ||||
|      * @return string $url The URL resulting from assembling the | ||||
|      * specified components. | ||||
|      */ | ||||
|     function urlunparse($scheme, $host, $port = null, $path = '/', | ||||
|     static function urlunparse($scheme, $host, $port = null, $path = '/', | ||||
|                         $query = '', $fragment = '') | ||||
|     { | ||||
|  | ||||
| @@ -412,7 +413,7 @@ class Auth_OpenID { | ||||
|      * @return mixed $new_url The URL after normalization, or null if | ||||
|      * $url was malformed. | ||||
|      */ | ||||
|     function normalizeUrl($url) | ||||
|     static function normalizeUrl($url) | ||||
|     { | ||||
|         @$parsed = parse_url($url); | ||||
|  | ||||
| @@ -443,7 +444,7 @@ class Auth_OpenID { | ||||
|      * | ||||
|      * @access private | ||||
|      */ | ||||
|     function intval($value) | ||||
|     static function intval($value) | ||||
|     { | ||||
|         $re = "/^\\d+$/"; | ||||
|  | ||||
| @@ -461,7 +462,7 @@ class Auth_OpenID { | ||||
|      * @param string $str The string of bytes to count. | ||||
|      * @return int The number of bytes in $str. | ||||
|      */ | ||||
|     function bytes($str) | ||||
|     static function bytes($str) | ||||
|     { | ||||
|         return strlen(bin2hex($str)) / 2; | ||||
|     } | ||||
| @@ -470,7 +471,7 @@ class Auth_OpenID { | ||||
|      * Get the bytes in a string independently of multibyte support | ||||
|      * conditions. | ||||
|      */ | ||||
|     function toBytes($str) | ||||
|     static function toBytes($str) | ||||
|     { | ||||
|         $hex = bin2hex($str); | ||||
|  | ||||
| @@ -486,7 +487,7 @@ class Auth_OpenID { | ||||
|         return $b; | ||||
|     } | ||||
|  | ||||
|     function urldefrag($url) | ||||
|     static function urldefrag($url) | ||||
|     { | ||||
|         $parts = explode("#", $url, 2); | ||||
|  | ||||
| @@ -497,7 +498,7 @@ class Auth_OpenID { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     function filter($callback, &$sequence) | ||||
|     static function filter($callback, &$sequence) | ||||
|     { | ||||
|         $result = array(); | ||||
|  | ||||
| @@ -510,7 +511,7 @@ class Auth_OpenID { | ||||
|         return $result; | ||||
|     } | ||||
|  | ||||
|     function update(&$dest, &$src) | ||||
|     static function update(&$dest, &$src) | ||||
|     { | ||||
|         foreach ($src as $k => $v) { | ||||
|             $dest[$k] = $v; | ||||
| @@ -524,14 +525,14 @@ class Auth_OpenID { | ||||
|      * | ||||
|      * @param string $format_string The sprintf format for the message | ||||
|      */ | ||||
|     function log($format_string) | ||||
|     static function log($format_string) | ||||
|     { | ||||
|         $args = func_get_args(); | ||||
|         $message = call_user_func_array('sprintf', $args); | ||||
|         error_log($message); | ||||
|     } | ||||
|  | ||||
|     function autoSubmitHTML($form, $title="OpenId transaction in progress") | ||||
|     static function autoSubmitHTML($form, $title="OpenId transaction in progress") | ||||
|     { | ||||
|         return("<html>". | ||||
|                "<head><title>". | ||||
| @@ -549,4 +550,14 @@ class Auth_OpenID { | ||||
|                "</html>"); | ||||
|     } | ||||
| } | ||||
| ?> | ||||
|  | ||||
| /* | ||||
|  * Function to run when this file is included. | ||||
|  * Abstracted to a function to make life easier | ||||
|  * for some PHP optimizers. | ||||
|  */ | ||||
| function Auth_OpenID_include_init() { | ||||
|   if (Auth_OpenID_getMathLib() === null) { | ||||
|     Auth_OpenID_setNoMathSupport(); | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -38,7 +38,7 @@ class Auth_OpenID_AX { | ||||
|      * @return bool true if $thing is an Auth_OpenID_AX_Error; false | ||||
|      * if not. | ||||
|      */ | ||||
|     function isError($thing) | ||||
|     static function isError($thing) | ||||
|     { | ||||
|         return is_a($thing, 'Auth_OpenID_AX_Error'); | ||||
|     } | ||||
| @@ -191,7 +191,7 @@ class Auth_OpenID_AX_AttrInfo { | ||||
|      * Construct an attribute information object.  For parameter | ||||
|      * details, see the constructor. | ||||
|      */ | ||||
|     function make($type_uri, $count=1, $required=false, | ||||
|     static function make($type_uri, $count=1, $required=false, | ||||
|                   $alias=null) | ||||
|     { | ||||
|         if ($alias !== null) { | ||||
| @@ -235,7 +235,7 @@ class Auth_OpenID_AX_AttrInfo { | ||||
|  * return null If an alias is present in the list of aliases but | ||||
|  * is not present in the namespace map. | ||||
|  */ | ||||
| function Auth_OpenID_AX_toTypeURIs(&$namespace_map, $alias_list_s) | ||||
| function Auth_OpenID_AX_toTypeURIs($namespace_map, $alias_list_s) | ||||
| { | ||||
|     $uris = array(); | ||||
|  | ||||
| @@ -386,7 +386,7 @@ class Auth_OpenID_AX_FetchRequest extends Auth_OpenID_AX_Message { | ||||
|      * Auth_OpenID_AX_FetchRequest extracted from the request message if | ||||
|      * successful | ||||
|      */ | ||||
|     function &fromOpenIDRequest($request) | ||||
|     static function fromOpenIDRequest($request) | ||||
|     { | ||||
|         $m = $request->message; | ||||
|         $obj = new Auth_OpenID_AX_FetchRequest(); | ||||
| @@ -484,7 +484,7 @@ class Auth_OpenID_AX_FetchRequest extends Auth_OpenID_AX_Message { | ||||
|                          Auth_OpenID::arrayGet($ax_args, 'required')); | ||||
|  | ||||
|         foreach ($required as $type_uri) { | ||||
|             $attrib =& $this->requested_attributes[$type_uri]; | ||||
|             $attrib = $this->requested_attributes[$type_uri]; | ||||
|             $attrib->required = true; | ||||
|         } | ||||
|  | ||||
| @@ -587,7 +587,7 @@ class Auth_OpenID_AX_KeyValueMessage extends Auth_OpenID_AX_Message { | ||||
|      * | ||||
|      * @access private | ||||
|      */ | ||||
|     function _getExtensionKVArgs(&$aliases) | ||||
|     function _getExtensionKVArgs($aliases) | ||||
|     { | ||||
|         if ($aliases === null) { | ||||
|             $aliases = new Auth_OpenID_NamespaceMap(); | ||||
| @@ -652,7 +652,7 @@ class Auth_OpenID_AX_KeyValueMessage extends Auth_OpenID_AX_Message { | ||||
|         foreach ($aliases->iteritems() as $pair) { | ||||
|             list($type_uri, $alias) = $pair; | ||||
|  | ||||
|             if (array_key_exists('count.' . $alias, $ax_args)) { | ||||
|             if (array_key_exists('count.' . $alias, $ax_args) && ($ax_args['count.' . $alias] !== Auth_OpenID_AX_UNLIMITED_VALUES)) { | ||||
|  | ||||
|                 $count_key = 'count.' . $alias; | ||||
|                 $count_s = $ax_args[$count_key]; | ||||
| @@ -888,7 +888,7 @@ class Auth_OpenID_AX_FetchResponse extends Auth_OpenID_AX_KeyValueMessage { | ||||
|             $ax_args['update_url'] = $update_url; | ||||
|         } | ||||
|  | ||||
|         Auth_OpenID::update(&$ax_args, $kv_args); | ||||
|         Auth_OpenID::update($ax_args, $kv_args); | ||||
|  | ||||
|         return $ax_args; | ||||
|     } | ||||
| @@ -922,7 +922,7 @@ class Auth_OpenID_AX_FetchResponse extends Auth_OpenID_AX_KeyValueMessage { | ||||
|      * @return $response A FetchResponse containing the data from the | ||||
|      * OpenID message | ||||
|      */ | ||||
|     function fromSuccessResponse($success_response, $signed=true) | ||||
|     static function fromSuccessResponse($success_response, $signed=true) | ||||
|     { | ||||
|         $obj = new Auth_OpenID_AX_FetchResponse(); | ||||
|         if ($signed) { | ||||
| @@ -960,7 +960,7 @@ class Auth_OpenID_AX_StoreRequest extends Auth_OpenID_AX_KeyValueMessage { | ||||
|     { | ||||
|         $ax_args = $this->_newArgs(); | ||||
|         $kv_args = $this->_getExtensionKVArgs($aliases); | ||||
|         Auth_OpenID::update(&$ax_args, $kv_args); | ||||
|         Auth_OpenID::update($ax_args, $kv_args); | ||||
|         return $ax_args; | ||||
|     } | ||||
| } | ||||
| @@ -980,7 +980,7 @@ class Auth_OpenID_AX_StoreResponse extends Auth_OpenID_AX_Message { | ||||
|      * Returns Auth_OpenID_AX_Error on error or an | ||||
|      * Auth_OpenID_AX_StoreResponse object on success. | ||||
|      */ | ||||
|     function &make($succeeded=true, $error_message=null) | ||||
|     function make($succeeded=true, $error_message=null) | ||||
|     { | ||||
|         if (($succeeded) && ($error_message !== null)) { | ||||
|             return new Auth_OpenID_AX_Error('An error message may only be '. | ||||
| @@ -1020,4 +1020,3 @@ class Auth_OpenID_AX_StoreResponse extends Auth_OpenID_AX_Message { | ||||
|     } | ||||
| } | ||||
|  | ||||
| ?> | ||||
| @@ -94,7 +94,7 @@ class Auth_OpenID_Association { | ||||
|      * @return association An {@link Auth_OpenID_Association} | ||||
|      * instance. | ||||
|      */ | ||||
|     function fromExpiresIn($expires_in, $handle, $secret, $assoc_type) | ||||
|     static function fromExpiresIn($expires_in, $handle, $secret, $assoc_type) | ||||
|     { | ||||
|         $issued = time(); | ||||
|         $lifetime = $expires_in; | ||||
| @@ -132,7 +132,7 @@ class Auth_OpenID_Association { | ||||
|         $handle, $secret, $issued, $lifetime, $assoc_type) | ||||
|     { | ||||
|         if (!in_array($assoc_type, | ||||
|                       Auth_OpenID_getSupportedAssociationTypes())) { | ||||
|                       Auth_OpenID_getSupportedAssociationTypes(), true)) { | ||||
|             $fmt = 'Unsupported association type (%s)'; | ||||
|             trigger_error(sprintf($fmt, $assoc_type), E_USER_ERROR); | ||||
|         } | ||||
| @@ -206,7 +206,7 @@ class Auth_OpenID_Association { | ||||
|      * @param string $assoc_s Association as serialized by serialize() | ||||
|      * @return Auth_OpenID_Association $result instance of this class | ||||
|      */ | ||||
|     function deserialize($class_name, $assoc_s) | ||||
|     static function deserialize($class_name, $assoc_s) | ||||
|     { | ||||
|         $pairs = Auth_OpenID_KVForm::toArray($assoc_s, $strict = true); | ||||
|         $keys = array(); | ||||
| @@ -327,7 +327,7 @@ class Auth_OpenID_Association { | ||||
|      * | ||||
|      * @access private | ||||
|      */ | ||||
|     function _makePairs(&$message) | ||||
|     function _makePairs($message) | ||||
|     { | ||||
|         $signed = $message->getArg(Auth_OpenID_OPENID_NS, 'signed'); | ||||
|         if (!$signed || Auth_OpenID::isFailure($signed)) { | ||||
| @@ -352,7 +352,7 @@ class Auth_OpenID_Association { | ||||
|      * | ||||
|      * @access private | ||||
|      */ | ||||
|     function getMessageSignature(&$message) | ||||
|     function getMessageSignature($message) | ||||
|     { | ||||
|         $pairs = $this->_makePairs($message); | ||||
|         return base64_encode($this->sign($pairs)); | ||||
| @@ -364,7 +364,7 @@ class Auth_OpenID_Association { | ||||
|      * | ||||
|      * @access private | ||||
|      */ | ||||
|     function checkMessageSignature(&$message) | ||||
|     function checkMessageSignature($message) | ||||
|     { | ||||
|         $sig = $message->getArg(Auth_OpenID_OPENID_NS, | ||||
|                                 'sig'); | ||||
| @@ -374,7 +374,42 @@ class Auth_OpenID_Association { | ||||
|         } | ||||
|  | ||||
|         $calculated_sig = $this->getMessageSignature($message); | ||||
|         return $calculated_sig == $sig; | ||||
|  | ||||
|         return $this->constantTimeCompare($calculated_sig, $sig); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * String comparison function which will complete in a constant time | ||||
|      * for strings of any given matching length, to help prevent an attacker | ||||
|      * from distinguishing how much of a signature token they have guessed | ||||
|      * correctly. | ||||
|      * | ||||
|      * For this usage, it's assumed that the length of the string is known, | ||||
|      * so we may safely short-circuit on mismatched lengths which will be known | ||||
|      * to be invalid by the attacker. | ||||
|      * | ||||
|      * http://lists.openid.net/pipermail/openid-security/2010-July/001156.html | ||||
|      * http://rdist.root.org/2010/01/07/timing-independent-array-comparison/ | ||||
|      */ | ||||
|     private function constantTimeCompare($a, $b) | ||||
|     { | ||||
|         $len = strlen($a); | ||||
|         if (strlen($b) !== $len) { | ||||
|             // Short-circuit on length mismatch; attackers will already know | ||||
|             // the correct target length so this is safe. | ||||
|             return false; | ||||
|         } | ||||
|         if ($len == 0) { | ||||
|             // 0-length valid input shouldn't really happen. :) | ||||
|             return true; | ||||
|         } | ||||
|         $result = 0; | ||||
|         for ($i = 0; $i < strlen($a); $i++) { | ||||
|             // We use scary bitwise operations to avoid logical short-circuits | ||||
|             // in lower-level code. | ||||
|             $result |= ord($a{$i}) ^ ord($b{$i}); | ||||
|         } | ||||
|         return ($result == 0); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -469,18 +504,16 @@ function Auth_OpenID_getOnlyEncryptedOrder() | ||||
|     return $result; | ||||
| } | ||||
|  | ||||
| function &Auth_OpenID_getDefaultNegotiator() | ||||
| function Auth_OpenID_getDefaultNegotiator() | ||||
| { | ||||
|     $x = new Auth_OpenID_SessionNegotiator( | ||||
|     return new Auth_OpenID_SessionNegotiator( | ||||
|                  Auth_OpenID_getDefaultAssociationOrder()); | ||||
|     return $x; | ||||
| } | ||||
|  | ||||
| function &Auth_OpenID_getEncryptedNegotiator() | ||||
| function Auth_OpenID_getEncryptedNegotiator() | ||||
| { | ||||
|     $x = new Auth_OpenID_SessionNegotiator( | ||||
|     return new Auth_OpenID_SessionNegotiator( | ||||
|                  Auth_OpenID_getOnlyEncryptedOrder()); | ||||
|     return $x; | ||||
| } | ||||
|  | ||||
| /** | ||||
| @@ -610,4 +643,3 @@ class Auth_OpenID_SessionNegotiator { | ||||
|     } | ||||
| } | ||||
|  | ||||
| ?> | ||||
| @@ -351,8 +351,7 @@ function Auth_OpenID_math_extensions() | ||||
|                   'class' => 'Auth_OpenID_GmpMathWrapper'); | ||||
|     } | ||||
|  | ||||
|     $result[] = array( | ||||
|                       'modules' => array('bcmath', 'php_bcmath'), | ||||
|     $result[] = array('modules' => array('bcmath', 'php_bcmath'), | ||||
|                       'extension' => 'bcmath', | ||||
|                       'class' => 'Auth_OpenID_BcMathWrapper'); | ||||
|  | ||||
| @@ -366,27 +365,9 @@ function Auth_OpenID_detectMathLibrary($exts) | ||||
| { | ||||
|     $loaded = false; | ||||
|  | ||||
| 	$hasDl = function_exists('dl'); | ||||
|     foreach ($exts as $extension) { | ||||
|         // See if the extension specified is already loaded. | ||||
|         if ($extension['extension'] && | ||||
|             extension_loaded($extension['extension'])) { | ||||
|             $loaded = true; | ||||
|         } | ||||
|  | ||||
|         // Try to load dynamic modules. | ||||
|         if (!$loaded) { | ||||
|             foreach ($extension['modules'] as $module) { | ||||
|                 if (@dl($module . "." . PHP_SHLIB_SUFFIX)) { | ||||
|                     $loaded = true; | ||||
|                     break; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         // If the load succeeded, supply an instance of | ||||
|         // Auth_OpenID_MathWrapper which wraps the specified | ||||
|         // module's functionality. | ||||
|         if ($loaded) { | ||||
|         if (extension_loaded($extension['extension'])) { | ||||
|             return $extension; | ||||
|         } | ||||
|     } | ||||
| @@ -405,7 +386,7 @@ function Auth_OpenID_detectMathLibrary($exts) | ||||
|  * instance of a wrapper for that extension module.  If no extension | ||||
|  * module is found, an instance of {@link Auth_OpenID_MathWrapper} is | ||||
|  * returned, which wraps the native PHP integer implementation.  The | ||||
|  * proper calling convention for this method is $lib =& | ||||
|  * proper calling convention for this method is $lib = | ||||
|  * Auth_OpenID_getMathLib(). | ||||
|  * | ||||
|  * This function checks for the existence of specific long number | ||||
| @@ -416,7 +397,7 @@ function Auth_OpenID_detectMathLibrary($exts) | ||||
|  * | ||||
|  * @package OpenID | ||||
|  */ | ||||
| function &Auth_OpenID_getMathLib() | ||||
| function Auth_OpenID_getMathLib() | ||||
| { | ||||
|     // The instance of Auth_OpenID_MathWrapper that we choose to | ||||
|     // supply will be stored here, so that subseqent calls to this | ||||
| @@ -468,4 +449,4 @@ function Auth_OpenID_noMathSupport() | ||||
|     return defined('Auth_OpenID_NO_MATH_SUPPORT'); | ||||
| } | ||||
|  | ||||
| ?> | ||||
|  | ||||
|   | ||||
| @@ -258,19 +258,19 @@ class Auth_OpenID_Consumer { | ||||
|      * when creating the internal consumer object.  This is used for | ||||
|      * testing. | ||||
|      */ | ||||
|     function Auth_OpenID_Consumer(&$store, $session = null, | ||||
|     function Auth_OpenID_Consumer($store, $session = null, | ||||
|                                   $consumer_cls = null) | ||||
|     { | ||||
|         if ($session === null) { | ||||
|             $session = new Auth_Yadis_PHPSession(); | ||||
|         } | ||||
|  | ||||
|         $this->session =& $session; | ||||
|         $this->session = $session; | ||||
|  | ||||
|         if ($consumer_cls !== null) { | ||||
|             $this->consumer =& new $consumer_cls($store); | ||||
|             $this->consumer = new $consumer_cls($store); | ||||
|         } else { | ||||
|             $this->consumer =& new Auth_OpenID_GenericConsumer($store); | ||||
|             $this->consumer = new Auth_OpenID_GenericConsumer($store); | ||||
|         } | ||||
|  | ||||
|         $this->_token_key = $this->session_key_prefix . $this->_token_suffix; | ||||
| @@ -281,7 +281,7 @@ class Auth_OpenID_Consumer { | ||||
|      * | ||||
|      * @access private | ||||
|      */ | ||||
|     function getDiscoveryObject(&$session, $openid_url, | ||||
|     function getDiscoveryObject($session, $openid_url, | ||||
|                                 $session_key_prefix) | ||||
|     { | ||||
|         return new Auth_Yadis_Discovery($session, $openid_url, | ||||
| @@ -339,7 +339,7 @@ class Auth_OpenID_Consumer { | ||||
|                                            $this->consumer->fetcher); | ||||
|  | ||||
|         // Reset the 'stale' attribute of the manager. | ||||
|         $m =& $disco->getManager(); | ||||
|         $m = $disco->getManager(); | ||||
|         if ($m) { | ||||
|             $m->stale = false; | ||||
|             $disco->session->set($disco->session_key, | ||||
| @@ -370,7 +370,7 @@ class Auth_OpenID_Consumer { | ||||
|      * @return Auth_OpenID_AuthRequest $auth_request An OpenID | ||||
|      * authentication request object. | ||||
|      */ | ||||
|     function &beginWithoutDiscovery($endpoint, $anonymous=false) | ||||
|     function beginWithoutDiscovery($endpoint, $anonymous=false) | ||||
|     { | ||||
|         $loader = new Auth_OpenID_ServiceEndpointLoader(); | ||||
|         $auth_req = $this->consumer->begin($endpoint); | ||||
| @@ -467,7 +467,7 @@ class Auth_OpenID_DiffieHellmanSHA1ConsumerSession { | ||||
|  | ||||
|     function getRequest() | ||||
|     { | ||||
|         $math =& Auth_OpenID_getMathLib(); | ||||
|         $math = Auth_OpenID_getMathLib(); | ||||
|  | ||||
|         $cpub = $math->longToBase64($this->dh->public); | ||||
|  | ||||
| @@ -496,7 +496,7 @@ class Auth_OpenID_DiffieHellmanSHA1ConsumerSession { | ||||
|             return null; | ||||
|         } | ||||
|  | ||||
|         $math =& Auth_OpenID_getMathLib(); | ||||
|         $math = Auth_OpenID_getMathLib(); | ||||
|  | ||||
|         $spub = $math->base64ToLong($response->getArg(Auth_OpenID_OPENID_NS, | ||||
|                                                       'dh_server_public')); | ||||
| @@ -611,11 +611,11 @@ class Auth_OpenID_GenericConsumer { | ||||
|      * in the module description.  The default value is False, which | ||||
|      * disables immediate mode. | ||||
|      */ | ||||
|     function Auth_OpenID_GenericConsumer(&$store) | ||||
|     function Auth_OpenID_GenericConsumer($store) | ||||
|     { | ||||
|         $this->store =& $store; | ||||
|         $this->negotiator =& Auth_OpenID_getDefaultNegotiator(); | ||||
|         $this->_use_assocs = ($this->store ? true : false); | ||||
|         $this->store = $store; | ||||
|         $this->negotiator = Auth_OpenID_getDefaultNegotiator(); | ||||
|         $this->_use_assocs = (is_null($this->store) ? false : true); | ||||
|  | ||||
|         $this->fetcher = Auth_Yadis_Yadis::getHTTPFetcher(); | ||||
|  | ||||
| @@ -665,14 +665,14 @@ class Auth_OpenID_GenericConsumer { | ||||
|         $method = Auth_OpenID::arrayGet($mode_methods, $mode, | ||||
|                                         '_completeInvalid'); | ||||
|  | ||||
|         return call_user_func_array(array(&$this, $method), | ||||
|                                     array($message, $endpoint, $return_to)); | ||||
|         return call_user_func_array(array($this, $method), | ||||
|                                     array($message, &$endpoint, $return_to)); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @access private | ||||
|      */ | ||||
|     function _completeInvalid($message, &$endpoint, $unused) | ||||
|     function _completeInvalid($message, $endpoint, $unused) | ||||
|     { | ||||
|         $mode = $message->getArg(Auth_OpenID_OPENID_NS, 'mode', | ||||
|                                  '<No mode set>'); | ||||
| @@ -684,7 +684,7 @@ class Auth_OpenID_GenericConsumer { | ||||
|     /** | ||||
|      * @access private | ||||
|      */ | ||||
|     function _complete_cancel($message, &$endpoint, $unused) | ||||
|     function _complete_cancel($message, $endpoint, $unused) | ||||
|     { | ||||
|         return new Auth_OpenID_CancelResponse($endpoint); | ||||
|     } | ||||
| @@ -692,7 +692,7 @@ class Auth_OpenID_GenericConsumer { | ||||
|     /** | ||||
|      * @access private | ||||
|      */ | ||||
|     function _complete_error($message, &$endpoint, $unused) | ||||
|     function _complete_error($message, $endpoint, $unused) | ||||
|     { | ||||
|         $error = $message->getArg(Auth_OpenID_OPENID_NS, 'error'); | ||||
|         $contact = $message->getArg(Auth_OpenID_OPENID_NS, 'contact'); | ||||
| @@ -705,7 +705,7 @@ class Auth_OpenID_GenericConsumer { | ||||
|     /** | ||||
|      * @access private | ||||
|      */ | ||||
|     function _complete_setup_needed($message, &$endpoint, $unused) | ||||
|     function _complete_setup_needed($message, $endpoint, $unused) | ||||
|     { | ||||
|         if (!$message->isOpenID2()) { | ||||
|             return $this->_completeInvalid($message, $endpoint); | ||||
| @@ -719,7 +719,7 @@ class Auth_OpenID_GenericConsumer { | ||||
|     /** | ||||
|      * @access private | ||||
|      */ | ||||
|     function _complete_id_res($message, &$endpoint, $return_to) | ||||
|     function _complete_id_res($message, $endpoint, $return_to) | ||||
|     { | ||||
|         $user_setup_url = $message->getArg(Auth_OpenID_OPENID1_NS, | ||||
|                                            'user_setup_url'); | ||||
| @@ -1181,7 +1181,7 @@ class Auth_OpenID_GenericConsumer { | ||||
|         // oidutil.log('Performing discovery on %s' % (claimed_id,)) | ||||
|         list($unused, $services) = call_user_func($this->discoverMethod, | ||||
|                                                   $claimed_id, | ||||
|                                                   $this->fetcher); | ||||
| 												  &$this->fetcher); | ||||
|  | ||||
|         if (!$services) { | ||||
|             return new Auth_OpenID_FailureResponse(null, | ||||
| @@ -1197,7 +1197,7 @@ class Auth_OpenID_GenericConsumer { | ||||
|      * @access private | ||||
|      */ | ||||
|     function _verifyDiscoveryServices($claimed_id,  | ||||
|                                       &$services, &$to_match_endpoints) | ||||
|                                       $services, $to_match_endpoints) | ||||
|     { | ||||
|         // Search the services resulting from discovery to find one | ||||
|         // that matches the information from the assertion | ||||
| @@ -1216,8 +1216,8 @@ class Auth_OpenID_GenericConsumer { | ||||
|         } | ||||
|  | ||||
|         return new Auth_OpenID_FailureResponse(null, | ||||
|           sprintf('No matching endpoint found after discovering %s', | ||||
|                   $claimed_id)); | ||||
|           sprintf('No matching endpoint found after discovering %s: %s', | ||||
|                   $claimed_id, $result->message)); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -1397,7 +1397,7 @@ class Auth_OpenID_GenericConsumer { | ||||
|      * | ||||
|      * @access private | ||||
|      */ | ||||
|     function _httpResponseToMessage($response, $server_url) | ||||
|     static function _httpResponseToMessage($response, $server_url) | ||||
|     { | ||||
|         // Should this function be named Message.fromHTTPResponse instead? | ||||
|         $response_message = Auth_OpenID_Message::fromKVForm($response->body); | ||||
| @@ -1461,7 +1461,7 @@ class Auth_OpenID_GenericConsumer { | ||||
|      * | ||||
|      * @access private | ||||
|      */ | ||||
|     function _extractSupportedAssociationType(&$server_error, &$endpoint, | ||||
|     function _extractSupportedAssociationType($server_error, $endpoint, | ||||
|                                               $assoc_type) | ||||
|     { | ||||
|         // Any error message whose code is not 'unsupported-type' | ||||
| @@ -1566,7 +1566,7 @@ class Auth_OpenID_GenericConsumer { | ||||
|     /** | ||||
|      * @access private | ||||
|      */ | ||||
|     function _extractAssociation(&$assoc_response, &$assoc_session) | ||||
|     function _extractAssociation($assoc_response, $assoc_session) | ||||
|     { | ||||
|         // Extract the common fields from the response, raising an | ||||
|         // exception if they are not found | ||||
| @@ -1748,10 +1748,10 @@ class Auth_OpenID_AuthRequest { | ||||
|      * class.  Instances of this class are created by the library when | ||||
|      * needed. | ||||
|      */ | ||||
|     function Auth_OpenID_AuthRequest(&$endpoint, $assoc) | ||||
|     function Auth_OpenID_AuthRequest($endpoint, $assoc) | ||||
|     { | ||||
|         $this->assoc = $assoc; | ||||
|         $this->endpoint =& $endpoint; | ||||
|         $this->endpoint = $endpoint; | ||||
|         $this->return_to_args = array(); | ||||
|         $this->message = new Auth_OpenID_Message( | ||||
|             $endpoint->preferredNamespace()); | ||||
| @@ -1764,7 +1764,7 @@ class Auth_OpenID_AuthRequest { | ||||
|      * $extension_request: An object that implements the extension | ||||
|      * request interface for adding arguments to an OpenID message. | ||||
|      */ | ||||
|     function addExtension(&$extension_request) | ||||
|     function addExtension($extension_request) | ||||
|     { | ||||
|         $extension_request->toMessage($this->message); | ||||
|     } | ||||
| @@ -2089,7 +2089,7 @@ class Auth_OpenID_SuccessResponse extends Auth_OpenID_ConsumerResponse { | ||||
|  | ||||
|         foreach ($msg_args as $key => $value) { | ||||
|             if (!$this->isSigned($ns_uri, $key)) { | ||||
|                 return null; | ||||
|                 unset($msg_args[$key]); | ||||
|             } | ||||
|         } | ||||
|  | ||||
| @@ -2167,7 +2167,7 @@ class Auth_OpenID_ServerErrorContainer { | ||||
|     /** | ||||
|      * @access private | ||||
|      */ | ||||
|     function fromMessage($message) | ||||
|     static function fromMessage($message) | ||||
|     { | ||||
|         $error_text = $message->getArg( | ||||
|            Auth_OpenID_OPENID_NS, 'error', '<no error message supplied>'); | ||||
| @@ -2227,4 +2227,4 @@ class Auth_OpenID_SetupNeededResponse extends Auth_OpenID_ConsumerResponse { | ||||
|     } | ||||
| } | ||||
|  | ||||
| ?> | ||||
|  | ||||
|   | ||||
| @@ -37,7 +37,7 @@ class Auth_OpenID_CryptUtil { | ||||
|      * @param int $num_bytes The length of the return value | ||||
|      * @return string $bytes random bytes | ||||
|      */ | ||||
|     function getBytes($num_bytes) | ||||
|     static function getBytes($num_bytes) | ||||
|     { | ||||
|         static $f = null; | ||||
|         $bytes = ''; | ||||
| @@ -77,7 +77,7 @@ class Auth_OpenID_CryptUtil { | ||||
|      * @return string $result A string of randomly-chosen characters | ||||
|      * from $chrs | ||||
|      */ | ||||
|     function randomString($length, $population = null) | ||||
|     static function randomString($length, $population = null) | ||||
|     { | ||||
|         if ($population === null) { | ||||
|             return Auth_OpenID_CryptUtil::getBytes($length); | ||||
| @@ -106,4 +106,3 @@ class Auth_OpenID_CryptUtil { | ||||
|     } | ||||
| } | ||||
|  | ||||
| ?> | ||||
| @@ -128,4 +128,3 @@ class Auth_OpenID_DatabaseConnection { | ||||
|     } | ||||
| } | ||||
|  | ||||
| ?> | ||||
| @@ -51,9 +51,9 @@ class Auth_OpenID_DiffieHellman { | ||||
|                                        $private = null, $lib = null) | ||||
|     { | ||||
|         if ($lib === null) { | ||||
|             $this->lib =& Auth_OpenID_getMathLib(); | ||||
|             $this->lib = Auth_OpenID_getMathLib(); | ||||
|         } else { | ||||
|             $this->lib =& $lib; | ||||
|             $this->lib = $lib; | ||||
|         } | ||||
|  | ||||
|         if ($mod === null) { | ||||
| @@ -110,4 +110,4 @@ class Auth_OpenID_DiffieHellman { | ||||
|     } | ||||
| } | ||||
|  | ||||
| ?> | ||||
|  | ||||
|   | ||||
| @@ -28,8 +28,34 @@ function Auth_OpenID_getOpenIDTypeURIs() | ||||
|                  Auth_OpenID_TYPE_2_0, | ||||
|                  Auth_OpenID_TYPE_1_2, | ||||
|                  Auth_OpenID_TYPE_1_1, | ||||
|                  Auth_OpenID_TYPE_1_0, | ||||
|                  Auth_OpenID_RP_RETURN_TO_URL_TYPE); | ||||
|                  Auth_OpenID_TYPE_1_0); | ||||
| } | ||||
|  | ||||
| function Auth_OpenID_getOpenIDConsumerTypeURIs() | ||||
| { | ||||
|     return array(Auth_OpenID_RP_RETURN_TO_URL_TYPE); | ||||
| } | ||||
|  | ||||
|  | ||||
| /* | ||||
|  * Provides a user-readable interpretation of a type uri. | ||||
|  * Useful for error messages. | ||||
|  */ | ||||
| function Auth_OpenID_getOpenIDTypeName($type_uri) { | ||||
|     switch ($type_uri) { | ||||
|     case Auth_OpenID_TYPE_2_0_IDP: | ||||
|       return 'OpenID 2.0 IDP'; | ||||
|     case Auth_OpenID_TYPE_2_0: | ||||
|       return 'OpenID 2.0'; | ||||
|     case Auth_OpenID_TYPE_1_2: | ||||
|       return 'OpenID 1.2'; | ||||
|     case Auth_OpenID_TYPE_1_1: | ||||
|       return 'OpenID 1.1'; | ||||
|     case Auth_OpenID_TYPE_1_0: | ||||
|       return 'OpenID 1.0'; | ||||
|     case Auth_OpenID_RP_RETURN_TO_URL_TYPE: | ||||
|       return 'OpenID relying party'; | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
| @@ -124,7 +150,7 @@ class Auth_OpenID_ServiceEndpoint { | ||||
|         return in_array(Auth_OpenID_TYPE_2_0_IDP, $this->type_uris); | ||||
|     } | ||||
|  | ||||
|     function fromOPEndpointURL($op_endpoint_url) | ||||
|     static function fromOPEndpointURL($op_endpoint_url) | ||||
|     { | ||||
|         // Construct an OP-Identifier OpenIDServiceEndpoint object for | ||||
|         // a given OP Endpoint URL | ||||
| @@ -171,15 +197,34 @@ class Auth_OpenID_ServiceEndpoint { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /* | ||||
|      * Parse the given document as XRDS looking for OpenID consumer services. | ||||
|      * | ||||
|      * @return array of Auth_OpenID_ServiceEndpoint or null if the | ||||
|      * document cannot be parsed. | ||||
|      */ | ||||
|     function consumerFromXRDS($uri, $xrds_text) | ||||
|     { | ||||
|         $xrds =& Auth_Yadis_XRDS::parseXRDS($xrds_text); | ||||
|  | ||||
|         if ($xrds) { | ||||
|             $yadis_services = | ||||
|               $xrds->services(array('filter_MatchesAnyOpenIDConsumerType')); | ||||
|             return Auth_OpenID_makeOpenIDEndpoints($uri, $yadis_services); | ||||
|         } | ||||
|  | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     /* | ||||
|      * Parse the given document as XRDS looking for OpenID services. | ||||
|      * | ||||
|      * @return array of Auth_OpenID_ServiceEndpoint or null if the | ||||
|      * document cannot be parsed. | ||||
|      */ | ||||
|     function fromXRDS($uri, $xrds_text) | ||||
|     static function fromXRDS($uri, $xrds_text) | ||||
|     { | ||||
|         $xrds =& Auth_Yadis_XRDS::parseXRDS($xrds_text); | ||||
|         $xrds = Auth_Yadis_XRDS::parseXRDS($xrds_text); | ||||
|  | ||||
|         if ($xrds) { | ||||
|             $yadis_services = | ||||
| @@ -197,7 +242,7 @@ class Auth_OpenID_ServiceEndpoint { | ||||
|      * @return array of Auth_OpenID_ServiceEndpoint or null if | ||||
|      * endpoints cannot be created. | ||||
|      */ | ||||
|     function fromDiscoveryResult($discoveryResult) | ||||
|     static function fromDiscoveryResult($discoveryResult) | ||||
|     { | ||||
|         if ($discoveryResult->isXRDS()) { | ||||
|             return Auth_OpenID_ServiceEndpoint::fromXRDS( | ||||
| @@ -210,7 +255,7 @@ class Auth_OpenID_ServiceEndpoint { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     function fromHTML($uri, $html) | ||||
|     static function fromHTML($uri, $html) | ||||
|     { | ||||
|         $discovery_types = array( | ||||
|                                  array(Auth_OpenID_TYPE_2_0, | ||||
| @@ -273,7 +318,7 @@ function Auth_OpenID_findOPLocalIdentifier($service, $type_uris) | ||||
|     $service->parser->registerNamespace('xrd', | ||||
|                                         Auth_Yadis_XMLNS_XRD_2_0); | ||||
|  | ||||
|     $parser =& $service->parser; | ||||
|     $parser = $service->parser; | ||||
|  | ||||
|     $permitted_tags = array(); | ||||
|  | ||||
| @@ -305,7 +350,7 @@ function Auth_OpenID_findOPLocalIdentifier($service, $type_uris) | ||||
|     return $local_id; | ||||
| } | ||||
|  | ||||
| function filter_MatchesAnyOpenIDType(&$service) | ||||
| function filter_MatchesAnyOpenIDType($service) | ||||
| { | ||||
|     $uris = $service->getTypes(); | ||||
|  | ||||
| @@ -318,6 +363,19 @@ function filter_MatchesAnyOpenIDType(&$service) | ||||
|     return false; | ||||
| } | ||||
|  | ||||
| function filter_MatchesAnyOpenIDConsumerType(&$service) | ||||
| { | ||||
|     $uris = $service->getTypes(); | ||||
|  | ||||
|     foreach ($uris as $uri) { | ||||
|         if (in_array($uri, Auth_OpenID_getOpenIDConsumerTypeURIs())) { | ||||
|             return true; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     return false; | ||||
| } | ||||
|  | ||||
| function Auth_OpenID_bestMatchingService($service, $preferred_types) | ||||
| { | ||||
|     // Return the index of the first matching type, or something | ||||
| @@ -415,7 +473,7 @@ function Auth_OpenID_makeOpenIDEndpoints($uri, $yadis_services) | ||||
|     return $s; | ||||
| } | ||||
|  | ||||
| function Auth_OpenID_discoverWithYadis($uri, &$fetcher, | ||||
| function Auth_OpenID_discoverWithYadis($uri, $fetcher, | ||||
|               $endpoint_filter='Auth_OpenID_getOPOrUserServices', | ||||
|               $discover_function=null) | ||||
| { | ||||
| @@ -433,12 +491,12 @@ function Auth_OpenID_discoverWithYadis($uri, &$fetcher, | ||||
|     $openid_services = array(); | ||||
|  | ||||
|     $response = call_user_func_array($discover_function, | ||||
|                                      array($uri, &$fetcher)); | ||||
|                                      array($uri, $fetcher)); | ||||
|  | ||||
|     $yadis_url = $response->normalized_uri; | ||||
|     $yadis_services = array(); | ||||
|  | ||||
|     if ($response->isFailure()) { | ||||
|     if ($response->isFailure() && !$response->isXRDS()) { | ||||
|         return array($uri, array()); | ||||
|     } | ||||
|  | ||||
| @@ -460,18 +518,18 @@ function Auth_OpenID_discoverWithYadis($uri, &$fetcher, | ||||
|     } | ||||
|  | ||||
|     $openid_services = call_user_func_array($endpoint_filter, | ||||
|                                             array(&$openid_services)); | ||||
|                                             array($openid_services)); | ||||
|  | ||||
|     return array($yadis_url, $openid_services); | ||||
| } | ||||
|  | ||||
| function Auth_OpenID_discoverURI($uri, &$fetcher) | ||||
| function Auth_OpenID_discoverURI($uri, $fetcher) | ||||
| { | ||||
|     $uri = Auth_OpenID::normalizeUrl($uri); | ||||
|     return Auth_OpenID_discoverWithYadis($uri, $fetcher); | ||||
| } | ||||
|  | ||||
| function Auth_OpenID_discoverWithoutYadis($uri, &$fetcher) | ||||
| function Auth_OpenID_discoverWithoutYadis($uri, $fetcher) | ||||
| { | ||||
|     $http_resp = @$fetcher->get($uri); | ||||
|  | ||||
| @@ -490,7 +548,7 @@ function Auth_OpenID_discoverWithoutYadis($uri, &$fetcher) | ||||
|     return array($identity_url, $openid_services); | ||||
| } | ||||
|  | ||||
| function Auth_OpenID_discoverXRI($iname, &$fetcher) | ||||
| function Auth_OpenID_discoverXRI($iname, $fetcher) | ||||
| { | ||||
|     $resolver = new Auth_Yadis_ProxyResolver($fetcher); | ||||
|     list($canonicalID, $yadis_services) = | ||||
| @@ -513,7 +571,7 @@ function Auth_OpenID_discoverXRI($iname, &$fetcher) | ||||
|     return array($iname, $openid_services); | ||||
| } | ||||
|  | ||||
| function Auth_OpenID_discover($uri, &$fetcher) | ||||
| function Auth_OpenID_discover($uri, $fetcher) | ||||
| { | ||||
|     // If the fetcher (i.e., PHP) doesn't support SSL, we can't do | ||||
|     // discovery on an HTTPS URL. | ||||
| @@ -545,4 +603,4 @@ function Auth_OpenID_discover($uri, &$fetcher) | ||||
|     return $result; | ||||
| } | ||||
|  | ||||
| ?> | ||||
|  | ||||
|   | ||||
| @@ -97,4 +97,3 @@ class Auth_OpenID_DumbStore extends Auth_OpenID_OpenIDStore { | ||||
|     } | ||||
| } | ||||
|  | ||||
| ?> | ||||
| @@ -39,7 +39,7 @@ class Auth_OpenID_Extension { | ||||
|      * | ||||
|      * Returns the message with the extension arguments added. | ||||
|      */ | ||||
|     function toMessage(&$message) | ||||
|     function toMessage($message) | ||||
|     { | ||||
|         $implicit = $message->isOpenID1(); | ||||
|         $added = $message->namespaces->addAlias($this->ns_uri, | ||||
| @@ -59,4 +59,3 @@ class Auth_OpenID_Extension { | ||||
|     } | ||||
| } | ||||
|  | ||||
| ?> | ||||
| @@ -367,7 +367,7 @@ class Auth_OpenID_FileStore extends Auth_OpenID_OpenIDStore { | ||||
|         } | ||||
|  | ||||
|         if ( abs($timestamp - time()) > $Auth_OpenID_SKEW ) { | ||||
|             return False; | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         if ($server_url) { | ||||
| @@ -519,7 +519,7 @@ class Auth_OpenID_FileStore extends Auth_OpenID_OpenIDStore { | ||||
|     /** | ||||
|      * @access private | ||||
|      */ | ||||
|     function _mkdtemp($dir) | ||||
|     static function _mkdtemp($dir) | ||||
|     { | ||||
|         foreach (range(0, 4) as $i) { | ||||
|             $name = $dir . strval(DIRECTORY_SEPARATOR) . strval(getmypid()) . | ||||
| @@ -615,4 +615,4 @@ class Auth_OpenID_FileStore extends Auth_OpenID_OpenIDStore { | ||||
|     } | ||||
| } | ||||
|  | ||||
| ?> | ||||
|  | ||||
|   | ||||
| @@ -96,4 +96,3 @@ if (function_exists('hash_hmac') && | ||||
|     define('Auth_OpenID_HMACSHA256_SUPPORTED', false); | ||||
| } | ||||
|  | ||||
| ?> | ||||
| @@ -194,4 +194,3 @@ class Auth_OpenID_OpenIDStore { | ||||
|     } | ||||
|  | ||||
| } | ||||
| ?> | ||||
| @@ -26,7 +26,7 @@ class Auth_OpenID_KVForm { | ||||
|      * @static | ||||
|      * @access private | ||||
|      */ | ||||
|     function toArray($kvs, $strict=false) | ||||
|     static function toArray($kvs, $strict=false) | ||||
|     { | ||||
|         $lines = explode("\n", $kvs); | ||||
|  | ||||
| @@ -78,7 +78,7 @@ class Auth_OpenID_KVForm { | ||||
|      * @static | ||||
|      * @access private | ||||
|      */ | ||||
|     function fromArray($values) | ||||
|     static function fromArray($values) | ||||
|     { | ||||
|         if ($values === null) { | ||||
|             return null; | ||||
| @@ -109,4 +109,3 @@ class Auth_OpenID_KVForm { | ||||
|     } | ||||
| } | ||||
|  | ||||
| ?> | ||||
| @@ -205,4 +205,3 @@ class Auth_OpenID_MemcachedStore extends Auth_OpenID_OpenIDStore { | ||||
|     } | ||||
| } | ||||
|  | ||||
| ?> | ||||
| @@ -143,7 +143,7 @@ class Auth_OpenID_Mapping { | ||||
|      * Returns true if $thing is an Auth_OpenID_Mapping object; false | ||||
|      * if not. | ||||
|      */ | ||||
|     function isA($thing) | ||||
|     static function isA($thing) | ||||
|     { | ||||
|         return (is_object($thing) && | ||||
|                 strtolower(get_class($thing)) == 'auth_openid_mapping'); | ||||
| @@ -442,7 +442,7 @@ class Auth_OpenID_Message { | ||||
|         return $this->getOpenIDNamespace() == Auth_OpenID_OPENID2_NS; | ||||
|     } | ||||
|  | ||||
|     function fromPostArgs($args) | ||||
|     static function fromPostArgs($args) | ||||
|     { | ||||
|         // Construct a Message containing a set of POST arguments | ||||
|         $obj = new Auth_OpenID_Message(); | ||||
| @@ -477,7 +477,7 @@ class Auth_OpenID_Message { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     function fromOpenIDArgs($openid_args) | ||||
|     static function fromOpenIDArgs($openid_args) | ||||
|     { | ||||
|         // Takes an array. | ||||
|  | ||||
| @@ -594,7 +594,7 @@ class Auth_OpenID_Message { | ||||
|         return $this->_openid_ns_uri; | ||||
|     } | ||||
|  | ||||
|     function fromKVForm($kvform_string) | ||||
|     static function fromKVForm($kvform_string) | ||||
|     { | ||||
|         // Create a Message from a KVForm string | ||||
|         return Auth_OpenID_Message::fromOpenIDArgs( | ||||
| @@ -917,4 +917,4 @@ class Auth_OpenID_Message { | ||||
|     } | ||||
| } | ||||
|  | ||||
| ?> | ||||
|  | ||||
|   | ||||
| @@ -75,4 +75,3 @@ class Auth_OpenID_MySQLStore extends Auth_OpenID_SQLStore { | ||||
|     } | ||||
| } | ||||
|  | ||||
| ?> | ||||
| @@ -106,4 +106,3 @@ function Auth_OpenID_mkNonce($when = null) | ||||
|     return $time_str . $salt; | ||||
| } | ||||
|  | ||||
| ?> | ||||
| @@ -21,7 +21,7 @@ define('PAPE_AUTH_PHISHING_RESISTANT', | ||||
|        'http://schemas.openid.net/pape/policies/2007/06/phishing-resistant'); | ||||
|  | ||||
| define('PAPE_TIME_VALIDATOR', | ||||
|        '^[0-9]{4,4}-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9]Z$'); | ||||
|       '/^[0-9]{4,4}-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9]Z$/'); | ||||
| /** | ||||
|  * A Provider Authentication Policy request, sent from a relying party | ||||
|  * to a provider | ||||
| @@ -82,7 +82,7 @@ class Auth_OpenID_PAPE_Request extends Auth_OpenID_Extension { | ||||
|      * Instantiate a Request object from the arguments in a checkid_* | ||||
|      * OpenID message | ||||
|      */ | ||||
|     function fromOpenIDRequest($request) | ||||
|     static function fromOpenIDRequest($request) | ||||
|     { | ||||
|         $obj = new Auth_OpenID_PAPE_Request(); | ||||
|         $args = $request->message->getArgs(Auth_OpenID_PAPE_NS_URI); | ||||
| @@ -201,7 +201,7 @@ class Auth_OpenID_PAPE_Response extends Auth_OpenID_Extension { | ||||
|      * @returns: A provider authentication policy response from the | ||||
|      * data that was supplied with the id_res response. | ||||
|      */ | ||||
|     function fromSuccessResponse($success_response) | ||||
|     static function fromSuccessResponse($success_response) | ||||
|     { | ||||
|         $obj = new Auth_OpenID_PAPE_Response(); | ||||
|  | ||||
| @@ -262,7 +262,7 @@ class Auth_OpenID_PAPE_Response extends Auth_OpenID_Extension { | ||||
|  | ||||
|         $auth_time = Auth_OpenID::arrayGet($args, 'auth_time'); | ||||
|         if ($auth_time !== null) { | ||||
|             if (ereg(PAPE_TIME_VALIDATOR, $auth_time)) { | ||||
|             if (preg_match(PAPE_TIME_VALIDATOR, $auth_time)) { | ||||
|                 $this->auth_time = $auth_time; | ||||
|             } else if ($strict) { | ||||
|                 return false; | ||||
| @@ -287,7 +287,7 @@ class Auth_OpenID_PAPE_Response extends Auth_OpenID_Extension { | ||||
|         } | ||||
|  | ||||
|         if ($this->auth_time !== null) { | ||||
|             if (!ereg(PAPE_TIME_VALIDATOR, $this->auth_time)) { | ||||
|             if (!preg_match(PAPE_TIME_VALIDATOR, $this->auth_time)) { | ||||
|                 return false; | ||||
|             } | ||||
|  | ||||
| @@ -298,4 +298,3 @@ class Auth_OpenID_PAPE_Response extends Auth_OpenID_Extension { | ||||
|     } | ||||
| } | ||||
|  | ||||
| ?> | ||||
| @@ -101,7 +101,7 @@ class Auth_OpenID_Parse { | ||||
|      * Starts with the tag name at a word boundary, where the tag name | ||||
|      * is not a namespace | ||||
|      */ | ||||
|     var $_tag_expr = "<%s\b(?!:)([^>]*?)(?:\/>|>(.*?)(?:<\/?%s\s*>|\Z))"; | ||||
|     var $_tag_expr = "<%s\b(?!:)([^>]*?)(?:\/>|>(.*)(?:<\/?%s\s*>|\Z))"; | ||||
|  | ||||
|     var $_attr_find = '\b(\w+)=("[^"]*"|\'[^\']*\'|[^\'"\s\/<>]+)'; | ||||
|  | ||||
| @@ -215,11 +215,31 @@ class Auth_OpenID_Parse { | ||||
|             return $str; | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     function match($regexp, $text, &$match) | ||||
|     { | ||||
|         if (!is_callable('mb_ereg_search_init')) { | ||||
|             return preg_match($regexp, $text, $match); | ||||
|         } | ||||
|  | ||||
|         $regexp = substr($regexp, 1, strlen($regexp) - 2 - strlen($this->_re_flags)); | ||||
|         mb_ereg_search_init($text); | ||||
|         if (!mb_ereg_search($regexp)) { | ||||
|             return false; | ||||
|         } | ||||
|         list($match) = mb_ereg_search_getregs(); | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Find all link tags in a string representing a HTML document and | ||||
|      * return a list of their attributes. | ||||
|      * | ||||
|      * @todo This is quite ineffective and may fail with the default | ||||
|      *       pcre.backtrack_limit of 100000 in PHP 5.2, if $html is big. | ||||
|      *       It should rather use stripos (in PHP5) or strpos()+strtoupper() | ||||
|      *       in PHP4 to manage this. | ||||
|      * | ||||
|      * @param string $html The text to parse | ||||
|      * @return array $list An array of arrays of attributes, one for each | ||||
|      * link tag | ||||
| @@ -244,18 +264,23 @@ class Auth_OpenID_Parse { | ||||
|         $stripped = substr($stripped, $html_begin, | ||||
|                            $html_end - $html_begin); | ||||
|  | ||||
|         // Workaround to prevent PREG_BACKTRACK_LIMIT_ERROR: | ||||
|         $old_btlimit = ini_set( 'pcre.backtrack_limit', -1 ); | ||||
|  | ||||
|         // Try to find the <HEAD> tag. | ||||
|         $head_re = $this->headFind(); | ||||
|         $head_matches = array(); | ||||
|         if (!preg_match($head_re, $stripped, $head_matches)) { | ||||
|             return array(); | ||||
|         $head_match = ''; | ||||
|         if (!$this->match($head_re, $stripped, $head_match)) { | ||||
|                      ini_set( 'pcre.backtrack_limit', $old_btlimit ); | ||||
|                      return array(); | ||||
|         } | ||||
|  | ||||
|         $link_data = array(); | ||||
|         $link_matches = array(); | ||||
|  | ||||
|         if (!preg_match_all($this->_link_find, $head_matches[0], | ||||
|         if (!preg_match_all($this->_link_find, $head_match, | ||||
|                             $link_matches)) { | ||||
|             ini_set( 'pcre.backtrack_limit', $old_btlimit ); | ||||
|             return array(); | ||||
|         } | ||||
|  | ||||
| @@ -273,6 +298,7 @@ class Auth_OpenID_Parse { | ||||
|             $link_data[] = $link_attrs; | ||||
|         } | ||||
|  | ||||
|         ini_set( 'pcre.backtrack_limit', $old_btlimit ); | ||||
|         return $link_data; | ||||
|     } | ||||
|  | ||||
| @@ -349,4 +375,3 @@ function Auth_OpenID_legacy_discover($html_text, $server_rel, | ||||
|     } | ||||
| } | ||||
|  | ||||
| ?> | ||||
| @@ -110,4 +110,3 @@ class Auth_OpenID_PostgreSQLStore extends Auth_OpenID_SQLStore { | ||||
|     } | ||||
| } | ||||
|  | ||||
| ?> | ||||
| @@ -13,16 +13,6 @@ | ||||
|  * @license http://www.apache.org/licenses/LICENSE-2.0 Apache | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|  * Require the PEAR DB module because we'll need it for the SQL-based | ||||
|  * stores implemented here.  We silence any errors from the inclusion | ||||
|  * because it might not be present, and a user of the SQL stores may | ||||
|  * supply an Auth_OpenID_DatabaseConnection instance that implements | ||||
|  * its own storage. | ||||
|  */ | ||||
| global $__Auth_OpenID_PEAR_AVAILABLE; | ||||
| $__Auth_OpenID_PEAR_AVAILABLE = @include_once 'DB.php'; | ||||
|  | ||||
| /** | ||||
|  * @access private | ||||
|  */ | ||||
| @@ -89,8 +79,6 @@ class Auth_OpenID_SQLStore extends Auth_OpenID_OpenIDStore { | ||||
|                                   $associations_table = null, | ||||
|                                   $nonces_table = null) | ||||
|     { | ||||
|         global $__Auth_OpenID_PEAR_AVAILABLE; | ||||
|  | ||||
|         $this->associations_table_name = "oid_associations"; | ||||
|         $this->nonces_table_name = "oid_nonces"; | ||||
|  | ||||
| @@ -113,7 +101,7 @@ class Auth_OpenID_SQLStore extends Auth_OpenID_OpenIDStore { | ||||
|         // constant, so only try to use it if PEAR is present.  Note | ||||
|         // that Auth_Openid_Databaseconnection instances need not | ||||
|         // implement ::setFetchMode for this reason. | ||||
|         if ($__Auth_OpenID_PEAR_AVAILABLE) { | ||||
|         if (is_subclass_of($this->connection, 'db_common')) { | ||||
|             $this->connection->setFetchMode(DB_FETCHMODE_ASSOC); | ||||
|         } | ||||
|  | ||||
| @@ -482,7 +470,7 @@ class Auth_OpenID_SQLStore extends Auth_OpenID_OpenIDStore { | ||||
|         global $Auth_OpenID_SKEW; | ||||
|  | ||||
|         if ( abs($timestamp - time()) > $Auth_OpenID_SKEW ) { | ||||
|             return False; | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         return $this->_add_nonce($server_url, $timestamp, $salt); | ||||
| @@ -566,4 +554,4 @@ class Auth_OpenID_SQLStore extends Auth_OpenID_OpenIDStore { | ||||
|     } | ||||
| } | ||||
|  | ||||
| ?> | ||||
|  | ||||
|   | ||||
| @@ -68,4 +68,3 @@ class Auth_OpenID_SQLiteStore extends Auth_OpenID_SQLStore { | ||||
|     } | ||||
| } | ||||
|  | ||||
| ?> | ||||
| @@ -94,7 +94,7 @@ Auth_OpenID_registerNamespaceAlias(Auth_OpenID_SREG_NS_URI_1_1, 'sreg'); | ||||
|  * $endpoint: The endpoint object as returned by OpenID discovery. | ||||
|  * returns whether an sreg type was advertised by the endpoint | ||||
|  */ | ||||
| function Auth_OpenID_supportsSReg(&$endpoint) | ||||
| function Auth_OpenID_supportsSReg($endpoint) | ||||
| { | ||||
|     return ($endpoint->usesExtension(Auth_OpenID_SREG_NS_URI_1_1) || | ||||
|             $endpoint->usesExtension(Auth_OpenID_SREG_NS_URI_1_0)); | ||||
| @@ -122,7 +122,7 @@ class Auth_OpenID_SRegBase extends Auth_OpenID_Extension { | ||||
|      * | ||||
|      * @access private | ||||
|      */ | ||||
|     function _getSRegNS(&$message) | ||||
|     static function _getSRegNS($message) | ||||
|     { | ||||
|         $alias = null; | ||||
|         $found_ns_uri = null; | ||||
| @@ -173,7 +173,7 @@ class Auth_OpenID_SRegRequest extends Auth_OpenID_SRegBase { | ||||
|     /** | ||||
|      * Initialize an empty simple registration request. | ||||
|      */ | ||||
|     function build($required=null, $optional=null, | ||||
|     static function build($required=null, $optional=null, | ||||
|                    $policy_url=null, | ||||
|                    $sreg_ns_uri=Auth_OpenID_SREG_NS_URI, | ||||
|                    $cls='Auth_OpenID_SRegRequest') | ||||
| @@ -213,7 +213,7 @@ class Auth_OpenID_SRegRequest extends Auth_OpenID_SRegBase { | ||||
|      * | ||||
|      * Returns the newly created simple registration request | ||||
|      */ | ||||
|     function fromOpenIDRequest($request, $cls='Auth_OpenID_SRegRequest') | ||||
|     static function fromOpenIDRequest($request, $cls='Auth_OpenID_SRegRequest') | ||||
|     { | ||||
|  | ||||
|         $obj = call_user_func_array(array($cls, 'build'), | ||||
| @@ -442,7 +442,7 @@ class Auth_OpenID_SRegResponse extends Auth_OpenID_SRegBase { | ||||
|      * string (unicode) value. For instance, the nickname should be | ||||
|      * stored under the key 'nickname'. | ||||
|      */ | ||||
|     function extractResponse($request, $data) | ||||
|     static function extractResponse($request, $data) | ||||
|     { | ||||
|         $obj = new Auth_OpenID_SRegResponse(); | ||||
|         $obj->ns_uri = $request->ns_uri; | ||||
| @@ -471,7 +471,7 @@ class Auth_OpenID_SRegResponse extends Auth_OpenID_SRegBase { | ||||
|      * Returns a simple registration response containing the data that | ||||
|      * was supplied with the C{id_res} response. | ||||
|      */ | ||||
|     function fromSuccessResponse(&$success_response, $signed_only=true) | ||||
|     static function fromSuccessResponse($success_response, $signed_only=true) | ||||
|     { | ||||
|         global $Auth_OpenID_sreg_data_fields; | ||||
|  | ||||
| @@ -518,4 +518,4 @@ class Auth_OpenID_SRegResponse extends Auth_OpenID_SRegBase { | ||||
|     } | ||||
| } | ||||
|  | ||||
| ?> | ||||
|  | ||||
|   | ||||
| @@ -43,7 +43,7 @@ | ||||
|  * consumers to add extensions to their requests.  For example, with | ||||
|  * sites using the Simple Registration | ||||
|  * Extension | ||||
|  * (http://www.openidenabled.com/openid/simple-registration-extension/), | ||||
|  * (http://openid.net/specs/openid-simple-registration-extension-1_0.html), | ||||
|  * a user can agree to have their nickname and e-mail address sent to | ||||
|  * a site when they sign up. | ||||
|  * | ||||
| @@ -365,7 +365,7 @@ class Auth_OpenID_CheckAuthRequest extends Auth_OpenID_Request { | ||||
|         $this->message = null; | ||||
|     } | ||||
|  | ||||
|     function fromMessage($message, $server=null) | ||||
|     static function fromMessage($message, $server=null) | ||||
|     { | ||||
|         $required_keys = array('assoc_handle', 'sig', 'signed'); | ||||
|  | ||||
| @@ -396,7 +396,7 @@ class Auth_OpenID_CheckAuthRequest extends Auth_OpenID_Request { | ||||
|         return $result; | ||||
|     } | ||||
|  | ||||
|     function answer(&$signatory) | ||||
|     function answer($signatory) | ||||
|     { | ||||
|         $is_valid = $signatory->verify($this->assoc_handle, $this->signed); | ||||
|  | ||||
| @@ -436,7 +436,7 @@ class Auth_OpenID_PlainTextServerSession { | ||||
|     var $needs_math = false; | ||||
|     var $allowed_assoc_types = array('HMAC-SHA1', 'HMAC-SHA256'); | ||||
|  | ||||
|     function fromMessage($unused_request) | ||||
|     static function fromMessage($unused_request) | ||||
|     { | ||||
|         return new Auth_OpenID_PlainTextServerSession(); | ||||
|     } | ||||
| @@ -469,7 +469,7 @@ class Auth_OpenID_DiffieHellmanSHA1ServerSession { | ||||
|         $this->consumer_pubkey = $consumer_pubkey; | ||||
|     } | ||||
|  | ||||
|     function getDH($message) | ||||
|     static function getDH($message) | ||||
|     { | ||||
|         $dh_modulus = $message->getArg(Auth_OpenID_OPENID_NS, 'dh_modulus'); | ||||
|         $dh_gen = $message->getArg(Auth_OpenID_OPENID_NS, 'dh_gen'); | ||||
| @@ -489,7 +489,7 @@ class Auth_OpenID_DiffieHellmanSHA1ServerSession { | ||||
|                                 $missing); | ||||
|         } | ||||
|  | ||||
|         $lib =& Auth_OpenID_getMathLib(); | ||||
|         $lib = Auth_OpenID_getMathLib(); | ||||
|  | ||||
|         if ($dh_modulus || $dh_gen) { | ||||
|             $dh_modulus = $lib->base64ToLong($dh_modulus); | ||||
| @@ -523,7 +523,7 @@ class Auth_OpenID_DiffieHellmanSHA1ServerSession { | ||||
|         return array($dh, $consumer_pubkey); | ||||
|     } | ||||
|  | ||||
|     function fromMessage($message) | ||||
|     static function fromMessage($message) | ||||
|     { | ||||
|         $result = Auth_OpenID_DiffieHellmanSHA1ServerSession::getDH($message); | ||||
|  | ||||
| @@ -538,7 +538,7 @@ class Auth_OpenID_DiffieHellmanSHA1ServerSession { | ||||
|  | ||||
|     function answer($secret) | ||||
|     { | ||||
|         $lib =& Auth_OpenID_getMathLib(); | ||||
|         $lib = Auth_OpenID_getMathLib(); | ||||
|         $mac_key = $this->dh->xorSecret($this->consumer_pubkey, $secret, | ||||
|                                         $this->hash_func); | ||||
|         return array( | ||||
| @@ -560,7 +560,7 @@ class Auth_OpenID_DiffieHellmanSHA256ServerSession | ||||
|     var $hash_func = 'Auth_OpenID_SHA256'; | ||||
|     var $allowed_assoc_types = array('HMAC-SHA256'); | ||||
|  | ||||
|     function fromMessage($message) | ||||
|     static function fromMessage($message) | ||||
|     { | ||||
|         $result = Auth_OpenID_DiffieHellmanSHA1ServerSession::getDH($message); | ||||
|  | ||||
| @@ -582,7 +582,7 @@ class Auth_OpenID_DiffieHellmanSHA256ServerSession | ||||
| class Auth_OpenID_AssociateRequest extends Auth_OpenID_Request { | ||||
|     var $mode = "associate"; | ||||
|  | ||||
|     function getSessionClasses() | ||||
|     static function getSessionClasses() | ||||
|     { | ||||
|         return array( | ||||
|           'no-encryption' => 'Auth_OpenID_PlainTextServerSession', | ||||
| @@ -590,14 +590,14 @@ class Auth_OpenID_AssociateRequest extends Auth_OpenID_Request { | ||||
|           'DH-SHA256' => 'Auth_OpenID_DiffieHellmanSHA256ServerSession'); | ||||
|     } | ||||
|  | ||||
|     function Auth_OpenID_AssociateRequest(&$session, $assoc_type) | ||||
|     function Auth_OpenID_AssociateRequest($session, $assoc_type) | ||||
|     { | ||||
|         $this->session =& $session; | ||||
|         $this->session = $session; | ||||
|         $this->namespace = Auth_OpenID_OPENID2_NS; | ||||
|         $this->assoc_type = $assoc_type; | ||||
|     } | ||||
|  | ||||
|     function fromMessage($message, $server=null) | ||||
|     static function fromMessage($message, $server=null) | ||||
|     { | ||||
|         if ($message->isOpenID1()) { | ||||
|             $session_type = $message->getArg(Auth_OpenID_OPENID_NS, | ||||
| @@ -696,7 +696,7 @@ class Auth_OpenID_AssociateRequest extends Auth_OpenID_Request { | ||||
|                                       'session_type', | ||||
|                                       $preferred_session_type); | ||||
|         } | ||||
|  | ||||
|         $response->code = AUTH_OPENID_HTTP_ERROR; | ||||
|         return $response; | ||||
|     } | ||||
| } | ||||
| @@ -734,7 +734,7 @@ class Auth_OpenID_CheckIDRequest extends Auth_OpenID_Request { | ||||
|      */ | ||||
|     var $namespace; | ||||
|      | ||||
|     function make(&$message, $identity, $return_to, $trust_root = null, | ||||
|     static function make($message, $identity, $return_to, $trust_root = null, | ||||
|                   $immediate = false, $assoc_handle = null, $server = null) | ||||
|     { | ||||
|         if ($server === null) { | ||||
| @@ -752,7 +752,7 @@ class Auth_OpenID_CheckIDRequest extends Auth_OpenID_Request { | ||||
|                                             $assoc_handle, $server); | ||||
|  | ||||
|         $r->namespace = $message->getOpenIDNamespace(); | ||||
|         $r->message =& $message; | ||||
|         $r->message = $message; | ||||
|  | ||||
|         if (!$r->trustRootValid()) { | ||||
|             return new Auth_OpenID_UntrustedReturnURL($message, | ||||
| @@ -778,7 +778,7 @@ class Auth_OpenID_CheckIDRequest extends Auth_OpenID_Request { | ||||
|         } | ||||
|         $this->return_to = $return_to; | ||||
|         $this->trust_root = $trust_root; | ||||
|         $this->server =& $server; | ||||
|         $this->server = $server; | ||||
|  | ||||
|         if ($immediate) { | ||||
|             $this->immediate = true; | ||||
| @@ -817,11 +817,12 @@ class Auth_OpenID_CheckIDRequest extends Auth_OpenID_Request { | ||||
|      */ | ||||
|     function returnToVerified() | ||||
|     { | ||||
|     	$fetcher = Auth_Yadis_Yadis::getHTTPFetcher(); | ||||
|         return call_user_func_array($this->verifyReturnTo, | ||||
|                                     array($this->trust_root, $this->return_to)); | ||||
|                                     array($this->trust_root, $this->return_to, $fetcher)); | ||||
|     } | ||||
|  | ||||
|     function fromMessage(&$message, $server) | ||||
|      | ||||
|     static function fromMessage($message, $server) | ||||
|     { | ||||
|         $mode = $message->getArg(Auth_OpenID_OPENID_NS, 'mode'); | ||||
|         $immediate = null; | ||||
| @@ -1097,7 +1098,7 @@ class Auth_OpenID_CheckIDRequest extends Auth_OpenID_Request { | ||||
|                                   in OpenID 1.x immediate mode.'); | ||||
|                 } | ||||
|  | ||||
|                 $setup_request =& new Auth_OpenID_CheckIDRequest( | ||||
|                 $setup_request = new Auth_OpenID_CheckIDRequest( | ||||
|                                                 $this->identity, | ||||
|                                                 $this->return_to, | ||||
|                                                 $this->trust_root, | ||||
| @@ -1183,9 +1184,9 @@ class Auth_OpenID_CheckIDRequest extends Auth_OpenID_Request { | ||||
|  */ | ||||
| class Auth_OpenID_ServerResponse { | ||||
|  | ||||
|     function Auth_OpenID_ServerResponse(&$request) | ||||
|     function Auth_OpenID_ServerResponse($request) | ||||
|     { | ||||
|         $this->request =& $request; | ||||
|         $this->request = $request; | ||||
|         $this->fields = new Auth_OpenID_Message($this->request->namespace); | ||||
|     } | ||||
|  | ||||
| @@ -1310,10 +1311,10 @@ class Auth_OpenID_Signatory { | ||||
|     /** | ||||
|      * Create a new signatory using a given store. | ||||
|      */ | ||||
|     function Auth_OpenID_Signatory(&$store) | ||||
|     function Auth_OpenID_Signatory($store) | ||||
|     { | ||||
|         // assert store is not None | ||||
|         $this->store =& $store; | ||||
|         $this->store = $store; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -1447,7 +1448,7 @@ class Auth_OpenID_Encoder { | ||||
|      * Encode an {@link Auth_OpenID_ServerResponse} and return an | ||||
|      * {@link Auth_OpenID_WebResponse}. | ||||
|      */ | ||||
|     function encode(&$response) | ||||
|     function encode($response) | ||||
|     { | ||||
|         $cls = $this->responseFactory; | ||||
|  | ||||
| @@ -1463,10 +1464,14 @@ class Auth_OpenID_Encoder { | ||||
|                            array('location' => $location)); | ||||
|         } else if ($encode_as == Auth_OpenID_ENCODE_HTML_FORM) { | ||||
|           $wr = new $cls(AUTH_OPENID_HTTP_OK, array(), | ||||
|                          $response->toFormMarkup()); | ||||
|                          $response->toHTML()); | ||||
|         } else { | ||||
|             return new Auth_OpenID_EncodingError($response); | ||||
|         } | ||||
|         /* Allow the response to carry a custom error code (ex: for Association errors) */ | ||||
|         if(isset($response->code)) { | ||||
|             $wr->code = $response->code; | ||||
|         } | ||||
|         return $wr; | ||||
|     } | ||||
| } | ||||
| @@ -1478,16 +1483,16 @@ class Auth_OpenID_Encoder { | ||||
|  */ | ||||
| class Auth_OpenID_SigningEncoder extends Auth_OpenID_Encoder { | ||||
|  | ||||
|     function Auth_OpenID_SigningEncoder(&$signatory) | ||||
|     function Auth_OpenID_SigningEncoder($signatory) | ||||
|     { | ||||
|         $this->signatory =& $signatory; | ||||
|         $this->signatory = $signatory; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Sign an {@link Auth_OpenID_ServerResponse} and return an | ||||
|      * {@link Auth_OpenID_WebResponse}. | ||||
|      */ | ||||
|     function encode(&$response) | ||||
|     function encode($response) | ||||
|     { | ||||
|         // the isinstance is a bit of a kludge... it means there isn't | ||||
|         // really an adapter to make the interfaces quite match. | ||||
| @@ -1516,9 +1521,9 @@ class Auth_OpenID_SigningEncoder extends Auth_OpenID_Encoder { | ||||
|  */ | ||||
| class Auth_OpenID_Decoder { | ||||
|  | ||||
|     function Auth_OpenID_Decoder(&$server) | ||||
|     function Auth_OpenID_Decoder($server) | ||||
|     { | ||||
|         $this->server =& $server; | ||||
|         $this->server = $server; | ||||
|  | ||||
|         $this->handlers = array( | ||||
|             'checkid_setup' => 'Auth_OpenID_CheckIDRequest', | ||||
| @@ -1599,9 +1604,9 @@ class Auth_OpenID_Decoder { | ||||
|  * @package OpenID | ||||
|  */ | ||||
| class Auth_OpenID_EncodingError { | ||||
|     function Auth_OpenID_EncodingError(&$response) | ||||
|     function Auth_OpenID_EncodingError($response) | ||||
|     { | ||||
|         $this->response =& $response; | ||||
|         $this->response = $response; | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -1674,14 +1679,14 @@ class Auth_OpenID_UntrustedReturnURL extends Auth_OpenID_ServerError { | ||||
|  * @package OpenID | ||||
|  */ | ||||
| class Auth_OpenID_Server { | ||||
|     function Auth_OpenID_Server(&$store, $op_endpoint=null) | ||||
|     function Auth_OpenID_Server($store, $op_endpoint=null) | ||||
|     { | ||||
|         $this->store =& $store; | ||||
|         $this->signatory =& new Auth_OpenID_Signatory($this->store); | ||||
|         $this->encoder =& new Auth_OpenID_SigningEncoder($this->signatory); | ||||
|         $this->decoder =& new Auth_OpenID_Decoder($this); | ||||
|         $this->store = $store; | ||||
|         $this->signatory = new Auth_OpenID_Signatory($this->store); | ||||
|         $this->encoder = new Auth_OpenID_SigningEncoder($this->signatory); | ||||
|         $this->decoder = new Auth_OpenID_Decoder($this); | ||||
|         $this->op_endpoint = $op_endpoint; | ||||
|         $this->negotiator =& Auth_OpenID_getDefaultNegotiator(); | ||||
|         $this->negotiator = Auth_OpenID_getDefaultNegotiator(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -1699,7 +1704,7 @@ class Auth_OpenID_Server { | ||||
|     { | ||||
|         if (method_exists($this, "openid_" . $request->mode)) { | ||||
|             $handler = array($this, "openid_" . $request->mode); | ||||
|             return call_user_func($handler, $request); | ||||
|             return call_user_func($handler, &$request); | ||||
|         } | ||||
|         return null; | ||||
|     } | ||||
| @@ -1707,7 +1712,7 @@ class Auth_OpenID_Server { | ||||
|     /** | ||||
|      * The callback for 'check_authentication' messages. | ||||
|      */ | ||||
|     function openid_check_authentication(&$request) | ||||
|     function openid_check_authentication($request) | ||||
|     { | ||||
|         return $request->answer($this->signatory); | ||||
|     } | ||||
| @@ -1715,7 +1720,7 @@ class Auth_OpenID_Server { | ||||
|     /** | ||||
|      * The callback for 'associate' messages. | ||||
|      */ | ||||
|     function openid_associate(&$request) | ||||
|     function openid_associate($request) | ||||
|     { | ||||
|         $assoc_type = $request->assoc_type; | ||||
|         $session_type = $request->session->session_type; | ||||
| @@ -1738,7 +1743,7 @@ class Auth_OpenID_Server { | ||||
|      * Encodes as response in the appropriate format suitable for | ||||
|      * sending to the user agent. | ||||
|      */ | ||||
|     function encodeResponse(&$response) | ||||
|     function encodeResponse($response) | ||||
|     { | ||||
|         return $this->encoder->encode($response); | ||||
|     } | ||||
| @@ -1757,4 +1762,4 @@ class Auth_OpenID_Server { | ||||
|     } | ||||
| } | ||||
|  | ||||
| ?> | ||||
|  | ||||
|   | ||||
| @@ -34,4 +34,3 @@ class Auth_OpenID_ServerRequest { | ||||
|     } | ||||
| } | ||||
|  | ||||
| ?> | ||||
| @@ -58,7 +58,7 @@ class Auth_OpenID_TrustRoot { | ||||
|      * @return The URL upon which relying party discovery should be | ||||
|      * run in order to verify the return_to URL | ||||
|      */ | ||||
|     function buildDiscoveryURL($realm) | ||||
|     static function buildDiscoveryURL($realm) | ||||
|     { | ||||
|         $parsed = Auth_OpenID_TrustRoot::_parse($realm); | ||||
|  | ||||
| @@ -93,7 +93,7 @@ class Auth_OpenID_TrustRoot { | ||||
|      * @return mixed $parsed Either an associative array of trust root | ||||
|      * parts or false if parsing failed. | ||||
|      */ | ||||
|     function _parse($trust_root) | ||||
|     static function _parse($trust_root) | ||||
|     { | ||||
|         $trust_root = Auth_OpenID_urinorm($trust_root); | ||||
|         if ($trust_root === null) { | ||||
| @@ -199,7 +199,7 @@ class Auth_OpenID_TrustRoot { | ||||
|      * @param string $trust_root The trust root to check | ||||
|      * @return bool $sanity Whether the trust root looks OK | ||||
|      */ | ||||
|     function isSane($trust_root) | ||||
|     static function isSane($trust_root) | ||||
|     { | ||||
|         $parts = Auth_OpenID_TrustRoot::_parse($trust_root); | ||||
|         if ($parts === false) { | ||||
| @@ -269,7 +269,7 @@ class Auth_OpenID_TrustRoot { | ||||
|      * @return bool $matches Whether the URL matches against the | ||||
|      * trust root | ||||
|      */ | ||||
|     function match($trust_root, $url) | ||||
|     static function match($trust_root, $url) | ||||
|     { | ||||
|         $trust_root_parsed = Auth_OpenID_TrustRoot::_parse($trust_root); | ||||
|         $url_parsed = Auth_OpenID_TrustRoot::_parse($url); | ||||
| @@ -341,7 +341,7 @@ class Auth_OpenID_TrustRoot { | ||||
|  * @returns: The endpoint URL or None if the endpoint is not a | ||||
|  * relying party endpoint. | ||||
|  */ | ||||
| function filter_extractReturnURL(&$endpoint) | ||||
| function filter_extractReturnURL($endpoint) | ||||
| { | ||||
|     if ($endpoint->matchTypes(array(Auth_OpenID_RP_RETURN_TO_URL_TYPE))) { | ||||
|         return $endpoint; | ||||
| @@ -394,14 +394,14 @@ function Auth_OpenID_returnToMatches($allowed_return_to_urls, $return_to) | ||||
|  * Given a relying party discovery URL return a list of return_to | ||||
|  * URLs. | ||||
|  */ | ||||
| function Auth_OpenID_getAllowedReturnURLs($relying_party_url, &$fetcher, | ||||
| function Auth_OpenID_getAllowedReturnURLs($relying_party_url, $fetcher, | ||||
|               $discover_function=null) | ||||
| { | ||||
|     if ($discover_function === null) { | ||||
|         $discover_function = array('Auth_Yadis_Yadis', 'discover'); | ||||
|     } | ||||
|  | ||||
|     $xrds_parse_cb = array('Auth_OpenID_ServiceEndpoint', 'fromXRDS'); | ||||
|     $xrds_parse_cb = array('Auth_OpenID_ServiceEndpoint', 'consumerFromXRDS'); | ||||
|  | ||||
|     list($rp_url_after_redirects, $endpoints) = | ||||
|         Auth_Yadis_getServiceEndpoints($relying_party_url, $xrds_parse_cb, | ||||
| @@ -413,7 +413,7 @@ function Auth_OpenID_getAllowedReturnURLs($relying_party_url, &$fetcher, | ||||
|     } | ||||
|  | ||||
|     call_user_func_array($discover_function, | ||||
|                          array($relying_party_url, $fetcher)); | ||||
|                          array($relying_party_url, &$fetcher)); | ||||
|  | ||||
|     $return_to_urls = array(); | ||||
|     $matching_endpoints = Auth_OpenID_extractReturnURL($endpoints); | ||||
| @@ -435,7 +435,7 @@ function Auth_OpenID_getAllowedReturnURLs($relying_party_url, &$fetcher, | ||||
|  * | ||||
|  * @return true if the return_to URL is valid for the realm | ||||
|  */ | ||||
| function Auth_OpenID_verifyReturnTo($realm_str, $return_to, &$fetcher, | ||||
| function Auth_OpenID_verifyReturnTo($realm_str, $return_to, $fetcher, | ||||
|               $_vrfy='Auth_OpenID_getAllowedReturnURLs') | ||||
| { | ||||
|     $disco_url = Auth_OpenID_TrustRoot::buildDiscoveryURL($realm_str); | ||||
| @@ -445,7 +445,7 @@ function Auth_OpenID_verifyReturnTo($realm_str, $return_to, &$fetcher, | ||||
|     } | ||||
|  | ||||
|     $allowable_urls = call_user_func_array($_vrfy, | ||||
|                            array($disco_url, &$fetcher)); | ||||
|                            array($disco_url, $fetcher)); | ||||
|  | ||||
|     // The realm_str could not be parsed. | ||||
|     if ($allowable_urls === false) { | ||||
| @@ -459,4 +459,3 @@ function Auth_OpenID_verifyReturnTo($realm_str, $return_to, &$fetcher, | ||||
|     } | ||||
| } | ||||
|  | ||||
| ?> | ||||
| @@ -246,4 +246,4 @@ function Auth_OpenID_urinorm($uri) | ||||
|     return $scheme . '://' . $authority . $path . $query . $fragment; | ||||
| } | ||||
|  | ||||
| ?> | ||||
|  | ||||
|   | ||||
| @@ -115,12 +115,40 @@ class Auth_Yadis_HTTPFetcher { | ||||
|     /** | ||||
|      * @access private | ||||
|      */ | ||||
|     function _findRedirect($headers) | ||||
|     function _findRedirect($headers, $url) | ||||
|     { | ||||
|         foreach ($headers as $line) { | ||||
|             if (strpos(strtolower($line), "location: ") === 0) { | ||||
|                 $parts = explode(" ", $line, 2); | ||||
|                 return $parts[1]; | ||||
|                 $loc = $parts[1]; | ||||
|                 $ppos = strpos($loc, "://"); | ||||
|                 if ($ppos === false || $ppos > strpos($loc, "/")) { | ||||
|                   /* no host; add it */ | ||||
|                   $hpos = strpos($url, "://"); | ||||
|                   $prt = substr($url, 0, $hpos+3); | ||||
|                   $url = substr($url, $hpos+3); | ||||
|                   if (substr($loc, 0, 1) == "/") { | ||||
|                     /* absolute path */ | ||||
|                     $fspos = strpos($url, "/"); | ||||
|                     if ($fspos) $loc = $prt.substr($url, 0, $fspos).$loc; | ||||
|                     else $loc = $prt.$url.$loc; | ||||
|                   } else { | ||||
|                     /* relative path */ | ||||
|                     $pp = $prt; | ||||
|                     while (1) { | ||||
|                       $xpos = strpos($url, "/"); | ||||
|                       if ($xpos === false) break; | ||||
|                       $apos = strpos($url, "?"); | ||||
|                       if ($apos !== false && $apos < $xpos) break; | ||||
|                       $apos = strpos($url, "&"); | ||||
|                       if ($apos !== false && $apos < $xpos) break; | ||||
|                       $pp .= substr($url, 0, $xpos+1); | ||||
|                       $url = substr($url, $xpos+1); | ||||
|                     } | ||||
|                     $loc = $pp.$loc; | ||||
|                   } | ||||
|                 } | ||||
|                 return $loc; | ||||
|             } | ||||
|         } | ||||
|         return null; | ||||
| @@ -144,4 +172,3 @@ class Auth_Yadis_HTTPFetcher { | ||||
|     } | ||||
| } | ||||
|  | ||||
| ?> | ||||
| @@ -387,11 +387,11 @@ class Auth_Yadis_Discovery { | ||||
|      * @param string $session_key_suffix The optional session key | ||||
|      * suffix override. | ||||
|      */ | ||||
|     function Auth_Yadis_Discovery(&$session, $url, | ||||
|     function Auth_Yadis_Discovery($session, $url, | ||||
|                                       $session_key_suffix = null) | ||||
|     { | ||||
|         /// Initialize a discovery object | ||||
|         $this->session =& $session; | ||||
|         $this->session = $session; | ||||
|         $this->url = $url; | ||||
|         if ($session_key_suffix === null) { | ||||
|             $session_key_suffix = $this->DEFAULT_SUFFIX; | ||||
| @@ -405,7 +405,7 @@ class Auth_Yadis_Discovery { | ||||
|      * Return the next authentication service for the pair of | ||||
|      * user_input and session. This function handles fallback. | ||||
|      */ | ||||
|     function getNextService($discover_cb, &$fetcher) | ||||
|     function getNextService($discover_cb, $fetcher) | ||||
|     { | ||||
|         $manager = $this->getManager(); | ||||
|         if (!$manager || (!$manager->services)) { | ||||
| @@ -413,7 +413,7 @@ class Auth_Yadis_Discovery { | ||||
|  | ||||
|             list($yadis_url, $services) = call_user_func($discover_cb, | ||||
|                                                          $this->url, | ||||
|                                                          $fetcher); | ||||
|                                                          &$fetcher); | ||||
|  | ||||
|             $manager = $this->createManager($services, $yadis_url); | ||||
|         } | ||||
| @@ -466,7 +466,7 @@ class Auth_Yadis_Discovery { | ||||
|      * @param $force True if the manager should be returned regardless | ||||
|      * of whether it's a manager for $this->url. | ||||
|      */ | ||||
|     function &getManager($force=false) | ||||
|     function getManager($force=false) | ||||
|     { | ||||
|         // Extract the YadisServiceManager for this object's URL and | ||||
|         // suffix from the session. | ||||
| @@ -481,16 +481,13 @@ class Auth_Yadis_Discovery { | ||||
|  | ||||
|         if ($manager && ($manager->forURL($this->url) || $force)) { | ||||
|             return $manager; | ||||
|         } else { | ||||
|             $unused = null; | ||||
|             return $unused; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @access private | ||||
|      */ | ||||
|     function &createManager($services, $yadis_url = null) | ||||
|     function createManager($services, $yadis_url = null) | ||||
|     { | ||||
|         $key = $this->getSessionKey(); | ||||
|         if ($this->getManager()) { | ||||
| @@ -504,10 +501,6 @@ class Auth_Yadis_Discovery { | ||||
|             $this->session->set($this->session_key, | ||||
|                                 serialize($loader->toSession($manager))); | ||||
|             return $manager; | ||||
|         } else { | ||||
|             // Oh, PHP. | ||||
|             $unused = null; | ||||
|             return $unused; | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -526,4 +519,3 @@ class Auth_Yadis_Discovery { | ||||
|     } | ||||
| } | ||||
|  | ||||
| ?> | ||||
| @@ -56,4 +56,3 @@ function Auth_Yadis_startswith($s, $stuff) | ||||
|     return strpos($s, $stuff) === 0; | ||||
| } | ||||
|  | ||||
| ?> | ||||
| @@ -109,9 +109,9 @@ class Auth_Yadis_ParanoidHTTPFetcher extends Auth_Yadis_HTTPFetcher { | ||||
|             } | ||||
|  | ||||
|             curl_setopt($c, CURLOPT_WRITEFUNCTION, | ||||
|                         array(&$this, "_writeData")); | ||||
|                         array($this, "_writeData")); | ||||
|             curl_setopt($c, CURLOPT_HEADERFUNCTION, | ||||
|                         array(&$this, "_writeHeader")); | ||||
|                         array($this, "_writeHeader")); | ||||
|  | ||||
|             if ($extra_headers) { | ||||
|                 curl_setopt($c, CURLOPT_HTTPHEADER, $extra_headers); | ||||
| @@ -128,6 +128,10 @@ class Auth_Yadis_ParanoidHTTPFetcher extends Auth_Yadis_HTTPFetcher { | ||||
|             curl_setopt($c, CURLOPT_TIMEOUT, $off); | ||||
|             curl_setopt($c, CURLOPT_URL, $url); | ||||
|  | ||||
|             if (defined('Auth_OpenID_VERIFY_HOST')) { | ||||
|                 curl_setopt($c, CURLOPT_SSL_VERIFYPEER, true); | ||||
|                 curl_setopt($c, CURLOPT_SSL_VERIFYHOST, 2); | ||||
|             } | ||||
|             curl_exec($c); | ||||
|  | ||||
|             $code = curl_getinfo($c, CURLINFO_HTTP_CODE); | ||||
| @@ -142,12 +146,17 @@ class Auth_Yadis_ParanoidHTTPFetcher extends Auth_Yadis_HTTPFetcher { | ||||
|             } | ||||
|  | ||||
|             if (in_array($code, array(301, 302, 303, 307))) { | ||||
|                 $url = $this->_findRedirect($headers); | ||||
|                 $url = $this->_findRedirect($headers, $url); | ||||
|                 $redir = true; | ||||
|             } else { | ||||
|                 $redir = false; | ||||
|                 curl_close($c); | ||||
|  | ||||
|                 if (defined('Auth_OpenID_VERIFY_HOST') && | ||||
|                     $this->isHTTPS($url)) { | ||||
|                     Auth_OpenID::log('OpenID: Verified SSL host %s using '. | ||||
|                                      'curl/get', $url); | ||||
|                 } | ||||
|                 $new_headers = array(); | ||||
|  | ||||
|                 foreach ($headers as $header) { | ||||
| @@ -190,7 +199,12 @@ class Auth_Yadis_ParanoidHTTPFetcher extends Auth_Yadis_HTTPFetcher { | ||||
|         curl_setopt($c, CURLOPT_TIMEOUT, $this->timeout); | ||||
|         curl_setopt($c, CURLOPT_URL, $url); | ||||
|         curl_setopt($c, CURLOPT_WRITEFUNCTION, | ||||
|                     array(&$this, "_writeData")); | ||||
|                     array($this, "_writeData")); | ||||
|  | ||||
|         if (defined('Auth_OpenID_VERIFY_HOST')) { | ||||
|             curl_setopt($c, CURLOPT_SSL_VERIFYPEER, true); | ||||
|             curl_setopt($c, CURLOPT_SSL_VERIFYHOST, 2); | ||||
|         } | ||||
|  | ||||
|         curl_exec($c); | ||||
|  | ||||
| @@ -198,9 +212,15 @@ class Auth_Yadis_ParanoidHTTPFetcher extends Auth_Yadis_HTTPFetcher { | ||||
|  | ||||
|         if (!$code) { | ||||
|             Auth_OpenID::log("Got no response code when fetching %s", $url); | ||||
|             Auth_OpenID::log("CURL error (%s): %s", | ||||
|                              curl_errno($c), curl_error($c)); | ||||
|             return null; | ||||
|         } | ||||
|  | ||||
|         if (defined('Auth_OpenID_VERIFY_HOST') && $this->isHTTPS($url)) { | ||||
|             Auth_OpenID::log('OpenID: Verified SSL host %s using '. | ||||
|                              'curl/post', $url); | ||||
|         } | ||||
|         $body = $this->data; | ||||
|  | ||||
|         curl_close($c); | ||||
| @@ -223,4 +243,3 @@ class Auth_Yadis_ParanoidHTTPFetcher extends Auth_Yadis_HTTPFetcher { | ||||
|     } | ||||
| } | ||||
|  | ||||
| ?> | ||||
| @@ -256,4 +256,3 @@ class Auth_Yadis_ParseHTML { | ||||
|     } | ||||
| } | ||||
|  | ||||
| ?> | ||||
| @@ -122,7 +122,7 @@ class Auth_Yadis_PlainHTTPFetcher extends Auth_Yadis_HTTPFetcher { | ||||
|             $code = $http_code[1]; | ||||
|  | ||||
|             if (in_array($code, array('301', '302'))) { | ||||
|                 $url = $this->_findRedirect($headers); | ||||
|                 $url = $this->_findRedirect($headers, $url); | ||||
|                 $redir = true; | ||||
|             } else { | ||||
|                 $redir = false; | ||||
| @@ -246,4 +246,3 @@ class Auth_Yadis_PlainHTTPFetcher extends Auth_Yadis_HTTPFetcher { | ||||
|     } | ||||
| } | ||||
|  | ||||
| ?> | ||||
| @@ -310,20 +310,16 @@ $__Auth_Yadis_defaultParser = null; | ||||
|  * @param Auth_Yadis_XMLParser $parser An instance of a | ||||
|  * Auth_Yadis_XMLParser subclass. | ||||
|  */ | ||||
| function Auth_Yadis_setDefaultParser(&$parser) | ||||
| function Auth_Yadis_setDefaultParser($parser) | ||||
| { | ||||
|     global $__Auth_Yadis_defaultParser; | ||||
|     $__Auth_Yadis_defaultParser =& $parser; | ||||
|     $__Auth_Yadis_defaultParser = $parser; | ||||
| } | ||||
|  | ||||
| function Auth_Yadis_getSupportedExtensions() | ||||
| { | ||||
|     return array( | ||||
|                  'dom' => array('classname' => 'Auth_Yadis_dom', | ||||
|                        'libname' => array('dom.so', 'dom.dll')), | ||||
|                  'domxml' => array('classname' => 'Auth_Yadis_domxml', | ||||
|                        'libname' => array('domxml.so', 'php_domxml.dll')), | ||||
|                  ); | ||||
|     return array('dom'    => 'Auth_Yadis_dom', | ||||
|                  'domxml' => 'Auth_Yadis_domxml'); | ||||
| } | ||||
|  | ||||
| /** | ||||
| @@ -332,43 +328,25 @@ function Auth_Yadis_getSupportedExtensions() | ||||
|  * Auth_Yadis_setDefaultParser has been called, the parser used in | ||||
|  * that call will be returned instead. | ||||
|  */ | ||||
| function &Auth_Yadis_getXMLParser() | ||||
| function Auth_Yadis_getXMLParser() | ||||
| { | ||||
|     global $__Auth_Yadis_defaultParser; | ||||
|  | ||||
|      | ||||
|     if (isset($__Auth_Yadis_defaultParser)) { | ||||
|         return $__Auth_Yadis_defaultParser; | ||||
|     } | ||||
|  | ||||
|     $p = null; | ||||
|     $classname = null; | ||||
|  | ||||
|     $extensions = Auth_Yadis_getSupportedExtensions(); | ||||
|  | ||||
|     // Return a wrapper for the resident implementation, if any. | ||||
|     foreach ($extensions as $name => $params) { | ||||
|         if (!extension_loaded($name)) { | ||||
|             foreach ($params['libname'] as $libname) { | ||||
|                 if (@dl($libname)) { | ||||
|                     $classname = $params['classname']; | ||||
|                 } | ||||
|             } | ||||
|         } else { | ||||
|             $classname = $params['classname']; | ||||
|         } | ||||
|         if (isset($classname)) { | ||||
|             $p = new $classname(); | ||||
|             return $p; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     if (!isset($p)) { | ||||
|         trigger_error('No XML parser was found', E_USER_ERROR); | ||||
|     } else { | ||||
|      | ||||
|     foreach(Auth_Yadis_getSupportedExtensions() as $extension => $classname) | ||||
|     { | ||||
|       if (extension_loaded($extension)) | ||||
|       { | ||||
|         $p = new $classname(); | ||||
|         Auth_Yadis_setDefaultParser($p); | ||||
|         return $p; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     return $p; | ||||
|      | ||||
|     return false; | ||||
| } | ||||
|  | ||||
| ?> | ||||
|  | ||||
|   | ||||
| @@ -255,11 +255,11 @@ class Auth_Yadis_XRDS { | ||||
|      * Instantiate a Auth_Yadis_XRDS object.  Requires an XPath | ||||
|      * instance which has been used to parse a valid XRDS document. | ||||
|      */ | ||||
|     function Auth_Yadis_XRDS(&$xmlParser, &$xrdNodes) | ||||
|     function Auth_Yadis_XRDS($xmlParser, $xrdNodes) | ||||
|     { | ||||
|         $this->parser =& $xmlParser; | ||||
|         $this->parser = $xmlParser; | ||||
|         $this->xrdNode = $xrdNodes[count($xrdNodes) - 1]; | ||||
|         $this->allXrdNodes =& $xrdNodes; | ||||
|         $this->allXrdNodes = $xrdNodes; | ||||
|         $this->serviceList = array(); | ||||
|         $this->_parse(); | ||||
|     } | ||||
| @@ -273,7 +273,7 @@ class Auth_Yadis_XRDS { | ||||
|      * @return mixed $xrds An instance of Auth_Yadis_XRDS or null, | ||||
|      * depending on the validity of $xml_string | ||||
|      */ | ||||
|     function &parseXRDS($xml_string, $extra_ns_map = null) | ||||
|     static function parseXRDS($xml_string, $extra_ns_map = null) | ||||
|     { | ||||
|         $_null = null; | ||||
|  | ||||
| @@ -352,9 +352,9 @@ class Auth_Yadis_XRDS { | ||||
|         $services = $this->parser->evalXPath('xrd:Service', $this->xrdNode); | ||||
|  | ||||
|         foreach ($services as $node) { | ||||
|             $s =& new Auth_Yadis_Service(); | ||||
|             $s = new Auth_Yadis_Service(); | ||||
|             $s->element = $node; | ||||
|             $s->parser =& $this->parser; | ||||
|             $s->parser = $this->parser; | ||||
|  | ||||
|             $priority = $s->getPriority(); | ||||
|  | ||||
| @@ -428,7 +428,8 @@ class Auth_Yadis_XRDS { | ||||
|                 $matches = 0; | ||||
|  | ||||
|                 foreach ($filters as $filter) { | ||||
|                     if (call_user_func_array($filter, array($service))) { | ||||
|  | ||||
|                     if (call_user_func_array($filter, array(&$service))) { | ||||
|                         $matches++; | ||||
|  | ||||
|                         if ($filter_mode == SERVICES_YADIS_MATCH_ANY) { | ||||
| @@ -475,4 +476,3 @@ class Auth_Yadis_XRDS { | ||||
|     } | ||||
| } | ||||
|  | ||||
| ?> | ||||
| @@ -190,7 +190,7 @@ function Auth_Yadis_getCanonicalID($iname, $xrds) | ||||
|  | ||||
|     // Now nodes are in reverse order. | ||||
|     $xrd_list = array_reverse($xrds->allXrdNodes); | ||||
|     $parser =& $xrds->parser; | ||||
|     $parser = $xrds->parser; | ||||
|     $node = $xrd_list[0]; | ||||
|  | ||||
|     $canonicalID_nodes = $parser->evalXPath('xrd:CanonicalID', $node); | ||||
| @@ -231,4 +231,4 @@ function Auth_Yadis_getCanonicalID($iname, $xrds) | ||||
|     return $canonicalID; | ||||
| } | ||||
|  | ||||
| ?> | ||||
|  | ||||
|   | ||||
| @@ -8,9 +8,9 @@ require_once 'Auth/Yadis/XRDS.php'; | ||||
| require_once 'Auth/Yadis/XRI.php'; | ||||
|  | ||||
| class Auth_Yadis_ProxyResolver { | ||||
|     function Auth_Yadis_ProxyResolver(&$fetcher, $proxy_url = null) | ||||
|     function Auth_Yadis_ProxyResolver($fetcher, $proxy_url = null) | ||||
|     { | ||||
|         $this->fetcher =& $fetcher; | ||||
|         $this->fetcher = $fetcher; | ||||
|         $this->proxy_url = $proxy_url; | ||||
|         if (!$this->proxy_url) { | ||||
|             $this->proxy_url = Auth_Yadis_getDefaultProxy(); | ||||
| @@ -69,4 +69,4 @@ class Auth_Yadis_ProxyResolver { | ||||
|     } | ||||
| } | ||||
|  | ||||
| ?> | ||||
|  | ||||
|   | ||||
| @@ -105,7 +105,7 @@ class Auth_Yadis_DiscoveryResult { | ||||
|     function usedYadisLocation() | ||||
|     { | ||||
|         // Was the Yadis protocol's indirection used? | ||||
|         return $this->normalized_uri != $this->xrds_uri; | ||||
|         return ($this->xrds_uri && $this->normalized_uri != $this->xrds_uri); | ||||
|     } | ||||
|  | ||||
|     function isXRDS() | ||||
| @@ -141,7 +141,7 @@ function Auth_Yadis_getServiceEndpoints($input_url, $xrds_parse_func, | ||||
|     } | ||||
|  | ||||
|     $yadis_result = call_user_func_array($discover_func, | ||||
|                                          array($input_url, $fetcher)); | ||||
|                                          array($input_url, &$fetcher)); | ||||
|  | ||||
|     if ($yadis_result === null) { | ||||
|         return array($input_url, array()); | ||||
| @@ -196,7 +196,7 @@ function Auth_Yadis_getServiceEndpoints($input_url, $xrds_parse_func, | ||||
|  * The filter functions (whose names appear in the array passed to | ||||
|  * services()) take the following form: | ||||
|  * | ||||
|  * <pre>  function myFilter(&$service) { | ||||
|  * <pre>  function myFilter($service) { | ||||
|  *       // Query $service object here.  Return true if the service | ||||
|  *       // matches your query; false if not. | ||||
|  *  }</pre> | ||||
| @@ -207,7 +207,7 @@ function Auth_Yadis_getServiceEndpoints($input_url, $xrds_parse_func, | ||||
|  * this contrived example): | ||||
|  * | ||||
|  * <pre> | ||||
|  *  function URIMatcher(&$service) { | ||||
|  *  function URIMatcher($service) { | ||||
|  *      foreach ($service->getElements('xrd:URI') as $uri) { | ||||
|  *          if (preg_match("/some_pattern/", | ||||
|  *                         $service->parser->content($uri))) { | ||||
| @@ -250,7 +250,7 @@ class Auth_Yadis_Yadis { | ||||
|      * If Auth_Yadis_CURL_OVERRIDE is defined, this method will always | ||||
|      * return a {@link Auth_Yadis_PlainHTTPFetcher}. | ||||
|      */ | ||||
|     function getHTTPFetcher($timeout = 20) | ||||
|     static function getHTTPFetcher($timeout = 20) | ||||
|     { | ||||
|         if (Auth_Yadis_Yadis::curlPresent() && | ||||
|             (!defined('Auth_Yadis_CURL_OVERRIDE'))) { | ||||
| @@ -261,7 +261,7 @@ class Auth_Yadis_Yadis { | ||||
|         return $fetcher; | ||||
|     } | ||||
|  | ||||
|     function curlPresent() | ||||
|     static function curlPresent() | ||||
|     { | ||||
|         return function_exists('curl_init'); | ||||
|     } | ||||
| @@ -269,7 +269,7 @@ class Auth_Yadis_Yadis { | ||||
|     /** | ||||
|      * @access private | ||||
|      */ | ||||
|     function _getHeader($header_list, $names) | ||||
|    static function _getHeader($header_list, $names) | ||||
|     { | ||||
|         foreach ($header_list as $name => $value) { | ||||
|             foreach ($names as $n) { | ||||
| @@ -285,7 +285,7 @@ class Auth_Yadis_Yadis { | ||||
|     /** | ||||
|      * @access private | ||||
|      */ | ||||
|     function _getContentType($content_type_header) | ||||
|     static function _getContentType($content_type_header) | ||||
|     { | ||||
|         if ($content_type_header) { | ||||
|             $parts = explode(";", $content_type_header); | ||||
| @@ -317,7 +317,7 @@ class Auth_Yadis_Yadis { | ||||
|      * Auth_Yadis_Yadis, depending on whether the discovery | ||||
|      * succeeded. | ||||
|      */ | ||||
|     function discover($uri, &$fetcher, | ||||
|     static function discover($uri, $fetcher, | ||||
|                       $extra_ns_map = null, $timeout = 20) | ||||
|     { | ||||
|         $result = new Auth_Yadis_DiscoveryResult($uri); | ||||
| @@ -379,4 +379,4 @@ class Auth_Yadis_Yadis { | ||||
|     } | ||||
| } | ||||
|  | ||||
| ?> | ||||
|  | ||||
|   | ||||
| @@ -54,6 +54,24 @@ class OAuthSignatureMethod {/*{{{*/ | ||||
|   public function check_signature(&$request, $consumer, $token, $signature) { | ||||
|     $built = $this->build_signature($request, $consumer, $token); | ||||
|     return $built == $signature; | ||||
|  | ||||
|     // Check for zero length, although unlikely here | ||||
|     if (strlen($built) == 0 || strlen($signature) == 0) { | ||||
|       return false; | ||||
|     } | ||||
|  | ||||
|     if (strlen($built) != strlen($signature)) { | ||||
|       return false; | ||||
|     } | ||||
|  | ||||
|     $result = 0; | ||||
|  | ||||
|     // Avoid a timing leak with a (hopefully) time insensitive compare | ||||
|     for ($i = 0; $i < strlen($signature); $i++) { | ||||
|       $result |= ord($built{$i}) ^ ord($signature{$i}); | ||||
|     } | ||||
|  | ||||
|     return $result == 0; | ||||
|   } | ||||
| }/*}}}*/ | ||||
|  | ||||
|   | ||||
| @@ -1,14 +1,6 @@ | ||||
| <?php | ||||
|  | ||||
| require_once 'xrds_mapper.php'; | ||||
| require_once 'constants.php'; | ||||
|  | ||||
| /** | ||||
|  * Map XRDS actions to URLs using base URLs. | ||||
|  * | ||||
|  * This interface specifies classes which write the XRDS file announcing | ||||
|  * the OMB server. An instance of an implementing class should be passed to | ||||
|  * OMB_Service_Provider->writeXRDS. | ||||
|  * This file is part of libomb | ||||
|  * | ||||
|  * PHP version 5 | ||||
|  * | ||||
| @@ -25,27 +17,56 @@ require_once 'constants.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 | ||||
|  **/ | ||||
|  * @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 | ||||
|  */ | ||||
|  | ||||
| class OMB_Base_URL_XRDS_Mapper implements OMB_XRDS_Mapper { | ||||
| require_once 'xrds_mapper.php'; | ||||
| require_once 'constants.php'; | ||||
|  | ||||
|   protected $urls; | ||||
| /** | ||||
|  * Map XRDS actions to URLs using base URLs | ||||
|  * | ||||
|  * This class realizes a simple mapping of action URIs to handler URLs. The | ||||
|  * target URLs are constructed using a base URL. | ||||
|  */ | ||||
| class OMB_Base_URL_XRDS_Mapper implements OMB_XRDS_Mapper | ||||
| { | ||||
|     protected $urls; | ||||
|  | ||||
|   public function __construct($oauth_base, $omb_base) { | ||||
|     $this->urls = array( | ||||
|         OAUTH_ENDPOINT_REQUEST => $oauth_base . 'requesttoken', | ||||
|         OAUTH_ENDPOINT_AUTHORIZE => $oauth_base . 'userauthorization', | ||||
|         OAUTH_ENDPOINT_ACCESS => $oauth_base . 'accesstoken', | ||||
|         OMB_ENDPOINT_POSTNOTICE => $omb_base . 'postnotice', | ||||
|         OMB_ENDPOINT_UPDATEPROFILE => $omb_base . 'updateprofile'); | ||||
|   } | ||||
|     /** | ||||
|      * Constructor | ||||
|      * | ||||
|      * Initialize the XRDS mapper with base URLs for OAuth and OMB endpoints. | ||||
|      * | ||||
|      * @param string $oauth_base The base URL for OAuth endpoints | ||||
|      * @param string $omb_base   The base URL for OMB endpoints | ||||
|      */ | ||||
|     public function __construct($oauth_base, $omb_base) | ||||
|     { | ||||
|         $this->urls = array( | ||||
|                 OAUTH_ENDPOINT_REQUEST => $oauth_base . 'requesttoken', | ||||
|                 OAUTH_ENDPOINT_AUTHORIZE => $oauth_base . 'userauthorization', | ||||
|                 OAUTH_ENDPOINT_ACCESS => $oauth_base . 'accesstoken', | ||||
|                 OMB_ENDPOINT_POSTNOTICE => $omb_base . 'postnotice', | ||||
|                 OMB_ENDPOINT_UPDATEPROFILE => $omb_base . 'updateprofile'); | ||||
|     } | ||||
|  | ||||
|   public function getURL($action) { | ||||
|     return $this->urls[$action]; | ||||
|   } | ||||
|     /** | ||||
|      * Fetch an URL for a specified action | ||||
|      * | ||||
|      * Returns the action URL for an action specified by the endpoint URI. | ||||
|      * | ||||
|      * @param string $action The endpoint URI | ||||
|      * | ||||
|      * @return string The action URL | ||||
|      */ | ||||
|     public function getURL($action) | ||||
|     { | ||||
|         return $this->urls[$action]; | ||||
|     } | ||||
| } | ||||
| ?> | ||||
|   | ||||
| @@ -20,15 +20,16 @@ | ||||
|  * 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 | ||||
|  **/ | ||||
|  * @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 | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|  * The OMB constants. | ||||
|  **/ | ||||
|  */ | ||||
|  | ||||
| define('OMB_VERSION_01', 'http://openmicroblogging.org/protocol/0.1'); | ||||
|  | ||||
| @@ -40,7 +41,7 @@ define('OMB_ENDPOINT_POSTNOTICE', OMB_VERSION . '/postNotice'); | ||||
|  | ||||
| /** | ||||
|  * The OAuth constants. | ||||
|  **/ | ||||
|  */ | ||||
|  | ||||
| define('OAUTH_NAMESPACE', 'http://oauth.net/core/1.0/'); | ||||
|  | ||||
|   | ||||
| @@ -1,4 +1,28 @@ | ||||
| <?php | ||||
| /** | ||||
|  * This file is part of libomb | ||||
|  * | ||||
|  * 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> | ||||
|  * @license http://www.gnu.org/licenses/agpl.html GNU AGPL 3.0 | ||||
|  * @version 0.1a-20090828 | ||||
|  * @link    http://adrianlang.de/libomb | ||||
|  */ | ||||
|  | ||||
| require_once 'OAuth.php'; | ||||
|  | ||||
| @@ -27,174 +51,162 @@ require_once 'OAuth.php'; | ||||
|  * Most of the parameters passed to these methods are unescaped and unverified | ||||
|  * user input. Therefore they should be handled with extra care to avoid | ||||
|  * security problems like SQL injections. | ||||
|  * | ||||
|  * 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_Datastore extends OAuthDataStore | ||||
| { | ||||
|  | ||||
| class OMB_Datastore extends OAuthDataStore { | ||||
|     /********* | ||||
|      * OAUTH * | ||||
|      *********/ | ||||
|  | ||||
|   /********* | ||||
|    * OAUTH * | ||||
|    *********/ | ||||
|     /** | ||||
|      * Revoke specified OAuth token | ||||
|      * | ||||
|      * Revokes the authorization token specified by $token_key. | ||||
|      * Throws exceptions in case of error. | ||||
|      * | ||||
|      * @param string $token_key The key of the token to be revoked | ||||
|      * | ||||
|      * @access public | ||||
|      */ | ||||
|     public function revoke_token($token_key) | ||||
|     { | ||||
|         throw new Exception(); | ||||
|     } | ||||
|  | ||||
|   /** | ||||
|    * Revoke specified OAuth token | ||||
|    * | ||||
|    * Revokes the authorization token specified by $token_key. | ||||
|    * Throws exceptions in case of error. | ||||
|    * | ||||
|    * @param string $token_key The key of the token to be revoked | ||||
|    * | ||||
|    * @access public | ||||
|    **/ | ||||
|   public function revoke_token($token_key) { | ||||
|     throw new Exception(); | ||||
|   } | ||||
|     /** | ||||
|      * Authorize specified OAuth token | ||||
|      * | ||||
|      * Authorizes the authorization token specified by $token_key. | ||||
|      * Throws exceptions in case of error. | ||||
|      * | ||||
|      * @param string $token_key The key of the token to be authorized | ||||
|      * | ||||
|      * @access public | ||||
|      */ | ||||
|     public function authorize_token($token_key) | ||||
|     { | ||||
|         throw new Exception(); | ||||
|     } | ||||
|  | ||||
|   /** | ||||
|    * Authorize specified OAuth token | ||||
|    * | ||||
|    * Authorizes the authorization token specified by $token_key. | ||||
|    * Throws exceptions in case of error. | ||||
|    * | ||||
|    * @param string $token_key The key of the token to be authorized | ||||
|    * | ||||
|    * @access public | ||||
|    **/ | ||||
|   public function authorize_token($token_key) { | ||||
|     throw new Exception(); | ||||
|   } | ||||
|     /********* | ||||
|      *  OMB  * | ||||
|      *********/ | ||||
|  | ||||
|   /********* | ||||
|    *  OMB  * | ||||
|    *********/ | ||||
|     /** | ||||
|      * Get profile by identifying URI | ||||
|      * | ||||
|      * Returns an OMB_Profile object representing the OMB profile identified by | ||||
|      * $identifier_uri. | ||||
|      * Returns null if there is no such OMB profile. | ||||
|      * Throws exceptions in case of other error. | ||||
|      * | ||||
|      * @param string $identifier_uri The OMB identifier URI specifying the | ||||
|      *                               requested profile | ||||
|      * | ||||
|      * @access public | ||||
|      * | ||||
|      * @return OMB_Profile The corresponding profile | ||||
|      */ | ||||
|     public function getProfile($identifier_uri) | ||||
|     { | ||||
|         throw new Exception(); | ||||
|     } | ||||
|  | ||||
|   /** | ||||
|    * Get profile by identifying URI | ||||
|    * | ||||
|    * Returns an OMB_Profile object representing the OMB profile identified by | ||||
|    * $identifier_uri. | ||||
|    * Returns null if there is no such OMB profile. | ||||
|    * Throws exceptions in case of other error. | ||||
|    * | ||||
|    * @param string $identifier_uri The OMB identifier URI specifying the | ||||
|    *                               requested profile | ||||
|    * | ||||
|    * @access public | ||||
|    * | ||||
|    * @return OMB_Profile The corresponding profile | ||||
|    **/ | ||||
|   public function getProfile($identifier_uri) { | ||||
|     throw new Exception(); | ||||
|   } | ||||
|     /** | ||||
|      * Save passed profile | ||||
|      * | ||||
|      * Stores the OMB profile $profile. Overwrites an existing entry. | ||||
|      * Throws exceptions in case of error. | ||||
|      * | ||||
|      * @param OMB_Profile $profile The OMB profile which should be saved | ||||
|      * | ||||
|      * @access public | ||||
|      */ | ||||
|     public function saveProfile($profile) | ||||
|     { | ||||
|         throw new Exception(); | ||||
|     } | ||||
|  | ||||
|   /** | ||||
|    * Save passed profile | ||||
|    * | ||||
|    * Stores the OMB profile $profile. Overwrites an existing entry. | ||||
|    * Throws exceptions in case of error. | ||||
|    * | ||||
|    * @param OMB_Profile $profile   The OMB profile which should be saved | ||||
|    * | ||||
|    * @access public | ||||
|    **/ | ||||
|   public function saveProfile($profile) { | ||||
|     throw new Exception(); | ||||
|   } | ||||
|     /** | ||||
|      * Save passed notice | ||||
|      * | ||||
|      * Stores the OMB notice $notice. The datastore may change the passed | ||||
|      * notice. This might by necessary for URIs depending on a database key. | ||||
|      * Note that it is the user’s duty to present a mechanism for his | ||||
|      * OMB_Datastore to appropriately change his OMB_Notice. | ||||
|      * Throws exceptions in case of error. | ||||
|      * | ||||
|      * @param OMB_Notice &$notice The OMB notice which should be saved | ||||
|      * | ||||
|      * @access public | ||||
|      */ | ||||
|     public function saveNotice(&$notice) | ||||
|     { | ||||
|         throw new Exception(); | ||||
|     } | ||||
|  | ||||
|   /** | ||||
|    * Save passed notice | ||||
|    * | ||||
|    * Stores the OMB notice $notice. The datastore may change the passed notice. | ||||
|    * This might by neccessary for URIs depending on a database key. Note that | ||||
|    * it is the user’s duty to present a mechanism for his OMB_Datastore to | ||||
|    * appropriately change his OMB_Notice. TODO: Ugly. | ||||
|    * Throws exceptions in case of error. | ||||
|    * | ||||
|    * @param OMB_Notice $notice The OMB notice which should be saved | ||||
|    * | ||||
|    * @access public | ||||
|    **/ | ||||
|   public function saveNotice(&$notice) { | ||||
|     throw new Exception(); | ||||
|   } | ||||
|     /** | ||||
|      * Get subscriptions of a given profile | ||||
|      * | ||||
|      * Returns an array containing subscription informations for the specified | ||||
|      * profile. Every array entry should in turn be an array with keys | ||||
|      *   'uri´: The identifier URI of the subscriber | ||||
|      *   'token´: The subscribe token | ||||
|      *   'secret´: The secret token | ||||
|      * Throws exceptions in case of error. | ||||
|      * | ||||
|      * @param string $subscribed_user_uri The OMB identifier URI specifying the | ||||
|      *                                    subscribed profile | ||||
|      * | ||||
|      * @access public | ||||
|      * | ||||
|      * @return mixed An array containing the subscriptions or 0 if no | ||||
|      *               subscription has been found. | ||||
|      */ | ||||
|     public function getSubscriptions($subscribed_user_uri) | ||||
|     { | ||||
|         throw new Exception(); | ||||
|     } | ||||
|  | ||||
|   /** | ||||
|    * Get subscriptions of a given profile | ||||
|    * | ||||
|    * Returns an array containing subscription informations for the specified | ||||
|    * profile. Every array entry should in turn be an array with keys | ||||
|    *   'uri´: The identifier URI of the subscriber | ||||
|    *   'token´: The subscribe token | ||||
|    *   'secret´: The secret token | ||||
|    * Throws exceptions in case of error. | ||||
|    * | ||||
|    * @param string $subscribed_user_uri The OMB identifier URI specifying the | ||||
|    *                                    subscribed profile | ||||
|    * | ||||
|    * @access public | ||||
|    * | ||||
|    * @return mixed An array containing the subscriptions or 0 if no | ||||
|    *               subscription has been found. | ||||
|    **/ | ||||
|   public function getSubscriptions($subscribed_user_uri) { | ||||
|     throw new Exception(); | ||||
|   } | ||||
|     /** | ||||
|      * Delete a subscription | ||||
|      * | ||||
|      * Deletes the subscription from $subscriber_uri to $subscribed_user_uri. | ||||
|      * Throws exceptions in case of error. | ||||
|      * | ||||
|      * @param string $subscriber_uri      The OMB identifier URI specifying the | ||||
|      *                                    subscribing profile | ||||
|      * | ||||
|      * @param string $subscribed_user_uri The OMB identifier URI specifying the | ||||
|      *                                    subscribed profile | ||||
|      * | ||||
|      * @access public | ||||
|      */ | ||||
|     public function deleteSubscription($subscriber_uri, $subscribed_user_uri) | ||||
|     { | ||||
|         throw new Exception(); | ||||
|     } | ||||
|  | ||||
|   /** | ||||
|    * Delete a subscription | ||||
|    * | ||||
|    * Deletes the subscription from $subscriber_uri to $subscribed_user_uri. | ||||
|    * Throws exceptions in case of error. | ||||
|    * | ||||
|    * @param string $subscriber_uri      The OMB identifier URI specifying the | ||||
|    *                                    subscribing profile | ||||
|    * | ||||
|    * @param string $subscribed_user_uri The OMB identifier URI specifying the | ||||
|    *                                    subscribed profile | ||||
|    * | ||||
|    * @access public | ||||
|    **/ | ||||
|   public function deleteSubscription($subscriber_uri, $subscribed_user_uri) { | ||||
|     throw new Exception(); | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * Save a subscription | ||||
|    * | ||||
|    * Saves the subscription from $subscriber_uri to $subscribed_user_uri. | ||||
|    * Throws exceptions in case of error. | ||||
|    * | ||||
|    * @param string     $subscriber_uri      The OMB identifier URI specifying | ||||
|    *                                        the subscribing profile | ||||
|    * | ||||
|    * @param string     $subscribed_user_uri The OMB identifier URI specifying | ||||
|    *                                        the subscribed profile | ||||
|    * @param OAuthToken $token               The access token | ||||
|    * | ||||
|    * @access public | ||||
|    **/ | ||||
|   public function saveSubscription($subscriber_uri, $subscribed_user_uri, | ||||
|                                                                        $token) { | ||||
|     throw new Exception(); | ||||
|   } | ||||
|     /** | ||||
|      * Save a subscription | ||||
|      * | ||||
|      * Saves the subscription from $subscriber_uri to $subscribed_user_uri. | ||||
|      * Throws exceptions in case of error. | ||||
|      * | ||||
|      * @param string     $subscriber_uri      The OMB identifier URI specifying | ||||
|      *                                            the subscribing profile | ||||
|      * | ||||
|      * @param string     $subscribed_user_uri The OMB identifier URI specifying | ||||
|      *                                            the subscribed profile | ||||
|      * @param OAuthToken $token               The access token | ||||
|      * | ||||
|      * @access public | ||||
|      */ | ||||
|     public function saveSubscription($subscriber_uri, $subscribed_user_uri, | ||||
|                                      $token) | ||||
|     { | ||||
|         throw new Exception(); | ||||
|     } | ||||
| } | ||||
| ?> | ||||
|   | ||||
| @@ -1,11 +1,6 @@ | ||||
| <?php | ||||
|  | ||||
| require_once 'Validate.php'; | ||||
|  | ||||
| /** | ||||
|  * Helper functions for libomb | ||||
|  * | ||||
|  * This file contains helper functions for libomb. | ||||
|  * This file is part of libomb | ||||
|  * | ||||
|  * PHP version 5 | ||||
|  * | ||||
| @@ -22,78 +17,88 @@ require_once 'Validate.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 | ||||
|  **/ | ||||
|  * @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 | ||||
|  */ | ||||
|  | ||||
| class OMB_Helper { | ||||
| require_once 'Validate.php'; | ||||
|  | ||||
|   /** | ||||
|    * Non-scalar constants | ||||
|    * | ||||
|    * The set of OMB and OAuth Services an OMB Server has to implement. | ||||
|    */ | ||||
| /** | ||||
|  * Helper functions for libomb | ||||
|  * | ||||
|  * This class contains helper functions for libomb. | ||||
|  */ | ||||
| class OMB_Helper | ||||
| { | ||||
|  | ||||
|   public static $OMB_SERVICES = | ||||
|     array(OMB_ENDPOINT_UPDATEPROFILE, OMB_ENDPOINT_POSTNOTICE); | ||||
|   public static $OAUTH_SERVICES = | ||||
|     array(OAUTH_ENDPOINT_REQUEST, OAUTH_ENDPOINT_AUTHORIZE, OAUTH_ENDPOINT_ACCESS); | ||||
|     /** | ||||
|      * Non-scalar constants | ||||
|      * | ||||
|      * The set of OMB and OAuth Services an OMB Server has to implement. | ||||
|      */ | ||||
|  | ||||
|   /** | ||||
|    * Validate URL | ||||
|    * | ||||
|    * Basic URL validation. Currently http, https, ftp and gopher are supported | ||||
|    * schemes. | ||||
|    * | ||||
|    * @param string $url The URL which is to be validated. | ||||
|    * | ||||
|    * @return bool Whether URL is valid. | ||||
|    * | ||||
|    * @access public | ||||
|    */ | ||||
|   public static function validateURL($url) { | ||||
|     return Validate::uri($url, array('allowed_schemes' => array('http', 'https', | ||||
|             'gopher', 'ftp'))); | ||||
|   } | ||||
|     public static $OMB_SERVICES   = array(OMB_ENDPOINT_UPDATEPROFILE, | ||||
|                                           OMB_ENDPOINT_POSTNOTICE); | ||||
|     public static $OAUTH_SERVICES = array(OAUTH_ENDPOINT_REQUEST, | ||||
|                                           OAUTH_ENDPOINT_AUTHORIZE, | ||||
|                                           OAUTH_ENDPOINT_ACCESS); | ||||
|  | ||||
|   /** | ||||
|    * Validate Media type | ||||
|    * | ||||
|    * Basic Media type validation. Checks for valid maintype and correct format. | ||||
|    * | ||||
|    * @param string $mediatype The Media type which is to be validated. | ||||
|    * | ||||
|    * @return bool Whether media type is valid. | ||||
|    * | ||||
|    * @access public | ||||
|    */ | ||||
|   public static function validateMediaType($mediatype) { | ||||
|     if (0 === preg_match('/^(\w+)\/([\w\d-+.]+)$/', $mediatype, $subtypes)) { | ||||
|       return false; | ||||
|     /** | ||||
|      * Validate URL | ||||
|      * | ||||
|      * Basic URL validation. Currently http, https, ftp and gopher are supported | ||||
|      * schemes. | ||||
|      * | ||||
|      * @param string $url The URL which is to be validated. | ||||
|      * | ||||
|      * @return bool Whether URL is valid. | ||||
|      * | ||||
|      * @access public | ||||
|      */ | ||||
|     public static function validateURL($url) | ||||
|     { | ||||
|         return Validate::uri($url, array('allowed_schemes' => array('http', | ||||
|                                                     'https', 'gopher', 'ftp'))); | ||||
|     } | ||||
|     if (!in_array(strtolower($subtypes[1]), array('application', 'audio', 'image', | ||||
|               'message', 'model', 'multipart', 'text', 'video'))) { | ||||
|       return false; | ||||
|     } | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * Remove escaping from request parameters | ||||
|    * | ||||
|    * Neutralise the evil effects of magic_quotes_gpc in the current request. | ||||
|    * This is used before handing a request off to OAuthRequest::from_request. | ||||
|    * Many thanks to Ciaran Gultnieks for this fix. | ||||
|    * | ||||
|    * @access public | ||||
|    */ | ||||
|   public static function removeMagicQuotesFromRequest() { | ||||
|     if(get_magic_quotes_gpc() == 1) { | ||||
|       $_POST = array_map('stripslashes', $_POST); | ||||
|       $_GET = array_map('stripslashes', $_GET); | ||||
|     /** | ||||
|      * Validate Media type | ||||
|      * | ||||
|      * Basic Media type validation. Checks for valid maintype and correct | ||||
|      * format. | ||||
|      * | ||||
|      * @param string $mediatype The Media type which is to be validated. | ||||
|      * | ||||
|      * @return bool Whether media type is valid. | ||||
|      * | ||||
|      * @access public | ||||
|      */ | ||||
|     public static function validateMediaType($mediatype) | ||||
|     { | ||||
|         return preg_match('/^(\w+)\/([\w\d-+.]+)$/', $mediatype, $subtypes) > 0 | ||||
|                && | ||||
|                in_array(strtolower($subtypes[1]), array('application', 'audio', | ||||
|                'image', 'message', 'model', 'multipart', 'text', 'video')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Remove escaping from request parameters | ||||
|      * | ||||
|      * Neutralise the evil effects of magic_quotes_gpc in the current request. | ||||
|      * This is used before handing a request off to OAuthRequest::from_request. | ||||
|      * Many thanks to Ciaran Gultnieks for this fix. | ||||
|      * | ||||
|      * @access public | ||||
|      */ | ||||
|     public static function removeMagicQuotesFromRequest() | ||||
|     { | ||||
|         if (get_magic_quotes_gpc() === 1) { | ||||
|             $_POST = array_map('stripslashes', $_POST); | ||||
|             $_GET  = array_map('stripslashes', $_GET); | ||||
|         } | ||||
|     } | ||||
|   } | ||||
| } | ||||
| ?> | ||||
|   | ||||
| @@ -1,8 +1,6 @@ | ||||
| <?php | ||||
| /** | ||||
|  * Exception stating that a passed parameter is invalid | ||||
|  * | ||||
|  * This exception is raised when a parameter does not obey the OMB standard. | ||||
|  * This file is part of libomb | ||||
|  * | ||||
|  * PHP version 5 | ||||
|  * | ||||
| @@ -19,14 +17,36 @@ | ||||
|  * 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_InvalidParameterException extends Exception { | ||||
|   public function __construct($value, $type, $parameter) { | ||||
|     parent::__construct("Invalid value $value for parameter $parameter in $type"); | ||||
|   } | ||||
|  * @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 | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|  * Exception stating that a passed parameter is invalid | ||||
|  * | ||||
|  * This exception is raised when a parameter does not obey the OMB standard. | ||||
|  */ | ||||
| class OMB_InvalidParameterException extends Exception | ||||
| { | ||||
|     /** | ||||
|      * Constructor | ||||
|      * | ||||
|      * Creates a new exception based on a parameter name, value, and object | ||||
|      * type. | ||||
|      * | ||||
|      * @param string $value     The wrong value passed | ||||
|      * @param string $type      The object type the parameter belongs to; | ||||
|      *                          Currently OMB uses profiles and notices | ||||
|      * @param string $parameter The name of the parameter the wrong value has | ||||
|      *                          been passed for | ||||
|      */ | ||||
|     public function __construct($value, $type, $parameter) | ||||
|     { | ||||
|         parent::__construct("Invalid value ‘${value}’ for parameter " . | ||||
|                             "‘${parameter}’ in $type"); | ||||
|     } | ||||
| } | ||||
| ?> | ||||
|   | ||||
| @@ -1,9 +1,6 @@ | ||||
| <?php | ||||
| /** | ||||
|  * Exception stating that a requested url does not resolve to a valid yadis | ||||
|  * | ||||
|  * This exception is raised when OMB_Service is not able to discover a valid | ||||
|  * yadis location with XRDS. | ||||
|  * This file is part of libomb | ||||
|  * | ||||
|  * PHP version 5 | ||||
|  * | ||||
| @@ -20,12 +17,21 @@ | ||||
|  * 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_InvalidYadisException extends Exception { | ||||
|  * @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 | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|  * Exception stating that a requested url does not resolve to a valid yadis | ||||
|  * | ||||
|  * This exception is raised when OMB_Service is not able to discover a valid | ||||
|  * yadis location with XRDS. | ||||
|  */ | ||||
| class OMB_InvalidYadisException extends Exception | ||||
| { | ||||
|  | ||||
| } | ||||
| ?> | ||||
|   | ||||
| @@ -1,15 +1,6 @@ | ||||
| <?php | ||||
| require_once 'invalidparameterexception.php'; | ||||
| require_once 'Validate.php'; | ||||
| require_once 'helper.php'; | ||||
|  | ||||
| /** | ||||
|  * OMB Notice representation | ||||
|  * | ||||
|  * This class represents an OMB notice. | ||||
|  * | ||||
|  * Do not call the setters with null values. Instead, if you want to delete a | ||||
|  * field, pass an empty string. The getters will return null for empty fields. | ||||
|  * This file is part of libomb | ||||
|  * | ||||
|  * PHP version 5 | ||||
|  * | ||||
| @@ -26,247 +17,278 @@ 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 | ||||
|  **/ | ||||
|  * @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 | ||||
|  */ | ||||
|  | ||||
| class OMB_Notice { | ||||
|   protected $author; | ||||
|   protected $uri; | ||||
|   protected $content; | ||||
|   protected $url; | ||||
|   protected $license_url; /* url is an own addition for clarification. */ | ||||
|   protected $seealso_url; /* url is an own addition for clarification. */ | ||||
|   protected $seealso_disposition; | ||||
|   protected $seealso_mediatype; | ||||
|   protected $seealso_license_url; /* url is an addition for clarification. */ | ||||
| require_once 'invalidparameterexception.php'; | ||||
| require_once 'Validate.php'; | ||||
| require_once 'helper.php'; | ||||
|  | ||||
|   /* The notice as OMB param array. Cached and rebuild on usage. | ||||
|      false while outdated. */ | ||||
|   protected $param_array; | ||||
| /** | ||||
|  * OMB Notice representation | ||||
|  * | ||||
|  * This class represents an OMB notice. | ||||
|  * | ||||
|  * Do not call the setters with null values. Instead, if you want to delete a | ||||
|  * field, pass an empty string. The getters will return null for empty fields. | ||||
|  */ | ||||
| class OMB_Notice | ||||
| { | ||||
|     protected $author; | ||||
|     protected $uri; | ||||
|     protected $content; | ||||
|     protected $url; | ||||
|     protected $license_url; /* url is an own addition for clarification. */ | ||||
|     protected $seealso_url; /* url is an own addition for clarification. */ | ||||
|     protected $seealso_disposition; | ||||
|     protected $seealso_mediatype; | ||||
|     protected $seealso_license_url; /* url is an addition for clarification. */ | ||||
|  | ||||
|   /** | ||||
|    * Constructor for OMB_Notice | ||||
|    * | ||||
|    * Initializes the OMB_Notice object with author, uri and content. | ||||
|    * These parameters are mandatory for postNotice. | ||||
|    * | ||||
|    * @param object $author  An OMB_Profile object representing the author of the | ||||
|    *                        notice. | ||||
|    * @param string $uri     The notice URI as defined by the OMB. A unique and | ||||
|    *                        unchanging identifier for a notice. | ||||
|    * @param string $content The content of the notice. 140 chars recommended, | ||||
|    *                        but there is no limit. | ||||
|    * | ||||
|    * @access public | ||||
|    */ | ||||
|   public function __construct($author, $uri, $content) { | ||||
|     $this->content = $content; | ||||
|     if (is_null($author)) { | ||||
|       throw new OMB_InvalidParameterException('', 'notice', 'omb_listenee'); | ||||
|     } | ||||
|     $this->author = $author; | ||||
|     /* The notice as OMB param array. Cached and rebuild on usage. | ||||
|        false while outdated. */ | ||||
|     protected $param_array; | ||||
|  | ||||
|     if (!Validate::uri($uri)) { | ||||
|       throw new OMB_InvalidParameterException($uri, 'notice', 'omb_notice'); | ||||
|     } | ||||
|     $this->uri = $uri; | ||||
|     /** | ||||
|      * Constructor for OMB_Notice | ||||
|      * | ||||
|      * Initializes the OMB_Notice object with author, uri and content. | ||||
|      * These parameters are mandatory for postNotice. | ||||
|      * | ||||
|      * @param object $author  An OMB_Profile object representing the author of | ||||
|      *                        the notice. | ||||
|      * @param string $uri     The notice URI as defined by the OMB. A unique and | ||||
|      *                        never changing identifier for a notice. | ||||
|      * @param string $content The content of the notice. 140 chars recommended, | ||||
|      *                        but there is no limit. | ||||
|      * | ||||
|      * @access public | ||||
|      */ | ||||
|     public function __construct($author, $uri, $content) | ||||
|     { | ||||
|         $this->content = $content; | ||||
|         if (is_null($author)) { | ||||
|             throw new OMB_InvalidParameterException('', 'notice', 'omb_listenee'); | ||||
|         } | ||||
|         $this->author = $author; | ||||
|  | ||||
|     $this->param_array = false; | ||||
|   } | ||||
|         if (!Validate::uri($uri)) { | ||||
|             throw new OMB_InvalidParameterException($uri, 'notice', 'omb_notice'); | ||||
|         } | ||||
|         $this->uri = $uri; | ||||
|  | ||||
|   /** | ||||
|    * Returns the notice as array | ||||
|    * | ||||
|    * The method returns an array which contains the whole notice as array. The | ||||
|    * array is cached and only rebuilt on changes of the notice. | ||||
|    * Empty optional values are not passed. | ||||
|    * | ||||
|    *  @access  public | ||||
|    *  @returns array The notice as parameter array | ||||
|    */ | ||||
|   public function asParameters() { | ||||
|     if ($this->param_array !== false) { | ||||
|       return $this->param_array; | ||||
|         $this->param_array = false; | ||||
|     } | ||||
|  | ||||
|     $this->param_array = array( | ||||
|                  'omb_notice' => $this->uri, | ||||
|                  'omb_notice_content' => $this->content); | ||||
|     /** | ||||
|      * Return the notice as array | ||||
|      * | ||||
|      * Returns an array which contains the whole notice as array. The array is | ||||
|      * cached and only rebuilt on changes of the notice. | ||||
|      * Empty optional values are not passed. | ||||
|      * | ||||
|      * @access public | ||||
|      * @return array The notice as parameter array | ||||
|      */ | ||||
|     public function asParameters() | ||||
|     { | ||||
|         if ($this->param_array !== false) { | ||||
|             return $this->param_array; | ||||
|         } | ||||
|  | ||||
|     if (!is_null($this->url)) | ||||
|       $this->param_array['omb_notice_url'] = $this->url; | ||||
|         $this->param_array = array( | ||||
|                                  'omb_notice' => $this->uri, | ||||
|                                  'omb_notice_content' => $this->content); | ||||
|  | ||||
|     if (!is_null($this->license_url)) | ||||
|       $this->param_array['omb_notice_license'] = $this->license_url; | ||||
|         if (!is_null($this->url)) | ||||
|             $this->param_array['omb_notice_url'] = $this->url; | ||||
|  | ||||
|     if (!is_null($this->seealso_url)) { | ||||
|       $this->param_array['omb_seealso'] = $this->seealso_url; | ||||
|         if (!is_null($this->license_url)) | ||||
|             $this->param_array['omb_notice_license'] = $this->license_url; | ||||
|  | ||||
|       /* This is actually a free interpretation of the OMB standard. We assume | ||||
|          that additional seealso parameters are not of any use if seealso itself | ||||
|          is not set. */ | ||||
|       if (!is_null($this->seealso_disposition)) | ||||
|         $this->param_array['omb_seealso_disposition'] = | ||||
|         if (!is_null($this->seealso_url)) { | ||||
|             $this->param_array['omb_seealso'] = $this->seealso_url; | ||||
|  | ||||
|             /* This is actually a free interpretation of the OMB standard. We | ||||
|                assume that additional seealso parameters are not of any use if | ||||
|                seealso itself is not set. */ | ||||
|             if (!is_null($this->seealso_disposition)) | ||||
|                 $this->param_array['omb_seealso_disposition'] = | ||||
|                                                      $this->seealso_disposition; | ||||
|  | ||||
|       if (!is_null($this->seealso_mediatype)) | ||||
|         $this->param_array['omb_seealso_mediatype'] = $this->seealso_mediatype; | ||||
|             if (!is_null($this->seealso_mediatype)) | ||||
|                 $this->param_array['omb_seealso_mediatype'] = | ||||
|                                                        $this->seealso_mediatype; | ||||
|  | ||||
|       if (!is_null($this->seealso_license_url)) | ||||
|         $this->param_array['omb_seealso_license'] = $this->seealso_license_url; | ||||
|     } | ||||
|     return $this->param_array; | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * Builds an OMB_Notice object from array | ||||
|    * | ||||
|    * The method builds an OMB_Notice object from the passed parameters array. | ||||
|    * The array MUST provide a notice URI and content. The array fields HAVE TO | ||||
|    * be named according to the OMB standard, i. e. omb_notice_* and | ||||
|    * omb_seealso_*. Values are handled as not passed if the corresponding array | ||||
|    * fields are not set or the empty string. | ||||
|    * | ||||
|    * @param object $author     An OMB_Profile object representing the author of | ||||
|    *                           the notice. | ||||
|    * @param string $parameters An array containing the notice parameters. | ||||
|    * | ||||
|    * @access public | ||||
|    * | ||||
|    * @returns OMB_Notice The built OMB_Notice. | ||||
|    */ | ||||
|   public static function fromParameters($author, $parameters) { | ||||
|     $notice = new OMB_Notice($author, $parameters['omb_notice'], | ||||
|                              $parameters['omb_notice_content']); | ||||
|  | ||||
|     if (isset($parameters['omb_notice_url'])) { | ||||
|       $notice->setURL($parameters['omb_notice_url']); | ||||
|             if (!is_null($this->seealso_license_url)) | ||||
|                 $this->param_array['omb_seealso_license'] = | ||||
|                                                      $this->seealso_license_url; | ||||
|         } | ||||
|         return $this->param_array; | ||||
|     } | ||||
|  | ||||
|     if (isset($parameters['omb_notice_license'])) { | ||||
|       $notice->setLicenseURL($parameters['omb_notice_license']); | ||||
|     /** | ||||
|      * Build an OMB_Notice object from array | ||||
|      * | ||||
|      * Builds an OMB_Notice object from the passed parameters array. The array | ||||
|      * MUST provide a notice URI and content. The array fields HAVE TO be named | ||||
|      * according to the OMB standard, i. e. omb_notice_* and omb_seealso_*. | ||||
|      * Values are handled as not passed if the corresponding array fields are | ||||
|      * not set or the empty string. | ||||
|      * | ||||
|      * @param object $author     An OMB_Profile object representing the author | ||||
|      *                           of the notice. | ||||
|      * @param string $parameters An array containing the notice parameters. | ||||
|      * | ||||
|      * @access public | ||||
|      * | ||||
|      * @returns OMB_Notice The built OMB_Notice. | ||||
|      */ | ||||
|     public static function fromParameters($author, $parameters) | ||||
|     { | ||||
|         $notice = new OMB_Notice($author, $parameters['omb_notice'], | ||||
|                                              $parameters['omb_notice_content']); | ||||
|  | ||||
|         if (isset($parameters['omb_notice_url'])) { | ||||
|             $notice->setURL($parameters['omb_notice_url']); | ||||
|         } | ||||
|  | ||||
|         if (isset($parameters['omb_notice_license'])) { | ||||
|             $notice->setLicenseURL($parameters['omb_notice_license']); | ||||
|         } | ||||
|  | ||||
|         if (isset($parameters['omb_seealso'])) { | ||||
|             $notice->setSeealsoURL($parameters['omb_seealso']); | ||||
|         } | ||||
|  | ||||
|         if (isset($parameters['omb_seealso_disposition'])) { | ||||
|             $notice->setSeealsoDisposition($parameters['omb_seealso_disposition']); | ||||
|         } | ||||
|  | ||||
|         if (isset($parameters['omb_seealso_mediatype'])) { | ||||
|             $notice->setSeealsoMediatype($parameters['omb_seealso_mediatype']); | ||||
|         } | ||||
|  | ||||
|         if (isset($parameters['omb_seealso_license'])) { | ||||
|             $notice->setSeealsoLicenseURL($parameters['omb_seealso_license']); | ||||
|         } | ||||
|         return $notice; | ||||
|     } | ||||
|  | ||||
|     if (isset($parameters['omb_seealso'])) { | ||||
|       $notice->setSeealsoURL($parameters['omb_seealso']); | ||||
|     public function getAuthor() | ||||
|     { | ||||
|         return $this->author; | ||||
|     } | ||||
|  | ||||
|     if (isset($parameters['omb_seealso_disposition'])) { | ||||
|       $notice->setSeealsoDisposition($parameters['omb_seealso_disposition']); | ||||
|     public function getIdentifierURI() | ||||
|     { | ||||
|         return $this->uri; | ||||
|     } | ||||
|  | ||||
|     if (isset($parameters['omb_seealso_mediatype'])) { | ||||
|       $notice->setSeealsoMediatype($parameters['omb_seealso_mediatype']); | ||||
|     public function getContent() | ||||
|     { | ||||
|         return $this->content; | ||||
|     } | ||||
|  | ||||
|     if (isset($parameters['omb_seealso_license'])) { | ||||
|       $notice->setSeealsoLicenseURL($parameters['omb_seealso_license']); | ||||
|     public function getURL() | ||||
|     { | ||||
|         return $this->url; | ||||
|     } | ||||
|     return $notice; | ||||
|   } | ||||
|  | ||||
|   public function getAuthor() { | ||||
|     return $this->author; | ||||
|   } | ||||
|  | ||||
|   public function getIdentifierURI() { | ||||
|     return $this->uri; | ||||
|   } | ||||
|  | ||||
|   public function getContent() { | ||||
|     return $this->content; | ||||
|   } | ||||
|  | ||||
|   public function getURL() { | ||||
|     return $this->url; | ||||
|   } | ||||
|  | ||||
|   public function getLicenseURL() { | ||||
|     return $this->license_url; | ||||
|   } | ||||
|  | ||||
|   public function getSeealsoURL() { | ||||
|     return $this->seealso_url; | ||||
|   } | ||||
|  | ||||
|   public function getSeealsoDisposition() { | ||||
|     return $this->seealso_disposition; | ||||
|   } | ||||
|  | ||||
|   public function getSeealsoMediatype() { | ||||
|     return $this->seealso_mediatype; | ||||
|   } | ||||
|  | ||||
|   public function getSeealsoLicenseURL() { | ||||
|     return $this->seealso_license_url; | ||||
|   } | ||||
|  | ||||
|   public function setURL($url) { | ||||
|     if ($url === '') { | ||||
|       $url = null; | ||||
|     } elseif (!OMB_Helper::validateURL($url)) { | ||||
|       throw new OMB_InvalidParameterException($url, 'notice', 'omb_notice_url'); | ||||
|     public function getLicenseURL() | ||||
|     { | ||||
|         return $this->license_url; | ||||
|     } | ||||
|     $this->url = $url; | ||||
|     $this->param_array = false; | ||||
|   } | ||||
|  | ||||
|   public function setLicenseURL($license_url) { | ||||
|     if ($license_url === '') { | ||||
|       $license_url = null; | ||||
|     } elseif (!OMB_Helper::validateURL($license_url)) { | ||||
|       throw new OMB_InvalidParameterException($license_url, 'notice', | ||||
|                                               'omb_notice_license'); | ||||
|     public function getSeealsoURL() | ||||
|     { | ||||
|         return $this->seealso_url; | ||||
|     } | ||||
|     $this->license_url = $license_url; | ||||
|     $this->param_array = false; | ||||
|   } | ||||
|  | ||||
|   public function setSeealsoURL($seealso_url) { | ||||
|     if ($seealso_url === '') { | ||||
|       $seealso_url = null; | ||||
|     } elseif (!OMB_Helper::validateURL($seealso_url)) { | ||||
|       throw new OMB_InvalidParameterException($seealso_url, 'notice', | ||||
|                                               'omb_seealso'); | ||||
|     public function getSeealsoDisposition() | ||||
|     { | ||||
|         return $this->seealso_disposition; | ||||
|     } | ||||
|     $this->seealso_url = $seealso_url; | ||||
|     $this->param_array = false; | ||||
|   } | ||||
|  | ||||
|   public function setSeealsoDisposition($seealso_disposition) { | ||||
|     if ($seealso_disposition === '') { | ||||
|       $seealso_disposition = null; | ||||
|     } elseif ($seealso_disposition !== 'link' && $seealso_disposition !== 'inline') { | ||||
|       throw new OMB_InvalidParameterException($seealso_disposition, 'notice', | ||||
|                                               'omb_seealso_disposition'); | ||||
|     public function getSeealsoMediatype() | ||||
|     { | ||||
|         return $this->seealso_mediatype; | ||||
|     } | ||||
|     $this->seealso_disposition = $seealso_disposition; | ||||
|     $this->param_array = false; | ||||
|   } | ||||
|  | ||||
|   public function setSeealsoMediatype($seealso_mediatype) { | ||||
|     if ($seealso_mediatype === '') { | ||||
|       $seealso_mediatype = null; | ||||
|     } elseif (!OMB_Helper::validateMediaType($seealso_mediatype)) { | ||||
|       throw new OMB_InvalidParameterException($seealso_mediatype, 'notice', | ||||
|                                               'omb_seealso_mediatype'); | ||||
|     public function getSeealsoLicenseURL() | ||||
|     { | ||||
|         return $this->seealso_license_url; | ||||
|     } | ||||
|     $this->seealso_mediatype = $seealso_mediatype; | ||||
|     $this->param_array = false; | ||||
|   } | ||||
|  | ||||
|   public function setSeealsoLicenseURL($seealso_license_url) { | ||||
|     if ($seealso_license_url === '') { | ||||
|       $seealso_license_url = null; | ||||
|     } elseif (!OMB_Helper::validateURL($seealso_license_url)) { | ||||
|       throw new OMB_InvalidParameterException($seealso_license_url, 'notice', | ||||
|                                               'omb_seealso_license'); | ||||
|     public function setURL($url) | ||||
|     { | ||||
|         $this->setVal('notice_url', $url, 'OMB_Helper::validateURL', 'url'); | ||||
|     } | ||||
|  | ||||
|     public function setLicenseURL($license_url) | ||||
|     { | ||||
|         $this->setVal('license', $license_url, 'OMB_Helper::validateURL', | ||||
|                       'license_url'); | ||||
|     } | ||||
|  | ||||
|     public function setSeealsoURL($seealso_url) | ||||
|     { | ||||
|         $this->setVal('seealso', $seealso_url, 'OMB_Helper::validateURL', | ||||
|                       'seealso_url'); | ||||
|     } | ||||
|  | ||||
|     public function setSeealsoDisposition($seealso_disposition) | ||||
|     { | ||||
|         $this->setVal('seealso_disposition', $seealso_disposition, | ||||
|                       'OMB_Notice::validateDisposition'); | ||||
|     } | ||||
|  | ||||
|     protected static function validateDisposition($str) | ||||
|     { | ||||
|         return in_array($str, array('link', 'inline')); | ||||
|     } | ||||
|  | ||||
|     public function setSeealsoMediatype($seealso_mediatype) | ||||
|     { | ||||
|         $this->setVal('seealso_mediatype', $seealso_mediatype, | ||||
|                       'OMB_Helper::validateMediaType'); | ||||
|     } | ||||
|  | ||||
|     public function setSeealsoLicenseURL($seealso_license_url) | ||||
|     { | ||||
|         $this->setVal('seealso_license', $seealso_license_url, | ||||
|                       'OMB_Helper::validateURL', 'seealso_license_url'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Set a value | ||||
|      * | ||||
|      * Updates a value specified by a parameter name and the new value. | ||||
|      * | ||||
|      * @param string   $param     The parameter name according to OMB | ||||
|      * @param string   $value     The new value | ||||
|      * @param callback $validator A validator function for the parameter | ||||
|      * @param string   $field     The name of the field in OMB_Notice | ||||
|      * @param bool     $force     Whether null values should be checked as well | ||||
|      */ | ||||
|     protected function setVal($param, $value, $validator, $field = null, | ||||
|                               $force = false) | ||||
|     { | ||||
|         if (is_null($field)) { | ||||
|             $field = $param; | ||||
|         } | ||||
|         if ($value === '' && !$force) { | ||||
|             $value = null; | ||||
|         } elseif (!call_user_func($validator, $value)) { | ||||
|             throw new OMB_InvalidParameterException($value, 'notice', $param); | ||||
|         } | ||||
|         if ($this->$field !== $value) { | ||||
|             $this->$field      = $value; | ||||
|             $this->param_array = false; | ||||
|         } | ||||
|     } | ||||
|     $this->seealso_license_url = $seealso_license_url; | ||||
|     $this->param_array = false; | ||||
|   } | ||||
| } | ||||
| ?> | ||||
|   | ||||
| @@ -1,14 +1,6 @@ | ||||
| <?php | ||||
|  | ||||
| require_once 'Auth/Yadis/Yadis.php'; | ||||
| require_once 'unsupportedserviceexception.php'; | ||||
| require_once 'invalidyadisexception.php'; | ||||
|  | ||||
| /** | ||||
|  * OMB XRDS representation | ||||
|  * | ||||
|  * This class represents a Yadis XRDS file for OMB. It adds some useful methods to | ||||
|  * Auth_Yadis_XRDS. | ||||
|  * This file is part of libomb | ||||
|  * | ||||
|  * PHP version 5 | ||||
|  * | ||||
| @@ -25,172 +17,193 @@ require_once 'invalidyadisexception.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 | ||||
|  **/ | ||||
|  * @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 | ||||
|  */ | ||||
|  | ||||
| class OMB_Yadis_XRDS extends Auth_Yadis_XRDS { | ||||
| require_once 'Auth/Yadis/Yadis.php'; | ||||
| require_once 'unsupportedserviceexception.php'; | ||||
| require_once 'invalidyadisexception.php'; | ||||
|  | ||||
|   protected $fetcher; | ||||
| /** | ||||
|  * OMB XRDS representation | ||||
|  * | ||||
|  * This class represents a Yadis XRDS file for OMB. It adds some useful methods to | ||||
|  * Auth_Yadis_XRDS. | ||||
|  */ | ||||
| class OMB_Yadis_XRDS extends Auth_Yadis_XRDS | ||||
| { | ||||
|  | ||||
|   /** | ||||
|    * Create an instance from URL | ||||
|    * | ||||
|    * Constructs an OMB_Yadis_XRDS object from a given URL. A full Yadis | ||||
|    * discovery is performed on the URL and the XRDS is parsed. | ||||
|    * Throws an OMB_InvalidYadisException when no Yadis is discovered or the | ||||
|    * detected XRDS file is broken. | ||||
|    * | ||||
|    * @param string                 $url     The URL on which Yadis discovery | ||||
|    *                                        should be performed on | ||||
|    * @param Auth_Yadis_HTTPFetcher $fetcher A fetcher used to get HTTP | ||||
|    *                                        resources | ||||
|    * | ||||
|    * @access public | ||||
|    * | ||||
|    * @return OMB_Yadis_XRDS The initialized object representing the given | ||||
|    *                        resource | ||||
|    **/ | ||||
|   public static function fromYadisURL($url, $fetcher) { | ||||
|     /* Perform a Yadis discovery. */ | ||||
|     $yadis = Auth_Yadis_Yadis::discover($url, $fetcher); | ||||
|     if ($yadis->failed) { | ||||
|       throw new OMB_InvalidYadisException($url); | ||||
|     protected $fetcher; | ||||
|  | ||||
|     /** | ||||
|      * Create an instance from URL | ||||
|      * | ||||
|      * Constructs an OMB_Yadis_XRDS object from a given URL. A full Yadis | ||||
|      * discovery is performed on the URL and the XRDS is parsed. | ||||
|      * Throws an OMB_InvalidYadisException when no Yadis is discovered or the | ||||
|      * detected XRDS file is broken. | ||||
|      * | ||||
|      * @param string                 $url     The URL on which Yadis discovery | ||||
|      *                                        should be performed on | ||||
|      * @param Auth_Yadis_HTTPFetcher $fetcher A fetcher used to get HTTP | ||||
|      *                                        resources | ||||
|      * | ||||
|      * @access public | ||||
|      * | ||||
|      * @return OMB_Yadis_XRDS The initialized object representing the given | ||||
|      *                        resource | ||||
|      */ | ||||
|     public static function fromYadisURL($url, $fetcher) | ||||
|     { | ||||
|         /* Perform a Yadis discovery. */ | ||||
|         $yadis = Auth_Yadis_Yadis::discover($url, $fetcher); | ||||
|         if ($yadis->failed) { | ||||
|             throw new OMB_InvalidYadisException($url); | ||||
|         } | ||||
|  | ||||
|         /* Parse the XRDS file. */ | ||||
|         $xrds = OMB_Yadis_XRDS::parseXRDS($yadis->response_text); | ||||
|         if ($xrds === null) { | ||||
|             throw new OMB_InvalidYadisException($url); | ||||
|         } | ||||
|         $xrds->fetcher = $fetcher; | ||||
|         return $xrds; | ||||
|     } | ||||
|  | ||||
|     /* Parse the XRDS file. */ | ||||
|     $xrds = OMB_Yadis_XRDS::parseXRDS($yadis->response_text); | ||||
|     if ($xrds === null) { | ||||
|       throw new OMB_InvalidYadisException($url); | ||||
|     } | ||||
|     $xrds->fetcher = $fetcher; | ||||
|     return $xrds; | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * Get a specific service | ||||
|    * | ||||
|    * Returns the Auth_Yadis_Service object corresponding to the given service | ||||
|    * URI. | ||||
|    * Throws an OMB_UnsupportedServiceException if the service is not available. | ||||
|    * | ||||
|    * @param string $service URI specifier of the requested service | ||||
|    * | ||||
|    * @access public | ||||
|    * | ||||
|    * @return Auth_Yadis_Service The object representing the requested service | ||||
|    **/ | ||||
|   public function getService($service) { | ||||
|     $match = $this->services(array( create_function('$s', | ||||
|                            "return in_array('$service', \$s->getTypes());"))); | ||||
|     if ($match === array()) { | ||||
|       throw new OMB_UnsupportedServiceException($service); | ||||
|     } | ||||
|     return $match[0]; | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * Get a specific XRD | ||||
|    * | ||||
|    * Returns the OMB_Yadis_XRDS object corresponding to the given URI. | ||||
|    * Throws an OMB_UnsupportedServiceException if the XRD is not available. | ||||
|    * Note that getXRD tries to resolve external XRD parts as well. | ||||
|    * | ||||
|    * @param string $uri URI specifier of the requested XRD | ||||
|    * | ||||
|    * @access public | ||||
|    * | ||||
|    * @return OMB_Yadis_XRDS The object representing the requested XRD | ||||
|    **/ | ||||
|   public function getXRD($uri) { | ||||
|     $nexthash = strpos($uri, '#'); | ||||
|     if ($nexthash !== 0) { | ||||
|       if ($nexthash !== false) { | ||||
|         $cururi = substr($uri, 0, $nexthash); | ||||
|         $nexturi = substr($uri, $nexthash); | ||||
|       } | ||||
|       return | ||||
|         OMB_Yadis_XRDS::fromYadisURL($cururi, $this->fetcher)->getXRD($nexturi); | ||||
|     /** | ||||
|      * Get a specific service | ||||
|      * | ||||
|      * Returns the Auth_Yadis_Service object corresponding to the given service | ||||
|      * URI. | ||||
|      * Throws an OMB_UnsupportedServiceException if the service is not | ||||
|      * available. | ||||
|      * | ||||
|      * @param string $service URI specifier of the requested service | ||||
|      * | ||||
|      * @access public | ||||
|      * | ||||
|      * @return Auth_Yadis_Service The object representing the requested service | ||||
|      */ | ||||
|     public function getService($service) | ||||
|     { | ||||
|         $match = $this->services(array(create_function('$s', | ||||
|                              "return in_array('$service', \$s->getTypes());"))); | ||||
|         if ($match === array()) { | ||||
|             throw new OMB_UnsupportedServiceException($service); | ||||
|         } | ||||
|         return $match[0]; | ||||
|     } | ||||
|  | ||||
|     $id = substr($uri, 1); | ||||
|     foreach ($this->allXrdNodes as $node) { | ||||
|       $attrs = $this->parser->attributes($node); | ||||
|       if (array_key_exists('xml:id', $attrs) && $attrs['xml:id'] == $id) { | ||||
|         /* Trick the constructor into thinking this is the only node. */ | ||||
|         $bogus_nodes = array($node); | ||||
|         return new OMB_Yadis_XRDS($this->parser, $bogus_nodes); | ||||
|       } | ||||
|     } | ||||
|     throw new OMB_UnsupportedServiceException($uri); | ||||
|   } | ||||
|     /** | ||||
|      * Get a specific XRD | ||||
|      * | ||||
|      * Returns the OMB_Yadis_XRDS object corresponding to the given URI. | ||||
|      * Throws an OMB_UnsupportedServiceException if the XRD is not available. | ||||
|      * Note that getXRD tries to resolve external XRD parts as well. | ||||
|      * | ||||
|      * @param string $uri URI specifier of the requested XRD | ||||
|      * | ||||
|      * @access public | ||||
|      * | ||||
|      * @return OMB_Yadis_XRDS The object representing the requested XRD | ||||
|      */ | ||||
|     public function getXRD($uri) | ||||
|     { | ||||
|         $nexthash = strpos($uri, '#'); | ||||
|         if ($nexthash === false) { | ||||
|             throw new OMB_InvalidYadisException("‘$uri’ does not specify a " . | ||||
|                                                 'valid XML node.'); | ||||
|         } | ||||
|  | ||||
|   /** | ||||
|    * Parse an XML string containing a XRDS document | ||||
|    * | ||||
|    * Parse an XML string (XRDS document) and return either a | ||||
|    * Auth_Yadis_XRDS object or null, depending on whether the | ||||
|    * XRDS XML is valid. | ||||
|    * Copy and paste from parent to select correct constructor. | ||||
|    * | ||||
|    * @param string $xml_string An XRDS XML string. | ||||
|    * | ||||
|    * @access public | ||||
|    * | ||||
|    * @return mixed An instance of OMB_Yadis_XRDS or null, | ||||
|    *               depending on the validity of $xml_string | ||||
|    **/ | ||||
|         if ($nexthash > 0) { | ||||
|             $cururi  = substr($uri, 0, $nexthash); | ||||
|             $nexturi = substr($uri, $nexthash); | ||||
|             return OMB_Yadis_XRDS::fromYadisURL($cururi, $this->fetcher) | ||||
|                                                ->getXRD($nexturi); | ||||
|         } | ||||
|  | ||||
|   public function &parseXRDS($xml_string, $extra_ns_map = null) { | ||||
|     $_null = null; | ||||
|  | ||||
|     if (!$xml_string) { | ||||
|       return $_null; | ||||
|         $id = substr($uri, 1); | ||||
|         foreach ($this->allXrdNodes as $node) { | ||||
|             $attrs = $this->parser->attributes($node); | ||||
|             if (array_key_exists('xml:id', $attrs) && $attrs['xml:id'] == $id) { | ||||
|                 /* Trick the constructor into thinking this is the only node. */ | ||||
|                 $bogus_nodes = array($node); | ||||
|                 return new OMB_Yadis_XRDS($this->parser, $bogus_nodes); | ||||
|             } | ||||
|         } | ||||
|         throw new OMB_UnsupportedServiceException($uri); | ||||
|     } | ||||
|  | ||||
|     $parser = Auth_Yadis_getXMLParser(); | ||||
|     /** | ||||
|      * Parse an XML string containing a XRDS document | ||||
|      * | ||||
|      * Parses an XML string (XRDS document) and returns either an | ||||
|      * Auth_Yadis_XRDS object or null, depending on whether the XRDS XML is | ||||
|      * valid. | ||||
|      * This method is just copy and paste from the parent class to select the | ||||
|      * correct constructor. | ||||
|      * | ||||
|      * @param string $xml_string   An XRDS XML string | ||||
|      * @param array  $extra_ns_map Additional namespace declarations | ||||
|      * | ||||
|      * @access public | ||||
|      * | ||||
|      * @return mixed An instance of OMB_Yadis_XRDS or null, | ||||
|      *               depending on the validity of $xml_string | ||||
|      */ | ||||
|     public static function parseXRDS($xml_string, $extra_ns_map = null) | ||||
|     { | ||||
|         $_null = null; | ||||
|  | ||||
|     $ns_map = Auth_Yadis_getNSMap(); | ||||
|         if (!$xml_string) { | ||||
|             return $_null; | ||||
|         } | ||||
|  | ||||
|     if ($extra_ns_map && is_array($extra_ns_map)) { | ||||
|       $ns_map = array_merge($ns_map, $extra_ns_map); | ||||
|         $parser = Auth_Yadis_getXMLParser(); | ||||
|  | ||||
|         $ns_map = Auth_Yadis_getNSMap(); | ||||
|  | ||||
|         if ($extra_ns_map && is_array($extra_ns_map)) { | ||||
|             $ns_map = array_merge($ns_map, $extra_ns_map); | ||||
|         } | ||||
|  | ||||
|         if (!($parser && $parser->init($xml_string, $ns_map))) { | ||||
|             return $_null; | ||||
|         } | ||||
|  | ||||
|         // Try to get root element. | ||||
|         $root = $parser->evalXPath('/xrds:XRDS[1]'); | ||||
|         if (!$root) { | ||||
|             return $_null; | ||||
|         } | ||||
|  | ||||
|         if (is_array($root)) { | ||||
|             $root = $root[0]; | ||||
|         } | ||||
|  | ||||
|         $attrs = $parser->attributes($root); | ||||
|  | ||||
|         if (array_key_exists('xmlns:xrd', $attrs) && | ||||
|                     $attrs['xmlns:xrd'] != Auth_Yadis_XMLNS_XRDS) { | ||||
|             return $_null; | ||||
|         } else if (array_key_exists('xmlns', $attrs) && | ||||
|                                      preg_match('/xri/', $attrs['xmlns']) && | ||||
|                                      $attrs['xmlns'] != Auth_Yadis_XMLNS_XRD_2_0) { | ||||
|             return $_null; | ||||
|         } | ||||
|  | ||||
|         // Get the last XRD node. | ||||
|         $xrd_nodes = $parser->evalXPath('/xrds:XRDS[1]/xrd:XRD'); | ||||
|  | ||||
|         if (!$xrd_nodes) { | ||||
|             return $_null; | ||||
|         } | ||||
|  | ||||
|         $xrds = new OMB_Yadis_XRDS($parser, $xrd_nodes); | ||||
|         return $xrds; | ||||
|     } | ||||
|  | ||||
|     if (!($parser && $parser->init($xml_string, $ns_map))) { | ||||
|       return $_null; | ||||
|     } | ||||
|  | ||||
|     // Try to get root element. | ||||
|     $root = $parser->evalXPath('/xrds:XRDS[1]'); | ||||
|     if (!$root) { | ||||
|       return $_null; | ||||
|     } | ||||
|  | ||||
|     if (is_array($root)) { | ||||
|       $root = $root[0]; | ||||
|     } | ||||
|  | ||||
|     $attrs = $parser->attributes($root); | ||||
|  | ||||
|     if (array_key_exists('xmlns:xrd', $attrs) && | ||||
|           $attrs['xmlns:xrd'] != Auth_Yadis_XMLNS_XRDS) { | ||||
|       return $_null; | ||||
|     } else if (array_key_exists('xmlns', $attrs) && | ||||
|                    preg_match('/xri/', $attrs['xmlns']) && | ||||
|                    $attrs['xmlns'] != Auth_Yadis_XMLNS_XRD_2_0) { | ||||
|       return $_null; | ||||
|     } | ||||
|  | ||||
|     // Get the last XRD node. | ||||
|     $xrd_nodes = $parser->evalXPath('/xrds:XRDS[1]/xrd:XRD'); | ||||
|  | ||||
|     if (!$xrd_nodes) { | ||||
|       return $_null; | ||||
|     } | ||||
|  | ||||
|     $xrds = new OMB_Yadis_XRDS($parser, $xrd_nodes); | ||||
|     return $xrds; | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -1,13 +1,6 @@ | ||||
| <?php | ||||
|  | ||||
| require_once 'xrds_writer.php'; | ||||
|  | ||||
| /** | ||||
|  * Write OMB-specific XRDS using XMLWriter. | ||||
|  * | ||||
|  * This class writes the XRDS file announcing the OMB server. It uses | ||||
|  * OMB_XMLWriter, which is a subclass of XMLWriter. An instance of | ||||
|  * OMB_Plain_XRDS_Writer should be passed to OMB_Service_Provider->writeXRDS. | ||||
|  * This file is part of libomb | ||||
|  * | ||||
|  * PHP version 5 | ||||
|  * | ||||
| @@ -24,25 +17,45 @@ require_once 'xrds_writer.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 | ||||
|  **/ | ||||
|  * @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 | ||||
|  */ | ||||
|  | ||||
| class OMB_Plain_XRDS_Writer implements OMB_XRDS_Writer { | ||||
|   public function writeXRDS($user, $mapper) { | ||||
|     header('Content-Type: application/xrds+xml'); | ||||
|     $xw = new XMLWriter(); | ||||
|     $xw->openURI('php://output'); | ||||
|     $xw->setIndent(true); | ||||
| require_once 'xrds_writer.php'; | ||||
|  | ||||
|     $xw->startDocument('1.0', 'UTF-8'); | ||||
|     $this->writeFullElement($xw, 'XRDS',  array('xmlns' => 'xri://$xrds'), array( | ||||
|         array('XRD',  array('xmlns' => 'xri://$xrd*($v*2.0)', | ||||
|                                           'xml:id' => 'oauth', | ||||
|                                           'xmlns:simple' => 'http://xrds-simple.net/core/1.0', | ||||
|                                           'version' => '2.0'), array( | ||||
| /** | ||||
|  * Write OMB-specific XRDS using XMLWriter | ||||
|  * | ||||
|  * This class writes the XRDS file announcing the OMB server. It uses XMLWriter. | ||||
|  * An instance of OMB_Plain_XRDS_Writer should be passed to | ||||
|  * OMB_Service_Provider->writeXRDS. | ||||
|  */ | ||||
| class OMB_Plain_XRDS_Writer implements OMB_XRDS_Writer | ||||
| { | ||||
|     /** | ||||
|      * Write XRDS using XMLWriter | ||||
|      * | ||||
|      * Outputs a XRDS document specifying an OMB service. | ||||
|      * | ||||
|      * @param OMB_profile     $user   The target user for the OMB service | ||||
|      * @param OMB_XRDS_Mapper $mapper An OMB_XRDS_Mapper providing endpoint URLs | ||||
|      */ | ||||
|     public function writeXRDS($user, $mapper) | ||||
|     { | ||||
|         header('Content-Type: application/xrds+xml'); | ||||
|         $xw = new XMLWriter(); | ||||
|         $xw->openURI('php://output'); | ||||
|         $xw->setIndent(true); | ||||
|  | ||||
|         $xw->startDocument('1.0', 'UTF-8'); | ||||
|         $this->_writeFullElement($xw, 'XRDS', array('xmlns' => 'xri://$xrds'), array( | ||||
|         array('XRD', array('xmlns' => 'xri://$xrd*($v*2.0)', | ||||
|                             'xml:id' => 'oauth', | ||||
|                             'xmlns:simple' => 'http://xrds-simple.net/core/1.0', | ||||
|                             'version' => '2.0'), array( | ||||
|           array('Type', null, 'xri://$xrds*simple'), | ||||
|           array('Service', null, array( | ||||
|             array('Type', null, OAUTH_ENDPOINT_REQUEST), | ||||
| @@ -73,10 +86,10 @@ class OMB_Plain_XRDS_Writer implements OMB_XRDS_Writer { | ||||
|             array('Type', null, OAUTH_HMAC_SHA1) | ||||
|           )) | ||||
|         )), | ||||
|         array('XRD',  array('xmlns' => 'xri://$xrd*($v*2.0)', | ||||
|                                           'xml:id' => 'omb', | ||||
|                                           'xmlns:simple' => 'http://xrds-simple.net/core/1.0', | ||||
|                                           'version' => '2.0'), array( | ||||
|         array('XRD', array('xmlns' => 'xri://$xrd*($v*2.0)', | ||||
|                            'xml:id' => 'omb', | ||||
|                            'xmlns:simple' => 'http://xrds-simple.net/core/1.0', | ||||
|                            'version' => '2.0'), array( | ||||
|           array('Type', null, 'xri://$xrds*simple'), | ||||
|           array('Service', null, array( | ||||
|             array('Type', null, OMB_ENDPOINT_POSTNOTICE), | ||||
| @@ -87,8 +100,8 @@ class OMB_Plain_XRDS_Writer implements OMB_XRDS_Writer { | ||||
|             array('URI', null, $mapper->getURL(OMB_ENDPOINT_UPDATEPROFILE)) | ||||
|           )) | ||||
|         )), | ||||
|         array('XRD',  array('xmlns' => 'xri://$xrd*($v*2.0)', | ||||
|                                           'version' => '2.0'), array( | ||||
|         array('XRD', array('xmlns' => 'xri://$xrd*($v*2.0)', | ||||
|                            'version' => '2.0'), array( | ||||
|           array('Type', null, 'xri://$xrds*simple'), | ||||
|           array('Service', null, array( | ||||
|             array('Type', null, OAUTH_DISCOVERY), | ||||
| @@ -98,27 +111,40 @@ class OMB_Plain_XRDS_Writer implements OMB_XRDS_Writer { | ||||
|             array('Type', null, OMB_VERSION), | ||||
|             array('URI', null, '#omb') | ||||
|           )) | ||||
|         )) | ||||
|       )); | ||||
|     $xw->endDocument(); | ||||
|     $xw->flush(); | ||||
|   } | ||||
|         )))); | ||||
|         $xw->endDocument(); | ||||
|         $xw->flush(); | ||||
|     } | ||||
|  | ||||
|   public static function writeFullElement($xw, $tag, $attributes, $content) { | ||||
|     $xw->startElement($tag); | ||||
|     if (!is_null($attributes)) { | ||||
|       foreach ($attributes as $name => $value) { | ||||
|         $xw->writeAttribute($name, $value); | ||||
|       } | ||||
|     /** | ||||
|      * Write a complex XML element | ||||
|      * | ||||
|      * Outputs a XML element with attributes and content. | ||||
|      * | ||||
|      * @param XMLWriter    $xw         The XMLWriter used to output the element | ||||
|      * @param string       $tag        The tag name | ||||
|      * @param array|null   $attributes A map of XML attributes | ||||
|      * @param array|string $content    The content of the element; either an | ||||
|      *                                 array of child nodes each specified by a | ||||
|      *                                 three entry-array ($tag, $attributes, | ||||
|      *                                 $content) or a string | ||||
|      */ | ||||
|     private function _writeFullElement($xw, $tag, $attributes, $content) | ||||
|     { | ||||
|         $xw->startElement($tag); | ||||
|         if (!is_null($attributes)) { | ||||
|             foreach ($attributes as $name => $value) { | ||||
|                 $xw->writeAttribute($name, $value); | ||||
|             } | ||||
|         } | ||||
|         if (is_array($content)) { | ||||
|             foreach ($content as $val) { | ||||
|                 $this->_writeFullElement($xw, $val[0], $val[1], $val[2]); | ||||
|             } | ||||
|         } else { | ||||
|             $xw->text($content); | ||||
|         } | ||||
|         $xw->fullEndElement(); | ||||
|     } | ||||
|     if (is_array($content)) { | ||||
|       foreach ($content as $values) { | ||||
|         OMB_Plain_XRDS_Writer::writeFullElement($xw, $values[0], $values[1], $values[2]); | ||||
|       } | ||||
|     } else { | ||||
|       $xw->text($content); | ||||
|     } | ||||
|     $xw->fullEndElement(); | ||||
|   } | ||||
| } | ||||
| ?> | ||||
|   | ||||
| @@ -1,15 +1,6 @@ | ||||
| <?php | ||||
| require_once 'invalidparameterexception.php'; | ||||
| require_once 'Validate.php'; | ||||
| require_once 'helper.php'; | ||||
|  | ||||
| /** | ||||
|  * OMB profile representation | ||||
|  * | ||||
|  * This class represents an OMB profile. | ||||
|  * | ||||
|  * Do not call the setters with null values. Instead, if you want to delete a | ||||
|  * field, pass an empty string. The getters will return null for empty fields. | ||||
|  * This file is part of libomb | ||||
|  * | ||||
|  * PHP version 5 | ||||
|  * | ||||
| @@ -26,292 +17,329 @@ 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 | ||||
|  **/ | ||||
|  * @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 | ||||
|  */ | ||||
|  | ||||
| class OMB_Profile { | ||||
|   protected $identifier_uri; | ||||
|   protected $profile_url; | ||||
|   protected $nickname; | ||||
|   protected $license_url; | ||||
|   protected $fullname; | ||||
|   protected $homepage; | ||||
|   protected $bio; | ||||
|   protected $location; | ||||
|   protected $avatar_url; | ||||
| require_once 'invalidparameterexception.php'; | ||||
| require_once 'Validate.php'; | ||||
| require_once 'helper.php'; | ||||
|  | ||||
|   /* The profile as OMB param array. Cached and rebuild on usage. | ||||
|      false while outdated. */ | ||||
|   protected $param_array; | ||||
| /** | ||||
|  * OMB profile representation | ||||
|  * | ||||
|  * This class represents an OMB profile. | ||||
|  * | ||||
|  * Do not call the setters with null values. Instead, if you want to delete a | ||||
|  * field, pass an empty string. The getters will return null for empty fields. | ||||
|  */ | ||||
| class OMB_Profile | ||||
| { | ||||
|     protected $identifier_uri; | ||||
|     protected $profile_url; | ||||
|     protected $nickname; | ||||
|     protected $license_url; | ||||
|     protected $fullname; | ||||
|     protected $homepage; | ||||
|     protected $bio; | ||||
|     protected $location; | ||||
|     protected $avatar_url; | ||||
|  | ||||
|   /** | ||||
|    * Constructor for OMB_Profile | ||||
|    * | ||||
|    * Initializes the OMB_Profile object with an identifier uri. | ||||
|    * | ||||
|    * @param string $identifier_uri The profile URI as defined by the OMB. A unique | ||||
|    *                               and unchanging identifier for a profile. | ||||
|    * | ||||
|    * @access public | ||||
|    */ | ||||
|   public function __construct($identifier_uri) { | ||||
|     if (!Validate::uri($identifier_uri)) { | ||||
|       throw new OMB_InvalidParameterException($identifier_uri, 'profile', | ||||
|     /* The profile as OMB param array. Cached and rebuild on usage. | ||||
|        false while outdated. */ | ||||
|     protected $param_array; | ||||
|  | ||||
|     /** | ||||
|      * Constructor for OMB_Profile | ||||
|      * | ||||
|      * Initializes the OMB_Profile object with an identifier uri. | ||||
|      * | ||||
|      * @param string $identifier_uri The profile URI as defined by the OMB; | ||||
|      *                               A unique and never changing identifier for | ||||
|      *                               a profile | ||||
|      * | ||||
|      * @access public | ||||
|      */ | ||||
|     public function __construct($identifier_uri) | ||||
|     { | ||||
|         if (!Validate::uri($identifier_uri)) { | ||||
|             throw new OMB_InvalidParameterException($identifier_uri, 'profile', | ||||
|                                                 'omb_listenee or omb_listener'); | ||||
|     } | ||||
|     $this->identifier_uri = $identifier_uri; | ||||
|     $this->param_array = false; | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * Returns the profile as array | ||||
|    * | ||||
|    * The method returns an array which contains the whole profile as array. The | ||||
|    * array is cached and only rebuilt on changes of the profile. | ||||
|    * | ||||
|    * @param bool   $force_all Specifies whether empty fields should be added to | ||||
|    *                          the array as well. This is neccessary to clear | ||||
|    *                          fields via updateProfile. | ||||
|    * | ||||
|    * @param string $prefix    The common prefix to the key for all parameters. | ||||
|    * | ||||
|    * @access public | ||||
|    * | ||||
|    * @return array The profile as parameter array | ||||
|    */ | ||||
|   public function asParameters($prefix, $force_all = false) { | ||||
|     if ($this->param_array === false) { | ||||
|       $this->param_array = array('' => $this->identifier_uri); | ||||
|  | ||||
|       if ($force_all || !is_null($this->profile_url)) { | ||||
|         $this->param_array['_profile'] = $this->profile_url; | ||||
|       } | ||||
|  | ||||
|       if ($force_all || !is_null($this->homepage)) { | ||||
|         $this->param_array['_homepage'] = $this->homepage; | ||||
|       } | ||||
|  | ||||
|       if ($force_all || !is_null($this->nickname)) { | ||||
|         $this->param_array['_nickname'] = $this->nickname; | ||||
|       } | ||||
|  | ||||
|       if ($force_all || !is_null($this->license_url)) { | ||||
|         $this->param_array['_license'] = $this->license_url; | ||||
|       } | ||||
|  | ||||
|       if ($force_all || !is_null($this->fullname)) { | ||||
|         $this->param_array['_fullname'] = $this->fullname; | ||||
|       } | ||||
|  | ||||
|       if ($force_all || !is_null($this->bio)) { | ||||
|         $this->param_array['_bio'] = $this->bio; | ||||
|       } | ||||
|  | ||||
|       if ($force_all || !is_null($this->location)) { | ||||
|         $this->param_array['_location'] = $this->location; | ||||
|       } | ||||
|  | ||||
|       if ($force_all || !is_null($this->avatar_url)) { | ||||
|         $this->param_array['_avatar'] = $this->avatar_url; | ||||
|       } | ||||
|  | ||||
|     } | ||||
|     $ret = array(); | ||||
|     foreach ($this->param_array as $k => $v) { | ||||
|       $ret[$prefix . $k] = $v; | ||||
|     } | ||||
|     return $ret; | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * Builds an OMB_Profile object from array | ||||
|    * | ||||
|    * The method builds an OMB_Profile object from the passed parameters array. The | ||||
|    * array MUST provide a profile URI. The array fields HAVE TO be named according | ||||
|    * to the OMB standard. The prefix (omb_listener or omb_listenee) is passed as a | ||||
|    * parameter. | ||||
|    * | ||||
|    * @param string $parameters An array containing the profile parameters. | ||||
|    * @param string $prefix     The common prefix of the profile parameter keys. | ||||
|    * | ||||
|    * @access public | ||||
|    * | ||||
|    * @returns OMB_Profile The built OMB_Profile. | ||||
|    */ | ||||
|   public static function fromParameters($parameters, $prefix) { | ||||
|     if (!isset($parameters[$prefix])) { | ||||
|       throw new OMB_InvalidParameterException('', 'profile', $prefix); | ||||
|         } | ||||
|         $this->identifier_uri = $identifier_uri; | ||||
|         $this->param_array    = false; | ||||
|     } | ||||
|  | ||||
|     $profile = new OMB_Profile($parameters[$prefix]); | ||||
|     $profile->updateFromParameters($parameters, $prefix); | ||||
|     return $profile; | ||||
|   } | ||||
|     /** | ||||
|      * Return the profile as array | ||||
|      * | ||||
|      * Returns an array which contains the whole profile as array. | ||||
|      * The array is cached and only rebuilt on changes of the profile. | ||||
|      * | ||||
|      * @param string $prefix    The common prefix to the key for all parameters | ||||
|      * @param bool   $force_all Specifies whether empty fields should be added | ||||
|      *                          to the array as well; This is necessary to | ||||
|      *                          clear fields via updateProfile | ||||
|      * | ||||
|      * @access public | ||||
|      * | ||||
|      * @return array The profile as parameter array | ||||
|      */ | ||||
|     public function asParameters($prefix, $force_all = false) | ||||
|     { | ||||
|         if ($this->param_array === false) { | ||||
|             $this->param_array = array('' => $this->identifier_uri); | ||||
|  | ||||
|   /** | ||||
|    * Update from array | ||||
|    * | ||||
|    * Updates from the passed parameters array. The array does not have to | ||||
|    * provide a profile URI. The array fields HAVE TO be named according to the | ||||
|    * OMB standard. The prefix (omb_listener or omb_listenee) is passed as a | ||||
|    * parameter. | ||||
|    * | ||||
|    * @param string $parameters An array containing the profile parameters. | ||||
|    * @param string $prefix     The common prefix of the profile parameter keys. | ||||
|    * | ||||
|    * @access public | ||||
|    */ | ||||
|   public function updateFromParameters($parameters, $prefix) { | ||||
|     if (isset($parameters[$prefix.'_profile'])) { | ||||
|       $this->setProfileURL($parameters[$prefix.'_profile']); | ||||
|             if ($force_all || !is_null($this->profile_url)) { | ||||
|                 $this->param_array['_profile'] = $this->profile_url; | ||||
|             } | ||||
|  | ||||
|             if ($force_all || !is_null($this->homepage)) { | ||||
|                 $this->param_array['_homepage'] = $this->homepage; | ||||
|             } | ||||
|  | ||||
|             if ($force_all || !is_null($this->nickname)) { | ||||
|                 $this->param_array['_nickname'] = $this->nickname; | ||||
|             } | ||||
|  | ||||
|             if ($force_all || !is_null($this->license_url)) { | ||||
|                 $this->param_array['_license'] = $this->license_url; | ||||
|             } | ||||
|  | ||||
|             if ($force_all || !is_null($this->fullname)) { | ||||
|                 $this->param_array['_fullname'] = $this->fullname; | ||||
|             } | ||||
|  | ||||
|             if ($force_all || !is_null($this->bio)) { | ||||
|                 $this->param_array['_bio'] = $this->bio; | ||||
|             } | ||||
|  | ||||
|             if ($force_all || !is_null($this->location)) { | ||||
|                 $this->param_array['_location'] = $this->location; | ||||
|             } | ||||
|  | ||||
|             if ($force_all || !is_null($this->avatar_url)) { | ||||
|                 $this->param_array['_avatar'] = $this->avatar_url; | ||||
|             } | ||||
|  | ||||
|         } | ||||
|         $ret = array(); | ||||
|         foreach ($this->param_array as $k => $v) { | ||||
|             $ret[$prefix . $k] = $v; | ||||
|         } | ||||
|         return $ret; | ||||
|     } | ||||
|  | ||||
|     if (isset($parameters[$prefix.'_license'])) { | ||||
|       $this->setLicenseURL($parameters[$prefix.'_license']); | ||||
|     /** | ||||
|      * Build an OMB_Profile object from array | ||||
|      * | ||||
|      * Builds an OMB_Profile object from the passed parameters array. The | ||||
|      * array MUST provide a profile URI. The array fields HAVE TO be named | ||||
|      * according to the OMB standard. The prefix (omb_listener or omb_listenee) | ||||
|      * is passed as a parameter. | ||||
|      * | ||||
|      * @param string $parameters An array containing the profile parameters | ||||
|      * @param string $prefix     The common prefix of the profile parameter keys | ||||
|      * | ||||
|      * @access public | ||||
|      * | ||||
|      * @returns OMB_Profile The built OMB_Profile | ||||
|      */ | ||||
|     public static function fromParameters($parameters, $prefix) | ||||
|     { | ||||
|         if (!isset($parameters[$prefix])) { | ||||
|             throw new OMB_InvalidParameterException('', 'profile', $prefix); | ||||
|         } | ||||
|  | ||||
|         $profile = new OMB_Profile($parameters[$prefix]); | ||||
|         $profile->updateFromParameters($parameters, $prefix); | ||||
|         return $profile; | ||||
|     } | ||||
|  | ||||
|     if (isset($parameters[$prefix.'_nickname'])) { | ||||
|       $this->setNickname($parameters[$prefix.'_nickname']); | ||||
|     /** | ||||
|      * Update from array | ||||
|      * | ||||
|      * Updates from the passed parameters array. The array does not have to | ||||
|      * provide a profile URI. The array fields HAVE TO be named according to the | ||||
|      * OMB standard. The prefix (omb_listener or omb_listenee) is passed as a | ||||
|      * parameter. | ||||
|      * | ||||
|      * @param string $parameters An array containing the profile parameters | ||||
|      * @param string $prefix     The common prefix of the profile parameter keys | ||||
|      * | ||||
|      * @access public | ||||
|      */ | ||||
|     public function updateFromParameters($parameters, $prefix) | ||||
|     { | ||||
|         if (isset($parameters[$prefix.'_profile'])) { | ||||
|             $this->setProfileURL($parameters[$prefix.'_profile']); | ||||
|         } | ||||
|  | ||||
|         if (isset($parameters[$prefix.'_license'])) { | ||||
|             $this->setLicenseURL($parameters[$prefix.'_license']); | ||||
|         } | ||||
|  | ||||
|         if (isset($parameters[$prefix.'_nickname'])) { | ||||
|             $this->setNickname($parameters[$prefix.'_nickname']); | ||||
|         } | ||||
|  | ||||
|         if (isset($parameters[$prefix.'_fullname'])) { | ||||
|             $this->setFullname($parameters[$prefix.'_fullname']); | ||||
|         } | ||||
|  | ||||
|         if (isset($parameters[$prefix.'_homepage'])) { | ||||
|             $this->setHomepage($parameters[$prefix.'_homepage']); | ||||
|         } | ||||
|  | ||||
|         if (isset($parameters[$prefix.'_bio'])) { | ||||
|             $this->setBio($parameters[$prefix.'_bio']); | ||||
|         } | ||||
|  | ||||
|         if (isset($parameters[$prefix.'_location'])) { | ||||
|             $this->setLocation($parameters[$prefix.'_location']); | ||||
|         } | ||||
|  | ||||
|         if (isset($parameters[$prefix.'_avatar'])) { | ||||
|             $this->setAvatarURL($parameters[$prefix.'_avatar']); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     if (isset($parameters[$prefix.'_fullname'])) { | ||||
|       $this->setFullname($parameters[$prefix.'_fullname']); | ||||
|     public function getIdentifierURI() | ||||
|     { | ||||
|         return $this->identifier_uri; | ||||
|     } | ||||
|  | ||||
|     if (isset($parameters[$prefix.'_homepage'])) { | ||||
|       $this->setHomepage($parameters[$prefix.'_homepage']); | ||||
|     public function getProfileURL() | ||||
|     { | ||||
|         return $this->profile_url; | ||||
|     } | ||||
|  | ||||
|     if (isset($parameters[$prefix.'_bio'])) { | ||||
|       $this->setBio($parameters[$prefix.'_bio']); | ||||
|     public function getHomepage() | ||||
|     { | ||||
|         return $this->homepage; | ||||
|     } | ||||
|  | ||||
|     if (isset($parameters[$prefix.'_location'])) { | ||||
|       $this->setLocation($parameters[$prefix.'_location']); | ||||
|     public function getNickname() | ||||
|     { | ||||
|         return $this->nickname; | ||||
|     } | ||||
|  | ||||
|     if (isset($parameters[$prefix.'_avatar'])) { | ||||
|       $this->setAvatarURL($parameters[$prefix.'_avatar']); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   public function getIdentifierURI() { | ||||
|     return $this->identifier_uri; | ||||
|   } | ||||
|  | ||||
|   public function getProfileURL() { | ||||
|     return $this->profile_url; | ||||
|   } | ||||
|  | ||||
|   public function getHomepage() { | ||||
|     return $this->homepage; | ||||
|   } | ||||
|  | ||||
|   public function getNickname() { | ||||
|     return $this->nickname; | ||||
|   } | ||||
|  | ||||
|   public function getLicenseURL() { | ||||
|     return $this->license_url; | ||||
|   } | ||||
|  | ||||
|   public function getFullname() { | ||||
|     return $this->fullname; | ||||
|   } | ||||
|  | ||||
|   public function getBio() { | ||||
|     return $this->bio; | ||||
|   } | ||||
|  | ||||
|   public function getLocation() { | ||||
|     return $this->location; | ||||
|   } | ||||
|  | ||||
|   public function getAvatarURL() { | ||||
|     return $this->avatar_url; | ||||
|   } | ||||
|  | ||||
|   public function setProfileURL($profile_url) { | ||||
|     if (!OMB_Helper::validateURL($profile_url)) { | ||||
|       throw new OMB_InvalidParameterException($profile_url, 'profile', | ||||
|                                     'omb_listenee_profile or omb_listener_profile'); | ||||
|     } | ||||
|     $this->profile_url = $profile_url; | ||||
|     $this->param_array = false; | ||||
|   } | ||||
|  | ||||
|   public function setNickname($nickname) { | ||||
|     if (!Validate::string($nickname, | ||||
|                           array('min_length' => 1, | ||||
|                                 'max_length' => 64, | ||||
|                                 'format' => VALIDATE_NUM . VALIDATE_ALPHA))) { | ||||
|       throw new OMB_InvalidParameterException($nickname, 'profile', 'nickname'); | ||||
|     public function getLicenseURL() | ||||
|     { | ||||
|         return $this->license_url; | ||||
|     } | ||||
|  | ||||
|     $this->nickname = $nickname; | ||||
|     $this->param_array = false; | ||||
|   } | ||||
|  | ||||
|   public function setLicenseURL($license_url) { | ||||
|     if (!OMB_Helper::validateURL($license_url)) { | ||||
|       throw new OMB_InvalidParameterException($license_url, 'profile', | ||||
|                                     'omb_listenee_license or omb_listener_license'); | ||||
|     public function getFullname() | ||||
|     { | ||||
|         return $this->fullname; | ||||
|     } | ||||
|     $this->license_url = $license_url; | ||||
|     $this->param_array = false; | ||||
|   } | ||||
|  | ||||
|   public function setFullname($fullname) { | ||||
|     if ($fullname === '') { | ||||
|       $fullname = null; | ||||
|     } elseif (!Validate::string($fullname, array('max_length' => 255))) { | ||||
|       throw new OMB_InvalidParameterException($fullname, 'profile', 'fullname'); | ||||
|     public function getBio() | ||||
|     { | ||||
|         return $this->bio; | ||||
|     } | ||||
|     $this->fullname = $fullname; | ||||
|     $this->param_array = false; | ||||
|   } | ||||
|  | ||||
|   public function setHomepage($homepage) { | ||||
|     if ($homepage === '') { | ||||
|       $homepage = null; | ||||
|     public function getLocation() | ||||
|     { | ||||
|         return $this->location; | ||||
|     } | ||||
|     $this->homepage = $homepage; | ||||
|     $this->param_array = false; | ||||
|   } | ||||
|  | ||||
|   public function setBio($bio) { | ||||
|     if ($bio === '') { | ||||
|       $bio = null; | ||||
|     } elseif (!Validate::string($bio, array('max_length' => 140))) { | ||||
|       throw new OMB_InvalidParameterException($bio, 'profile', 'fullname'); | ||||
|     public function getAvatarURL() | ||||
|     { | ||||
|         return $this->avatar_url; | ||||
|     } | ||||
|     $this->bio = $bio; | ||||
|     $this->param_array = false; | ||||
|   } | ||||
|  | ||||
|   public function setLocation($location) { | ||||
|     if ($location === '') { | ||||
|       $location = null; | ||||
|     } elseif (!Validate::string($location, array('max_length' => 255))) { | ||||
|       throw new OMB_InvalidParameterException($location, 'profile', 'fullname'); | ||||
|     public function setProfileURL($profile_url) | ||||
|     { | ||||
|         $this->setVal('profile', $profile_url, 'OMB_Helper::validateURL', | ||||
|                       'profile_url'); | ||||
|     } | ||||
|     $this->location = $location; | ||||
|     $this->param_array = false; | ||||
|   } | ||||
|  | ||||
|   public function setAvatarURL($avatar_url) { | ||||
|     if ($avatar_url === '') { | ||||
|       $avatar_url = null; | ||||
|     } elseif (!OMB_Helper::validateURL($avatar_url)) { | ||||
|       throw new OMB_InvalidParameterException($avatar_url, 'profile', | ||||
|                                       'omb_listenee_avatar or omb_listener_avatar'); | ||||
|     public function setNickname($nickname) | ||||
|     { | ||||
|         $this->setVal('nickname', $nickname, 'OMB_Profile::validateNickname', | ||||
|                       'nickname', true); | ||||
|     } | ||||
|     $this->avatar_url = $avatar_url; | ||||
|     $this->param_array = false; | ||||
|   } | ||||
|  | ||||
|     public function setLicenseURL($license_url) | ||||
|     { | ||||
|         $this->setVal('license', $license_url, 'OMB_Helper::validateURL', | ||||
|                       'license_url'); | ||||
|     } | ||||
|  | ||||
|     public function setFullname($fullname) | ||||
|     { | ||||
|         $this->setVal('fullname', $fullname, 'OMB_Profile::validate255'); | ||||
|     } | ||||
|  | ||||
|     public function setHomepage($homepage) | ||||
|     { | ||||
|         $this->setVal('homepage', $homepage, 'OMB_Helper::validateURL'); | ||||
|     } | ||||
|  | ||||
|     public function setBio($bio) | ||||
|     { | ||||
|         $this->setVal('bio', $bio, 'OMB_Profile::validate140'); | ||||
|     } | ||||
|  | ||||
|     public function setLocation($location) | ||||
|     { | ||||
|         $this->setVal('location', $location, 'OMB_Profile::validate255'); | ||||
|     } | ||||
|  | ||||
|     public function setAvatarURL($avatar_url) | ||||
|     { | ||||
|         $this->setVal('avatar', $avatar_url, 'OMB_Helper::validateURL', | ||||
|                       'avatar_url'); | ||||
|     } | ||||
|  | ||||
|     protected static function validate255($str) | ||||
|     { | ||||
|         return Validate::string($str, array('max_length' => 255)); | ||||
|     } | ||||
|  | ||||
|     protected static function validate140($str) | ||||
|     { | ||||
|         return Validate::string($str, array('max_length' => 140)); | ||||
|     } | ||||
|  | ||||
|     protected static function validateNickname($str) | ||||
|     { | ||||
|         return Validate::string($str, | ||||
|                               array('min_length' => 1, | ||||
|                                     'max_length' => 64, | ||||
|                                     'format' => VALIDATE_NUM . VALIDATE_ALPHA)); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Set a value | ||||
|      * | ||||
|      * Updates a value specified by a parameter name and the new value. | ||||
|      * | ||||
|      * @param string   $param     The parameter name according to OMB | ||||
|      * @param string   $value     The new value | ||||
|      * @param callback $validator A validator function for the parameter | ||||
|      * @param string   $field     The name of the field in OMB_Profile | ||||
|      * @param bool     $force     Whether null values should be checked as well | ||||
|      */ | ||||
|     protected function setVal($param, $value, $validator, $field = null, | ||||
|                               $force = false) | ||||
|     { | ||||
|         if (is_null($field)) { | ||||
|             $field = $param; | ||||
|         } | ||||
|         if ($value === '' && !$force) { | ||||
|             $value = null; | ||||
|         } elseif (!call_user_func($validator, $value)) { | ||||
|             throw new OMB_InvalidParameterException($value, 'profile', $param); | ||||
|         } | ||||
|         if ($this->$field !== $value) { | ||||
|             $this->$field      = $value; | ||||
|             $this->param_array = false; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| ?> | ||||
|   | ||||
| @@ -1,9 +1,6 @@ | ||||
| <?php | ||||
| /** | ||||
|  * Exception stating that the remote service had a failure | ||||
|  * | ||||
|  * This exception is raised when a remote service failed to return a valid | ||||
|  * response to a request or send a valid request. | ||||
|  * This file is part of libomb | ||||
|  * | ||||
|  * PHP version 5 | ||||
|  * | ||||
| @@ -20,23 +17,57 @@ | ||||
|  * 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_RemoteServiceException extends Exception { | ||||
|   public static function fromYadis($request_uri, $result) { | ||||
|     if ($result->status == 200) { | ||||
|         $err = 'Got wrong response ' . $result->body; | ||||
|     } else { | ||||
|         $err = 'Got error code ' . $result->status . ' with response ' . $result->body; | ||||
|     } | ||||
|     return new OMB_RemoteServiceException($request_uri . ': ' .  $err); | ||||
|   } | ||||
|  * @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 | ||||
|  */ | ||||
|  | ||||
|   public static function forRequest($action_uri, $failure) { | ||||
|     return new OMB_RemoteServiceException("Handler for $action_uri: " .  $failure); | ||||
|   } | ||||
| /** | ||||
|  * Exception stating that the remote service had a failure | ||||
|  * | ||||
|  * This exception is raised when a remote service failed to return a valid | ||||
|  * response to a request or send a valid request. | ||||
|  */ | ||||
| class OMB_RemoteServiceException extends Exception | ||||
| { | ||||
|     /** | ||||
|      * Create exception from Yadis response | ||||
|      * | ||||
|      * Creates an exception from a passed yadis result. | ||||
|      * | ||||
|      * @param string                  $request_uri The target URI for the failed | ||||
|      *                                             request | ||||
|      * @param Auth_Yadis_HTTPResponse $result      The result of the failed | ||||
|      *                                             request | ||||
|      * | ||||
|      * @return OMB_RemoteServiceException A new exception | ||||
|      */ | ||||
|     public static function fromYadis($request_uri, $result) | ||||
|     { | ||||
|         if ($result->status == 200) { | ||||
|             $err = 'Got wrong response ' . $result->body; | ||||
|         } else { | ||||
|             $err = 'Got error code ' . $result->status . ' with response ' . | ||||
|                    $result->body; | ||||
|         } | ||||
|         return OMB_RemoteServiceException::forRequest($request_uri, $err); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Create exception for a call to a resource | ||||
|      * | ||||
|      * Creates an exception for a given error message and target URI. | ||||
|      * | ||||
|      * @param string $action_uri The target URI for the failed request | ||||
|      * @param string $failure    An error message | ||||
|      * | ||||
|      * @return OMB_RemoteServiceException A new exception | ||||
|      */ | ||||
|     public static function forRequest($action_uri, $failure) | ||||
|     { | ||||
|         return new OMB_RemoteServiceException("Handler for $action_uri: $failure"); | ||||
|     } | ||||
| } | ||||
| ?> | ||||
|   | ||||
| @@ -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 | ||||
|  **/ | ||||
|  * @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 | ||||
|  */ | ||||
|  | ||||
| class OMB_Service_Consumer { | ||||
|   protected $url; /* The service URL */ | ||||
|   protected $services; /* An array of strings mapping service URI to | ||||
|                           service URL */ | ||||
| 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'; | ||||
|  | ||||
|   protected $token; /* An OAuthToken */ | ||||
| /** | ||||
|  * 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 $listener_uri; /* The URI identifying the listener, i. e. the | ||||
|                               remote user. */ | ||||
|     protected $token; /* An OAuthToken */ | ||||
|  | ||||
|   protected $listenee_uri; /* The URI identifying the listenee, i. e. the | ||||
|                               local user during an auth request. */ | ||||
|     protected $listener_uri; /* The URI identifying the listener, i. e. the | ||||
|                                 remote user. */ | ||||
|  | ||||
|   /** | ||||
|    * 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; | ||||
|     protected $listenee_uri; /* The URI identifying the listenee, i. e. the | ||||
|                                 local user during an auth request. */ | ||||
|  | ||||
|   /* Helper stuff we are going to need. */ | ||||
|   protected $fetcher; | ||||
|   protected $oauth_consumer; | ||||
|   protected $datastore; | ||||
|     /** | ||||
|      * 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; | ||||
|  | ||||
|   /** | ||||
|    * 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, ''); | ||||
|     /* Helper stuff we are going to need. */ | ||||
|     protected $fetcher; | ||||
|     protected $oauth_consumer; | ||||
|     protected $datastore; | ||||
|  | ||||
|     $xrds = OMB_Yadis_XRDS::fromYadisURL($service_url, $this->fetcher); | ||||
|     /** | ||||
|      * 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, ''); | ||||
|  | ||||
|     /* Detect our services. This performs a validation as well, since | ||||
|        getService und getXRD throw exceptions on failure. */ | ||||
|     $this->services = array(); | ||||
|         $xrds = OMB_Yadis_XRDS::fromYadisURL($service_url, $this->fetcher); | ||||
|  | ||||
|     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]); | ||||
|         /* 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); | ||||
|     } | ||||
|     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; | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * | ||||
|    * 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) . '&'; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     $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.'); | ||||
|     /** | ||||
|      * 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]; | ||||
|     } | ||||
|  | ||||
|     if ($req->get_parameter('omb_version') != OMB_VERSION) { | ||||
|       throw new OMB_RemoteServiceException('The remote service uses an ' . | ||||
|                                            'unsupported OMB version'); | ||||
|     /** | ||||
|      * 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; | ||||
|     } | ||||
|  | ||||
|     /* 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; | ||||
|  | ||||
|     require_once 'profile.php'; | ||||
|     $listener = OMB_Profile::fromParameters($params, 'omb_listener'); | ||||
|  | ||||
|     /* 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'); | ||||
|     /** | ||||
|      * 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; | ||||
|     } | ||||
|  | ||||
|     parse_str($result->body, $return); | ||||
|     if (!isset($return['oauth_token']) || !isset($return['oauth_token_secret'])) { | ||||
|       throw new OAuthException('Could not get access 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; | ||||
|     } | ||||
|     $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. */ | ||||
|     /** | ||||
|      * 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; | ||||
|  | ||||
|     $this->datastore->saveProfile($listener); | ||||
|     $this->datastore->saveSubscription($this->listener_uri, | ||||
|                                        $this->listenee_uri, | ||||
|                                        $this->token); | ||||
|   } | ||||
|             $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); | ||||
|  | ||||
|   /** | ||||
|    * 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 = array_merge($profile->asParameters('omb_listenee', false), | ||||
|                                   $params); | ||||
|  | ||||
|   /** | ||||
|    * 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()); | ||||
|   } | ||||
|             /* 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) . '&'; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|   /** | ||||
|    * 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']); | ||||
|   } | ||||
|         $this->listenee_uri = $profile->getIdentifierURI(); | ||||
|  | ||||
|   /** | ||||
|    * 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); | ||||
|         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.'); | ||||
|         } | ||||
|  | ||||
|         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'); | ||||
|  | ||||
|         /* 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; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 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 – 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); | ||||
|         } | ||||
|     } | ||||
|   } | ||||
| } | ||||
| ?> | ||||
|   | ||||
| @@ -1,13 +1,6 @@ | ||||
| <?php | ||||
|  | ||||
| require_once 'constants.php'; | ||||
| require_once 'remoteserviceexception.php'; | ||||
| require_once 'helper.php'; | ||||
|  | ||||
| /** | ||||
|  * OMB service realization | ||||
|  * | ||||
|  * This class realizes a complete, simple OMB service. | ||||
|  * This file is part of libomb | ||||
|  * | ||||
|  * PHP version 5 | ||||
|  * | ||||
| @@ -24,406 +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 | ||||
|  **/ | ||||
|  * @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 | ||||
|  */ | ||||
|  | ||||
| class OMB_Service_Provider { | ||||
|   protected $user; /* An OMB_Profile representing the user */ | ||||
|   protected $datastore; /* AN OMB_Datastore */ | ||||
| require_once 'constants.php'; | ||||
| require_once 'helper.php'; | ||||
| require_once 'notice.php'; | ||||
| require_once 'remoteserviceexception.php'; | ||||
|  | ||||
|   protected $remote_user; /* An OMB_Profile representing the remote user during | ||||
|                             the authorization process */ | ||||
| /** | ||||
|  * OMB service realization | ||||
|  * | ||||
|  * This class realizes a complete, simple OMB service. | ||||
|  */ | ||||
| class OMB_Service_Provider | ||||
| { | ||||
|     protected $user; /* An OMB_Profile representing the user */ | ||||
|     protected $datastore; /* AN OMB_Datastore */ | ||||
|  | ||||
|   protected $oauth_server; /* An OAuthServer; should only be accessed via | ||||
|                               getOAuthServer. */ | ||||
|     protected $remote_user; /* An OMB_Profile representing the remote user | ||||
|                                during the authorization process */ | ||||
|  | ||||
|   /** | ||||
|    * 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; | ||||
|   } | ||||
|     protected $oauth_server; /* An OAuthServer; should only be accessed via | ||||
|                                 getOAuthServer. */ | ||||
|  | ||||
|   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.'); | ||||
|     /** | ||||
|      * 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; | ||||
|     } | ||||
|  | ||||
|     /* Verify the OMB part. */ | ||||
|  | ||||
|     if ($_GET['omb_version'] !== OMB_VERSION) { | ||||
|       throw OMB_RemoteServiceException::forRequest(OAUTH_ENDPOINT_AUTHORIZE, | ||||
|                                    'Wrong OMB version ' . $_GET['omb_version']); | ||||
|     /** | ||||
|      * Return the remote user during user authorization | ||||
|      * | ||||
|      * Returns an OMB_Profile representing the remote user during the user | ||||
|      * authorization request. | ||||
|      * | ||||
|      * @return OMB_Profile The remote user | ||||
|      */ | ||||
|     public function getRemoteUser() | ||||
|     { | ||||
|         return $this->remote_user; | ||||
|     } | ||||
|  | ||||
|     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) . '&'; | ||||
|     /** | ||||
|      * 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); | ||||
|     } | ||||
|     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( | ||||
|     /** | ||||
|      * 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; | ||||
|  | ||||
|         } 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'); | ||||
|       // @debug hack | ||||
|       throw OMB_RemoteServiceException::forRequest($uri, | ||||
|                                    'Revoked accesstoken for ' . $listenee . ': ' . $e->getMessage()); | ||||
|       // @end debug | ||||
|       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); | ||||
|     /** | ||||
|      * 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; | ||||
|     } | ||||
|  | ||||
|     $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); | ||||
|     /** | ||||
|      * 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); | ||||
|  | ||||
|         $notice = OMB_Notice::fromParameters($profile, $req->get_parameters()); | ||||
|         $this->datastore->saveNotice($notice); | ||||
|         $this->finishOMBRequest(); | ||||
|  | ||||
|         return $notice; | ||||
|     } | ||||
|  | ||||
|     $subscribers = $this->datastore->getSubscriptions($listenee); | ||||
|     if (count($subscribers) === 0) { | ||||
|       header('HTTP/1.1 403 Forbidden'); | ||||
|       throw OMB_RemoteServiceException::forRequest($uri, | ||||
|                                    'No subscriber for ' . $listenee); | ||||
|     /** | ||||
|      * 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); | ||||
|     } | ||||
|  | ||||
|     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; | ||||
|     } | ||||
|  | ||||
|   /** | ||||
|    * 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( | ||||
|     /** | ||||
|      * 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(); | ||||
|         } | ||||
|         return $this->oauth_server; | ||||
|     } | ||||
|  | ||||
|     require_once 'service_consumer.php'; | ||||
|     /** | ||||
|      * 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(); | ||||
|  | ||||
|     $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; | ||||
|   } | ||||
|         /* $notice is passed by reference and may change. */ | ||||
|         $this->datastore->saveNotice($notice); | ||||
|         $subscribers = $this->datastore->getSubscriptions($uri); | ||||
|  | ||||
|   /** | ||||
|    * 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(); | ||||
|         /* No one to post to. */ | ||||
|         if (is_null($subscribers)) { | ||||
|             return array(); | ||||
|         } | ||||
|  | ||||
|     $this->datastore->saveProfile($this->user); | ||||
|     $subscribers = $this->datastore->getSubscriptions($uri); | ||||
|         require_once 'service_consumer.php'; | ||||
|  | ||||
|     /* No one to post to. */ | ||||
|     if (is_null($subscribers)) { | ||||
|         return array(); | ||||
|         $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; | ||||
|     } | ||||
|  | ||||
|     require_once 'service_consumer.php'; | ||||
|     /** | ||||
|      * 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(); | ||||
|  | ||||
|     $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; | ||||
|       } | ||||
|         $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; | ||||
|     } | ||||
|     return $err; | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -1,9 +1,6 @@ | ||||
| <?php | ||||
| /** | ||||
|  * Exception stating that a requested service is not available | ||||
|  * | ||||
|  * This exception is raised when OMB_Service is asked to call a service the remote | ||||
|  * server does not provide. | ||||
|  * This file is part of libomb | ||||
|  * | ||||
|  * PHP version 5 | ||||
|  * | ||||
| @@ -20,12 +17,20 @@ | ||||
|  * 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_UnsupportedServiceException extends Exception { | ||||
|  * @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 | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|  * Exception stating that a requested service is not available | ||||
|  * | ||||
|  * This exception is raised when OMB_Service is asked to call a service the | ||||
|  * remote server does not provide. | ||||
|  */ | ||||
| class OMB_UnsupportedServiceException extends Exception | ||||
| { | ||||
| } | ||||
| ?> | ||||
|   | ||||
| @@ -1,10 +1,6 @@ | ||||
| <?php | ||||
| /** | ||||
|  * Map XRDS actions to URLs | ||||
|  * | ||||
|  * This interface specifies classes which write the XRDS file announcing | ||||
|  * the OMB server. An instance of an implementing class should be passed to | ||||
|  * OMB_Service_Provider->writeXRDS. | ||||
|  * This file is part of libomb | ||||
|  * | ||||
|  * PHP version 5 | ||||
|  * | ||||
| @@ -21,13 +17,31 @@ | ||||
|  * 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 | ||||
|  **/ | ||||
|  * @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 | ||||
|  */ | ||||
|  | ||||
| interface OMB_XRDS_Mapper { | ||||
|   public function getURL($action); | ||||
| /** | ||||
|  * Map XRDS actions to URLs | ||||
|  * | ||||
|  * This interface specifies classes which write the XRDS file announcing | ||||
|  * the OMB server. An instance of an implementing class should be passed to | ||||
|  * OMB_Service_Provider->writeXRDS. | ||||
|  */ | ||||
| interface OMB_XRDS_Mapper | ||||
| { | ||||
|     /** | ||||
|      * Fetch an URL for a specified action | ||||
|      * | ||||
|      * Returns the action URL for an action specified by the endpoint URI. | ||||
|      * | ||||
|      * @param string $action The endpoint URI | ||||
|      * | ||||
|      * @return string The action URL | ||||
|      */ | ||||
|     public function getURL($action); | ||||
| } | ||||
| ?> | ||||
|   | ||||
| @@ -1,10 +1,6 @@ | ||||
| <?php | ||||
| /** | ||||
|  * Write OMB-specific XRDS | ||||
|  * | ||||
|  * This interface specifies classes which write the XRDS file announcing | ||||
|  * the OMB server. An instance of an implementing class should be passed to | ||||
|  * OMB_Service_Provider->writeXRDS. | ||||
|  * This file is part of libomb | ||||
|  * | ||||
|  * PHP version 5 | ||||
|  * | ||||
| @@ -21,13 +17,30 @@ | ||||
|  * 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 | ||||
|  **/ | ||||
|  * @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 | ||||
|  */ | ||||
|  | ||||
| interface OMB_XRDS_Writer { | ||||
|   public function writeXRDS($user, $mapper); | ||||
| /** | ||||
|  * Write OMB-specific XRDS | ||||
|  * | ||||
|  * This interface specifies classes which write the XRDS file announcing | ||||
|  * the OMB server. An instance of an implementing class should be passed to | ||||
|  * OMB_Service_Provider->writeXRDS. | ||||
|  */ | ||||
| interface OMB_XRDS_Writer | ||||
| { | ||||
|     /** | ||||
|      * Write XRDS | ||||
|      * | ||||
|      * Outputs a XRDS document specifying an OMB service. | ||||
|      * | ||||
|      * @param OMB_profile     $user   The target user for the OMB service | ||||
|      * @param OMB_XRDS_Mapper $mapper An OMB_XRDS_Mapper providing endpoint URLs | ||||
|      */ | ||||
|     public function writeXRDS($user, $mapper); | ||||
| } | ||||
| ?> | ||||
|   | ||||
							
								
								
									
										39
									
								
								js/util.js
									
									
									
									
									
								
							
							
						
						
									
										39
									
								
								js/util.js
									
									
									
									
									
								
							| @@ -258,9 +258,10 @@ var SN = { // StatusNet | ||||
|                             form.append('<p class="form_response success">'+result+'</p>'); | ||||
|                         } | ||||
|                         else { | ||||
|                             // New notice post was successful. If on our timeline, show it! | ||||
|                             var notice = document._importNode($('li', data)[0], true); | ||||
|                             var notices = $('#notices_primary .notices'); | ||||
|                             if (notices.length > 0) { | ||||
|                                 var notice = document._importNode($('li', data)[0], true); | ||||
|                             if (notices.length > 0 && SN.U.belongsOnTimeline(notice)) { | ||||
|                                 if ($('#'+notice.id).length === 0) { | ||||
|                                     var notice_irt_value = $('#'+SN.C.S.NoticeInReplyTo).val(); | ||||
|                                     var notice_irt = '#notices_primary #notice-'+notice_irt_value; | ||||
| @@ -281,6 +282,8 @@ var SN = { // StatusNet | ||||
|                                 } | ||||
|                             } | ||||
|                             else { | ||||
|                                 // Not on a timeline that this belongs on? | ||||
|                                 // Just show a success message. | ||||
|                                 result = document._importNode($('title', data)[0], true); | ||||
|                                 result_title = result.textContent || result.innerHTML; | ||||
|                                 form.append('<p class="form_response success">'+result_title+'</p>'); | ||||
| @@ -707,6 +710,38 @@ var SN = { // StatusNet | ||||
|             Delete: function() { | ||||
|                 $.cookie(SN.C.S.StatusNetInstance, null); | ||||
|             } | ||||
|         }, | ||||
|  | ||||
|         /** | ||||
|          * Check if the current page is a timeline where the current user's | ||||
|          * posts should be displayed immediately on success. | ||||
|          * | ||||
|          * @fixme this should be done in a saner way, with machine-readable | ||||
|          * info about what page we're looking at. | ||||
|          */ | ||||
|         belongsOnTimeline: function(notice) { | ||||
|             var action = $("body").attr('id'); | ||||
|             if (action == 'public') { | ||||
|                 return true; | ||||
|             } | ||||
|  | ||||
|             var profileLink = $('#nav_profile a').attr('href'); | ||||
|             if (profileLink) { | ||||
|                 var authorUrl = $(notice).find('.entry-title .author a.url').attr('href'); | ||||
|                 if (authorUrl == profileLink) { | ||||
|                     if (action == 'all' || action == 'showstream') { | ||||
|                         // Posts always show on your own friends and profile streams. | ||||
|                         return true; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             // @fixme tag, group, reply timelines should be feasible as well. | ||||
|             // Mismatch between id-based and name-based user/group links currently complicates | ||||
|             // the lookup, since all our inline mentions contain the absolute links but the | ||||
|             // UI links currently on the page use malleable names. | ||||
|  | ||||
|             return false; | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|   | ||||
| @@ -51,6 +51,7 @@ class ActivityContext | ||||
|     const POINT     = 'point'; | ||||
|  | ||||
|     const ATTENTION    = 'ostatus:attention'; | ||||
|     const MENTIONED    = 'mentioned'; | ||||
|     const CONVERSATION = 'ostatus:conversation'; | ||||
|  | ||||
|     function __construct($element) | ||||
| @@ -76,8 +77,12 @@ class ActivityContext | ||||
|  | ||||
|             $linkRel = $link->getAttribute(ActivityUtils::REL); | ||||
|  | ||||
|             // XXX: Deprecate this in favour of "mentioned" from Salmon spec | ||||
|             // http://salmon-protocol.googlecode.com/svn/trunk/draft-panzer-salmon-00.html#SALR | ||||
|             if ($linkRel == self::ATTENTION) { | ||||
|                 $this->attention[] = $link->getAttribute(self::HREF); | ||||
|             } elseif ($linkRel == self::MENTIONED) { | ||||
|                 $this->attention[] = $link->getAttribute(self::HREF); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|   | ||||
| @@ -257,6 +257,12 @@ class ActivityUtils | ||||
|      */ | ||||
|     static function validateUri($uri) | ||||
|     { | ||||
|         // Check mailto: URIs first | ||||
|  | ||||
|         if (preg_match('/^mailto:(.*)$/', $uri, $match)) { | ||||
|             return Validate::email($match[1], common_config('email', 'check_domain')); | ||||
|         } | ||||
|  | ||||
|         if (Validate::uri($uri)) { | ||||
|             return true; | ||||
|         } | ||||
|   | ||||
| @@ -27,7 +27,7 @@ | ||||
|  * @author    Jeffery To <jeffery.to@gmail.com> | ||||
|  * @author    Toby Inkster <mail@tobyinkster.co.uk> | ||||
|  * @author    Zach Copley <zach@status.net> | ||||
|  * @copyright 2009 StatusNet, Inc. | ||||
|  * @copyright 2009-2010 StatusNet, Inc. | ||||
|  * @copyright 2009 Free Software Foundation, Inc http://www.fsf.org | ||||
|  * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 | ||||
|  * @link      http://status.net/ | ||||
| @@ -128,6 +128,7 @@ class ApiAction extends Action | ||||
|     var $max_id    = null; | ||||
|     var $since_id  = null; | ||||
|     var $source    = null; | ||||
|     var $callback  = null; | ||||
|  | ||||
|     var $access    = self::READ_ONLY;  // read (default) or read-write | ||||
|  | ||||
| @@ -147,6 +148,7 @@ class ApiAction extends Action | ||||
|         parent::prepare($args); | ||||
|  | ||||
|         $this->format   = $this->arg('format'); | ||||
|         $this->callback = $this->arg('callback'); | ||||
|         $this->page     = (int)$this->arg('page', 1); | ||||
|         $this->count    = (int)$this->arg('count', 20); | ||||
|         $this->max_id   = (int)$this->arg('max_id', 0); | ||||
| @@ -463,6 +465,7 @@ class ApiAction extends Action | ||||
|     function twitterRssEntryArray($notice) | ||||
|     { | ||||
|         $profile = $notice->getProfile(); | ||||
|  | ||||
|         $entry = array(); | ||||
|  | ||||
|         // We trim() to avoid extraneous whitespace in the output | ||||
| @@ -735,14 +738,16 @@ class ApiAction extends Action | ||||
|                                               'xmlns:statusnet' => 'http://status.net/schema/api/1/')); | ||||
|  | ||||
|         if (is_array($notice)) { | ||||
|             foreach ($notice as $n) { | ||||
|                 $twitter_status = $this->twitterStatusArray($n); | ||||
|                 $this->showTwitterXmlStatus($twitter_status); | ||||
|             } | ||||
|         } else { | ||||
|             while ($notice->fetch()) { | ||||
|             $notice = new ArrayWrapper($notice); | ||||
|         } | ||||
|  | ||||
|         while ($notice->fetch()) { | ||||
|             try { | ||||
|                 $twitter_status = $this->twitterStatusArray($notice); | ||||
|                 $this->showTwitterXmlStatus($twitter_status); | ||||
|             } catch (Exception $e) { | ||||
|                 common_log(LOG_ERR, $e->getMessage()); | ||||
|                 continue; | ||||
|             } | ||||
|         } | ||||
|  | ||||
| @@ -790,14 +795,16 @@ class ApiAction extends Action | ||||
|         $this->element('ttl', null, '40'); | ||||
|  | ||||
|         if (is_array($notice)) { | ||||
|             foreach ($notice as $n) { | ||||
|                 $entry = $this->twitterRssEntryArray($n); | ||||
|                 $this->showTwitterRssItem($entry); | ||||
|             } | ||||
|         } else { | ||||
|             while ($notice->fetch()) { | ||||
|             $notice = new ArrayWrapper($notice); | ||||
|         } | ||||
|  | ||||
|         while ($notice->fetch()) { | ||||
|             try { | ||||
|                 $entry = $this->twitterRssEntryArray($notice); | ||||
|                 $this->showTwitterRssItem($entry); | ||||
|             } catch (Exception $e) { | ||||
|                 common_log(LOG_ERR, $e->getMessage()); | ||||
|                 // continue on exceptions | ||||
|             } | ||||
|         } | ||||
|  | ||||
| @@ -833,12 +840,15 @@ class ApiAction extends Action | ||||
|         $this->element('subtitle', null, $subtitle); | ||||
|  | ||||
|         if (is_array($notice)) { | ||||
|             foreach ($notice as $n) { | ||||
|                 $this->raw($n->asAtomEntry()); | ||||
|             } | ||||
|         } else { | ||||
|             while ($notice->fetch()) { | ||||
|             $notice = new ArrayWrapper($notice); | ||||
|         } | ||||
|  | ||||
|         while ($notice->fetch()) { | ||||
|             try { | ||||
|                 $this->raw($notice->asAtomEntry()); | ||||
|             } catch (Exception $e) { | ||||
|                 common_log(LOG_ERR, $e->getMessage()); | ||||
|                 continue; | ||||
|             } | ||||
|         } | ||||
|  | ||||
| @@ -1033,14 +1043,16 @@ class ApiAction extends Action | ||||
|         $statuses = array(); | ||||
|  | ||||
|         if (is_array($notice)) { | ||||
|             foreach ($notice as $n) { | ||||
|                 $twitter_status = $this->twitterStatusArray($n); | ||||
|                 array_push($statuses, $twitter_status); | ||||
|             } | ||||
|         } else { | ||||
|             while ($notice->fetch()) { | ||||
|             $notice = new ArrayWrapper($notice); | ||||
|         } | ||||
|  | ||||
|         while ($notice->fetch()) { | ||||
|             try { | ||||
|                 $twitter_status = $this->twitterStatusArray($notice); | ||||
|                 array_push($statuses, $twitter_status); | ||||
|             } catch (Exception $e) { | ||||
|                 common_log(LOG_ERR, $e->getMessage()); | ||||
|                 continue; | ||||
|             } | ||||
|         } | ||||
|  | ||||
| @@ -1177,9 +1189,8 @@ class ApiAction extends Action | ||||
|             header('Content-Type: application/json; charset=utf-8'); | ||||
|  | ||||
|             // Check for JSONP callback | ||||
|             $callback = $this->arg('callback'); | ||||
|             if ($callback) { | ||||
|                 print $callback . '('; | ||||
|             if (isset($this->callback)) { | ||||
|                 print $this->callback . '('; | ||||
|             } | ||||
|             break; | ||||
|         case 'rss': | ||||
| @@ -1208,8 +1219,7 @@ class ApiAction extends Action | ||||
|         case 'json': | ||||
|  | ||||
|             // Check for JSONP callback | ||||
|             $callback = $this->arg('callback'); | ||||
|             if ($callback) { | ||||
|             if (isset($this->callback)) { | ||||
|                 print ')'; | ||||
|             } | ||||
|             break; | ||||
| @@ -1239,7 +1249,10 @@ class ApiAction extends Action | ||||
|  | ||||
|         $status_string = ClientErrorAction::$status[$code]; | ||||
|  | ||||
|         header('HTTP/1.1 '.$code.' '.$status_string); | ||||
|         // Do not emit error header for JSONP | ||||
|         if (!isset($this->callback)) { | ||||
|             header('HTTP/1.1 '.$code.' '.$status_string); | ||||
|         } | ||||
|  | ||||
|         if ($format == 'xml') { | ||||
|             $this->initDocument('xml'); | ||||
| @@ -1272,7 +1285,10 @@ class ApiAction extends Action | ||||
|  | ||||
|         $status_string = ServerErrorAction::$status[$code]; | ||||
|  | ||||
|         header('HTTP/1.1 '.$code.' '.$status_string); | ||||
|         // Do not emit error header for JSONP | ||||
|         if (!isset($this->callback)) { | ||||
|             header('HTTP/1.1 '.$code.' '.$status_string); | ||||
|         } | ||||
|  | ||||
|         if ($content_type == 'xml') { | ||||
|             $this->initDocument('xml'); | ||||
| @@ -1376,6 +1392,34 @@ class ApiAction extends Action | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     function getTargetProfile($id) | ||||
|     { | ||||
|         if (empty($id)) { | ||||
|  | ||||
|             // Twitter supports these other ways of passing the user ID | ||||
|             if (is_numeric($this->arg('id'))) { | ||||
|                 return Profile::staticGet($this->arg('id')); | ||||
|             } else if ($this->arg('id')) { | ||||
|                 $nickname = common_canonical_nickname($this->arg('id')); | ||||
|                 return Profile::staticGet('nickname', $nickname); | ||||
|             } 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'))) { | ||||
|                     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); | ||||
|             } | ||||
|         } else if (is_numeric($id)) { | ||||
|             return Profile::staticGet($id); | ||||
|         } else { | ||||
|             $nickname = common_canonical_nickname($id); | ||||
|             return Profile::staticGet('nickname', $nickname); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     function getTargetGroup($id) | ||||
|     { | ||||
|         if (empty($id)) { | ||||
|   | ||||
| @@ -227,7 +227,7 @@ class ApiAuthAction extends ApiAction | ||||
|  | ||||
|         } catch (OAuthException $e) { | ||||
|             common_log(LOG_WARNING, 'API OAuthException - ' . $e->getMessage()); | ||||
|             $this->showAuthError(); | ||||
|             $this->clientError($e->getMessage(), 401, $this->format); | ||||
|             exit; | ||||
|         } | ||||
|     } | ||||
| @@ -265,7 +265,7 @@ class ApiAuthAction extends ApiAction | ||||
|  | ||||
|             // show error if the user clicks 'cancel' | ||||
|  | ||||
|             $this->showAuthError(); | ||||
|             $this->clientError("Could not authenticate you.", 401, $this->format); | ||||
|             exit; | ||||
|  | ||||
|         } else { | ||||
| @@ -298,7 +298,7 @@ class ApiAuthAction extends ApiAction | ||||
|                                $proxy, | ||||
|                                $ip); | ||||
|                 common_log(LOG_WARNING, $msg); | ||||
|                 $this->showAuthError(); | ||||
|                 $this->clientError("Could not authenticate you.", 401, $this->format); | ||||
|                 exit; | ||||
|             } | ||||
|         } | ||||
| @@ -345,36 +345,4 @@ class ApiAuthAction extends ApiAction | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Output an authentication error message.  Use XML or JSON if one | ||||
|      * of those formats is specified, otherwise output plain text | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|  | ||||
|     function showAuthError() | ||||
|     { | ||||
|         header('HTTP/1.1 401 Unauthorized'); | ||||
|         $msg = 'Could not authenticate you.'; | ||||
|  | ||||
|         if ($this->format == 'xml') { | ||||
|             header('Content-Type: application/xml; charset=utf-8'); | ||||
|             $this->startXML(); | ||||
|             $this->elementStart('hash'); | ||||
|             $this->element('error', null, $msg); | ||||
|             $this->element('request', null, $_SERVER['REQUEST_URI']); | ||||
|             $this->elementEnd('hash'); | ||||
|             $this->endXML(); | ||||
|         } elseif ($this->format == 'json') { | ||||
|             header('Content-Type: application/json; charset=utf-8'); | ||||
|             $error_array = array('error' => $msg, | ||||
|                                  'request' => $_SERVER['REQUEST_URI']); | ||||
|             print(json_encode($error_array)); | ||||
|         } else { | ||||
|             header('Content-type: text/plain'); | ||||
|             print "$msg\n"; | ||||
|         } | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user