Skip to content

Commit

Permalink
adding rest of files
Browse files Browse the repository at this point in the history
  • Loading branch information
jjhoyt committed Sep 4, 2011
1 parent 1e9c323 commit e85ba87
Show file tree
Hide file tree
Showing 14 changed files with 886 additions and 0 deletions.
128 changes: 128 additions & 0 deletions Auth/EpiCurl.php
@@ -0,0 +1,128 @@
<?php
class EpiCurl
{
const timeout = 3;
static $inst = null;
static $singleton = 0;
private $mc;
private $msgs;
private $running;
private $requests = array();
private $responses = array();
private $properties = array();

function __construct()
{
if(self::$singleton == 0)
{
throw new Exception('This class cannot be instantiated by the new keyword. You must instantiate it using: $obj = EpiCurl::getInstance();');
}

$this->mc = curl_multi_init();
$this->properties = array(
'code' => CURLINFO_HTTP_CODE,
'time' => CURLINFO_TOTAL_TIME,
'length'=> CURLINFO_CONTENT_LENGTH_DOWNLOAD,
'type' => CURLINFO_CONTENT_TYPE
);
}

public function addCurl($ch)
{
$key = (string)$ch;
$this->requests[$key] = $ch;

$res = curl_multi_add_handle($this->mc, $ch);

// (1)
if($res === CURLM_OK || $res === CURLM_CALL_MULTI_PERFORM)
{
do {
$mrc = curl_multi_exec($this->mc, $active);
} while ($mrc === CURLM_CALL_MULTI_PERFORM);

return new EpiCurlManager($key);
}
else
{
return $res;
}
}

public function getResult($key = null)
{
if($key != null)
{
if(isset($this->responses[$key]))
{
return $this->responses[$key];
}

$running = null;
do
{
$resp = curl_multi_exec($this->mc, $runningCurrent);
if($running !== null && $runningCurrent != $running)
{
$this->storeResponses($key);
if(isset($this->responses[$key]))
{
return $this->responses[$key];
}
}
$running = $runningCurrent;
}while($runningCurrent > 0);
}

return false;
}

private function storeResponses()
{
while($done = curl_multi_info_read($this->mc))
{
$key = (string)$done['handle'];
$this->responses[$key]['data'] = curl_multi_getcontent($done['handle']);
foreach($this->properties as $name => $const)
{
$this->responses[$key][$name] = curl_getinfo($done['handle'], $const);
curl_multi_remove_handle($this->mc, $done['handle']);
}
}
}

static function getInstance()
{
if(self::$inst == null)
{
self::$singleton = 1;
self::$inst = new EpiCurl();
}

return self::$inst;
}
}

class EpiCurlManager
{
private $key;
private $epiCurl;

function __construct($key)
{
$this->key = $key;
$this->epiCurl = EpiCurl::getInstance();
}

function __get($name)
{
$responses = $this->epiCurl->getResult($this->key);
return $responses[$name];
}
}

