+
+ # Throws an OAuthException if anything goes wrong
+
+ function validate_request(&$req) {
+ # OAuth stuff -- have to copy from OAuth.php since they're
+ # all private methods, and there's no user-authentication method
+ common_debug('checking version', __FILE__);
+ $this->check_version($req);
+ common_debug('getting datastore', __FILE__);
+ $datastore = omb_oauth_datastore();
+ common_debug('getting consumer', __FILE__);
+ $consumer = $this->get_consumer($datastore, $req);
+ common_debug('getting token', __FILE__);
+ $token = $this->get_token($datastore, $req, $consumer);
+ common_debug('checking timestamp', __FILE__);
+ $this->check_timestamp($req);
+ common_debug('checking nonce', __FILE__);
+ $this->check_nonce($datastore, $req, $consumer, $token);
+ common_debug('checking signature', __FILE__);
+ $this->check_signature($req, $consumer, $token);
+ common_debug('validating omb stuff', __FILE__);
+ $this->validate_omb($req);
+ common_debug('done validating', __FILE__);
+ return true;
+ }
+
+ function validate_omb(&$req) {
+ foreach (array('omb_version', 'omb_listener', 'omb_listenee',
+ 'omb_listenee_profile', 'omb_listenee_nickname',
+ 'omb_listenee_license') as $param)
+ {
+ if (!$req->get_parameter($param)) {
+ throw new OAuthException("Required parameter '$param' not found");
+ }
+ }
+ # Now, OMB stuff
+ $version = $req->get_parameter('omb_version');
+ if ($version != OMB_VERSION_01) {
+ throw new OAuthException("OpenMicroBlogging version '$version' not supported");
+ }
+ $listener = $req->get_parameter('omb_listener');
+ $user = User::staticGet('uri', $listener);
+ if (!$user) {
+ throw new OAuthException("Listener URI '$listener' not found here");
+ }
+ $cur = common_current_user();
+ if ($cur->id != $user->id) {
+ throw new OAuthException("Can't add for another user!");
+ }
+ $listenee = $req->get_parameter('omb_listenee');
+ if (!Validate::uri($listenee) &&
+ !common_valid_tag($listenee)) {
+ throw new OAuthException("Listenee URI '$listenee' not a recognizable URI");
+ }
+ if (strlen($listenee) > 255) {
+ throw new OAuthException("Listenee URI '$listenee' too long");
+ }
+ $remote = Remote_profile::staticGet('uri', $listenee);
+ if ($remote) {
+ $sub = new Subscription();
+ $sub->subscriber = $user->id;
+ $sub->subscribed = $remote->id;
+ if ($sub->find(TRUE)) {
+ throw new OAuthException("Already subscribed to user!");
+ }
+ }
+ $nickname = $req->get_parameter('omb_listenee_nickname');
+ if (!Validate::string($nickname, array('min_length' => 1,
+ 'max_length' => 64,
+ 'format' => VALIDATE_NUM . VALIDATE_ALPHA_LOWER))) {
+ throw new OAuthException('Nickname must have only letters and numbers and no spaces.');
+ }
+ $profile = $req->get_parameter('omb_listenee_profile');
+ if (!common_valid_http_url($profile)) {
+ throw new OAuthException("Invalid profile URL '$profile'.");
+ }
+ $license = $req->get_parameter('omb_listenee_license');
+ if (!common_valid_http_url($license)) {
+ throw new OAuthException("Invalid license URL '$license'.");
+ }
+ # optional stuff
+ $fullname = $req->get_parameter('omb_listenee_fullname');
+ if ($fullname && strlen($fullname) > 255) {
+ throw new OAuthException("Full name '$fullname' too long.");
+ }
+ $homepage = $req->get_parameter('omb_listenee_homepage');
+ if ($homepage && (!common_valid_http_url($homepage) || strlen($homepage) > 255)) {
+ throw new OAuthException("Invalid homepage '$homepage'");
+ }
+ $bio = $req->get_parameter('omb_listenee_bio');
+ if ($bio && strlen($bio) > 140) {
+ throw new OAuthException("Bio too long '$bio'");
+ }
+ $location = $req->get_parameter('omb_listenee_location');
+ if ($location && strlen($location) > 255) {
+ throw new OAuthException("Location too long '$location'");
+ }
+ $avatar = $req->get_parameter('omb_listenee_avatar');
+ if ($avatar) {
+ if (!common_valid_http_url($avatar) || strlen($avatar) > 255) {
+ throw new OAuthException("Invalid avatar URL '$avatar'");
+ }
+ $size = @getimagesize($avatar);
+ if (!$size) {
+ throw new OAuthException("Can't read avatar URL '$avatar'");
+ }
+ if ($size[0] != AVATAR_PROFILE_SIZE || $size[1] != AVATAR_PROFILE_SIZE) {
+ throw new OAuthException("Wrong size image at '$avatar'");
+ }
+ if (!in_array($size[2], array(IMAGETYPE_GIF, IMAGETYPE_JPEG,
+ IMAGETYPE_PNG))) {
+ throw new OAuthException("Wrong image type for '$avatar'");
+ }
+ }
+ $callback = $req->get_parameter('oauth_callback');
+ if ($callback && !common_valid_http_url($callback)) {
+ throw new OAuthException("Invalid callback URL '$callback'");
+ }
+ }
+
+ # Snagged from OAuthServer
+
+ function check_version(&$req) {
+ $version = $req->get_parameter("oauth_version");
+ if (!$version) {
+ $version = 1.0;
+ }
+ if ($version != 1.0) {
+ throw new OAuthException("OAuth version '$version' not supported");
+ }
+ return $version;
+ }
+
+ # Snagged from OAuthServer
+
+ function get_consumer($datastore, $req) {
+ $consumer_key = @$req->get_parameter("oauth_consumer_key");
+ if (!$consumer_key) {
+ throw new OAuthException("Invalid consumer key");
+ }
+
+ $consumer = $datastore->lookup_consumer($consumer_key);
+ if (!$consumer) {
+ throw new OAuthException("Invalid consumer");
+ }
+ return $consumer;
+ }
+
+ # Mostly cadged from OAuthServer
+
+ function get_token($datastore, &$req, $consumer) {/*{{{*/
+ $token_field = @$req->get_parameter('oauth_token');
+ $token = $datastore->lookup_token($consumer, 'request', $token_field);
+ if (!$token) {
+ throw new OAuthException("Invalid $token_type token: $token_field");
+ }
+ return $token;
+ }
+
+ function check_timestamp(&$req) {
+ $timestamp = @$req->get_parameter('oauth_timestamp');
+ $now = time();
+ if ($now - $timestamp > TIMESTAMP_THRESHOLD) {
+ throw new OAuthException("Expired timestamp, yours $timestamp, ours $now");
+ }
+ }
+
+ # NOTE: don't call twice on the same request; will fail!
+ function check_nonce(&$datastore, &$req, $consumer, $token) {
+ $timestamp = @$req->get_parameter('oauth_timestamp');
+ $nonce = @$req->get_parameter('oauth_nonce');
+ $found = $datastore->lookup_nonce($consumer, $token, $nonce, $timestamp);
+ if ($found) {
+ throw new OAuthException("Nonce already used");
+ }
+ return true;
+ }
+
+ function check_signature(&$req, $consumer, $token) {
+ $signature_method = $this->get_signature_method($req);
+ $signature = $req->get_parameter('oauth_signature');
+ $valid_sig = $signature_method->check_signature($req,
+ $consumer,
+ $token,
+ $signature);
+ if (!$valid_sig) {
+ throw new OAuthException("Invalid signature");
+ }
+ }
+
+ function get_signature_method(&$req) {
+ $signature_method = @$req->get_parameter("oauth_signature_method");
+ if (!$signature_method) {
+ $signature_method = "PLAINTEXT";