Sfoglia il codice sorgente

WIP LTI add oauth lib - refs BT#13469

Angel Fernando Quiroz Campos 6 anni fa
parent
commit
60ff03ee73
40 ha cambiato i file con 2749 aggiunte e 0 eliminazioni
  1. 42 0
      plugin/ims_lti/vendor/oauth1/.gitignore
  2. 44 0
      plugin/ims_lti/vendor/oauth1/CHANGELOG.md
  3. 22 0
      plugin/ims_lti/vendor/oauth1/LICENSE.txt
  4. 6 0
      plugin/ims_lti/vendor/oauth1/README.md
  5. 16 0
      plugin/ims_lti/vendor/oauth1/code/OAuthConsumer.php
  6. 27 0
      plugin/ims_lti/vendor/oauth1/code/OAuthDataStore.php
  7. 7 0
      plugin/ims_lti/vendor/oauth1/code/OAuthException.php
  8. 260 0
      plugin/ims_lti/vendor/oauth1/code/OAuthRequest.php
  9. 223 0
      plugin/ims_lti/vendor/oauth1/code/OAuthServer.php
  10. 55 0
      plugin/ims_lti/vendor/oauth1/code/OAuthSignatureMethod.php
  11. 30 0
      plugin/ims_lti/vendor/oauth1/code/OAuthSignatureMethod_HMAC_SHA1.php
  12. 34 0
      plugin/ims_lti/vendor/oauth1/code/OAuthSignatureMethod_PLAINTEXT.php
  13. 69 0
      plugin/ims_lti/vendor/oauth1/code/OAuthSignatureMethod_RSA_SHA1.php
  14. 13 0
      plugin/ims_lti/vendor/oauth1/code/OAuthTests.xml
  15. 31 0
      plugin/ims_lti/vendor/oauth1/code/OAuthToken.php
  16. 153 0
      plugin/ims_lti/vendor/oauth1/code/OAuthUtil.php
  17. 106 0
      plugin/ims_lti/vendor/oauth1/code/OAuth_TestServer.php
  18. 30 0
      plugin/ims_lti/vendor/oauth1/composer.json
  19. 20 0
      plugin/ims_lti/vendor/oauth1/composer.lock
  20. 73 0
      plugin/ims_lti/vendor/oauth1/doc/design.md
  21. 74 0
      plugin/ims_lti/vendor/oauth1/example/SimpleOAuthDataStore.php
  22. 14 0
      plugin/ims_lti/vendor/oauth1/example/access_token.php
  23. 133 0
      plugin/ims_lti/vendor/oauth1/example/client.php
  24. 26 0
      plugin/ims_lti/vendor/oauth1/example/common.inc.php
  25. 21 0
      plugin/ims_lti/vendor/oauth1/example/echo_api.php
  26. 108 0
      plugin/ims_lti/vendor/oauth1/example/index.php
  27. 14 0
      plugin/ims_lti/vendor/oauth1/example/request_token.php
  28. 5 0
      plugin/ims_lti/vendor/oauth1/init.php
  29. 12 0
      plugin/ims_lti/vendor/oauth1/tests/Mock_OAuthBaseStringRequest.php
  30. 57 0
      plugin/ims_lti/vendor/oauth1/tests/Mock_OAuthDataStore.php
  31. 47 0
      plugin/ims_lti/vendor/oauth1/tests/Mock_OAuthSignatureMethod_RSA_SHA1.php
  32. 10 0
      plugin/ims_lti/vendor/oauth1/tests/OAuthConsumerTest.php
  33. 329 0
      plugin/ims_lti/vendor/oauth1/tests/OAuthRequestTest.php
  34. 225 0
      plugin/ims_lti/vendor/oauth1/tests/OAuthServerTest.php
  35. 60 0
      plugin/ims_lti/vendor/oauth1/tests/OAuthSignatureMethodHmacSha1Test.php
  36. 79 0
      plugin/ims_lti/vendor/oauth1/tests/OAuthSignatureMethodPlaintextTest.php
  37. 43 0
      plugin/ims_lti/vendor/oauth1/tests/OAuthSignatureMethodRsaSha1Test.php
  38. 20 0
      plugin/ims_lti/vendor/oauth1/tests/OAuthTokenTest.php
  39. 151 0
      plugin/ims_lti/vendor/oauth1/tests/OAuthUtilTest.php
  40. 60 0
      plugin/ims_lti/vendor/oauth1/tests/common.php

+ 42 - 0
plugin/ims_lti/vendor/oauth1/.gitignore

@@ -0,0 +1,42 @@
+
+# Created by https://www.gitignore.io/api/osx,svn,composer
+
+### OSX ###
+.DS_Store
+.AppleDouble
+.LSOverride
+
+# Icon must end with two \r
+Icon

+
+# Thumbnails
+._*
+
+# Files that might appear in the root of a volume
+.DocumentRevisions-V100
+.fseventsd
+.Spotlight-V100
+.TemporaryItems
+.Trashes
+.VolumeIcon.icns
+
+# Directories potentially created on remote AFP share
+.AppleDB
+.AppleDesktop
+Network Trash Folder
+Temporary Items
+.apdisk
+
+
+### SVN ###
+.svn/
+
+
+### Composer ###
+composer.phar
+/vendor/
+
+# Commit your application's lock file http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file
+# You may choose to ignore a library lock file http://getcomposer.org/doc/02-libraries.md#lock-file
+# composer.lock
+

+ 44 - 0
plugin/ims_lti/vendor/oauth1/CHANGELOG.md