/*
* Credits:
* - (1) Alistair pointed out that curl_multi_add_handle can return CURLM_CALL_MULTI_PERFORM on success.
*/
?>
258 changes: 258 additions & 0 deletions Auth/EpiOAuth.php
@@ -0,0 +1,258 @@
<?php
class EpiOAuth
{
public $version = '1.0';

protected $requestTokenUrl;
protected $accessTokenUrl;
protected $authenticateUrl;
protected $authorizeUrl;
protected $consumerKey;
protected $consumerSecret;
protected $token;
protected $tokenSecret;
protected $signatureMethod;

public function getAccessToken()
{
$resp = $this->httpRequest('GET', $this->accessTokenUrl);
return new EpiOAuthResponse($resp);
}

public function getAuthenticateUrl()
{
$token = $this->getRequestToken();
return $this->authenticateUrl . '?oauth_token=' . $token->oauth_token;
}

public function getAuthorizationUrl()
{
$token = $this->getRequestToken();
return $this->authorizeUrl . '?oauth_token=' . $token->oauth_token;
}

public function getRequestToken()
{
$resp = $this->httpRequest('GET', $this->requestTokenUrl);
return new EpiOAuthResponse($resp);
}

public function httpRequest($method = null, $url = null, $params = null)
{
if(empty($method) || empty($url))
return false;

if(empty($params['oauth_signature']))
$params = $this->prepareParameters($method, $url, $params);

switch($method)
{
case 'GET':
return $this->httpGet($url, $params);
break;
case 'POST':
return $this->httpPost($url, $params);
break;
}
}

public function setToken($token = null, $secret = null)
{
$params = func_get_args();
$this->token = $token;
$this->tokenSecret = $secret;
}

protected function encode_rfc3986($string)
{
return str_replace('+', ' ', str_replace('%7E', '~', rawurlencode(($string))));
}

protected function addOAuthHeaders(&$ch, $url, $oauthHeaders)
{
$_h = array('Expect:');
$urlParts = parse_url($url);
$oauth = 'Authorization: OAuth realm="' . $urlParts['path'] . '",';
foreach($oauthHeaders as $name => $value)
{
$oauth .= "{$name}=\"{$value}\",";
}
$_h[] = substr($oauth, 0, -1);

curl_setopt($ch, CURLOPT_HTTPHEADER, $_h);
}

protected function generateNonce()
{
if(isset($this->nonce)) // for unit testing
return $this->nonce;

return md5(uniqid(rand(), true));
}

protected function generateSignature($method = null, $url = null, $params = null)
{
if(empty($method) || empty($url))
return false;


// concatenating
$concatenatedParams = '';
foreach($params as $k => $v)
{
$v = $this->encode_rfc3986($v);
$concatenatedParams .= "{$k}={$v}&";
}
$concatenatedParams = $this->encode_rfc3986(substr($concatenatedParams, 0, -1));

// normalize url
$normalizedUrl = $this->encode_rfc3986($this->normalizeUrl($url));
$method = $this->encode_rfc3986($method); // don't need this but why not?
$signatureBaseString = "{$method}&{$normalizedUrl}&{$concatenatedParams}";
return $this->signString($signatureBaseString);
}

protected function httpGet($url, $params = null)
{
if(count($params['request']) > 0)
{
$url .= '?';
foreach($params['request'] as $k => $v)
{
$url .= "{$k}={$v}&";
}
$url = substr($url, 0, -1);
}
$ch = curl_init($url);
$this->addOAuthHeaders($ch, $url, $params['oauth']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$resp = $this->curl->addCurl($ch);

return $resp;
}

protected function httpPost($url, $params = null)
{
$ch = curl_init($url);
$this->addOAuthHeaders($ch, $url, $params['oauth']);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($params['request']));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$resp = $this->curl->addCurl($ch);
return $resp;
}

protected function normalizeUrl($url = null)
{
$urlParts = parse_url($url);
$scheme = strtolower($urlParts['scheme']);
$host = strtolower($urlParts['host']);
$port = intval($urlParts['port']);

$retval = "{$scheme}://{$host}";
if($port > 0 && ($scheme === 'http' && $port !== 80) || ($scheme === 'https' && $port !== 443))
{
$retval .= ":{$port}";
}
$retval .= $urlParts['path'];
if(!empty($urlParts['query']))
{
$retval .= "?{$urlParts['query']}";
}

return $retval;
}

protected function prepareParameters($method = null, $url = null, $params = null)
{
if(empty($method) || empty($url))
return false;

$oauth['oauth_consumer_key'] = $this->consumerKey;
$oauth['oauth_token'] = $this->token;
$oauth['oauth_nonce'] = $this->generateNonce();
$oauth['oauth_timestamp'] = !isset($this->timestamp) ? time() : $this->timestamp; // for unit test
$oauth['oauth_signature_method'] = $this->signatureMethod;
$oauth['oauth_version'] = $this->version;

// encoding
array_walk($oauth, array($this, 'encode_rfc3986'));
if(is_array($params))
array_walk($params, array($this, 'encode_rfc3986'));
$encodedParams = array_merge($oauth, (array)$params);

// sorting
ksort($encodedParams);

// signing
$oauth['oauth_signature'] = $this->encode_rfc3986($this->generateSignature($method, $url, $encodedParams));
return array('request' => $params, 'oauth' => $oauth);
}

protected function signString($string = null)
{
$retval = false;
switch($this->signatureMethod)
{
case 'HMAC-SHA1':
$key = $this->encode_rfc3986($this->consumerSecret) . '&' . $this->encode_rfc3986($this->tokenSecret);
$retval = base64_encode(hash_hmac('sha1', $string, $key, true));
break;
}

return $retval;
}

public function __construct($consumerKey, $consumerSecret, $signatureMethod='HMAC-SHA1')
{
$this->consumerKey = $consumerKey;
$this->consumerSecret = $consumerSecret;
$this->signatureMethod = $signatureMethod;
$this->curl = EpiCurl::getInstance();
}
}

class EpiOAuthResponse
{
private $__resp;

public function __construct($resp)
{
$this->__resp = $resp;
}

public function __get($name)
{
if($this->__resp->code != 200)
EpiOAuthException::raise($this->__resp->data, $this->__resp->code);

parse_str($this->__resp->data, $result);
foreach($result as $k => $v)
{
$this->$k = $v;
}

return $result[$name];
}
}

class EpiOAuthException extends Exception
{
public static function raise($message, $code)
{
switch($code)
{
case 400:
throw new EpiOAuthBadRequestException($message, $code);
case 401:
throw new EpiOAuthUnauthorizedException($message, $code);
default:
throw new EpiOAuthException($message, $code);
}
}
}


class EpiOAuthBadRequestException extends EpiOAuthException{}
class EpiOAuthUnauthorizedException extends EpiOAuthException{}

0 comments on commit e85ba87

Please sign in to comment.