You are here

OAuthDiscovery.php in Lingotek Translation 7.4

File

lib/oauth-php/library/OAuthDiscovery.php
View source
<?php

/**
 * Handle the discovery of OAuth service provider endpoints and static consumer identity.
 * 
 * @version $Id$
 * @author Marc Worrell <marcw@pobox.com>
 * @date  Sep 4, 2008 5:05:19 PM
 * 
 * The MIT License
 * 
 * Copyright (c) 2007-2008 Mediamatic Lab
 * 
 * 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.
 */
require_once dirname(__FILE__) . '/discovery/xrds_parse.php';
require_once dirname(__FILE__) . '/OAuthException2.php';
require_once dirname(__FILE__) . '/LingotekOAuthRequestLogger.php';
class OAuthDiscovery {

  /**
   * Return a description how we can do a consumer allocation.  Prefers static allocation if
   * possible.  If static allocation is possible
   *
   * See also: http://oauth.net/discovery/#consumer_identity_types
   *
   * @param string uri
   * @return array		provider description
   */
  static function discover($uri) {

    // See what kind of consumer allocations are available
    $xrds_file = self::discoverXRDS($uri);
    if (!empty($xrds_file)) {
      $xrds = xrds_parse($xrds_file);
      if (empty($xrds)) {
        throw new OAuthException2('Could not discover OAuth information for ' . $uri);
      }
    }
    else {
      throw new OAuthException2('Could not discover XRDS file at ' . $uri);
    }

    // Fill an LingotekOAuthServer record for the uri found
    $ps = parse_url($uri);
    $host = isset($ps['host']) ? $ps['host'] : 'localhost';
    $server_uri = $ps['scheme'] . '://' . $host . '/';
    $p = array(
      'user_id' => null,
      'consumer_key' => '',
      'consumer_secret' => '',
      'signature_methods' => '',
      'server_uri' => $server_uri,
      'request_token_uri' => '',
      'authorize_uri' => '',
      'access_token_uri' => '',
    );

    // Consumer identity (out of bounds or static)
    if (isset($xrds['consumer_identity'])) {

      // Try to find a static consumer allocation, we like those :)
      foreach ($xrds['consumer_identity'] as $ci) {
        if ($ci['method'] == 'static' && !empty($ci['consumer_key'])) {
          $p['consumer_key'] = $ci['consumer_key'];
          $p['consumer_secret'] = '';
        }
        else {
          if ($ci['method'] == 'oob' && !empty($ci['uri'])) {

            // TODO: Keep this uri somewhere for the user?
            $p['consumer_oob_uri'] = $ci['uri'];
          }
        }
      }
    }

    // The token uris
    if (isset($xrds['request'][0]['uri'])) {
      $p['request_token_uri'] = $xrds['request'][0]['uri'];
      if (!empty($xrds['request'][0]['signature_method'])) {
        $p['signature_methods'] = $xrds['request'][0]['signature_method'];
      }
    }
    if (isset($xrds['authorize'][0]['uri'])) {
      $p['authorize_uri'] = $xrds['authorize'][0]['uri'];
      if (!empty($xrds['authorize'][0]['signature_method'])) {
        $p['signature_methods'] = $xrds['authorize'][0]['signature_method'];
      }
    }
    if (isset($xrds['access'][0]['uri'])) {
      $p['access_token_uri'] = $xrds['access'][0]['uri'];
      if (!empty($xrds['access'][0]['signature_method'])) {
        $p['signature_methods'] = $xrds['access'][0]['signature_method'];
      }
    }
    return $p;
  }

  /**
   * Discover the XRDS file at the uri.  This is a bit primitive, you should overrule
   * this function so that the XRDS file can be cached for later referral.
   *
   * @param string uri
   * @return string		false when no XRDS file found
   */
  protected static function discoverXRDS($uri, $recur = 0) {

    // Bail out when we are following redirects
    if ($recur > 10) {
      return false;
    }
    $data = self::curl($uri);

    // Check what we got back, could be:
    // 1. The XRDS discovery file itself (check content-type)
    // 2. The X-XRDS-Location header
    if (is_string($data) && !empty($data)) {
      list($head, $body) = explode("\r\n\r\n", $data);
      $body = trim($body);
      $m = false;

      // See if we got the XRDS file itself or we have to follow a location header
      if (preg_match('/^Content-Type:\\s*application\\/xrds+xml/im', $head) || preg_match('/^<\\?xml[^>]*\\?>\\s*<xrds\\s/i', $body) || preg_match('/^<xrds\\s/i', $body)) {
        $xrds = $body;
      }
      else {
        if (preg_match('/^X-XRDS-Location:\\s*([^\\r\\n]*)/im', $head, $m) || preg_match('/^Location:\\s*([^\\r\\n]*)/im', $head, $m)) {

          // Recurse to the given location
          if ($uri != $m[1]) {
            $xrds = self::discoverXRDS($m[1], $recur + 1);
          }
          else {

            // Referring to the same uri, bail out
            $xrds = false;
          }
        }
        else {

          // Not an XRDS file an nowhere else to check
          $xrds = false;
        }
      }
    }
    else {
      $xrds = false;
    }
    return $xrds;
  }

  /**
   * Try to fetch an XRDS file at the given location.  Sends an accept header preferring the xrds file.
   *
   * @param string uri
   * @return array	(head,body), false on an error
   */
  protected static function curl($uri) {
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_HTTPHEADER, array(
      'Accept: application/xrds+xml, */*;q=0.1',
    ));
    curl_setopt($ch, CURLOPT_USERAGENT, 'anyMeta/OAuth 1.0 - (OAuth Discovery $LastChangedRevision: 45 $)');
    curl_setopt($ch, CURLOPT_URL, $uri);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HEADER, true);
    curl_setopt($ch, CURLOPT_TIMEOUT, 30);
    $txt = curl_exec($ch);
    curl_close($ch);

    // Tell the logger what we requested and what we received back
    $data = "GET {$uri}";
    LingotekOAuthRequestLogger::setSent($data, "");
    LingotekOAuthRequestLogger::setReceived($txt);
    return $txt;
  }

}

/* vi:set ts=4 sts=4 sw=4 binary noeol: */

Classes

Namesort descending Description
OAuthDiscovery