@@ -0,0 +1,44 @@
+### 2016.02.10
+----
+* Added composer.json
+* Separated classes to separate files
+
+### 2008.08.04
+----
+* Added LICENSE.txt file with MIT license, copyright owner is perhaps
+	dubious however.
+
+### 2008.07.22
+----
+* Change to encoding to fix last change to encoding of spaces
+
+### 2008.07.15
+----
+* Another change to encoding per:   
+	[http://groups.google.com/group/oauth/browse_thread/thread/d39931d39b4af4bd](http://groups.google.com/group/oauth/browse_thread/thread/d39931d39b4af4bd)
+* A change to port handling to better deal with https and the like per:  
+  [http://groups.google.com/group/oauth/browse_thread/thread/1b203a51d9590226](http://groups.google.com/group/oauth/browse_thread/thread/1b203a51d9590226)
+* Fixed a small bug per:  
+	[https://github.com/jtsternberg/oauth/issues/26](https://github.com/jtsternberg/oauth/issues/26)
+* Added missing base_string debug info when using RSA-SHA1
+* Increased size of example endpoint input field and added note about
+  query strings
+
+### 2009-2011.03.28
+----
+* Heaps of bug-fixes
+* Introduction of PHPUnit testcases (which aided in above mentioned bug-fixes)
+* Added support Revision A auth flows.
+* Possibly more, I've lost track..
+
+### 2001.03.29
+----
+* Fixed issue with hosts not being normalized correctly  
+  [http://tools.ietf.org/html/rfc5849#section-3.4.1.2](http://tools.ietf.org/html/rfc5849#section-3.4.1.2)  
+  [https://github.com/jtsternberg/oauth/issues/176](https://github.com/jtsternberg/oauth/issues/176)  
+  [https://github.com/jtsternberg/oauth/issues/187](https://github.com/jtsternberg/oauth/issues/187)  
+* Changed signature comparing to be timing insensitive  
+  [https://github.com/jtsternberg/oauth/issues/178](https://github.com/jtsternberg/oauth/issues/178)
+* Fixed issue with Host header on some servers on non-standard port includes the port-number
+  [https://github.com/jtsternberg/oauth/issues/170](https://github.com/jtsternberg/oauth/issues/170)  
+  [https://github.com/jtsternberg/oauth/issues/192](https://github.com/jtsternberg/oauth/issues/192)  

+ 22 - 0
plugin/ims_lti/vendor/oauth1/LICENSE.txt

@@ -0,0 +1,22 @@
+The MIT License
+
+Copyright (c) 2007 Andy Smith
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+

+ 6 - 0
plugin/ims_lti/vendor/oauth1/README.md

@@ -0,0 +1,6 @@
+# OAuth1 PHP
+[Andy Smith](http://term.ie/)'s basic php library for OAuth. Original code taken from google code. For reference (and since google code is going away), I have ported the entire project to github. [You can find it here](https://github.com/jtsternberg/oauth).
+
+To use this, be sure to run `composer install` in the root of the lib.
+
+I have also split out the spec portion of the google code repo to [its own repo](https://github.com/jtsternberg/oauth-spec).

+ 16 - 0
plugin/ims_lti/vendor/oauth1/code/OAuthConsumer.php

@@ -0,0 +1,16 @@
+<?php
+
+class OAuthConsumer {
+  public $key;
+  public $secret;
+
+  function __construct($key, $secret, $callback_url=NULL) {
+    $this->key = $key;
+    $this->secret = $secret;
+    $this->callback_url = $callback_url;
+  }
+
+  function __toString() {
+    return "OAuthConsumer[key=$this->key,secret=$this->secret]";
+  }
+}

+ 27 - 0
plugin/ims_lti/vendor/oauth1/code/OAuthDataStore.php

@@ -0,0 +1,27 @@
+<?php
+
+class OAuthDataStore {
+  function lookup_consumer($consumer_key) {
+    // implement me
+  }
+
+  function lookup_token($consumer, $token_type, $token) {
+    // implement me
+  }
+
+  function lookup_nonce($consumer, $token, $nonce, $timestamp) {
+    // implement me
+  }
+
+  function new_request_token($consumer, $callback = null) {
+    // return a new token attached to this consumer
+  }
+
+  function new_access_token($token, $consumer, $verifier = null) {
+    // return a new access token attached to this consumer
+    // for the user associated with this token if the request token
+    // is authorized
+    // should also invalidate the request token
+  }
+
+}

+ 7 - 0
plugin/ims_lti/vendor/oauth1/code/OAuthException.php

@@ -0,0 +1,7 @@
+<?php
+
+/* Generic exception class
+ */
+class OAuthException extends Exception {
+  // pass
+}

+ 260 - 0
plugin/ims_lti/vendor/oauth1/code/OAuthRequest.php

@@ -0,0 +1,260 @@
+<?php
+class OAuthRequest {
+  protected $parameters;
+  protected $http_method;
+  protected $http_url;
+  // for debug purposes
+  public $base_string;
+  public static $version = '1.0';
+  public static $POST_INPUT = 'php://input';
+
+  function __construct($http_method, $http_url, $parameters=NULL) {
+    $parameters = ($parameters) ? $parameters : array();
+    $parameters = array_merge( OAuthUtil::parse_parameters(parse_url($http_url, PHP_URL_QUERY)), $parameters);
+    $this->parameters = $parameters;
+    $this->http_method = $http_method;
+    $this->http_url = $http_url;
+  }
+
+
+  /**
+   * attempt to build up a request from what was passed to the server
+   */
+  public static function from_request($http_method=NULL, $http_url=NULL, $parameters=NULL) {
+    $scheme = (!isset($_SERVER['HTTPS']) || $_SERVER['HTTPS'] != "on")
+              ? 'http'
+              : 'https';
+    $http_url = ($http_url) ? $http_url : $scheme .
+                              '://' . $_SERVER['SERVER_NAME'] .
+                              ':' .
+                              $_SERVER['SERVER_PORT'] .
+                              $_SERVER['REQUEST_URI'];
+    $http_method = ($http_method) ? $http_method : $_SERVER['REQUEST_METHOD'];
+
+    // We weren't handed any parameters, so let's find the ones relevant to
+    // this request.
+    // If you run XML-RPC or similar you should use this to provide your own
+    // parsed parameter-list
+    if (!$parameters) {
+      // Find request headers
+      $request_headers = OAuthUtil::get_headers();
+
+      // Parse the query-string to find GET parameters
+      $parameters = OAuthUtil::parse_parameters($_SERVER['QUERY_STRING']);
+
+      // It's a POST request of the proper content-type, so parse POST
+      // parameters and add those overriding any duplicates from GET
+      if ($http_method == "POST"
+          &&  isset($request_headers['Content-Type'])
+          && strstr($request_headers['Content-Type'],
+                     'application/x-www-form-urlencoded')
+          ) {
+        $post_data = OAuthUtil::parse_parameters(
+          file_get_contents(self::$POST_INPUT)
+        );
+        $parameters = array_merge($parameters, $post_data);
+      }
+
+      // We have a Authorization-header with OAuth data. Parse the header
+      // and add those overriding any duplicates from GET or POST
+      if (isset($request_headers['Authorization']) && substr($request_headers['Authorization'], 0, 6) == 'OAuth ') {
+        $header_parameters = OAuthUtil::split_header(
+          $request_headers['Authorization']
+        );
+        $parameters = array_merge($parameters, $header_parameters);
+      }
+
+    }
+
+    return new OAuthRequest($http_method, $http_url, $parameters);
+  }
+
+  /**
+   * pretty much a helper function to set up the request
+   */
+  public static function from_consumer_and_token($consumer, $token, $http_method, $http_url, $parameters=NULL) {
+    $parameters = ($parameters) ?  $parameters : array();
+    $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 OAuthRequest($http_method, $http_url, $parameters);
+  }
+
+  public function set_parameter($name, $value, $allow_duplicates = true) {
+    if ($allow_duplicates && isset($this->parameters[$name])) {
+      // We have already added parameter(s) with this name, so add to the list
+      if (is_scalar($this->parameters[$name])) {
+        // This is the first duplicate, so transform scalar (string)
+        // into an array so we can add the duplicates
+        $this->parameters[$name] = array($this->parameters[$name]);
+      }
+
+      $this->parameters[$name][] = $value;
+    } else {
+      $this->parameters[$name] = $value;
+    }
+  }
+
+  public function get_parameter($name) {
+    return isset($this->parameters[$name]) ? $this->parameters[$name] : null;
+  }
+
+  public function get_parameters() {
+    return $this->parameters;
+  }
+
+  public function unset_parameter($name) {
+    unset($this->parameters[$name]);
+  }
+
+  /**
+   * The request parameters, sorted and concatenated into a normalized string.
+   * @return string
+   */
+  public function get_signable_parameters() {
+    // Grab all parameters
+    $params = $this->parameters;
+
+    // Remove oauth_signature if present
+    // Ref: Spec: 9.1.1 ("The oauth_signature parameter MUST be excluded.")
+    if (isset($params['oauth_signature'])) {
+      unset($params['oauth_signature']);
+    }
+
+    return OAuthUtil::build_http_query($params);
+  }
+
+  /**
+   * Returns the base string of this request
+   *
+   * The base string defined as the method, the url
+   * and the parameters (normalized), each urlencoded
+   * and the concated with &.
+   */
+  public function get_signature_base_string() {
+    $parts = array(
+      $this->get_normalized_http_method(),
+      $this->get_normalized_http_url(),
+      $this->get_signable_parameters()
+    );
+
+    $parts = OAuthUtil::urlencode_rfc3986($parts);
+
+    return implode('&', $parts);
+  }
+
+  /**
+   * just uppercases the http method
+   */
+  public function get_normalized_http_method() {
+    return strtoupper($this->http_method);
+  }
+
+  /**
+   * parses the url and rebuilds it to be
+   * scheme://host/path
+   */
+  public function get_normalized_http_url() {
+    $parts = parse_url($this->http_url);
+
+    $scheme = (isset($parts['scheme'])) ? $parts['scheme'] : 'http';
+    $port = (isset($parts['port'])) ? $parts['port'] : (($scheme == 'https') ? '443' : '80');
+    $host = (isset($parts['host'])) ? strtolower($parts['host']) : '';
+    $path = (isset($parts['path'])) ? $parts['path'] : '';
+
+    if (($scheme == 'https' && $port != '443')
+        || ($scheme == 'http' && $port != '80')) {
+      $host = "$host:$port";
+    }
+    return "$scheme://$host$path";
+  }
+
+  /**
+   * builds a url usable for a GET request
+   */
+  public function to_url() {
+    $post_data = $this->to_postdata();
+    $out = $this->get_normalized_http_url();
+    if ($post_data) {
+      $out .= '?'.$post_data;
+    }
+    return $out;
+  }
+
+  /**
+   * builds the data one would send in a POST request
+   */
+  public function to_postdata() {
+    return OAuthUtil::build_http_query($this->parameters);
+  }
+
+  /**
+   * builds the Authorization: header
+   */
+  public function to_header($realm=null) {
+    $first = true;
+	if($realm) {
+      $out = 'Authorization: OAuth realm="' . OAuthUtil::urlencode_rfc3986($realm) . '"';
+      $first = false;
+    } else
+      $out = 'Authorization: OAuth';
+
+    $total = array();
+    foreach ($this->parameters as $k => $v) {
+      if (substr($k, 0, 5) != "oauth") continue;
+      if (is_array($v)) {
+        throw new OAuthException('Arrays not supported in headers');
+      }
+      $out .= ($first) ? ' ' : ',';
+      $out .= OAuthUtil::urlencode_rfc3986($k) .
+              '="' .
+              OAuthUtil::urlencode_rfc3986($v) .
+              '"';
+      $first = false;
+    }
+    return $out;
+  }
+
+  public function __toString() {
+    return $this->to_url();
+  }
+
+
+  public function sign_request($signature_method, $consumer, $token) {
+    $this->set_parameter(
+      "oauth_signature_method",
+      $signature_method->get_name(),
+      false
+    );
+    $signature = $this->build_signature($signature_method, $consumer, $token);
+    $this->set_parameter("oauth_signature", $signature, false);
+  }
+
+  public function build_signature($signature_method, $consumer, $token) {
+    $signature = $signature_method->build_signature($this, $consumer, $token);
+    return $signature;
+  }
+
+  /**
+   * util function: current timestamp
+   */
+  private static function generate_timestamp() {
+    return time();
+  }
+
+  /**
+   * util function: current nonce
+   */
+  private static function generate_nonce() {
+    $mt = microtime();
+    $rand = mt_rand();
+
+    return md5($mt . $rand); // md5s look nicer than numbers
+  }
+}

+ 223 - 0
plugin/ims_lti/vendor/oauth1/code/OAuthServer.php

@@ -0,0 +1,223 @@
+<?php
+
+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 instanceof OAuthRequest
+        ? $request->get_parameter("oauth_signature_method")
+        : NULL;
+
+    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 instanceof OAuthRequest
+        ? $request->get_parameter("oauth_consumer_key")
+        : NULL;
+
+    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 instanceof OAuthRequest
+         ? $request->get_parameter('oauth_token')
+         : NULL;
+
+    $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 instanceof OAuthRequest
+        ? $request->get_parameter('oauth_timestamp')
+        : NULL;
+    $nonce = $request instanceof OAuthRequest
+        ? $request->get_parameter('oauth_nonce')
+        : NULL;
+
+    $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");
+    }
+  }
+
+}

+ 55 - 0
plugin/ims_lti/vendor/oauth1/code/OAuthSignatureMethod.php

@@ -0,0 +1,55 @@
+<?php
+
+/**
+ * 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);
+
+    // Check for zero length, although unlikely here
+    if (strlen($built) == 0 || strlen($signature) == 0) {
+      return false;
+    }
+
+    if (strlen($built) != strlen($signature)) {
+      return false;
+    }
+
+    // Avoid a timing leak with a (hopefully) time insensitive compare
+    $result = 0;
+    for ($i = 0; $i < strlen($signature); $i++) {
+      $result |= ord($built{$i}) ^ ord($signature{$i});
+    }
+
+    return $result == 0;
+  }
+}
+

+ 30 - 0
plugin/ims_lti/vendor/oauth1/code/OAuthSignatureMethod_HMAC_SHA1.php

@@ -0,0 +1,30 @@
+<?php
+
+/**
+ * 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) {
+    $base_string = $request->get_signature_base_string();
+    $request->base_string = $base_string;
+
+    $key_parts = array(
+      $consumer->secret,
+      ($token) ? $token->secret :  ""
+    );
+
+    $key_parts = OAuthUtil::urlencode_rfc3986($key_parts);
+    $key = implode('&', $key_parts);
+
+    return base64_encode(hash_hmac('sha1', $base_string, $key, true));
+  }
+}

+ 34 - 0
plugin/ims_lti/vendor/oauth1/code/OAuthSignatureMethod_PLAINTEXT.php

@@ -0,0 +1,34 @@
+<?php
+
+/**
+ * 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;
+  }
+}

+ 69 - 0
plugin/ims_lti/vendor/oauth1/code/OAuthSignatureMethod_RSA_SHA1.php

@@ -0,0 +1,69 @@
+<?php
+
+/**
+ * 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);
+
+    // 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;
+  }
+}
+

+ 13 - 0
plugin/ims_lti/vendor/oauth1/code/OAuthTests.xml

@@ -0,0 +1,13 @@
+<phpunit colors="true">
+  <testsuite name="OAuth">
+    <directory>tests</directory>
+  </testsuite>
+  <filter>
+    <blacklist>
+      <directory>tests</directory>
+    </blacklist>
+  </filter>
+  <logging>
+    <log type="coverage-html" target="./report" charset="UTF-8" yui="true" highlight="false" lowUpperBound="35" highLowerBound="70"/>
+  </logging>
+</phpunit>

+ 31 - 0
plugin/ims_lti/vendor/oauth1/code/OAuthToken.php

@@ -0,0 +1,31 @@
+<?php
+
+class OAuthToken {
+  // access tokens and request tokens
+  public $key;
+  public $secret;
+
+  /**
+   * key = the token
+   * secret = the token secret
+   */
+  function __construct($key, $secret) {
+    $this->key = $key;
+    $this->secret = $secret;
+  }
+
+  /**
+   * generates the basic string serialization of a token that a server
+   * would respond to request_token and access_token calls with
+   */
+  function to_string() {
+    return "oauth_token=" .
+           oauthutil::urlencode_rfc3986($this->key) .
+           "&oauth_token_secret=" .
+           oauthutil::urlencode_rfc3986($this->secret);
+  }
+
+  function __tostring() {
+    return $this->to_string();
+  }
+}

+ 153 - 0
plugin/ims_lti/vendor/oauth1/code/OAuthUtil.php

@@ -0,0 +1,153 @@
+<?php
+
+class OAuthUtil {
+  public static function urlencode_rfc3986($input) {
+  if (is_array($input)) {
+    return array_map(array('OAuthUtil', 'urlencode_rfc3986'), $input);
+  } else if (is_scalar($input)) {
+    return str_replace(
+      '+',
+      ' ',
+      str_replace('%7E', '~', rawurlencode($input))
+    );
+  } else {
+    return '';
+  }
+}
+
+
+  // This decode function isn't taking into consideration the above
+  // modifications to the encoding process. However, this method doesn't
+  // seem to be used anywhere so leaving it as is.
+  public static function urldecode_rfc3986($string) {
+    return urldecode($string);
+  }
+
+  // Utility function for turning the Authorization: header into
+  // parameters, has to do some unescaping
+  // Can filter out any non-oauth parameters if needed (default behaviour)
+  // May 28th, 2010 - method updated to tjerk.meesters for a speed improvement.
+  //                  see http://code.google.com/p/oauth/issues/detail?id=163
+  public static function split_header($header, $only_allow_oauth_parameters = true) {
+    $params = array();
+    if (preg_match_all('/('.($only_allow_oauth_parameters ? 'oauth_' : '').'[a-z_-]*)=(:?"([^"]*)"|([^,]*))/', $header, $matches)) {
+      foreach ($matches[1] as $i => $h) {
+        $params[$h] = OAuthUtil::urldecode_rfc3986(empty($matches[3][$i]) ? $matches[4][$i] : $matches[3][$i]);
+      }
+      if (isset($params['realm'])) {
+        unset($params['realm']);
+      }
+    }
+    return $params;
+  }
+
+  // helper to try to sort out headers for people who aren't running apache
+  public static function get_headers() {
+    if (function_exists('apache_request_headers')) {
+      // we need this to get the actual Authorization: header
+      // because apache tends to tell us it doesn't exist
+      $headers = apache_request_headers();
+
+      // sanitize the output of apache_request_headers because
+      // we always want the keys to be Cased-Like-This and arh()
+      // returns the headers in the same case as they are in the
+      // request
+      $out = array();
+      foreach ($headers AS $key => $value) {
+        $key = str_replace(
+            " ",
+            "-",
+            ucwords(strtolower(str_replace("-", " ", $key)))
+          );
+        $out[$key] = $value;
+      }
+    } else {
+      // otherwise we don't have apache and are just going to have to hope
+      // that $_SERVER actually contains what we need
+      $out = array();
+      if( isset($_SERVER['CONTENT_TYPE']) )
+        $out['Content-Type'] = $_SERVER['CONTENT_TYPE'];
+      if( isset($_ENV['CONTENT_TYPE']) )
+        $out['Content-Type'] = $_ENV['CONTENT_TYPE'];
+
+      foreach ($_SERVER as $key => $value) {
+        if (substr($key, 0, 5) == "HTTP_") {
+          // this is chaos, basically it is just there to capitalize the first
+          // letter of every word that is not an initial HTTP and strip HTTP
+          // code from przemek
+          $key = str_replace(
+            " ",
+            "-",
+            ucwords(strtolower(str_replace("_", " ", substr($key, 5))))
+          );
+          $out[$key] = $value;
+        }
+      }
+    }
+    return $out;
+  }
+
+  // This function takes a input like a=b&a=c&d=e and returns the parsed
+  // parameters like this
+  // array('a' => array('b','c'), 'd' => 'e')
+  public static function parse_parameters( $input ) {
+    if (!isset($input) || !$input) return array();
+
+    $pairs = explode('&', $input);
+
+    $parsed_parameters = array();
+    foreach ($pairs as $pair) {
+      $split = explode('=', $pair, 2);
+      $parameter = OAuthUtil::urldecode_rfc3986($split[0]);
+      $value = isset($split[1]) ? OAuthUtil::urldecode_rfc3986($split[1]) : '';
+
+      if (isset($parsed_parameters[$parameter])) {
+        // We have already recieved parameter(s) with this name, so add to the list
+        // of parameters with this name
+
+        if (is_scalar($parsed_parameters[$parameter])) {
+          // This is the first duplicate, so transform scalar (string) into an array
+          // so we can add the duplicates
+          $parsed_parameters[$parameter] = array($parsed_parameters[$parameter]);
+        }
+
+        $parsed_parameters[$parameter][] = $value;
+      } else {
+        $parsed_parameters[$parameter] = $value;
+      }
+    }
+    return $parsed_parameters;
+  }
+
+  public static function build_http_query($params) {
+    if (!$params) return '';
+
+    // Urlencode both keys and values
+    $keys = OAuthUtil::urlencode_rfc3986(array_keys($params));
+    $values = OAuthUtil::urlencode_rfc3986(array_values($params));
+    $params = array_combine($keys, $values);
+
+    // Parameters are sorted by name, using lexicographical byte value ordering.
+    // Ref: Spec: 9.1.1 (1)
+    uksort($params, 'strcmp');
+
+    $pairs = array();
+    foreach ($params as $parameter => $value) {
+      if (is_array($value)) {
+        // If two or more parameters share the same name, they are sorted by their value
+        // Ref: Spec: 9.1.1 (1)
+        // June 12th, 2010 - changed to sort because of issue 164 by hidetaka
+        sort($value, SORT_STRING);
+        foreach ($value as $duplicate_value) {
+          $pairs[] = $parameter . '=' . $duplicate_value;
+        }
+      } else {
+        $pairs[] = $parameter . '=' . $value;
+      }
+    }
+    // For each parameter, the name is separated from the corresponding value by an '=' character (ASCII code 61)
+    // Each name-value pair is separated by an '&' character (ASCII code 38)
+    return implode('&', $pairs);
+  }
+}
+

+ 106 - 0
plugin/ims_lti/vendor/oauth1/code/OAuth_TestServer.php

@@ -0,0 +1,106 @@
+<?php //vim: foldmethod=marker
+//require_once("../init.php");
+
+class TestOAuthServer extends OAuthServer {
+  public function get_signature_methods() {
+    return $this->signature_methods;
+  }
+}
+
+class TestOAuthSignatureMethod_RSA_SHA1 extends OAuthSignatureMethod_RSA_SHA1 {
+  public function fetch_private_cert(&$request) {
+    $cert = <<<EOD
+-----BEGIN PRIVATE KEY-----
+MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBALRiMLAh9iimur8V
+A7qVvdqxevEuUkW4K+2KdMXmnQbG9Aa7k7eBjK1S+0LYmVjPKlJGNXHDGuy5Fw/d
+7rjVJ0BLB+ubPK8iA/Tw3hLQgXMRRGRXXCn8ikfuQfjUS1uZSatdLB81mydBETlJ
+hI6GH4twrbDJCR2Bwy/XWXgqgGRzAgMBAAECgYBYWVtleUzavkbrPjy0T5FMou8H
+X9u2AC2ry8vD/l7cqedtwMPp9k7TubgNFo+NGvKsl2ynyprOZR1xjQ7WgrgVB+mm
+uScOM/5HVceFuGRDhYTCObE+y1kxRloNYXnx3ei1zbeYLPCHdhxRYW7T0qcynNmw
+rn05/KO2RLjgQNalsQJBANeA3Q4Nugqy4QBUCEC09SqylT2K9FrrItqL2QKc9v0Z
+zO2uwllCbg0dwpVuYPYXYvikNHHg+aCWF+VXsb9rpPsCQQDWR9TT4ORdzoj+Nccn
+qkMsDmzt0EfNaAOwHOmVJ2RVBspPcxt5iN4HI7HNeG6U5YsFBb+/GZbgfBT3kpNG
+WPTpAkBI+gFhjfJvRw38n3g/+UeAkwMI2TJQS4n8+hid0uus3/zOjDySH3XHCUno
+cn1xOJAyZODBo47E+67R4jV1/gzbAkEAklJaspRPXP877NssM5nAZMU0/O/NGCZ+
+3jPgDUno6WbJn5cqm8MqWhW1xGkImgRk+fkDBquiq4gPiT898jusgQJAd5Zrr6Q8
+AO/0isr/3aa6O6NLQxISLKcPDk2NOccAfS/xOtfOz4sJYM3+Bs4Io9+dZGSDCA54
+Lw03eHTNQghS0A==
+-----END PRIVATE KEY-----
+EOD;
+    return $cert;
+  }
+
+  public function fetch_public_cert(&$request) {
+    $cert = <<<EOD
+-----BEGIN CERTIFICATE-----
+MIIBpjCCAQ+gAwIBAgIBATANBgkqhkiG9w0BAQUFADAZMRcwFQYDVQQDDA5UZXN0
+IFByaW5jaXBhbDAeFw03MDAxMDEwODAwMDBaFw0zODEyMzEwODAwMDBaMBkxFzAV
+BgNVBAMMDlRlc3QgUHJpbmNpcGFsMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB
+gQC0YjCwIfYoprq/FQO6lb3asXrxLlJFuCvtinTF5p0GxvQGu5O3gYytUvtC2JlY
+zypSRjVxwxrsuRcP3e641SdASwfrmzyvIgP08N4S0IFzEURkV1wp/IpH7kH41Etb
+mUmrXSwfNZsnQRE5SYSOhh+LcK2wyQkdgcMv11l4KoBkcwIDAQABMA0GCSqGSIb3
+DQEBBQUAA4GBAGZLPEuJ5SiJ2ryq+CmEGOXfvlTtEL2nuGtr9PewxkgnOjZpUy+d
+4TvuXJbNQc8f4AMWL/tO9w0Fk80rWKp9ea8/df4qMq5qlFWlx6yOLQxumNOmECKb
+WpkUQDIDJEoFUzKMVuJf4KO/FJ345+BNLGgbJ6WujreoM1X/gYfdnJ/J
+-----END CERTIFICATE-----
+EOD;
+    return $cert;
+  }
+}
+
+/**
+ * A mock store for testing
+ */
+class MockOAuthDataStore extends OAuthDataStore {/*{{{*/
+    private $consumer;
+    private $request_token;
+    private $access_token;
+    private $nonce;
+
+    function __construct() {/*{{{*/
+        $this->consumer = new OAuthConsumer("key", "secret", NULL);
+        $this->request_token = new OAuthToken("requestkey", "requestsecret", 1);
+        $this->access_token = new OAuthToken("accesskey", "accesssecret", 1);
+        $this->nonce = "nonce";
+    }/*}}}*/
+
+    function lookup_consumer($consumer_key) {/*{{{*/
+        if ($consumer_key == $this->consumer->key) return $this->consumer;
+        return NULL;
+    }/*}}}*/
+
+    function lookup_token($consumer, $token_type, $token) {/*{{{*/
+        $token_attrib = $token_type . "_token";
+        if ($consumer->key == $this->consumer->key
+            && $token == $this->$token_attrib->key) {
+            return $this->$token_attrib;
+        }
+        return NULL;
+    }/*}}}*/
+
+    function lookup_nonce($consumer, $token, $nonce, $timestamp) {/*{{{*/
+        if ($consumer->key == $this->consumer->key
+            && (($token && $token->key == $this->request_token->key)
+                || ($token && $token->key == $this->access_token->key))
+            && $nonce == $this->nonce) {
+            return $this->nonce;
+        }
+        return NULL;
+    }/*}}}*/
+
+    function new_request_token($consumer) {/*{{{*/
+        if ($consumer->key == $this->consumer->key) {
+            return $this->request_token;
+        }
+        return NULL;
+    }/*}}}*/
+
+    function new_access_token($token, $consumer) {/*{{{*/
+        if ($consumer->key == $this->consumer->key
+            && $token->key == $this->request_token->key) {
+            return $this->access_token;
+        }
+        return NULL;
+    }/*}}}*/
+}/*}}}*/
+?>

+ 30 - 0
plugin/ims_lti/vendor/oauth1/composer.json

@@ -0,0 +1,30 @@
+{
+    "name": "jtsternberg/oauth1-php",
+    "description": "Andy Smith's basic php library for OAuth.",
+    "license": "MIT",
+    "authors": [
+        {
+            "name": "Andy Smith",
+            "homepage": "http://term.ie/",
+            "role": "Developer"
+        },
+        {
+            "name": "Justin Sternberg",
+            "email": "justin@dsgnwrks.pro",
+            "homepage": "https://dsgnwrks.pro",
+            "role": "Developer"
+        }
+    ],
+    "keywords": ["oauth", "oauth1", "php"],
+    "homepage": "https://github.com/jtsternberg/oauth1-php",
+    "support": {
+        "issues": "https://github.com/jtsternberg/oauth1-php/issues",
+        "source": "https://github.com/jtsternberg/oauth1-php"
+    },
+    "require": {
+        "php": ">5.3"
+    },
+    "autoload": {
+        "classmap": ["code"]
+    }
+}

+ 20 - 0
plugin/ims_lti/vendor/oauth1/composer.lock

@@ -0,0 +1,20 @@
+{
+    "_readme": [
+        "This file locks the dependencies of your project to a known state",
+        "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
+        "This file is @generated automatically"
+    ],
+    "hash": "9ec16f80a40b9ed7b9501632e2ab33c3",
+    "content-hash": "17d848aa0b54718b6bf5334fd7e94bcc",
+    "packages": [],
+    "packages-dev": [],
+    "aliases": [],
+    "minimum-stability": "stable",
+    "stability-flags": [],
+    "prefer-stable": false,
+    "prefer-lowest": false,
+    "platform": {
+        "php": ">5.3"
+    },
+    "platform-dev": []
+}

+ 73 - 0
plugin/ims_lti/vendor/oauth1/doc/design.md

@@ -0,0 +1,73 @@
+## Interfaces:
+
+**OAuthConsumer** is a data type that represents the identity of the Consumer via its shared secret with the Service Provider.
+
+OAuthConsumer
+  - `key : str`
+  - `secret : str`
+
+**OAuthToken** is a data type that represents an End User via either an access or request token
+
+OAuthToken
+  - `token : str`
+  - `secret : str`
+  - `to_string() -> str`
+  - `(static) from_string() -> OAuthToken`
+
+**OAuthSignatureMethod** is a strategy class that implements a signature method
+
+OAuthSignatureMethod
+  - `get_name() -> str`
+  - `build_signature (OAuthRequest, OAuthConsumer, OAuthToken) -> str`
+
+**OAuthRequest** represents the request and can be seriali
+
+OAuthRequest:
+  - `OAuthRequest(str http_method, str http_url, [dict parameters]) -> constructor`
+  - `set_parameter(str parameter, str value) -> void`
+    - `example parameters: oauth_consumer_key, foo`
+  - `get_parameter(str parameter) -> str`
+  - `get_parameters() -> dict`
+
+  - `get_normalized_http_method() -> str`
+  - `get_normalized_http_url() -> str`
+  - `get_signable_params() -> dict`
+
+  - `to_header () -> str   // serialize as a header for an HTTPAuth request`
+  - `to_postdata () -> str // serialize as post data for a POST request`
+  - `to_url () -> str      // serialize as a url for a GET request`
+  - `sign_request(OAuthSignatureMethod, OAuthConsumer, OAuthToken) -> void`
+  - `build_signature(OAuthSignatureMethod, OAuthConsumer, OAuthToken) -> str`
+  - `(static) from_request([str http_method, str http_url, dict parameters])`
+  - `(static) from_consumer_and_token(OAuthConsumer, OAuthToken, str http_method, str http_url, [dict parameters]) -> OAuthRequest`
+
+
+**OAuthServer** is a worker to check a requests validity against a data store
+
+OAuthServer:
+  - `OAuthServer(OAuthDataStore) -> constructor`
+  - `set_data_store(OAuthDataStore) -> void`
+  - `get_data_store() -> OAuthDataStore`
+
+  - `fetch_request_token (OAuthRequest) -> OAuthToken`
+  - `fetch_access_token (OAuthRequest) -> OAuthToken`
+  - `verify_request (OAuthRequest) -> OAuthToken`
+
+**OAuthClient** is a worker to attempt to execute a request
+
+OAuthClient:
+  - `OAuthClient(OAuthConsumer, OAuthToken) -> constructor`
+  - `get_consumer() -> OAuthConsumer`
+  - `get_token() -> OAuthToken`
+
+  - `fetch_request_token (OAuthRequest) -> OAuthToken`
+  - `fetch_access_token (OAuthRequest) -> OAuthToken`
+
+**OAuthDataStore** is a database abstraction used to lookup consumers and tokens
+
+OAuthDataStore:
+  - `lookup_consumer(str key) -> OAuthConsumer`
+  - `lookup_token(OAuthConsumer, str token_type, str token_token) -> OAuthToken`
+  - `lookup_nonce(OAuthConsumer, OAuthToken, str nonce, int timestamp) -> OAuthToken`
+  - `fetch_request_token(OAuthConsumer) -> OAuthToken`
+  - `fetch_access_token(OAuthConsumer, OAuthToken) -> OAuthToken`

+ 74 - 0
plugin/ims_lti/vendor/oauth1/example/SimpleOAuthDataStore.php

@@ -0,0 +1,74 @@
+<?php
+
+/*  A very naive dbm-based oauth storage
+ *
+ *  NOTE: This is for reference ONLY, 
+ *  and contains, amongst others, a hole
+ *  where you can get the token secret
+ *  easily..
+ */
+class SimpleOAuthDataStore extends OAuthDataStore {/*{{{*/
+  private $dbh;
+
+  function __construct($path = "oauth.gdbm") {/*{{{*/
+    $this->dbh = dba_popen($path, 'c', 'gdbm');
+  }/*}}}*/
+
+  function __destruct() {/*{{{*/
+    dba_close($this->dbh);
+  }/*}}}*/
+
+  function lookup_consumer($consumer_key) {/*{{{*/
+    $rv = dba_fetch("consumer_$consumer_key", $this->dbh);
+    if ($rv === FALSE) {
+      return NULL;
+    }
+    $obj = unserialize($rv);
+    if (!($obj instanceof OAuthConsumer)) {
+      return NULL;
+    }
+    return $obj;
+  }/*}}}*/
+
+  function lookup_token($consumer, $token_type, $token) {/*{{{*/
+    $rv = dba_fetch("${token_type}_${token}", $this->dbh);
+    if ($rv === FALSE) {
+      return NULL;
+    }
+    $obj = unserialize($rv);
+    if (!($obj instanceof OAuthToken)) {
+      return NULL;
+    }
+    return $obj;
+  }/*}}}*/
+
+  function lookup_nonce($consumer, $token, $nonce, $timestamp) {/*{{{*/
+    if (dba_exists("nonce_$nonce", $this->dbh)) {
+      return TRUE;
+    } else {
+      dba_insert("nonce_$nonce", "1", $this->dbh);
+      return FALSE;
+    }
+  }/*}}}*/
+
+  function new_token($consumer, $type="request") {/*{{{*/
+    $key = md5(time());
+    $secret = time() + time();
+    $token = new OAuthToken($key, md5(md5($secret)));
+    if (!dba_insert("${type}_$key", serialize($token), $this->dbh)) {
+      throw new OAuthException("doooom!");
+    }
+    return $token;
+  }/*}}}*/
+
+  function new_request_token($consumer) {/*{{{*/
+    return $this->new_token($consumer, "request");
+  }/*}}}*/
+
+  function new_access_token($token, $consumer) {/*{{{*/
+
+    $token = $this->new_token($consumer, 'access');
+    dba_delete("request_" . $token->key, $this->dbh);
+    return $token;
+  }/*}}}*/
+}/*}}}*/

+ 14 - 0
plugin/ims_lti/vendor/oauth1/example/access_token.php

@@ -0,0 +1,14 @@
+<?php
+require_once("common.inc.php");
+
+try {
+  $req = OAuthRequest::from_request();
+  $token = $test_server->fetch_access_token($req);
+  print $token;
+} catch (OAuthException $e) {
+  print($e->getMessage() . "\n<hr />\n");
+  print_r($req);
+  die();
+}
+
+?>

+ 133 - 0
plugin/ims_lti/vendor/oauth1/example/client.php

@@ -0,0 +1,133 @@
+<?php
+require_once("common.inc.php");
+
+$key = @$_REQUEST['key'];
+$secret = @$_REQUEST['secret'];
+$token = @$_REQUEST['token'];
+$token_secret = @$_REQUEST['token_secret'];
+$endpoint = @$_REQUEST['endpoint'];
+$action = @$_REQUEST['action'];
+$dump_request = @$_REQUEST['dump_request'];
+$user_sig_method = @$_REQUEST['sig_method'];
+$sig_method = $hmac_method;
+if ($user_sig_method) {
+  $sig_method = $sig_methods[$user_sig_method];
+}
+
+$test_consumer = new OAuthConsumer($key, $secret, NULL);
+
+$test_token = NULL;
+if ($token) {
+  $test_token = new OAuthConsumer($token, $token_secret);
+}
+
+
+if ($action == "request_token") {
+  $parsed = parse_url($endpoint);
+  $params = array();
+  parse_str($parsed['query'], $params);
+
+  $req_req = OAuthRequest::from_consumer_and_token($test_consumer, NULL, "GET", $endpoint, $params);
+  $req_req->sign_request($sig_method, $test_consumer, NULL);
+  if ($dump_request) {
+    Header('Content-type: text/plain');
+    print "request url: " . $req_req->to_url(). "\n";
+    print_r($req_req);
+    exit;
+  }
+  Header("Location: $req_req");
+} 
+else if ($action == "authorize") {
+  $callback_url = "$base_url/client.php?key=$key&secret=$secret&token=$token&token_secret=$token_secret&endpoint=" . urlencode($endpoint);
+  $auth_url = $endpoint . "?oauth_token=$token&oauth_callback=".urlencode($callback_url);
+  if ($dump_request) {
+    Header('Content-type: text/plain');
+    print("auth_url: " . $auth_url);
+    exit;
+  }
+  Header("Location: $auth_url");
+}
+else if ($action == "access_token") {
+  $parsed = parse_url($endpoint);
+  $params = array();
+  parse_str($parsed['query'], $params);
+
+  $acc_req = OAuthRequest::from_consumer_and_token($test_consumer, $test_token, "GET", $endpoint, $params);
+  $acc_req->sign_request($sig_method, $test_consumer, $test_token);
+  if ($dump_request) {
+    Header('Content-type: text/plain');
+    print "request url: " . $acc_req->to_url() . "\n";
+    print_r($acc_req);
+    exit;
+  }
+  Header("Location: $acc_req");
+}
+
+?>
+<html>
+<head>
+<title>OAuth Test Client</title>
+</head>
+<body>
+<div><a href="index.php">server</a> | <a href="client.php">client</a></div>
+<h1>OAuth Test Client</h1>
+<h2>Instructions for Use</h2>
+<p>This is a test client that will let you test your OAuth server code. Enter the appropriate information below to test.</p>
+<p>Note: we don't store any of the information you type in.</p>
+
+<form method="POST" name="oauth_client">
+<h3>Choose a Signature Method</h3>
+<select name="sig_method">
+<?php
+foreach ($sig_methods as $name=> $method) {
+  $selected = "";
+  if ($name == $sig_method->get_name()) {
+    $selected = " selected='selected'";
+  }
+  print "<option value='$name'$selected>$name</option>\n";
+}
+?>
+</select>
+<h3>Enter The Endpoint to Test</h3>
+endpoint: <input type="text" name="endpoint" value="<?php echo $endpoint; ?>" size="100"/><br />
+<small style="color: green">Note: You can include query parameters in there to have them parsed in and signed too</small>
+<h3>Enter Your Consumer Key / Secret</h3>
+consumer key: <input type="text" name="key" value="<?php echo $key; ?>" /><br />
+consumer secret: <input type="text" name="secret" value="<?php echo $secret;?>" /><br />
+dump request, don't redirect: <input type="checkbox" name="dump_request" value="1" <?php if ($dump_request) echo 'checked="checked"'; ?>/><br />
+make a token request (don't forget to copy down the values you get)
+<input type="submit" name="action" value="request_token" />
+<h3>Enter Your Request Token / Secret</h3>
+token: <input type="text" name="token" value="<?php echo $token; ?>" /><br />
+token secret: <input type="text" name="token_secret" value="<?php echo $token_secret; ?>" /><br />
+<p><strong>Don't forget to update your endpoint to point at the auth or access token url</strong></p>
+try to authorize this token: <input type="submit" name="action" value="authorize" /><br />
+try to get an access token: <input type="submit" name="action" value="access_token" /><br />
+
+<h3>Currently Supported Signature Methods</h3>
+<p>Current signing method is: <?php echo $sig_method->get_name() ?></p>
+<ul>
+<?php
+foreach ($sig_methods as $key => $method) {
+  
+  print "<li>$key";
+  if ($key != $sig_method->get_name()) {
+    print "(<a href='?sig_method=$key'>switch</a>)";
+  }
+  print "</li>\n";
+}
+?>
+</ul>
+
+<?php 
+if ("RSA-SHA1" == $sig_method->get_name()) {
+  // passing test_server as a dummy referecne
+  print "<pre>" . $sig_method->fetch_private_cert($test_server). "</pre>\n";
+  print "<pre>" . $sig_method->fetch_public_cert($test_server) . "</pre>\n";
+}
+?>
+
+<h3>Further Resources</h3>
+<p>There is also a <a href="index.php">test server</a> implementation in here.</p>
+<p>The code running this example can be downloaded from the PHP section of the OAuth google code project: <a href="http://code.google.com/p/oauth/">http://code.google.com/p/oauth/</a>
+</body>

+ 26 - 0
plugin/ims_lti/vendor/oauth1/example/common.inc.php

@@ -0,0 +1,26 @@
+<?php
+require_once("../init.php");
+require_once("../code/OAuth_TestServer.php");
+
+/*
+ * Config Section
+ */
+$domain = $_SERVER['HTTP_HOST'];
+$base = "/oauth/example";
+$base_url = "http://$domain$base";
+
+/**
+ * Some default objects
+ */
+
+$test_server = new TestOAuthServer(new MockOAuthDataStore());
+$hmac_method = new OAuthSignatureMethod_HMAC_SHA1();
+$plaintext_method = new OAuthSignatureMethod_PLAINTEXT();
+$rsa_method = new TestOAuthSignatureMethod_RSA_SHA1();
+
+$test_server->add_signature_method($hmac_method);
+$test_server->add_signature_method($plaintext_method);
+$test_server->add_signature_method($rsa_method);
+
+$sig_methods = $test_server->get_signature_methods();
+?>

+ 21 - 0
plugin/ims_lti/vendor/oauth1/example/echo_api.php

@@ -0,0 +1,21 @@
+<?php
+require_once("common.inc.php");
+
+try {
+  $req = OAuthRequest::from_request();
+  list($consumer, $token) = $test_server->verify_request($req);
+
+  // lsit back the non-OAuth params
+  $total = array();
+  foreach($req->get_parameters() as $k => $v) {
+    if (substr($k, 0, 5) == "oauth") continue;
+    $total[] = urlencode($k) . "=" . urlencode($v);
+  }
+  print implode("&", $total);
+} catch (OAuthException $e) {
+  print($e->getMessage() . "\n<hr />\n");
+  print_r($req);
+  die();
+}
+
+?>

+ 108 - 0
plugin/ims_lti/vendor/oauth1/example/index.php

@@ -0,0 +1,108 @@
+<?php
+require_once("common.inc.php");
+
+
+$test_consumer = new OAuthConsumer("key", "secret", NULL);
+$req_token = new OAuthConsumer("requestkey", "requestsecret", 1);
+$acc_token = new OAuthConsumer("accesskey", "accesssecret", 1);
+
+$sig_method = $hmac_method;
+$user_sig_method = @$_GET['sig_method'];
+if ($user_sig_method) {
+  $sig_method = $sig_methods[$user_sig_method];
+}
+
+$req_req = OAuthRequest::from_consumer_and_token($test_consumer, NULL, "GET", $base_url . "/request_token.php");
+$req_req->sign_request($sig_method, $test_consumer, NULL);
+
+$acc_req = OAuthRequest::from_consumer_and_token($test_consumer, $req_token, "GET", $base_url . "/access_token.php");
+$acc_req->sign_request($sig_method, $test_consumer, $req_token);
+
+$echo_req = OAuthRequest::from_consumer_and_token($test_consumer, $acc_token, "GET", $base_url . "/echo_api.php", array("method"=> "foo%20bar", "bar" => "baz"));
+$echo_req->sign_request($sig_method, $test_consumer, $acc_token);
+
+?>
+<html>
+<head>
+<title>OAuth Test Server</title>
+</head>
+<body>
+<div><a href="index.php">server</a> | <a href="client.php">client</a></div>
+<h1>OAuth Test Server</h1>
+<h2>Instructions for Use</h2>
+<p>This is a test server with a predefined static set of keys and tokens, you can make your requests using them to test your code (and mine ;)).</p>
+<h3>Your Consumer Key / Secret</h3>
+<ul>
+<li>consumer key: <code><strong>key</strong></code></li>
+<li>consumer secret: <code><strong>secret</strong></code></li>
+</ul>
+<p>Use this key and secret for all your requests.</p>
+<h3>Getting a Request Token</h3>
+
+<ul>
+<li>request token endpoint: <code><strong><?php echo $base_url . "/request_token.php"; ?></strong></code></li>
+</ul>
+
+<p>A successful request will return the following:</p>
+<p><code>oauth_token=requestkey&amp;oauth_token_secret=requestsecret</code></p>
+
+<p>An unsuccessful request will attempt to describe what went wrong.</p>
+
+<h4>Example</h4>
+<a href="<?php echo $req_req; ?>"><?php echo $req_req; ?></a>
+
+<h3>Getting an Access Token</h3>
+<p>The Request Token provided above is already authorized, you may use it to request an Access Token right away.</p>
+
+<ul>
+<li>access token endpoint: <code><strong><?php echo $base_url . "/access_token.php"; ?></strong></code></li>
+</ul>
+
+<p>A successful request will return the following:</p>
+<p><code>oauth_token=accesskey&amp;oauth_token_secret=accesssecret</code></p>
+
+<p>An unsuccessful request will attempt to describe what went wrong.</p>
+
+<h4>Example</h4>
+<a href="<?php echo $acc_req; ?>"><?php echo $acc_req; ?></a>
+
+<h3>Making Authenticated Calls</h3>
+<p>Using your Access Token you can make authenticated calls.</p>
+
+<ul>
+<li>api endpoint: <code><strong><?php echo $base_url . "/echo_api.php"; ?></strong></code></li>
+</ul>
+<p>
+A successful request will echo the non-OAuth parameters sent to it, for example:</p>
+<p><code>method=foo&amp;bar=baz</code></p>
+<p>An unsuccessful request will attempt to describe what went wrong.</p>
+
+<h4>Example</h4>
+<a href="<?php echo $echo_req; ?>"><?php echo $echo_req; ?></a>
+
+<h3>Currently Supported Signature Methods</h3>
+<p>Current signing method is: <?php echo $user_sig_method ?></p>
+<ul>
+<?php
+$sig_methods = $test_server->get_signature_methods();
+foreach ($sig_methods as $key => $method) {
+  print "<li>$key";
+  if ($key != $sig_method->get_name()) {
+    print "(<a href='?sig_method=$key'>switch</a>)";
+  }
+  print "</li>\n";
+}
+?>
+</ul>
+
+<?php 
+if ("RSA-SHA1" == $sig_method->get_name()) {
+  print "<pre>" . $sig_method->fetch_private_cert($req_req) . "</pre>\n";
+  print "<pre>" . $sig_method->fetch_public_cert($req_req) . "</pre>\n";
+}
+?>
+
+<h3>Further Resources</h3>
+<p>There is also a <a href="client.php">test client</a> implementation in here.</p>
+<p>The code running this example can be downloaded from the PHP section of the OAuth google code project: <a href="http://code.google.com/p/oauth/">http://code.google.com/p/oauth/</a>
+</body>

+ 14 - 0
plugin/ims_lti/vendor/oauth1/example/request_token.php

@@ -0,0 +1,14 @@
+<?php
+require_once("common.inc.php");
+
+try {
+  $req = OAuthRequest::from_request();
+  $token = $test_server->fetch_request_token($req);
+  print $token;
+} catch (OAuthException $e) {
+  print($e->getMessage() . "\n<hr />\n");
+  print_r($req);
+  die();
+}
+
+?>

+ 5 - 0
plugin/ims_lti/vendor/oauth1/init.php

@@ -0,0 +1,5 @@
+<?php
+
+// Include the autoloader to get started.
+// (make sure to run `composer install`!)
+require_once dirname( __FILE__ ) . '/vendor/autoload.php';

+ 12 - 0
plugin/ims_lti/vendor/oauth1/tests/Mock_OAuthBaseStringRequest.php

@@ -0,0 +1,12 @@
+<?php
+
+/**
+ * A very simple class that you can pass a base-string, and then have it returned again.
+ * Used for testing the signature-methods
+ */
+class Mock_OAuthBaseStringRequest {
+	private $provided_base_string;
+	public $base_string; // legacy
+	public function __construct($bs) { $this->provided_base_string = $bs; }
+	public function get_signature_base_string() { return $this->provided_base_string; }
+}

+ 57 - 0
plugin/ims_lti/vendor/oauth1/tests/Mock_OAuthDataStore.php

@@ -0,0 +1,57 @@
+<?php
+
+/**
+ * A mock store for testing
+ */
+class Mock_OAuthDataStore extends OAuthDataStore {
+	private $consumer;
+	private $request_token;
+	private $access_token;
+	private $nonce;
+
+	function __construct() {
+		$this->consumer = new OAuthConsumer("key", "secret", NULL);
+		$this->request_token = new OAuthToken("requestkey", "requestsecret", 1);
+		$this->access_token = new OAuthToken("accesskey", "accesssecret", 1);
+		$this->nonce = "nonce";
+	}
+
+	function lookup_consumer($consumer_key) {
+		if ($consumer_key == $this->consumer->key) return $this->consumer;
+		return NULL;
+	}
+
+	function lookup_token($consumer, $token_type, $token) {
+		$token_attrib = $token_type . "_token";
+		if ($consumer->key == $this->consumer->key
+			&& $token == $this->$token_attrib->key) {
+			return $this->$token_attrib;
+		}
+		return NULL;
+	}
+
+	function lookup_nonce($consumer, $token, $nonce, $timestamp) {
+		if ($consumer->key == $this->consumer->key
+			&& (($token && $token->key == $this->request_token->key)
+				|| ($token && $token->key == $this->access_token->key))
+			&& $nonce == $this->nonce) {
+			return $this->nonce;
+		}
+		return NULL;
+	}
+
+	function new_request_token($consumer, $callback = null) {
+		if ($consumer->key == $this->consumer->key) {
+			return $this->request_token;
+		}
+		return NULL;
+	}
+
+	function new_access_token($token, $consumer, $verifier = null) {
+		if ($consumer->key == $this->consumer->key
+			&& $token->key == $this->request_token->key) {
+			return $this->access_token;
+		}
+		return NULL;
+	}
+}

+ 47 - 0
plugin/ims_lti/vendor/oauth1/tests/Mock_OAuthSignatureMethod_RSA_SHA1.php

@@ -0,0 +1,47 @@
+<?php
+
+/**
+ * A mock implementation of OAuthSignatureMethod_RSA_SHA1
+ * Always returns the signatures described in 
+ * http://wiki.oauth.net/TestCases section 9.3 ("RSA-SHA1")
+ */
+class Mock_OAuthSignatureMethod_RSA_SHA1 extends OAuthSignatureMethod_RSA_SHA1 {
+  public function fetch_private_cert(&$request) {
+    $cert = <<<EOD
+-----BEGIN PRIVATE KEY-----
+MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBALRiMLAh9iimur8V
+A7qVvdqxevEuUkW4K+2KdMXmnQbG9Aa7k7eBjK1S+0LYmVjPKlJGNXHDGuy5Fw/d
+7rjVJ0BLB+ubPK8iA/Tw3hLQgXMRRGRXXCn8ikfuQfjUS1uZSatdLB81mydBETlJ
+hI6GH4twrbDJCR2Bwy/XWXgqgGRzAgMBAAECgYBYWVtleUzavkbrPjy0T5FMou8H
+X9u2AC2ry8vD/l7cqedtwMPp9k7TubgNFo+NGvKsl2ynyprOZR1xjQ7WgrgVB+mm
+uScOM/5HVceFuGRDhYTCObE+y1kxRloNYXnx3ei1zbeYLPCHdhxRYW7T0qcynNmw
+rn05/KO2RLjgQNalsQJBANeA3Q4Nugqy4QBUCEC09SqylT2K9FrrItqL2QKc9v0Z
+zO2uwllCbg0dwpVuYPYXYvikNHHg+aCWF+VXsb9rpPsCQQDWR9TT4ORdzoj+Nccn
+qkMsDmzt0EfNaAOwHOmVJ2RVBspPcxt5iN4HI7HNeG6U5YsFBb+/GZbgfBT3kpNG
+WPTpAkBI+gFhjfJvRw38n3g/+UeAkwMI2TJQS4n8+hid0uus3/zOjDySH3XHCUno
+cn1xOJAyZODBo47E+67R4jV1/gzbAkEAklJaspRPXP877NssM5nAZMU0/O/NGCZ+
+3jPgDUno6WbJn5cqm8MqWhW1xGkImgRk+fkDBquiq4gPiT898jusgQJAd5Zrr6Q8
+AO/0isr/3aa6O6NLQxISLKcPDk2NOccAfS/xOtfOz4sJYM3+Bs4Io9+dZGSDCA54
+Lw03eHTNQghS0A==
+-----END PRIVATE KEY-----
+EOD;
+    return $cert;
+  }
+
+  public function fetch_public_cert(&$request) {
+    $cert = <<<EOD
+-----BEGIN CERTIFICATE-----
+MIIBpjCCAQ+gAwIBAgIBATANBgkqhkiG9w0BAQUFADAZMRcwFQYDVQQDDA5UZXN0
+IFByaW5jaXBhbDAeFw03MDAxMDEwODAwMDBaFw0zODEyMzEwODAwMDBaMBkxFzAV
+BgNVBAMMDlRlc3QgUHJpbmNpcGFsMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB
+gQC0YjCwIfYoprq/FQO6lb3asXrxLlJFuCvtinTF5p0GxvQGu5O3gYytUvtC2JlY
+zypSRjVxwxrsuRcP3e641SdASwfrmzyvIgP08N4S0IFzEURkV1wp/IpH7kH41Etb
+mUmrXSwfNZsnQRE5SYSOhh+LcK2wyQkdgcMv11l4KoBkcwIDAQABMA0GCSqGSIb3
+DQEBBQUAA4GBAGZLPEuJ5SiJ2ryq+CmEGOXfvlTtEL2nuGtr9PewxkgnOjZpUy+d
+4TvuXJbNQc8f4AMWL/tO9w0Fk80rWKp9ea8/df4qMq5qlFWlx6yOLQxumNOmECKb
+WpkUQDIDJEoFUzKMVuJf4KO/FJ345+BNLGgbJ6WujreoM1X/gYfdnJ/J
+-----END CERTIFICATE-----
+EOD;
+    return $cert;
+  }
+}

+ 10 - 0
plugin/ims_lti/vendor/oauth1/tests/OAuthConsumerTest.php

@@ -0,0 +1,10 @@
+<?php
+
+require 'common.php';
+
+class OAuthConsumerTest extends PHPUnit_Framework_TestCase {
+	public function testConvertToString() {
+		$consumer = new OAuthConsumer('key', 'secret');
+		$this->assertEquals('OAuthConsumer[key=key,secret=secret]', (string) $consumer);
+	}
+}

+ 329 - 0
plugin/ims_lti/vendor/oauth1/tests/OAuthRequestTest.php

@@ -0,0 +1,329 @@
+<?php
+
+/*
+ * Tests of OAuthRequest
+ *
+ * The tests works by using OAuthTestUtils::build_request
+ * to populare $_SERVER, $_GET & $_POST.
+ *
+ * Most of the base string and signature tests
+ * are either very simple or based upon
+ * http://wiki.oauth.net/TestCases
+ */
+
+require_once dirname(__FILE__) . '/common.php';
+
+class OAuthRequestTest extends PHPUnit_Framework_TestCase {	
+	public function testCanGetSingleParameter() {
+		// Yes, a awesomely boring test.. But if this doesn't work, the other tests is unreliable
+		$request = new OAuthRequest('', '', array('test'=>'foo'));
+		$this->assertEquals( 'foo', $request->get_parameter('test'), 'Failed to read back parameter');
+
+		$request = new OAuthRequest('', '', array('test'=>array('foo', 'bar')));
+		$this->assertEquals( array('foo', 'bar'), $request->get_parameter('test'), 'Failed to read back parameter');
+
+	
+		$request = new OAuthRequest('', '', array('test'=>'foo', 'bar'=>'baz'));
+		$this->assertEquals( 'foo', $request->get_parameter('test'), 'Failed to read back parameter');
+		$this->assertEquals( 'baz', $request->get_parameter('bar'), 'Failed to read back parameter');
+	}
+	
+	public function testGetAllParameters() {
+		// Yes, a awesomely boring test.. But if this doesn't work, the other tests is unreliable
+		$request = new OAuthRequest('', '', array('test'=>'foo'));
+		$this->assertEquals( array('test'=>'foo'), $request->get_parameters(), 'Failed to read back parameters');
+
+		$request = new OAuthRequest('', '', array('test'=>'foo', 'bar'=>'baz'));
+		$this->assertEquals( array('test'=>'foo', 'bar'=>'baz'), $request->get_parameters(), 'Failed to read back parameters');
+
+		$request = new OAuthRequest('', '', array('test'=>array('foo', 'bar')));
+		$this->assertEquals( array('test'=>array('foo', 'bar')), $request->get_parameters(), 'Failed to read back parameters');
+	}
+	
+	public function testSetParameters() {
+		$request = new OAuthRequest('', '');
+		$this->assertEquals( NULL, $request->get_parameter('test'), 'Failed to assert that non-existing parameter is NULL');
+
+		$request->set_parameter('test', 'foo');
+		$this->assertEquals( 'foo', $request->get_parameter('test'), 'Failed to set single-entry parameter');
+
+		$request->set_parameter('test', 'bar');
+		$this->assertEquals( array('foo', 'bar'), $request->get_parameter('test'), 'Failed to set single-entry parameter');
+
+		$request->set_parameter('test', 'bar', false);
+		$this->assertEquals( 'bar', $request->get_parameter('test'), 'Failed to set single-entry parameter');
+	}
+	
+	public function testUnsetParameter() {
+		$request = new OAuthRequest('', '');
+		$this->assertEquals( NULL, $request->get_parameter('test'));
+
+		$request->set_parameter('test', 'foo');
+		$this->assertEquals( 'foo', $request->get_parameter('test'));
+
+		$request->unset_parameter('test');
+		$this->assertEquals( NULL, $request->get_parameter('test'), 'Failed to unset parameter');
+	}
+	
+	public function testCreateRequestFromConsumerAndToken() {
+		$cons = new OAuthConsumer('key', 'kd94hf93k423kf44');
+		$token = new OAuthToken('token', 'pfkkdhi9sl3r4s00');
+		
+		$request = OAuthRequest::from_consumer_and_token($cons, $token, 'POST', 'http://example.com');
+		$this->assertEquals('POST', $request->get_normalized_http_method());
+		$this->assertEquals('http://example.com', $request->get_normalized_http_url());
+		$this->assertEquals('1.0', $request->get_parameter('oauth_version'));
+		$this->assertEquals($cons->key, $request->get_parameter('oauth_consumer_key'));
+		$this->assertEquals($token->key, $request->get_parameter('oauth_token'));
+		$this->assertEquals(time(), $request->get_parameter('oauth_timestamp'));
+		$this->assertRegExp('/[0-9a-f]{32}/', $request->get_parameter('oauth_nonce'));
+		// We don't know what the nonce will be, except it'll be md5 and hence 32 hexa digits
+		
+		$request = OAuthRequest::from_consumer_and_token($cons, $token, 'POST', 'http://example.com', array('oauth_nonce'=>'foo'));
+		$this->assertEquals('foo', $request->get_parameter('oauth_nonce'));
+		
+		$request = OAuthRequest::from_consumer_and_token($cons, NULL, 'POST', 'http://example.com', array('oauth_nonce'=>'foo'));
+		$this->assertNull($request->get_parameter('oauth_token'));
+		
+		// Test that parameters given in the $http_url instead of in the $parameters-parameter
+		// will still be picked up
+		$request = OAuthRequest::from_consumer_and_token($cons, $token, 'POST', 'http://example.com/?foo=bar');
+		$this->assertEquals('http://example.com/', $request->get_normalized_http_url());
+		$this->assertEquals('bar', $request->get_parameter('foo'));
+	}
+	
+	public function testBuildRequestFromPost() {
+		OAuthTestUtils::build_request('POST', 'http://testbed/test', 'foo=bar&baz=blargh');
+		$this->assertEquals(array('foo'=>'bar','baz'=>'blargh'), OAuthRequest::from_request()->get_parameters(), 'Failed to parse POST parameters');
+	}
+	
+	public function testBuildRequestFromGet() {
+		OAuthTestUtils::build_request('GET', 'http://testbed/test?foo=bar&baz=blargh');		
+		$this->assertEquals(array('foo'=>'bar','baz'=>'blargh'), OAuthRequest::from_request()->get_parameters(), 'Failed to parse GET parameters');
+	}
+
+	public function testBuildRequestFromHeader() {
+		$test_header = 'OAuth realm="",oauth_foo=bar,oauth_baz="bla,rgh"';
+		OAuthTestUtils::build_request('POST', 'http://testbed/test', '', $test_header);
+		$this->assertEquals(array('oauth_foo'=>'bar','oauth_baz'=>'bla,rgh'), OAuthRequest::from_request()->get_parameters(), 'Failed to split auth-header correctly');
+	}
+	
+	public function testHasProperParameterPriority() {
+		$test_header = 'OAuth realm="",oauth_foo=header';
+		OAuthTestUtils::build_request('POST', 'http://testbed/test?oauth_foo=get', 'oauth_foo=post', $test_header);
+		$this->assertEquals('header', OAuthRequest::from_request()->get_parameter('oauth_foo'), 'Loaded parameters in with the wrong priorities');		
+
+		OAuthTestUtils::build_request('POST', 'http://testbed/test?oauth_foo=get', 'oauth_foo=post');
+		$this->assertEquals('post', OAuthRequest::from_request()->get_parameter('oauth_foo'), 'Loaded parameters in with the wrong priorities');		
+
+		OAuthTestUtils::build_request('POST', 'http://testbed/test?oauth_foo=get');
+		$this->assertEquals('get', OAuthRequest::from_request()->get_parameter('oauth_foo'), 'Loaded parameters in with the wrong priorities');				
+	}
+	
+	public function testNormalizeHttpMethod() {
+		OAuthTestUtils::build_request('POST', 'http://testbed/test');
+		$this->assertEquals('POST', OAuthRequest::from_request()->get_normalized_http_method(), 'Failed to normalize HTTP method: POST');
+
+		OAuthTestUtils::build_request('post', 'http://testbed/test');
+		$this->assertEquals('POST', OAuthRequest::from_request()->get_normalized_http_method(), 'Failed to normalize HTTP method: post');
+
+		OAuthTestUtils::build_request('GET', 'http://testbed/test');
+		$this->assertEquals('GET', OAuthRequest::from_request()->get_normalized_http_method(), 'Failed to normalize HTTP method: GET');
+
+		OAuthTestUtils::build_request('PUT', 'http://testbed/test');
+		$this->assertEquals('PUT', OAuthRequest::from_request()->get_normalized_http_method(), 'Failed to normalize HTTP method: PUT');
+	}
+	
+	public function testNormalizeParameters() {
+		// This is mostly repeats of OAuthUtilTest::testParseParameters & OAuthUtilTest::TestBuildHttpQuery
+
+		// Tests taken from
+		// http://wiki.oauth.net/TestCases ("Normalize Request Parameters")
+		OAuthTestUtils::build_request('POST', 'http://testbed/test', 'name');
+		$this->assertEquals( 'name=', OAuthRequest::from_request()->get_signable_parameters());
+
+		OAuthTestUtils::build_request('POST', 'http://testbed/test', 'a=b');
+		$this->assertEquals( 'a=b', OAuthRequest::from_request()->get_signable_parameters());
+		
+		OAuthTestUtils::build_request('POST', 'http://testbed/test', 'a=b&c=d');
+		$this->assertEquals( 'a=b&c=d', OAuthRequest::from_request()->get_signable_parameters());
+		
+		OAuthTestUtils::build_request('POST', 'http://testbed/test', 'a=x%21y&a=x+y');
+		$this->assertEquals( 'a=x%20y&a=x%21y', OAuthRequest::from_request()->get_signable_parameters());
+		
+		OAuthTestUtils::build_request('POST', 'http://testbed/test', 'x%21y=a&x=a');
+		$this->assertEquals( 'x=a&x%21y=a', OAuthRequest::from_request()->get_signable_parameters());
+		
+		OAuthTestUtils::build_request('POST', 'http://testbed/test', 'a=1&c=hi there&f=25&f=50&f=a&z=p&z=t');
+		$this->assertEquals( 'a=1&c=hi%20there&f=25&f=50&f=a&z=p&z=t', OAuthRequest::from_request()->get_signable_parameters());
+	}
+	
+	public function testNormalizeHttpUrl() {
+		OAuthTestUtils::build_request('POST', 'http://example.com');
+		$this->assertEquals('http://example.com', OAuthRequest::from_request()->get_normalized_http_url());
+		
+		OAuthTestUtils::build_request('POST', 'https://example.com');
+		$this->assertEquals('https://example.com', OAuthRequest::from_request()->get_normalized_http_url());
+		
+		// Tests that http on !80 and https on !443 keeps the port
+		OAuthTestUtils::build_request('POST', 'http://example.com:8080');
+		$this->assertEquals('http://example.com:8080', OAuthRequest::from_request()->get_normalized_http_url());
+		
+		OAuthTestUtils::build_request('POST', 'https://example.com:80');
+		$this->assertEquals('https://example.com:80', OAuthRequest::from_request()->get_normalized_http_url());
+		
+		OAuthTestUtils::build_request('POST', 'http://example.com:443');
+		$this->assertEquals('http://example.com:443', OAuthRequest::from_request()->get_normalized_http_url());
+		
+		OAuthTestUtils::build_request('POST', 'http://Example.COM');
+		$this->assertEquals('http://example.com', OAuthRequest::from_request()->get_normalized_http_url());
+		
+		// Emulate silly behavior by some clients, where there Host header includes the port
+		OAuthTestUtils::build_request('POST', 'http://example.com');
+		$_SERVER['HTTP_HOST'] = $_SERVER['HTTP_HOST'] . ':' . $_SERVER['SERVER_PORT'];
+		$this->assertEquals('http://example.com', OAuthRequest::from_request()->get_normalized_http_url());
+	}
+	
+	public function testBuildPostData() {
+		OAuthTestUtils::build_request('POST', 'http://example.com');
+		$this->assertEquals('', OAuthRequest::from_request()->to_postdata());
+
+		OAuthTestUtils::build_request('POST', 'http://example.com', 'foo=bar');
+		$this->assertEquals('foo=bar', OAuthRequest::from_request()->to_postdata());
+
+		OAuthTestUtils::build_request('GET', 'http://example.com?foo=bar');
+		$this->assertEquals('foo=bar', OAuthRequest::from_request()->to_postdata());	
+	}
+	
+	public function testBuildUrl() {
+		OAuthTestUtils::build_request('POST', 'http://example.com');
+		$this->assertEquals('http://example.com', OAuthRequest::from_request()->to_url());
+
+		OAuthTestUtils::build_request('POST', 'http://example.com', 'foo=bar');
+		$this->assertEquals('http://example.com?foo=bar', OAuthRequest::from_request()->to_url());
+
+		OAuthTestUtils::build_request('GET', 'http://example.com?foo=bar');
+		$this->assertEquals('http://example.com?foo=bar', OAuthRequest::from_request()->to_url());	
+	}
+
+	public function testConvertToString() {
+		OAuthTestUtils::build_request('POST', 'http://example.com');
+		$this->assertEquals('http://example.com', (string) OAuthRequest::from_request());
+
+		OAuthTestUtils::build_request('POST', 'http://example.com', 'foo=bar');
+		$this->assertEquals('http://example.com?foo=bar', (string) OAuthRequest::from_request());
+
+		OAuthTestUtils::build_request('GET', 'http://example.com?foo=bar');
+		$this->assertEquals('http://example.com?foo=bar', (string) OAuthRequest::from_request());	
+	}
+	
+	public function testBuildHeader() {
+		OAuthTestUtils::build_request('POST', 'http://example.com');
+		$this->assertEquals('Authorization: OAuth', OAuthRequest::from_request()->to_header());
+		$this->assertEquals('Authorization: OAuth realm="test"', OAuthRequest::from_request()->to_header('test'));
+
+		OAuthTestUtils::build_request('POST', 'http://example.com', 'foo=bar');
+		$this->assertEquals('Authorization: OAuth', OAuthRequest::from_request()->to_header());
+		$this->assertEquals('Authorization: OAuth realm="test"', OAuthRequest::from_request()->to_header('test'));
+
+		OAuthTestUtils::build_request('POST', 'http://example.com', 'oauth_test=foo');
+		$this->assertEquals('Authorization: OAuth oauth_test="foo"', OAuthRequest::from_request()->to_header());
+		$this->assertEquals('Authorization: OAuth realm="test",oauth_test="foo"', OAuthRequest::from_request()->to_header('test'));
+
+		// Is headers supposted to be Urlencoded. More to the point:
+		// Should it be baz = bla,rgh or baz = bla%2Crgh ??
+		// - morten.fangel
+		OAuthTestUtils::build_request('POST', 'http://example.com', '', 'OAuth realm="",oauth_foo=bar,oauth_baz="bla,rgh"');
+		$this->assertEquals('Authorization: OAuth oauth_foo="bar",oauth_baz="bla%2Crgh"', OAuthRequest::from_request()->to_header());
+		$this->assertEquals('Authorization: OAuth realm="test",oauth_foo="bar",oauth_baz="bla%2Crgh"', OAuthRequest::from_request()->to_header('test'));
+	}
+	
+	public function testWontBuildHeaderWithArrayInput() {
+		$this->setExpectedException('OAuthException');
+		OAuthTestUtils::build_request('POST', 'http://example.com', 'oauth_foo=bar&oauth_foo=baz');
+		OAuthRequest::from_request()->to_header();
+	}
+
+	public function testBuildBaseString() {
+		OAuthTestUtils::build_request('POST', 'http://testbed/test', 'n=v');
+		$this->assertEquals('POST&http%3A%2F%2Ftestbed%2Ftest&n%3Dv', OAuthRequest::from_request()->get_signature_base_string());
+		
+		OAuthTestUtils::build_request('POST', 'http://testbed/test', 'n=v&n=v2');
+		$this->assertEquals('POST&http%3A%2F%2Ftestbed%2Ftest&n%3Dv%26n%3Dv2', OAuthRequest::from_request()->get_signature_base_string());
+		
+		OAuthTestUtils::build_request('GET', 'http://example.com?n=v');
+		$this->assertEquals('GET&http%3A%2F%2Fexample.com&n%3Dv', OAuthRequest::from_request()->get_signature_base_string());
+		
+		$params  = 'oauth_version=1.0&oauth_consumer_key=dpf43f3p2l4k3l03&oauth_timestamp=1191242090';
+		$params .= '&oauth_nonce=hsu94j3884jdopsl&oauth_signature_method=PLAINTEXT&oauth_signature=ignored';
+		OAuthTestUtils::build_request('POST', 'https://photos.example.net/request_token', $params);			
+		$this->assertEquals('POST&https%3A%2F%2Fphotos.example.net%2Frequest_token&oauth_'
+							.'consumer_key%3Ddpf43f3p2l4k3l03%26oauth_nonce%3Dhsu94j3884j'
+							.'dopsl%26oauth_signature_method%3DPLAINTEXT%26oauth_timestam'
+							.'p%3D1191242090%26oauth_version%3D1.0', 
+							OAuthRequest::from_request()->get_signature_base_string());									
+
+		$params  = 'file=vacation.jpg&size=original&oauth_version=1.0&oauth_consumer_key=dpf43f3p2l4k3l03';
+		$params .= '&oauth_token=nnch734d00sl2jdk&oauth_timestamp=1191242096&oauth_nonce=kllo9940pd9333jh';
+		$params .= '&oauth_signature=ignored&oauth_signature_method=HMAC-SHA1';
+		OAuthTestUtils::build_request('GET', 'http://photos.example.net/photos?'.$params);			
+		$this->assertEquals('GET&http%3A%2F%2Fphotos.example.net%2Fphotos&file%3Dvacation'
+							.'.jpg%26oauth_consumer_key%3Ddpf43f3p2l4k3l03%26oauth_nonce%'
+							.'3Dkllo9940pd9333jh%26oauth_signature_method%3DHMAC-SHA1%26o'
+							.'auth_timestamp%3D1191242096%26oauth_token%3Dnnch734d00sl2jd'
+							.'k%26oauth_version%3D1.0%26size%3Doriginal', 
+							OAuthRequest::from_request()->get_signature_base_string());
+	}
+
+	public function testBuildSignature() {
+		$params  = 'file=vacation.jpg&size=original&oauth_version=1.0&oauth_consumer_key=dpf43f3p2l4k3l03';
+		$params .= '&oauth_token=nnch734d00sl2jdk&oauth_timestamp=1191242096&oauth_nonce=kllo9940pd9333jh';
+		$params .= '&oauth_signature=ignored&oauth_signature_method=HMAC-SHA1';
+		OAuthTestUtils::build_request('GET', 'http://photos.example.net/photos?'.$params);			
+		$r = OAuthRequest::from_request();
+		
+		$cons = new OAuthConsumer('key', 'kd94hf93k423kf44');
+		$token = new OAuthToken('token', 'pfkkdhi9sl3r4s00');
+		
+		$hmac = new OAuthSignatureMethod_HMAC_SHA1();
+		$plaintext = new OAuthSignatureMethod_PLAINTEXT();
+		
+		$this->assertEquals('tR3+Ty81lMeYAr/Fid0kMTYa/WM=', $r->build_signature($hmac, $cons, $token));
+		$this->assertEquals('kd94hf93k423kf44&pfkkdhi9sl3r4s00', $r->build_signature($plaintext, $cons, $token));
+	}
+
+	public function testSign() {
+		$params  = 'file=vacation.jpg&size=original&oauth_version=1.0&oauth_consumer_key=dpf43f3p2l4k3l03';
+		$params .= '&oauth_token=nnch734d00sl2jdk&oauth_timestamp=1191242096&oauth_nonce=kllo9940pd9333jh';
+		$params .= '&oauth_signature=__ignored__&oauth_signature_method=HMAC-SHA1';
+		OAuthTestUtils::build_request('GET', 'http://photos.example.net/photos?'.$params);			
+		$r = OAuthRequest::from_request();
+		
+		$cons = new OAuthConsumer('key', 'kd94hf93k423kf44');
+		$token = new OAuthToken('token', 'pfkkdhi9sl3r4s00');
+		
+		$hmac = new OAuthSignatureMethod_HMAC_SHA1();
+		$plaintext = new OAuthSignatureMethod_PLAINTEXT();
+		
+		// We need to test both what the parameter is, and how the serialized request is..
+		
+		$r->sign_request($hmac, $cons, $token);
+		$this->assertEquals('HMAC-SHA1', $r->get_parameter('oauth_signature_method'));
+		$this->assertEquals('tR3+Ty81lMeYAr/Fid0kMTYa/WM=', $r->get_parameter('oauth_signature'));
+		$expectedPostdata = 'file=vacation.jpg&oauth_consumer_key=dpf43f3p2l4k3l03&oauth_nonce=kllo9940pd9333jh&'
+				. 'oauth_signature=tR3%2BTy81lMeYAr%2FFid0kMTYa%2FWM%3D&oauth_signature_method=HMAC-SHA1&'
+				. 'oauth_timestamp=1191242096&oauth_token=nnch734d00sl2jdk&oauth_version=1.0&size=original';
+		$this->assertEquals( $expectedPostdata, $r->to_postdata());
+		
+		$r->sign_request($plaintext, $cons, $token);
+		$this->assertEquals('PLAINTEXT', $r->get_parameter('oauth_signature_method'));
+		$this->assertEquals('kd94hf93k423kf44&pfkkdhi9sl3r4s00', $r->get_parameter('oauth_signature'));
+		$expectedPostdata = 'file=vacation.jpg&oauth_consumer_key=dpf43f3p2l4k3l03&oauth_nonce=kllo9940pd9333jh&'
+				. 'oauth_signature=kd94hf93k423kf44%26pfkkdhi9sl3r4s00&oauth_signature_method=PLAINTEXT&'
+				. 'oauth_timestamp=1191242096&oauth_token=nnch734d00sl2jdk&oauth_version=1.0&size=original';
+		$this->assertEquals( $expectedPostdata, $r->to_postdata());
+		
+	}
+}
+
+?>

+ 225 - 0
plugin/ims_lti/vendor/oauth1/tests/OAuthServerTest.php

@@ -0,0 +1,225 @@
+<?php
+
+require_once dirname(__FILE__) . '/common.php';
+require_once dirname(__FILE__) . '/Mock_OAuthDataStore.php';
+
+/**
+ * Tests of OAuthUtil
+ */
+class OAuthServerTest extends PHPUnit_Framework_TestCase {
+	private $consumer;
+	private $request_token;
+	private $access_token;
+	private $hmac_sha1;
+	private $plaintext;
+	private $server;
+	
+	public function setUp() {
+		$this->consumer       = new OAuthConsumer('key', 'secret');
+		$this->request_token  = new OAuthToken('requestkey', 'requestsecret');
+		$this->access_token   = new OAuthToken('accesskey', 'accesssecret');
+		
+		$this->hmac_sha1      = new OAuthSignatureMethod_HMAC_SHA1();
+		$this->plaintext      = new OAuthSignatureMethod_PLAINTEXT();
+		
+		$this->server         = new OAuthServer( new Mock_OAuthDataStore() );
+		$this->server->add_signature_method( $this->hmac_sha1 );
+		$this->server->add_signature_method( $this->plaintext );
+	}
+
+	public function testAcceptValidRequest() {
+		$request = OAuthRequest::from_consumer_and_token( $this->consumer, $this->access_token, 'POST', 'http://example.com');
+		$request->sign_request( $this->plaintext, $this->consumer, $this->access_token );		
+		list($consumer, $token) = $this->server->verify_request( $request );
+		$this->assertEquals( $this->consumer, $consumer );
+		$this->assertEquals( $this->access_token, $token );
+		
+		$request->sign_request( $this->hmac_sha1, $this->consumer, $this->access_token );
+		list($consumer, $token) = $this->server->verify_request( $request );
+		$this->assertEquals( $this->consumer, $consumer );
+		$this->assertEquals( $this->access_token, $token );
+	}
+	
+	public function testAcceptRequestWithoutVersion() {
+		$request = OAuthRequest::from_consumer_and_token( $this->consumer, $this->access_token, 'POST', 'http://example.com');
+		$request->unset_parameter('oauth_version');
+		$request->sign_request( $this->hmac_sha1, $this->consumer, $this->access_token );
+	
+		$this->server->verify_request( $request );
+	}
+	
+	public function testRejectRequestSignedWithRequestToken() {
+		$request = OAuthRequest::from_consumer_and_token( $this->consumer, $this->request_token, 'POST', 'http://example.com');
+		$request->sign_request( $this->plaintext, $this->consumer, $this->request_token );		
+		
+		$this->setExpectedException('OAuthException');
+		$this->server->verify_request( $request );
+	}
+	
+	public function testRejectRequestWithMissingParameters() {
+		// The list of required parameters is taken from
+		// Chapter 7 ("Accessing Protected Resources")
+		
+		$required_parameters = array(
+			'oauth_consumer_key',
+			'oauth_token',
+			'oauth_signature_method',
+			'oauth_signature',
+			'oauth_timestamp',
+			'oauth_nonce'
+		);
+		
+		foreach( $required_parameters AS $required ) {
+			$request = OAuthRequest::from_consumer_and_token( $this->consumer, $this->access_token, 'POST', 'http://example.com');
+			$request->sign_request( $this->plaintext, $this->consumer, $this->access_token );
+			try {
+				$request->unset_parameter( $required );
+				$this->server->verify_request($request);
+				$this->fail('Allowed a request without `' . $required . '`');
+			} catch( OAuthException $e ) { /* expected */ }
+		}
+	}
+		
+	public function testRejectPastTimestamp() {
+		// We change the timestamp to be 10 hours ago, it should throw an exception
+		
+		$request = OAuthRequest::from_consumer_and_token( $this->consumer, $this->access_token, 'POST', 'http://example.com');
+		$request->set_parameter( 'oauth_timestamp', $request->get_parameter('oauth_timestamp') - 10*60*60, false);
+		$request->sign_request( $this->plaintext, $this->consumer, $this->access_token );
+		
+		$this->setExpectedException('OAuthException');
+		$this->server->verify_request($request);
+	}
+	
+	public function testRejectFutureTimestamp() {
+		// We change the timestamp to be 10 hours in the future, it should throw an exception
+		
+		$request = OAuthRequest::from_consumer_and_token( $this->consumer, $this->access_token, 'POST', 'http://example.com');
+		$request->set_parameter( 'oauth_timestamp', $request->get_parameter('oauth_timestamp') + 10*60*60, false);
+		$request->sign_request( $this->plaintext, $this->consumer, $this->access_token );
+		
+		$this->setExpectedException('OAuthException');
+		$this->server->verify_request($request);
+	}
+	
+	public function testRejectUsedNonce() {
+		// We give a known nonce and should see an exception
+	
+		$request = OAuthRequest::from_consumer_and_token( $this->consumer, $this->access_token, 'POST', 'http://example.com');
+		// The Mock datastore is set to say that the `nonce` nonce is known
+		$request->set_parameter( 'oauth_nonce', 'nonce', false);
+		$request->sign_request( $this->plaintext, $this->consumer, $this->access_token );
+
+		$this->setExpectedException('OAuthException');
+		$this->server->verify_request($request);
+	}
+	
+	public function testRejectInvalidSignature() {
+		// We change the signature post-signing to be something invalid
+	
+		$request = OAuthRequest::from_consumer_and_token( $this->consumer, $this->access_token, 'POST', 'http://example.com');
+		$request->sign_request( $this->plaintext, $this->consumer, $this->access_token );
+		$request->set_parameter( 'oauth_signature', '__whatever__', false);
+
+		$this->setExpectedException('OAuthException');
+		$this->server->verify_request($request);
+	}
+	
+	public function testRejectInvalidConsumer() {
+		// We use the consumer-key "unknown", which isn't known by the datastore. 
+		
+		$unknown_consumer = new OAuthConsumer('unknown', '__unused__');
+			
+		$request = OAuthRequest::from_consumer_and_token( $unknown_consumer, $this->access_token, 'POST', 'http://example.com');
+		$request->sign_request( $this->plaintext, $unknown_consumer, $this->access_token );
+		
+		$this->setExpectedException('OAuthException');
+		$this->server->verify_request( $request );	
+	}
+	
+	public function testRejectInvalidToken() {
+		// We use the access-token "unknown" which isn't known by the datastore
+		
+		$unknown_token = new OAuthToken('unknown', '__unused__');
+			
+		$request = OAuthRequest::from_consumer_and_token( $this->consumer, $unknown_token, 'POST', 'http://example.com');
+		$request->sign_request( $this->plaintext, $this->consumer, $unknown_token );
+		
+		$this->setExpectedException('OAuthException');
+		$this->server->verify_request( $request );	
+	}
+	
+	public function testRejectUnknownSignatureMethod() {
+		// We use a server that only supports HMAC-SHA1, but requests with PLAINTEXT signature
+		
+		$request = OAuthRequest::from_consumer_and_token( $this->consumer, $this->access_token, 'POST', 'http://example.com');
+		$request->sign_request( $this->plaintext, $this->consumer, $this->access_token );
+		
+		$server = new OAuthServer( new Mock_OAuthDataStore() );
+		$server->add_signature_method( $this->hmac_sha1 );
+		
+		$this->setExpectedException('OAuthException');
+		$server->verify_request( $request );	
+	}
+	
+	public function testRejectUnknownVersion() {
+		// We use the version "1.0a" which isn't "1.0", so reject the request
+		
+		$request = OAuthRequest::from_consumer_and_token( $this->consumer, $this->access_token, 'POST', 'http://example.com');
+		$request->sign_request( $this->plaintext, $this->consumer, $this->access_token );
+		$request->set_parameter('oauth_version', '1.0a', false);
+		
+		$this->setExpectedException('OAuthException');
+		$this->server->verify_request( $request );	
+	}
+	
+	public function testCreateRequestToken() {
+		// We request a new Request Token
+		
+		$request = OAuthRequest::from_consumer_and_token( $this->consumer, NULL, 'POST', 'http://example.com');
+		$request->sign_request( $this->plaintext, $this->consumer, NULL );
+		
+		$token = $this->server->fetch_request_token($request);
+		$this->assertEquals($this->request_token, $token);
+	}
+	
+	public function testRejectSignedRequestTokenRequest() {
+		// We request a new Request Token, but the request is signed with a token which should fail
+		
+		$request = OAuthRequest::from_consumer_and_token( $this->consumer, $this->request_token, 'POST', 'http://example.com');
+		$request->sign_request( $this->plaintext, $this->consumer, $this->request_token );
+		
+		$this->setExpectedException('OAuthException');
+		$token = $this->server->fetch_request_token($request);
+	}
+	
+	public function testCreateAccessToken() {
+		// We request a new Access Token
+		
+		$request = OAuthRequest::from_consumer_and_token( $this->consumer, $this->request_token, 'POST', 'http://example.com');
+		$request->sign_request( $this->plaintext, $this->consumer, $this->request_token );
+		
+		$token = $this->server->fetch_access_token($request);
+		$this->assertEquals($this->access_token, $token);
+	}
+	
+	public function testRejectUnsignedAccessTokenRequest() {
+		// We request a new Access Token, but we didn't sign the request with a Access Token
+		
+		$request = OAuthRequest::from_consumer_and_token( $this->consumer, NULL, 'POST', 'http://example.com');
+		$request->sign_request( $this->plaintext, $this->consumer, NULL );
+		
+		$this->setExpectedException('OAuthException');
+		$token = $this->server->fetch_access_token($request);
+	}
+	
+	public function testRejectAccessTokenSignedAccessTokenRequest() {
+		// We request a new Access Token, but the request is signed with an access token, so fail!
+		
+		$request = OAuthRequest::from_consumer_and_token( $this->consumer, $this->access_token, 'POST', 'http://example.com');
+		$request->sign_request( $this->plaintext, $this->consumer, $this->access_token );
+		
+		$this->setExpectedException('OAuthException');
+		$token = $this->server->fetch_access_token($request);
+	}
+}

+ 60 - 0
plugin/ims_lti/vendor/oauth1/tests/OAuthSignatureMethodHmacSha1Test.php

@@ -0,0 +1,60 @@
+<?php
+
+require_once 'common.php';
+require_once 'Mock_OAuthBaseStringRequest.php';
+
+class OAuthSignatureMethodHmacSha1Test extends PHPUnit_Framework_TestCase {
+	private $method;
+	
+	public function setUp() {
+		$this->method = new OAuthSignatureMethod_HMAC_SHA1();
+	}
+	
+	public function testIdentifyAsHmacSha1() {
+		$this->assertEquals('HMAC-SHA1', $this->method->get_name());
+	}
+	
+	public function testBuildSignature() {
+		// Tests taken from http://wiki.oauth.net/TestCases section 9.2 ("HMAC-SHA1")
+		$request  = new Mock_OAuthBaseStringRequest('bs');
+		$consumer = new OAuthConsumer('__unused__', 'cs');
+		$token    = NULL;
+		$this->assertEquals('egQqG5AJep5sJ7anhXju1unge2I=', $this->method->build_signature( $request, $consumer, $token) );
+		
+		$request  = new Mock_OAuthBaseStringRequest('bs');
+		$consumer = new OAuthConsumer('__unused__', 'cs');
+		$token    = new OAuthToken('__unused__', 'ts');
+		$this->assertEquals('VZVjXceV7JgPq/dOTnNmEfO0Fv8=', $this->method->build_signature( $request, $consumer, $token) );
+
+		$request  = new Mock_OAuthBaseStringRequest('GET&http%3A%2F%2Fphotos.example.net%2Fphotos&file%3Dvacation.jpg%26'
+			. 'oauth_consumer_key%3Ddpf43f3p2l4k3l03%26oauth_nonce%3Dkllo9940pd9333jh%26oauth_signature_method%3DHMAC-SHA1%26'
+			. 'oauth_timestamp%3D1191242096%26oauth_token%3Dnnch734d00sl2jdk%26oauth_version%3D1.0%26size%3Doriginal');
+		$consumer = new OAuthConsumer('__unused__', 'kd94hf93k423kf44');
+		$token    = new OAuthToken('__unused__', 'pfkkdhi9sl3r4s00');
+		$this->assertEquals('tR3+Ty81lMeYAr/Fid0kMTYa/WM=', $this->method->build_signature( $request, $consumer, $token) );
+	}
+	
+	public function testVerifySignature() {
+		// Tests taken from http://wiki.oauth.net/TestCases section 9.2 ("HMAC-SHA1")
+		$request   = new Mock_OAuthBaseStringRequest('bs');
+		$consumer  = new OAuthConsumer('__unused__', 'cs');
+		$token     = NULL;
+		$signature = 'egQqG5AJep5sJ7anhXju1unge2I=';
+		$this->assertTrue( $this->method->check_signature( $request, $consumer, $token, $signature) );
+		
+		$request   = new Mock_OAuthBaseStringRequest('bs');
+		$consumer  = new OAuthConsumer('__unused__', 'cs');
+		$token     = new OAuthToken('__unused__', 'ts');
+		$signature = 'VZVjXceV7JgPq/dOTnNmEfO0Fv8=';
+		$this->assertTrue($this->method->check_signature( $request, $consumer, $token, $signature) );
+
+		$request   = new Mock_OAuthBaseStringRequest('GET&http%3A%2F%2Fphotos.example.net%2Fphotos&file%3Dvacation.jpg%26'
+			. 'oauth_consumer_key%3Ddpf43f3p2l4k3l03%26oauth_nonce%3Dkllo9940pd9333jh%26oauth_signature_method%3DHMAC-SHA1%26'
+			. 'oauth_timestamp%3D1191242096%26oauth_token%3Dnnch734d00sl2jdk%26oauth_version%3D1.0%26size%3Doriginal');
+		$consumer  = new OAuthConsumer('__unused__', 'kd94hf93k423kf44');
+		$token     = new OAuthToken('__unused__', 'pfkkdhi9sl3r4s00');
+		$signature = 'tR3+Ty81lMeYAr/Fid0kMTYa/WM=';
+		$this->assertTrue($this->method->check_signature( $request, $consumer, $token, $signature) );
+		
+	}
+}

+ 79 - 0
plugin/ims_lti/vendor/oauth1/tests/OAuthSignatureMethodPlaintextTest.php

@@ -0,0 +1,79 @@
+<?php
+
+require_once 'common.php';
+require_once 'Mock_OAuthBaseStringRequest.php';
+
+class OAuthSignatureMethodPlaintextTest extends PHPUnit_Framework_TestCase {
+	private $method;
+	
+	public function setUp() {
+		$this->method = new OAuthSignatureMethod_PLAINTEXT();
+	}
+	
+	public function testIdentifyAsPlaintext() {
+		$this->assertEquals('PLAINTEXT', $this->method->get_name());
+	}
+	
+	public function testBuildSignature() {
+		// Tests based on from http://wiki.oauth.net/TestCases section 9.2 ("HMAC-SHA1")
+		$request  = new Mock_OAuthBaseStringRequest('__unused__');
+		$consumer = new OAuthConsumer('__unused__', 'cs');
+		$token    = NULL;
+		$this->assertEquals('cs&', $this->method->build_signature( $request, $consumer, $token) );
+		
+		$request  = new Mock_OAuthBaseStringRequest('__unused__');
+		$consumer = new OAuthConsumer('__unused__', 'cs');
+		$token    = new OAuthToken('__unused__', 'ts');
+		$this->assertEquals('cs&ts', $this->method->build_signature( $request, $consumer, $token) );
+
+		$request  = new Mock_OAuthBaseStringRequest('__unused__');
+		$consumer = new OAuthConsumer('__unused__', 'kd94hf93k423kf44');
+		$token    = new OAuthToken('__unused__', 'pfkkdhi9sl3r4s00');
+		$this->assertEquals('kd94hf93k423kf44&pfkkdhi9sl3r4s00', $this->method->build_signature( $request, $consumer, $token) );
+		
+		// Tests taken from Chapter 9.4.1 ("Generating Signature") from the spec
+		$request  = new Mock_OAuthBaseStringRequest('__unused__');
+		$consumer = new OAuthConsumer('__unused__', 'djr9rjt0jd78jf88');
+		$token    = new OAuthToken('__unused__', 'jjd999tj88uiths3');
+		$this->assertEquals('djr9rjt0jd78jf88&jjd999tj88uiths3', $this->method->build_signature( $request, $consumer, $token) );
+
+		$request  = new Mock_OAuthBaseStringRequest('__unused__');
+		$consumer = new OAuthConsumer('__unused__', 'djr9rjt0jd78jf88');
+		$token    = new OAuthToken('__unused__', 'jjd99$tj88uiths3');
+		$this->assertEquals('djr9rjt0jd78jf88&jjd99%24tj88uiths3', $this->method->build_signature( $request, $consumer, $token) );
+	}
+	
+	public function testVerifySignature() {
+		// Tests based on from http://wiki.oauth.net/TestCases section 9.2 ("HMAC-SHA1")
+		$request   = new Mock_OAuthBaseStringRequest('__unused__');
+		$consumer  = new OAuthConsumer('__unused__', 'cs');
+		$token     = NULL;
+		$signature = 'cs&';
+		$this->assertTrue( $this->method->check_signature( $request, $consumer, $token, $signature) );
+		
+		$request   = new Mock_OAuthBaseStringRequest('__unused__');
+		$consumer  = new OAuthConsumer('__unused__', 'cs');
+		$token     = new OAuthToken('__unused__', 'ts');
+		$signature = 'cs&ts';
+		$this->assertTrue($this->method->check_signature( $request, $consumer, $token, $signature) );
+
+		$request   = new Mock_OAuthBaseStringRequest('__unused__');
+		$consumer  = new OAuthConsumer('__unused__', 'kd94hf93k423kf44');
+		$token     = new OAuthToken('__unused__', 'pfkkdhi9sl3r4s00');
+		$signature = 'kd94hf93k423kf44&pfkkdhi9sl3r4s00';
+		$this->assertTrue($this->method->check_signature( $request, $consumer, $token, $signature) );
+		
+		// Tests taken from Chapter 9.4.1 ("Generating Signature") from the spec
+		$request   = new Mock_OAuthBaseStringRequest('__unused__');
+		$consumer  = new OAuthConsumer('__unused__', 'djr9rjt0jd78jf88');
+		$token     = new OAuthToken('__unused__', 'jjd999tj88uiths3');
+		$signature = 'djr9rjt0jd78jf88&jjd999tj88uiths3';
+		$this->assertTrue($this->method->check_signature( $request, $consumer, $token, $signature) );
+
+		$request   = new Mock_OAuthBaseStringRequest('__unused__');
+		$consumer  = new OAuthConsumer('__unused__', 'djr9rjt0jd78jf88');
+		$token     = new OAuthToken('__unused__', 'jjd99$tj88uiths3');
+		$signature = 'djr9rjt0jd78jf88&jjd99%24tj88uiths3';
+		$this->assertTrue($this->method->check_signature( $request, $consumer, $token, $signature) );
+	}
+}

+ 43 - 0
plugin/ims_lti/vendor/oauth1/tests/OAuthSignatureMethodRsaSha1Test.php

@@ -0,0 +1,43 @@
+<?php
+
+require_once 'common.php';
+require_once 'Mock_OAuthBaseStringRequest.php';
+require_once 'Mock_OAuthSignatureMethod_RSA_SHA1.php';
+
+class OAuthSignatureMethodRsaSha1Test extends PHPUnit_Framework_TestCase {
+	private $method;
+	
+	public function setUp() {
+		$this->method = new Mock_OAuthSignatureMethod_RSA_SHA1();
+	}
+	
+	public function testIdentifyAsRsaSha1() {
+		$this->assertEquals('RSA-SHA1', $this->method->get_name());
+	}
+	
+	public function testBuildSignature() {
+		if( ! function_exists('openssl_get_privatekey') ) {
+			$this->markTestSkipped('OpenSSL not available, can\'t test RSA-SHA1 functionality');
+		}
+		
+		// Tests taken from http://wiki.oauth.net/TestCases section 9.3 ("RSA-SHA1")
+		$request   = new Mock_OAuthBaseStringRequest('GET&http%3A%2F%2Fphotos.example.net%2Fphotos&file%3Dvacaction.jpg%26oauth_consumer_key%3Ddpf43f3p2l4k3l03%26oauth_nonce%3D13917289812797014437%26oauth_signature_method%3DRSA-SHA1%26oauth_timestamp%3D1196666512%26oauth_version%3D1.0%26size%3Doriginal');
+		$consumer  = new OAuthConsumer('dpf43f3p2l4k3l03', '__unused__');
+		$token     = NULL;
+		$signature = 'jvTp/wX1TYtByB1m+Pbyo0lnCOLIsyGCH7wke8AUs3BpnwZJtAuEJkvQL2/9n4s5wUmUl4aCI4BwpraNx4RtEXMe5qg5T1LVTGliMRpKasKsW//e+RinhejgCuzoH26dyF8iY2ZZ/5D1ilgeijhV/vBka5twt399mXwaYdCwFYE=';
+		$this->assertEquals($signature, $this->method->build_signature( $request, $consumer, $token) );
+	}
+	
+	public function testVerifySignature() {
+		if( ! function_exists('openssl_get_privatekey') ) {
+			$this->markTestSkipped('OpenSSL not available, can\'t test RSA-SHA1 functionality');
+		}
+	
+		// Tests taken from http://wiki.oauth.net/TestCases section 9.3 ("RSA-SHA1")
+		$request   = new Mock_OAuthBaseStringRequest('GET&http%3A%2F%2Fphotos.example.net%2Fphotos&file%3Dvacaction.jpg%26oauth_consumer_key%3Ddpf43f3p2l4k3l03%26oauth_nonce%3D13917289812797014437%26oauth_signature_method%3DRSA-SHA1%26oauth_timestamp%3D1196666512%26oauth_version%3D1.0%26size%3Doriginal');
+		$consumer  = new OAuthConsumer('dpf43f3p2l4k3l03', '__unused__');
+		$token     = NULL;
+		$signature = 'jvTp/wX1TYtByB1m+Pbyo0lnCOLIsyGCH7wke8AUs3BpnwZJtAuEJkvQL2/9n4s5wUmUl4aCI4BwpraNx4RtEXMe5qg5T1LVTGliMRpKasKsW//e+RinhejgCuzoH26dyF8iY2ZZ/5D1ilgeijhV/vBka5twt399mXwaYdCwFYE=';
+		$this->assertTrue($this->method->check_signature( $request, $consumer, $token, $signature) );	
+	}
+}

+ 20 - 0
plugin/ims_lti/vendor/oauth1/tests/OAuthTokenTest.php

@@ -0,0 +1,20 @@
+<?php
+
+require_once 'common.php';
+
+class OAuthTokenTest extends PHPUnit_Framework_TestCase {
+	public function testSerialize() {
+		$token = new OAuthToken('token', 'secret');
+		$this->assertEquals('oauth_token=token&oauth_token_secret=secret', $token->to_string());
+		
+		$token = new OAuthToken('token&', 'secret%');
+		$this->assertEquals('oauth_token=token%26&oauth_token_secret=secret%25', $token->to_string());
+	}
+	public function testConvertToString() {
+		$token = new OAuthToken('token', 'secret');
+		$this->assertEquals('oauth_token=token&oauth_token_secret=secret', (string) $token);
+		
+		$token = new OAuthToken('token&', 'secret%');
+		$this->assertEquals('oauth_token=token%26&oauth_token_secret=secret%25', (string) $token);
+	}
+}

+ 151 - 0
plugin/ims_lti/vendor/oauth1/tests/OAuthUtilTest.php

@@ -0,0 +1,151 @@
+<?php
+
+require_once dirname(__FILE__) . '/common.php';
+
+/**
+ * Tests of OAuthUtil
+ */
+class OAuthUtilTest extends PHPUnit_Framework_TestCase {
+	public function testUrlencode() {
+		// Tests taken from
+		// http://wiki.oauth.net/TestCases ("Parameter Encoding")
+		$this->assertEquals('abcABC123', OAuthUtil::urlencode_rfc3986('abcABC123'));
+		$this->assertEquals('-._~',      OAuthUtil::urlencode_rfc3986('-._~'));
+		$this->assertEquals('%25',       OAuthUtil::urlencode_rfc3986('%'));
+		$this->assertEquals('%2B',       OAuthUtil::urlencode_rfc3986('+'));
+		$this->assertEquals('%0A',       OAuthUtil::urlencode_rfc3986("\n"));
+		$this->assertEquals('%20',       OAuthUtil::urlencode_rfc3986(' '));
+		$this->assertEquals('%7F',       OAuthUtil::urlencode_rfc3986("\x7F"));
+		//$this->assertEquals('%C2%80',    OAuthUtil::urlencode_rfc3986("\x00\x80"));
+		//$this->assertEquals('%E3%80%81', OAuthUtil::urlencode_rfc3986("\x30\x01"));
+		
+		// Last two checks disabled because of lack of UTF-8 support, or lack
+		// of knowledge from me (morten.fangel) on how to use it properly..
+		
+		// A few tests to ensure code-coverage
+		$this->assertEquals( '', OAuthUtil::urlencode_rfc3986(NULL));
+		$this->assertEquals( '', OAuthUtil::urlencode_rfc3986(new stdClass()));
+	}
+
+	public function testUrldecode() {
+		// Tests taken from
+		// http://wiki.oauth.net/TestCases ("Parameter Encoding")
+		$this->assertEquals('abcABC123', OAuthUtil::urldecode_rfc3986('abcABC123'));
+		$this->assertEquals('-._~',      OAuthUtil::urldecode_rfc3986('-._~'));
+		$this->assertEquals('%',         OAuthUtil::urldecode_rfc3986('%25'));
+		$this->assertEquals('+',         OAuthUtil::urldecode_rfc3986('%2B'));
+		$this->assertEquals("\n",        OAuthUtil::urldecode_rfc3986('%0A'));
+		$this->assertEquals(' ',         OAuthUtil::urldecode_rfc3986('%20'));
+		$this->assertEquals("\x7F",      OAuthUtil::urldecode_rfc3986('%7F'));
+		//$this->assertEquals("\x00\x80",  OAuthUtil::urldecode_rfc3986('%C2%80'));
+		//$this->assertEquals("\x30\x01",  OAuthUtil::urldecode_rfc3986('%E3%80%81'));
+		
+		// Last two checks disabled because of lack of UTF-8 support, or lack
+		// of knowledge from me (morten.fangel) on how to use it properly..
+	}
+	
+	public function testParseParameter() {
+		// Tests taken from
+		// http://wiki.oauth.net/TestCases ("Normalize Request Parameters")
+	
+		$this->assertEquals(
+			array('name'=>''), 
+			OAuthUtil::parse_parameters('name')
+		);
+		$this->assertEquals(
+			array('a'=>'b'),
+			OAuthUtil::parse_parameters('a=b')
+		);
+		$this->assertEquals(
+			array('a'=>'b','c'=>'d'),
+			OAuthUtil::parse_parameters('a=b&c=d')
+		);
+		$this->assertEquals(
+			array('a'=>array('x!y','x y')),
+			OAuthUtil::parse_parameters('a=x!y&a=x+y')
+		);
+		$this->assertEquals(
+			array('x!y'=>'a', 'x' =>'a'),
+			OAuthUtil::parse_parameters('x!y=a&x=a')
+		);
+	}
+	
+	public function testBuildHttpQuery() {
+		// Tests taken from
+		// http://wiki.oauth.net/TestCases ("Normalize Request Parameters")
+		$this->assertEquals(
+		    'name=',
+			OAuthUtil::build_http_query(array('name'=>''))
+		);
+		$this->assertEquals(
+			'a=b',
+			OAuthUtil::build_http_query(array('a'=>'b'))
+		);
+		$this->assertEquals(
+			'a=b&c=d',
+			OAuthUtil::build_http_query(array('a'=>'b','c'=>'d'))
+		);
+		$this->assertEquals(
+			'a=x%20y&a=x%21y',
+			OAuthUtil::build_http_query(array('a'=>array('x!y','x y')))
+		);
+		$this->assertEquals(
+			'x=a&x%21y=a',
+			OAuthUtil::build_http_query(array('x!y'=>'a', 'x' =>'a'))
+		);
+		
+		// Test taken from the Spec 9.1.1
+		$this->assertEquals(
+			'a=1&c=hi%20there&f=25&f=50&f=a&z=p&z=t',
+			OAuthUtil::build_http_query(array('a'=>'1', 'c' =>'hi there', 'f'=>array(25, 50, 'a'), 'z'=>array('p','t')))
+		);
+		
+		// From issue 164, by hidetaka
+		// Based on discussion at 
+		// http://groups.google.com/group/oauth/browse_thread/thread/7c698004be0d536/dced7b6c82b917b2?lnk=gst&q=sort#
+		$this->assertEquals(
+			'x=200&x=25&y=B&y=a',
+			OAuthUtil::build_http_query(array('x'=>array(25, 200), 'y'=>array('a', 'B')))
+		);
+	}
+	
+	public function testSplitHeader() {
+		$this->assertEquals(
+			array('oauth_foo'=>'bar','oauth_baz'=>'bla,rgh'),
+			OAuthUtil::split_header('OAuth realm="",oauth_foo=bar,oauth_baz="bla,rgh"')
+		);
+		$this->assertEquals(
+			array(),
+			OAuthUtil::split_header('OAuth realm="",foo=bar,baz="bla,rgh"')
+		);
+		$this->assertEquals(
+			array('foo'=>'bar', 'baz'=>'bla,rgh'),
+			OAuthUtil::split_header('OAuth realm="",foo=bar,baz="bla,rgh"', false)
+		);
+		$this->assertEquals(
+			array('oauth_foo' => 'hi there'),
+			OAuthUtil::split_header('OAuth realm="",oauth_foo=hi+there,foo=bar,baz="bla,rgh"')
+		);
+		
+	}
+
+	public function testGetHeaders() {
+		if (function_exists('apache_request_headers')) {
+			$this->markTestSkipped('We assume the apache module is well tested. Since this module is present, no need testing our suplement');
+		}
+		
+		$_SERVER['HTTP_HOST'] = 'foo';
+		$_SERVER['HTTP_X_WHATEVER'] = 'bar';
+		$this->assertEquals( array('Host'=>'foo', 'X-Whatever'=>'bar'), OAuthUtil::get_headers() );
+		
+		// Test picking up the Content-Type of POST requests running as an Apache module but not having the ARH method
+		$_SERVER['CONTENT_TYPE'] = 'application/x-www-form-urlencoded';
+		$this->assertEquals( array('Host'=>'foo', 'X-Whatever'=>'bar', 'Content-Type'=>'application/x-www-form-urlencoded'), OAuthUtil::get_headers() );
+		
+		// Test picking up the Content-Type of POST requests when using CGI
+		unset($_SERVER['CONTENT_TYPE']);
+		$this->assertEquals( array('Host'=>'foo', 'X-Whatever'=>'bar'), OAuthUtil::get_headers() );
+		$_ENV['CONTENT_TYPE'] = 'application/x-www-form-urlencoded';
+		$this->assertEquals( array('Host'=>'foo', 'X-Whatever'=>'bar', 'Content-Type'=>'application/x-www-form-urlencoded'), OAuthUtil::get_headers() );
+	}
+}

+ 60 - 0
plugin/ims_lti/vendor/oauth1/tests/common.php

@@ -0,0 +1,60 @@
+<?php
+
+require dirname(__FILE__).'/../init.php';
+
+/**
+ * A simple utils class for methods needed
+ * during some of the tests
+ */
+class OAuthTestUtils {
+	private static function reset_request_vars() {
+		$_SERVER = array();
+		$_POST = array();
+		$_GET = array();
+	}
+
+	/**
+	 * Populates $_{SERVER,GET,POST} and whatever environment-variables needed to test everything..
+	 *
+	 * @param string $method GET or POST
+	 * @param string $uri What URI is the request to (eg http://example.com/foo?bar=baz)
+	 * @param string $post_data What should the post-data be
+	 * @param string $auth_header What to set the Authorization header to
+	 */
+	public static function build_request( $method, $uri, $post_data = '', $auth_header = '' ) {
+		self::reset_request_vars();
+
+		$method = strtoupper($method);
+
+		$parts = parse_url($uri);
+
+		$scheme = $parts['scheme'];
+		$port   = isset( $parts['port'] ) && $parts['port'] ? $parts['port'] : ( $scheme === 'https' ? '443' : '80' );
+		$host   = $parts['host'];
+		$path   = isset( $parts['path'] )  ? $parts['path']  : NULL;
+		$query  = isset( $parts['query'] ) ? $parts['query'] : NULL;
+
+		if( $scheme == 'https') {
+			$_SERVER['HTTPS'] = 'on';
+		}
+
+		$_SERVER['REQUEST_METHOD'] = $method;
+		$_SERVER['HTTP_HOST'] = $host;
+		$_SERVER['SERVER_NAME'] = $host;
+		$_SERVER['SERVER_PORT'] = $port;
+		$_SERVER['SCRIPT_NAME'] = $path;
+		$_SERVER['REQUEST_URI'] = $path . '?' . $query;
+		$_SERVER['QUERY_STRING'] = $query.'';
+		parse_str($query, $_GET);
+
+		if( $method == 'POST' ) {
+			$_SERVER['HTTP_CONTENT_TYPE'] = 'application/x-www-form-urlencoded';
+			$_POST = parse_str($post_data);
+			OAuthRequest::$POST_INPUT = 'data:application/x-www-form-urlencoded,'.$post_data;
+		}
+
+		if( $auth_header != '' ) {
+			$_SERVER['HTTP_AUTHORIZATION'] = $auth_header;
+		}
+	}
+}