krz/vox-populi

A Tumblr web client.

clone: git clone https://gitbay.org/krz/vox-populi.git

main: vendor/eher/oauth/src/Eher/OAuth/Request.php · raw

  1<?php
  2
  3namespace Eher\OAuth;
  4
  5class Request {
  6  protected $parameters;
  7  protected $http_method;
  8  protected $http_url;
  9  // for debug purposes
 10  public $base_string;
 11  public static $version = '1.0';
 12  public static $POST_INPUT = 'php://input';
 13
 14  function __construct($http_method, $http_url, $parameters=NULL) {
 15    $parameters = ($parameters) ? $parameters : array();
 16    $parameters = array_merge( Util::parse_parameters(parse_url($http_url, PHP_URL_QUERY)), $parameters);
 17    $this->parameters = $parameters;
 18    $this->http_method = $http_method;
 19    $this->http_url = $http_url;
 20  }
 21
 22
 23  /**
 24   * attempt to build up a request from what was passed to the server
 25   */
 26  public static function from_request($http_method=NULL, $http_url=NULL, $parameters=NULL) {
 27    $scheme = (!isset($_SERVER['HTTPS']) || $_SERVER['HTTPS'] != "on")
 28              ? 'http'
 29              : 'https';
 30    $http_url = ($http_url) ? $http_url : $scheme .
 31                              '://' . $_SERVER['HTTP_HOST'] .
 32                              ':' .
 33                              $_SERVER['SERVER_PORT'] .
 34                              $_SERVER['REQUEST_URI'];
 35    $http_method = ($http_method) ? $http_method : $_SERVER['REQUEST_METHOD'];
 36
 37    // We weren't handed any parameters, so let's find the ones relevant to
 38    // this request.
 39    // If you run XML-RPC or similar you should use this to provide your own
 40    // parsed parameter-list
 41    if (!$parameters) {
 42      // Find request headers
 43      $request_headers = Util::get_headers();
 44
 45      // Parse the query-string to find GET parameters
 46      $parameters = Util::parse_parameters($_SERVER['QUERY_STRING']);
 47
 48      // It's a POST request of the proper content-type, so parse POST
 49      // parameters and add those overriding any duplicates from GET
 50      if ($http_method == "POST"
 51          &&  isset($request_headers['Content-Type'])
 52          && strstr($request_headers['Content-Type'],
 53                     'application/x-www-form-urlencoded')
 54          ) {
 55        $post_data = Util::parse_parameters(
 56          file_get_contents(self::$POST_INPUT)
 57        );
 58        $parameters = array_merge($parameters, $post_data);
 59      }
 60
 61      // We have a Authorization-header with OAuth data. Parse the header
 62      // and add those overriding any duplicates from GET or POST
 63      if (isset($request_headers['Authorization']) && substr($request_headers['Authorization'], 0, 6) == 'OAuth ') {
 64        $header_parameters = Util::split_header(
 65          $request_headers['Authorization']
 66        );
 67        $parameters = array_merge($parameters, $header_parameters);
 68      }
 69
 70    }
 71
 72    return new Request($http_method, $http_url, $parameters);
 73  }
 74
 75  /**
 76   * pretty much a helper function to set up the request
 77   */
 78  public static function from_consumer_and_token($consumer, $token, $http_method, $http_url, $parameters=NULL) {
 79    $parameters = ($parameters) ?  $parameters : array();
 80    $defaults = array("oauth_version" => Request::$version,
 81                      "oauth_nonce" => Request::generate_nonce(),
 82                      "oauth_timestamp" => Request::generate_timestamp(),
 83                      "oauth_consumer_key" => $consumer->key);
 84    if ($token)
 85      $defaults['oauth_token'] = $token->key;
 86
 87    $parameters = array_merge($defaults, $parameters);
 88
 89    return new Request($http_method, $http_url, $parameters);
 90  }
 91
 92  public function set_parameter($name, $value, $allow_duplicates = true) {
 93    if ($allow_duplicates && isset($this->parameters[$name])) {
 94      // We have already added parameter(s) with this name, so add to the list
 95      if (is_scalar($this->parameters[$name])) {
 96        // This is the first duplicate, so transform scalar (string)
 97        // into an array so we can add the duplicates
 98        $this->parameters[$name] = array($this->parameters[$name]);
 99      }
100
101      $this->parameters[$name][] = $value;
102    } else {
103      $this->parameters[$name] = $value;
104    }
105  }
106
107  public function get_parameter($name) {
108    return isset($this->parameters[$name]) ? $this->parameters[$name] : null;
109  }
110
111  public function get_parameters() {
112    return $this->parameters;
113  }
114
115  public function unset_parameter($name) {
116    unset($this->parameters[$name]);
117  }
118
119  /**
120   * The request parameters, sorted and concatenated into a normalized string.
121   * @return string
122   */
123  public function get_signable_parameters() {
124    // Grab all parameters
125    $params = $this->parameters;
126
127    // Remove oauth_signature if present
128    // Ref: Spec: 9.1.1 ("The oauth_signature parameter MUST be excluded.")
129    if (isset($params['oauth_signature'])) {
130      unset($params['oauth_signature']);
131    }
132
133    return Util::build_http_query($params);
134  }
135
136  /**
137   * Returns the base string of this request
138   *
139   * The base string defined as the method, the url
140   * and the parameters (normalized), each urlencoded
141   * and the concated with &.
142   */
143  public function get_signature_base_string() {
144    $parts = array(
145      $this->get_normalized_http_method(),
146      $this->get_normalized_http_url(),
147      $this->get_signable_parameters()
148    );
149
150    $parts = Util::urlencode_rfc3986($parts);
151
152    return implode('&', $parts);
153  }
154
155  /**
156   * just uppercases the http method
157   */
158  public function get_normalized_http_method() {
159    return strtoupper($this->http_method);
160  }
161
162  /**
163   * parses the url and rebuilds it to be
164   * scheme://host/path
165   */
166  public function get_normalized_http_url() {
167    $parts = parse_url($this->http_url);
168
169    $scheme = (isset($parts['scheme'])) ? $parts['scheme'] : 'http';
170    $port = (isset($parts['port'])) ? $parts['port'] : (($scheme == 'https') ? '443' : '80');
171    $host = (isset($parts['host'])) ? $parts['host'] : '';
172    $path = (isset($parts['path'])) ? $parts['path'] : '';
173
174    if (($scheme == 'https' && $port != '443')
175        || ($scheme == 'http' && $port != '80')) {
176      $host = "$host:$port";
177    }
178    return "$scheme://$host$path";
179  }
180
181  /**
182   * builds a url usable for a GET request
183   */
184  public function to_url() {
185    $post_data = $this->to_postdata();
186    $out = $this->get_normalized_http_url();
187    if ($post_data) {
188      $out .= '?'.$post_data;
189    }
190    return $out;
191  }
192
193  /**
194   * builds the data one would send in a POST request
195   */
196  public function to_postdata() {
197    return Util::build_http_query($this->parameters);
198  }
199
200  /**
201   * builds the Authorization: header
202   */
203  public function to_header($realm=null) {
204    $first = true;
205	if($realm) {
206      $out = 'Authorization: OAuth realm="' . Util::urlencode_rfc3986($realm) . '"';
207      $first = false;
208    } else
209      $out = 'Authorization: OAuth';
210
211    $total = array();
212    foreach ($this->parameters as $k => $v) {
213      if (substr($k, 0, 5) != "oauth") continue;
214      if (is_array($v)) {
215        throw new OAuthException('Arrays not supported in headers');
216      }
217      $out .= ($first) ? ' ' : ',';
218      $out .= Util::urlencode_rfc3986($k) .
219              '="' .
220              Util::urlencode_rfc3986($v) .
221              '"';
222      $first = false;
223    }
224    return $out;
225  }
226
227  public function __toString() {
228    return $this->to_url();
229  }
230
231
232  public function sign_request($signature_method, $consumer, $token) {
233    $this->set_parameter(
234      "oauth_signature_method",
235      $signature_method->get_name(),
236      false
237    );
238    $signature = $this->build_signature($signature_method, $consumer, $token);
239    $this->set_parameter("oauth_signature", $signature, false);
240  }
241
242  public function build_signature($signature_method, $consumer, $token) {
243    $signature = $signature_method->build_signature($this, $consumer, $token);
244    return $signature;
245  }
246
247  /**
248   * util function: current timestamp
249   */
250  private static function generate_timestamp() {
251    return time();
252  }
253
254  /**
255   * util function: current nonce
256   */
257  private static function generate_nonce() {
258    $mt = microtime();
259    $rand = mt_rand();
260
261    return md5($mt . $rand); // md5s look nicer than numbers
262  }
263}
264