diff options
| author | Sem <sembrestels@riseup.net> | 2014-01-22 04:05:47 +0100 | 
|---|---|---|
| committer | Sem <sembrestels@riseup.net> | 2014-01-22 04:05:47 +0100 | 
| commit | 68614b769f4ae4f28c3f395f47b68baba7c48c64 (patch) | |
| tree | 2c5a744a3859d27883f92b72aef9cf81f1a947d0 /mod/twitter_api | |
| parent | 69e2d8c5d8732042c9319aef1fdea45a82b63e42 (diff) | |
| parent | c0295c275d6edbca6c6c8bb51dc199150d0d5fc3 (diff) | |
| download | elgg-68614b769f4ae4f28c3f395f47b68baba7c48c64.tar.gz elgg-68614b769f4ae4f28c3f395f47b68baba7c48c64.tar.bz2  | |
Merge branch 'release/1.8.1'
Diffstat (limited to 'mod/twitter_api')
| -rw-r--r-- | mod/twitter_api/languages/en.php | 4 | ||||
| -rw-r--r-- | mod/twitter_api/lib/twitter_api.php | 41 | ||||
| -rw-r--r-- | mod/twitter_api/manifest.xml | 10 | ||||
| -rw-r--r-- | mod/twitter_api/pages/twitter_api/interstitial.php | 4 | ||||
| -rw-r--r-- | mod/twitter_api/start.php | 33 | ||||
| -rw-r--r-- | mod/twitter_api/vendors/twitteroauth/OAuth.php | 390 | ||||
| -rw-r--r-- | mod/twitter_api/vendors/twitteroauth/README | 117 | ||||
| -rw-r--r-- | mod/twitter_api/vendors/twitteroauth/twitterOAuth.php | 16 | ||||
| -rw-r--r-- | mod/twitter_api/views/default/forms/twitter_api/interstitial_settings.php | 7 | ||||
| -rw-r--r-- | mod/twitter_api/views/default/plugins/twitter_api/settings.php | 15 | 
10 files changed, 561 insertions, 76 deletions
diff --git a/mod/twitter_api/languages/en.php b/mod/twitter_api/languages/en.php index f4b3c7f94..a6f4b40a5 100644 --- a/mod/twitter_api/languages/en.php +++ b/mod/twitter_api/languages/en.php @@ -25,7 +25,9 @@ $english = array(  	'twitter_api:revoke:success' => 'Twitter access has been revoked.', -	'twitter_api:login' => 'Allow existing users who have connected their Twitter account to sign in with Twitter?', +	'twitter_api:post_to_twitter' => "Send users' wire posts to Twitter?", + +	'twitter_api:login' => 'Allow users to sign in with Twitter?',  	'twitter_api:new_users' => 'Allow new users to sign up using their Twitter account even if user registration is disabled?',  	'twitter_api:login:success' => 'You have been logged in.',  	'twitter_api:login:error' => 'Unable to login with Twitter.', diff --git a/mod/twitter_api/lib/twitter_api.php b/mod/twitter_api/lib/twitter_api.php index e163d2b3e..a7b971876 100644 --- a/mod/twitter_api/lib/twitter_api.php +++ b/mod/twitter_api/lib/twitter_api.php @@ -6,6 +6,27 @@   */  /** + * Get the API wrapper object + *  + * @param string $oauth_token        User's OAuth token + * @param string $oauth_token_secret User's OAuth secret + * @return TwitterOAuth|null + */ +function twitter_api_get_api_object($oauth_token = null, $oauth_token_secret = null) { +	$consumer_key = elgg_get_plugin_setting('consumer_key', 'twitter_api'); +	$consumer_secret = elgg_get_plugin_setting('consumer_secret', 'twitter_api'); +	if (!($consumer_key && $consumer_secret)) { +		return null; +	} + +	$api = new TwitterOAuth($consumer_key, $consumer_secret, $oauth_token, $oauth_token_secret); +	if ($api) { +		$api->host = "https://api.twitter.com/1.1/"; +	} +	return $api; +} + +/**   * Tests if the system admin has enabled Sign-On-With-Twitter   *   * @param void @@ -94,7 +115,7 @@ function twitter_api_login() {  		$forward = $login_metadata['forward'];  	} -	if (!isset($token['oauth_token']) or !isset($token['oauth_token_secret'])) { +	if (!isset($token['oauth_token']) || !isset($token['oauth_token_secret'])) {  		register_error(elgg_echo('twitter_api:login:error'));  		forward();  	} @@ -121,9 +142,7 @@ function twitter_api_login() {  			forward();  		}  	} else { -		$consumer_key = elgg_get_plugin_setting('consumer_key', 'twitter_api'); -		$consumer_secret = elgg_get_plugin_setting('consumer_secret', 'twitter_api'); -		$api = new TwitterOAuth($consumer_key, $consumer_secret, $token['oauth_token'], $token['oauth_token_secret']); +		$api = twitter_api_get_api_object($token['oauth_token'], $token['oauth_token_secret']);  		$twitter = $api->get('account/verify_credentials');  		// backward compatibility for deprecated Twitter Login plugin @@ -255,7 +274,7 @@ function twitter_api_update_user_avatar($user, $file_location) {   * to establish session request tokens.   */  function twitter_api_authorize() { -	$token = twitter_api_get_access_token(); +	$token = twitter_api_get_access_token(get_input('oauth_verifier'));  	if (!isset($token['oauth_token']) || !isset($token['oauth_token_secret'])) {  		register_error(elgg_echo('twitter_api:authorize:error'));  		forward('settings/plugins', 'twitter_api'); @@ -314,11 +333,8 @@ function twitter_api_revoke() {  function twitter_api_get_authorize_url($callback = NULL, $login = true) {  	global $SESSION; -	$consumer_key = elgg_get_plugin_setting('consumer_key', 'twitter_api'); -	$consumer_secret = elgg_get_plugin_setting('consumer_secret', 'twitter_api'); -  	// request tokens from Twitter -	$twitter = new TwitterOAuth($consumer_key, $consumer_secret); +	$twitter = twitter_api_get_api_object();  	$token = $twitter->getRequestToken($callback);  	// save token in session for use after authorization @@ -340,16 +356,13 @@ function twitter_api_get_access_token($oauth_verifier = FALSE) {  	/* @var ElggSession $SESSION */  	global $SESSION; -	$consumer_key = elgg_get_plugin_setting('consumer_key', 'twitter_api'); -	$consumer_secret = elgg_get_plugin_setting('consumer_secret', 'twitter_api'); -  	// retrieve stored tokens  	$oauth_token = $SESSION['twitter_api']['oauth_token'];  	$oauth_token_secret = $SESSION['twitter_api']['oauth_token_secret'];  	unset($SESSION['twitter_api']);  	// fetch an access token -	$api = new TwitterOAuth($consumer_key, $consumer_secret, $oauth_token, $oauth_token_secret); +	$api = twitter_api_get_api_object($oauth_token, $oauth_token_secret);  	return $api->getAccessToken($oauth_verifier);  } @@ -367,4 +380,4 @@ function twitter_api_allow_new_users_with_twitter() {  	}  	return false; -}
\ No newline at end of file +} diff --git a/mod/twitter_api/manifest.xml b/mod/twitter_api/manifest.xml index 86bba4b50..3af866bba 100644 --- a/mod/twitter_api/manifest.xml +++ b/mod/twitter_api/manifest.xml @@ -2,7 +2,7 @@  <plugin_manifest xmlns="http://www.elgg.org/plugin_manifest/1.8">  	<name>Twitter API</name>  	<author>Core developers</author> -	<version>1.8</version> +	<version>1.8.15</version>  	<description>Allows users to authenticate their Elgg account with Twitter.</description>  	<category>api</category>  	<category>bundled</category> @@ -14,16 +14,16 @@  		<version>1.8</version>  	</requires>  	<requires> -		<type>plugin</type> -		<name>oauth_api</name> -	</requires> -	<requires>  		<type>php_extension</type>  		<name>curl</name>  	</requires>  	<conflicts>  		<type>plugin</type> +		<name>oauth_api</name> +	</conflicts> +	<conflicts> +		<type>plugin</type>  		<name>twitterservice</name>  	</conflicts>  </plugin_manifest> diff --git a/mod/twitter_api/pages/twitter_api/interstitial.php b/mod/twitter_api/pages/twitter_api/interstitial.php index d1f1ac20c..23b5069cb 100644 --- a/mod/twitter_api/pages/twitter_api/interstitial.php +++ b/mod/twitter_api/pages/twitter_api/interstitial.php @@ -8,9 +8,7 @@  $title = elgg_echo('twitter_api:interstitial:settings'); -$site = get_config('site'); -$content = elgg_echo('twitter_api:interstitial:description', array($site->name)); -$content .= elgg_view_form('twitter_api/interstitial_settings'); +$content = elgg_view_form('twitter_api/interstitial_settings');  $params = array(  	'content' => $content, diff --git a/mod/twitter_api/start.php b/mod/twitter_api/start.php index e6221de6b..7318ac55d 100644 --- a/mod/twitter_api/start.php +++ b/mod/twitter_api/start.php @@ -35,8 +35,10 @@ function twitter_api_init() {  	// register Walled Garden public pages  	elgg_register_plugin_hook_handler('public_pages', 'walled_garden', 'twitter_api_public_pages'); -	// push status messages to twitter -	elgg_register_plugin_hook_handler('status', 'user', 'twitter_api_tweet'); +	// push wire post messages to twitter +	if (elgg_get_plugin_setting('wire_posts', 'twitter_api') == 'yes') { +		elgg_register_plugin_hook_handler('status', 'user', 'twitter_api_tweet'); +	}  	$actions = dirname(__FILE__) . '/actions/twitter_api';  	elgg_register_action('twitter_api/interstitial_settings', "$actions/interstitial_settings.php", 'logged_in'); @@ -115,13 +117,6 @@ function twitter_api_tweet($hook, $type, $returnvalue, $params) {  	// @todo - allow admin to select origins? -	// check admin settings -	$consumer_key = elgg_get_plugin_setting('consumer_key', 'twitter_api'); -	$consumer_secret = elgg_get_plugin_setting('consumer_secret', 'twitter_api'); -	if (!($consumer_key && $consumer_secret)) { -		return; -	} -  	// check user settings  	$user_id = $params['user']->getGUID();  	$access_key = elgg_get_plugin_user_setting('access_key', $user_id, 'twitter_api'); @@ -130,8 +125,11 @@ function twitter_api_tweet($hook, $type, $returnvalue, $params) {  		return;  	} -	// send tweet -	$api = new TwitterOAuth($consumer_key, $consumer_secret, $access_key, $access_secret); +	$api = twitter_api_get_api_object($access_key, $access_secret); +	if (!$api) { +		return; +	} +  	$api->post('statuses/update', array('status' => $params['message']));  } @@ -143,12 +141,6 @@ function twitter_api_tweet($hook, $type, $returnvalue, $params) {   * @return array   */  function twitter_api_fetch_tweets($user_guid, $options = array()) { -	// check admin settings -	$consumer_key = elgg_get_plugin_setting('consumer_key', 'twitter_api'); -	$consumer_secret = elgg_get_plugin_setting('consumer_secret', 'twitter_api'); -	if (!($consumer_key && $consumer_secret)) { -		return FALSE; -	}  	// check user settings  	$access_key = elgg_get_plugin_user_setting('access_key', $user_guid, 'twitter_api'); @@ -157,8 +149,11 @@ function twitter_api_fetch_tweets($user_guid, $options = array()) {  		return FALSE;  	} -	// fetch tweets -	$api = new TwitterOAuth($consumer_key, $consumer_secret, $access_key, $access_secret); +	$api = twitter_api_get_api_object($access_key, $access_secret); +	if (!$api) { +		return FALSE; +	} +  	return $api->get('statuses/user_timeline', $options);  } diff --git a/mod/twitter_api/vendors/twitteroauth/OAuth.php b/mod/twitter_api/vendors/twitteroauth/OAuth.php index e132a5bc8..e76304146 100644 --- a/mod/twitter_api/vendors/twitteroauth/OAuth.php +++ b/mod/twitter_api/vendors/twitteroauth/OAuth.php @@ -1,6 +1,12 @@  <?php  // vim: foldmethod=marker +/* Generic exception class + */ +class OAuthException extends Exception { +  // pass +} +  class OAuthConsumer {    public $key;    public $secret; @@ -46,12 +52,56 @@ class OAuthToken {    }  } -class twitterOAuthSignatureMethod_HMAC_SHA1 extends OAuthSignatureMethod_HMAC_SHA1 {/*{{{*/ -  function get_name() {/*{{{*/ +/** + * A class for implementing a Signature Method + * See section 9 ("Signing Requests") in the spec + */ +abstract class OAuthSignatureMethod { +  /** +   * Needs to return the name of the Signature Method (ie HMAC-SHA1) +   * @return string +   */ +  abstract public function get_name(); + +  /** +   * Build up the signature +   * NOTE: The output of this function MUST NOT be urlencoded. +   * the encoding is handled in OAuthRequest when the final +   * request is serialized +   * @param OAuthRequest $request +   * @param OAuthConsumer $consumer +   * @param OAuthToken $token +   * @return string +   */ +  abstract public function build_signature($request, $consumer, $token); + +  /** +   * Verifies that a given signature is correct +   * @param OAuthRequest $request +   * @param OAuthConsumer $consumer +   * @param OAuthToken $token +   * @param string $signature +   * @return bool +   */ +  public function check_signature($request, $consumer, $token, $signature) { +    $built = $this->build_signature($request, $consumer, $token); +    return $built == $signature; +  } +} + +/** + * The HMAC-SHA1 signature method uses the HMAC-SHA1 signature algorithm as defined in [RFC2104]  + * where the Signature Base String is the text and the key is the concatenated values (each first  + * encoded per Parameter Encoding) of the Consumer Secret and Token Secret, separated by an '&'  + * character (ASCII code 38) even if empty. + *   - Chapter 9.2 ("HMAC-SHA1") + */ +class OAuthSignatureMethod_HMAC_SHA1 extends OAuthSignatureMethod { +  function get_name() {      return "HMAC-SHA1"; -  }/*}}}*/ +  } -  public function build_signature($request, $consumer, $token) {/*{{{*/ +  public function build_signature($request, $consumer, $token) {      $base_string = $request->get_signature_base_string();      $request->base_string = $base_string; @@ -63,16 +113,111 @@ class twitterOAuthSignatureMethod_HMAC_SHA1 extends OAuthSignatureMethod_HMAC_SH      $key_parts = OAuthUtil::urlencode_rfc3986($key_parts);      $key = implode('&', $key_parts); -    return base64_encode( hash_hmac('sha1', $base_string, $key, true)); -  }/*}}}*/ +    return base64_encode(hash_hmac('sha1', $base_string, $key, true)); +  } +} -  public function check_signature(&$request, $consumer, $token, $signature) { -    $built = $this->build_signature($request, $consumer, $token); -    return $built == $signature; +/** + * The PLAINTEXT method does not provide any security protection and SHOULD only be used  + * over a secure channel such as HTTPS. It does not use the Signature Base String. + *   - Chapter 9.4 ("PLAINTEXT") + */ +class OAuthSignatureMethod_PLAINTEXT extends OAuthSignatureMethod { +  public function get_name() { +    return "PLAINTEXT"; +  } + +  /** +   * oauth_signature is set to the concatenated encoded values of the Consumer Secret and  +   * Token Secret, separated by a '&' character (ASCII code 38), even if either secret is  +   * empty. The result MUST be encoded again. +   *   - Chapter 9.4.1 ("Generating Signatures") +   * +   * Please note that the second encoding MUST NOT happen in the SignatureMethod, as +   * OAuthRequest handles this! +   */ +  public function build_signature($request, $consumer, $token) { +    $key_parts = array( +      $consumer->secret, +      ($token) ? $token->secret : "" +    ); + +    $key_parts = OAuthUtil::urlencode_rfc3986($key_parts); +    $key = implode('&', $key_parts); +    $request->base_string = $key; + +    return $key;    } -}/*}}}*/ +} + +/** + * The RSA-SHA1 signature method uses the RSASSA-PKCS1-v1_5 signature algorithm as defined in  + * [RFC3447] section 8.2 (more simply known as PKCS#1), using SHA-1 as the hash function for  + * EMSA-PKCS1-v1_5. It is assumed that the Consumer has provided its RSA public key in a  + * verified way to the Service Provider, in a manner which is beyond the scope of this  + * specification. + *   - Chapter 9.3 ("RSA-SHA1") + */ +abstract class OAuthSignatureMethod_RSA_SHA1 extends OAuthSignatureMethod { +  public function get_name() { +    return "RSA-SHA1"; +  } + +  // Up to the SP to implement this lookup of keys. Possible ideas are: +  // (1) do a lookup in a table of trusted certs keyed off of consumer +  // (2) fetch via http using a url provided by the requester +  // (3) some sort of specific discovery code based on request +  // +  // Either way should return a string representation of the certificate +  protected abstract function fetch_public_cert(&$request); + +  // Up to the SP to implement this lookup of keys. Possible ideas are: +  // (1) do a lookup in a table of trusted certs keyed off of consumer +  // +  // Either way should return a string representation of the certificate +  protected abstract function fetch_private_cert(&$request); + +  public function build_signature($request, $consumer, $token) { +    $base_string = $request->get_signature_base_string(); +    $request->base_string = $base_string; + +    // Fetch the private key cert based on the request +    $cert = $this->fetch_private_cert($request); + +    // Pull the private key ID from the certificate +    $privatekeyid = openssl_get_privatekey($cert); + +    // Sign using the key +    $ok = openssl_sign($base_string, $signature, $privatekeyid); + +    // Release the key resource +    openssl_free_key($privatekeyid); + +    return base64_encode($signature); +  } + +  public function check_signature($request, $consumer, $token, $signature) { +    $decoded_sig = base64_decode($signature); + +    $base_string = $request->get_signature_base_string(); + +    // Fetch the public key cert based on the request +    $cert = $this->fetch_public_cert($request); + +    // Pull the public key ID from the certificate +    $publickeyid = openssl_get_publickey($cert); -class twitterOAuthRequest extends OAuthRequest { +    // Check the computed signature against the one passed in the query +    $ok = openssl_verify($base_string, $decoded_sig, $publickeyid); + +    // Release the key resource +    openssl_free_key($publickeyid); + +    return $ok == 1; +  } +} + +class OAuthRequest {    private $parameters;    private $http_method;    private $http_url; @@ -138,7 +283,7 @@ class twitterOAuthRequest extends OAuthRequest {      } -    return new twitterOAuthRequest($http_method, $http_url, $parameters); +    return new OAuthRequest($http_method, $http_url, $parameters);    }    /** @@ -146,16 +291,16 @@ class twitterOAuthRequest extends OAuthRequest {     */    public static function from_consumer_and_token($consumer, $token, $http_method, $http_url, $parameters=NULL) {      @$parameters or $parameters = array(); -    $defaults = array("oauth_version" => twitterOAuthRequest::$version, -                      "oauth_nonce" => twitterOAuthRequest::generate_nonce(), -                      "oauth_timestamp" => twitterOAuthRequest::generate_timestamp(), +    $defaults = array("oauth_version" => OAuthRequest::$version, +                      "oauth_nonce" => OAuthRequest::generate_nonce(), +                      "oauth_timestamp" => OAuthRequest::generate_timestamp(),                        "oauth_consumer_key" => $consumer->key);      if ($token)        $defaults['oauth_token'] = $token->key;      $parameters = array_merge($defaults, $parameters); -    return new twitterOAuthRequest($http_method, $http_url, $parameters); +    return new OAuthRequest($http_method, $http_url, $parameters);    }    public function set_parameter($name, $value, $allow_duplicates = true) { @@ -333,6 +478,217 @@ class twitterOAuthRequest extends OAuthRequest {    }  } +class OAuthServer { +  protected $timestamp_threshold = 300; // in seconds, five minutes +  protected $version = '1.0';             // hi blaine +  protected $signature_methods = array(); + +  protected $data_store; + +  function __construct($data_store) { +    $this->data_store = $data_store; +  } + +  public function add_signature_method($signature_method) { +    $this->signature_methods[$signature_method->get_name()] = +      $signature_method; +  } + +  // high level functions + +  /** +   * process a request_token request +   * returns the request token on success +   */ +  public function fetch_request_token(&$request) { +    $this->get_version($request); + +    $consumer = $this->get_consumer($request); + +    // no token required for the initial token request +    $token = NULL; + +    $this->check_signature($request, $consumer, $token); + +    // Rev A change +    $callback = $request->get_parameter('oauth_callback'); +    $new_token = $this->data_store->new_request_token($consumer, $callback); + +    return $new_token; +  } + +  /** +   * process an access_token request +   * returns the access token on success +   */ +  public function fetch_access_token(&$request) { +    $this->get_version($request); + +    $consumer = $this->get_consumer($request); + +    // requires authorized request token +    $token = $this->get_token($request, $consumer, "request"); + +    $this->check_signature($request, $consumer, $token); + +    // Rev A change +    $verifier = $request->get_parameter('oauth_verifier'); +    $new_token = $this->data_store->new_access_token($token, $consumer, $verifier); + +    return $new_token; +  } + +  /** +   * verify an api call, checks all the parameters +   */ +  public function verify_request(&$request) { +    $this->get_version($request); +    $consumer = $this->get_consumer($request); +    $token = $this->get_token($request, $consumer, "access"); +    $this->check_signature($request, $consumer, $token); +    return array($consumer, $token); +  } + +  // Internals from here +  /** +   * version 1 +   */ +  private function get_version(&$request) { +    $version = $request->get_parameter("oauth_version"); +    if (!$version) { +      // Service Providers MUST assume the protocol version to be 1.0 if this parameter is not present.  +      // Chapter 7.0 ("Accessing Protected Ressources") +      $version = '1.0'; +    } +    if ($version !== $this->version) { +      throw new OAuthException("OAuth version '$version' not supported"); +    } +    return $version; +  } + +  /** +   * figure out the signature with some defaults +   */ +  private function get_signature_method(&$request) { +    $signature_method = +        @$request->get_parameter("oauth_signature_method"); + +    if (!$signature_method) { +      // According to chapter 7 ("Accessing Protected Ressources") the signature-method +      // parameter is required, and we can't just fallback to PLAINTEXT +      throw new OAuthException('No signature method parameter. This parameter is required'); +    } + +    if (!in_array($signature_method, +                  array_keys($this->signature_methods))) { +      throw new OAuthException( +        "Signature method '$signature_method' not supported " . +        "try one of the following: " . +        implode(", ", array_keys($this->signature_methods)) +      ); +    } +    return $this->signature_methods[$signature_method]; +  } + +  /** +   * try to find the consumer for the provided request's consumer key +   */ +  private function get_consumer(&$request) { +    $consumer_key = @$request->get_parameter("oauth_consumer_key"); +    if (!$consumer_key) { +      throw new OAuthException("Invalid consumer key"); +    } + +    $consumer = $this->data_store->lookup_consumer($consumer_key); +    if (!$consumer) { +      throw new OAuthException("Invalid consumer"); +    } + +    return $consumer; +  } + +  /** +   * try to find the token for the provided request's token key +   */ +  private function get_token(&$request, $consumer, $token_type="access") { +    $token_field = @$request->get_parameter('oauth_token'); +    $token = $this->data_store->lookup_token( +      $consumer, $token_type, $token_field +    ); +    if (!$token) { +      throw new OAuthException("Invalid $token_type token: $token_field"); +    } +    return $token; +  } + +  /** +   * all-in-one function to check the signature on a request +   * should guess the signature method appropriately +   */ +  private function check_signature(&$request, $consumer, $token) { +    // this should probably be in a different method +    $timestamp = @$request->get_parameter('oauth_timestamp'); +    $nonce = @$request->get_parameter('oauth_nonce'); + +    $this->check_timestamp($timestamp); +    $this->check_nonce($consumer, $token, $nonce, $timestamp); + +    $signature_method = $this->get_signature_method($request); + +    $signature = $request->get_parameter('oauth_signature'); +    $valid_sig = $signature_method->check_signature( +      $request, +      $consumer, +      $token, +      $signature +    ); + +    if (!$valid_sig) { +      throw new OAuthException("Invalid signature"); +    } +  } + +  /** +   * check that the timestamp is new enough +   */ +  private function check_timestamp($timestamp) { +    if( ! $timestamp ) +      throw new OAuthException( +        'Missing timestamp parameter. The parameter is required' +      ); +     +    // verify that timestamp is recentish +    $now = time(); +    if (abs($now - $timestamp) > $this->timestamp_threshold) { +      throw new OAuthException( +        "Expired timestamp, yours $timestamp, ours $now" +      ); +    } +  } + +  /** +   * check that the nonce is not repeated +   */ +  private function check_nonce($consumer, $token, $nonce, $timestamp) { +    if( ! $nonce ) +      throw new OAuthException( +        'Missing nonce parameter. The parameter is required' +      ); + +    // verify that the nonce is uniqueish +    $found = $this->data_store->lookup_nonce( +      $consumer, +      $token, +      $nonce, +      $timestamp +    ); +    if ($found) { +      throw new OAuthException("Nonce already used: $nonce"); +    } +  } + +} +  class OAuthDataStore {    function lookup_consumer($consumer_key) {      // implement me @@ -514,5 +870,3 @@ class OAuthUtil {      return implode('&', $pairs);    }  } - -?> diff --git a/mod/twitter_api/vendors/twitteroauth/README b/mod/twitter_api/vendors/twitteroauth/README index 33cb91f21..c9a17ce4b 100644 --- a/mod/twitter_api/vendors/twitteroauth/README +++ b/mod/twitter_api/vendors/twitteroauth/README @@ -1,7 +1,114 @@ -Abraham Williams | abraham@poseurte.ch | http://abrah.am | @abraham +TwitterOAuth +------------ -The first PHP library for working with Twitter's OAuth API. +PHP library for working with Twitter's OAuth API. -Documentation: http://wiki.github.com/abraham/twitteroauth/documentation  -Source: http://github.com/abraham/twitteroauth -Twitter: http://apiwiki.twitter.com +Flow Overview +============= + +1. Build TwitterOAuth object using client credentials. +2. Request temporary credentials from Twitter. +3. Build authorize URL for Twitter. +4. Redirect user to authorize URL. +5. User authorizes access and returns from Twitter. +6. Rebuild TwitterOAuth object with client credentials and temporary credentials. +7. Get token credentials from Twitter. +8. Rebuild TwitterOAuth object with client credentials and token credentials. +9. Query Twitter API. + +Terminology +=========== + +The terminology has changed since 0.1.x to better match the draft-hammer-oauth IETF +RFC. You can read that at http://tools.ietf.org/html/draft-hammer-oauth. Some of the +terms will differ from those Twitter uses as well. + +client credentials - Consumer key/secret you get when registering an app with Twitter. +temporary credentials - Previously known as the request token. +token credentials - Previously known as the access token. + +Parameters +========== + +There are a number of parameters you can modify after creating a TwitterOAuth object. + +Switch an existing TwitterOAuth install to use version 1.1 of the API. + +    $connection->$host = "https://api.twitter.com/1.1/"; + +Custom useragent. + +    $connection->useragent = 'Custom useragent string'; + +Verify Twitters SSL certificate. + +    $connection->ssl_verifypeer = TRUE; + +There are several more you can find in TwitterOAuth.php. + +Extended flow using example code +================================ + +To use TwitterOAuth with the Twitter API you need *TwitterOAuth.php*, *OAuth.php* and +client credentials. You can get client credentials by registering your application at +[dev.twitter.com/apps](https://dev.twitter.com/apps). + +Users start out on connect.php which displays the "Sign in with Twitter" image hyperlinked +to redirect.php. This button should be displayed on your homepage in your login section. The +client credentials are saved in config.php as `CONSUMER_KEY` and `CONSUMER_SECRET`. You can +save a static callback URL in the app settings page, in the config file or use a dynamic +callback URL later in step 2. In example use https://example.com/callback.php. + +1) When a user lands on redirect.php we build a new TwitterOAuth object using the client credentials. +If you have your own configuration method feel free to use it instead of config.php. + +    $connection = new TwitterOAuth(CONSUMER_KEY, CONSUMER_SECRET); // Use config.php client credentials +    $connection = new TwitterOAuth('abc890', '123xyz'); + +2) Using the built $connection object you will ask Twitter for temporary credentials. The `oauth_callback` value is required. + +    $temporary_credentials = $connection->getRequestToken(OAUTH_CALLBACK); // Use config.php callback URL. + +3) Now that we have temporary credentials the user has to go to Twitter and authorize the app +to access and updates their data. You can also pass a second parameter of FALSE to not use [Sign +in with Twitter](https://dev.twitter.com/docs/auth/sign-twitter). + +    $redirect_url = $connection->getAuthorizeURL($temporary_credentials); // Use Sign in with Twitter +    $redirect_url = $connection->getAuthorizeURL($temporary_credentials, FALSE); + +4) You will now have a Twitter URL that you must send the user to. + +    https://api.twitter.com/oauth/authenticate?oauth_token=xyz123 + +5) The user is now on twitter.com and may have to login. Once authenticated with Twitter they will +will either have to click on allow/deny, or will be automatically redirected back to the callback. + +6) Now that the user has returned to callback.php and allowed access we need to build a new +TwitterOAuth object using the temporary credentials. + +    $connection = new TwitterOAuth(CONSUMER_KEY, CONSUMER_SECRET, $_SESSION['oauth_token'], +    $_SESSION['oauth_token_secret']); + +7) Now we ask Twitter for long lasting token credentials. These are specific to the application +and user and will act like password to make future requests. Normally the token credentials would +get saved in your database but for this example we are just using sessions. + +    $token_credentials = $connection->getAccessToken($_REQUEST['oauth_verifier']); + +8) With the token credentials we build a new TwitterOAuth object. + +    $connection = new TwitterOAuth(CONSUMER_KEY, CONSUMER_SECRET, $token_credentials['oauth_token'], +    $token_credentials['oauth_token_secret']); + +9) And finally we can make requests authenticated as the user. You can GET, POST, and DELETE API +methods. Directly copy the path from the API documentation and add an array of any parameter +you wish to include for the API method such as curser or in_reply_to_status_id. + +    $account = $connection->get('account/verify_credentials'); +    $status = $connection->post('statuses/update', array('status' => 'Text of status here', 'in_reply_to_status_id' => 123456)); +    $status = $connection->delete('statuses/destroy/12345'); + +Contributors +============ + +* [Abraham Williams](https://twitter.com/abraham) - Main developer, current maintainer. diff --git a/mod/twitter_api/vendors/twitteroauth/twitterOAuth.php b/mod/twitter_api/vendors/twitteroauth/twitterOAuth.php index f36e6158d..4c2447c46 100644 --- a/mod/twitter_api/vendors/twitteroauth/twitterOAuth.php +++ b/mod/twitter_api/vendors/twitteroauth/twitterOAuth.php @@ -57,7 +57,7 @@ class TwitterOAuth {     * construct TwitterOAuth object     */    function __construct($consumer_key, $consumer_secret, $oauth_token = NULL, $oauth_token_secret = NULL) { -    $this->sha1_method = new twitterOAuthSignatureMethod_HMAC_SHA1(); +    $this->sha1_method = new OAuthSignatureMethod_HMAC_SHA1();      $this->consumer = new OAuthConsumer($consumer_key, $consumer_secret);      if (!empty($oauth_token) && !empty($oauth_token_secret)) {        $this->token = new OAuthConsumer($oauth_token, $oauth_token_secret); @@ -72,11 +72,9 @@ class TwitterOAuth {     *     * @returns a key/value array containing oauth_token and oauth_token_secret     */ -  function getRequestToken($oauth_callback = NULL) { +  function getRequestToken($oauth_callback) {      $parameters = array(); -    if (!empty($oauth_callback)) { -      $parameters['oauth_callback'] = $oauth_callback; -    }  +    $parameters['oauth_callback'] = $oauth_callback;       $request = $this->oAuthRequest($this->requestTokenURL(), 'GET', $parameters);      $token = OAuthUtil::parse_parameters($request);      $this->token = new OAuthConsumer($token['oauth_token'], $token['oauth_token_secret']); @@ -108,11 +106,9 @@ class TwitterOAuth {     *                "user_id" => "9436992",     *                "screen_name" => "abraham")     */ -  function getAccessToken($oauth_verifier = FALSE) { +  function getAccessToken($oauth_verifier) {      $parameters = array(); -    if (!empty($oauth_verifier)) { -      $parameters['oauth_verifier'] = $oauth_verifier; -    } +    $parameters['oauth_verifier'] = $oauth_verifier;      $request = $this->oAuthRequest($this->accessTokenURL(), 'GET', $parameters);      $token = OAuthUtil::parse_parameters($request);      $this->token = new OAuthConsumer($token['oauth_token'], $token['oauth_token_secret']); @@ -179,7 +175,7 @@ class TwitterOAuth {      if (strrpos($url, 'https://') !== 0 && strrpos($url, 'http://') !== 0) {        $url = "{$this->host}{$url}.{$this->format}";      } -    $request = twitterOAuthRequest::from_consumer_and_token($this->consumer, $this->token, $method, $url, $parameters); +    $request = OAuthRequest::from_consumer_and_token($this->consumer, $this->token, $method, $url, $parameters);      $request->sign_request($this->sha1_method, $this->consumer, $this->token);      switch ($method) {      case 'GET': diff --git a/mod/twitter_api/views/default/forms/twitter_api/interstitial_settings.php b/mod/twitter_api/views/default/forms/twitter_api/interstitial_settings.php index cad2be345..b4882bb7f 100644 --- a/mod/twitter_api/views/default/forms/twitter_api/interstitial_settings.php +++ b/mod/twitter_api/views/default/forms/twitter_api/interstitial_settings.php @@ -3,6 +3,11 @@   * Make the user set up some alternative ways to login.   */ +echo '<div>'; +$site = get_config('site'); +echo elgg_echo('twitter_api:interstitial:description', array($site->name)); +echo '</div>'; +  $user = elgg_get_logged_in_user_entity();  if (elgg_is_sticky_form('twitter_api_interstitial')) { @@ -51,7 +56,7 @@ echo elgg_view_module('info', $title, $body);  // buttons  echo elgg_view('input/submit', array( -	'text' => elgg_echo('save') +	'value' => elgg_echo('save')  ));  echo elgg_view('output/url', array( diff --git a/mod/twitter_api/views/default/plugins/twitter_api/settings.php b/mod/twitter_api/views/default/plugins/twitter_api/settings.php index 0b9afd4cf..3a3ec93a2 100644 --- a/mod/twitter_api/views/default/plugins/twitter_api/settings.php +++ b/mod/twitter_api/views/default/plugins/twitter_api/settings.php @@ -39,12 +39,27 @@ $new_users_with_twitter_view = elgg_view('input/dropdown', array(  	'value' => $vars['entity']->new_users ? $vars['entity']->new_users : 'no',  )); +$post_to_twitter = ''; +if (elgg_is_active_plugin('thewire')) { +	$post_to_twitter_string = elgg_echo('twitter_api:post_to_twitter'); +	$post_to_twitter_view = elgg_view('input/dropdown', array( +		'name' => 'params[wire_posts]', +		'options_values' => array( +			'yes' => elgg_echo('option:yes'), +			'no' => elgg_echo('option:no'), +		), +		'value' => $vars['entity']->wire_posts ? $vars['entity']->wire_posts : 'no', +	)); +	$post_to_twitter = "<div>$post_to_twitter_string $post_to_twitter_view</div>"; +} +  $settings = <<<__HTML  <div class="elgg-content-thin mtm"><p>$instructions</p></div>  <div><label>$consumer_key_string</label><br /> $consumer_key_view</div>  <div><label>$consumer_secret_string</label><br /> $consumer_secret_view</div>  <div>$sign_on_with_twitter_string $sign_on_with_twitter_view</div>  <div>$new_users_with_twitter $new_users_with_twitter_view</div> +$post_to_twitter  __HTML;  echo $settings;  | 
