347 lines
7.7 KiB
PHP
347 lines
7.7 KiB
PHP
<?php
|
|
|
|
/**
|
|
* Simple oAuth wrapper for Facebook
|
|
* Designed to stream line log in and token exchange
|
|
* By Matt Mecham (Invision Power Services, Inc)
|
|
* http://hatynka.in
|
|
* April 2010
|
|
*
|
|
* Version 0.1
|
|
*/
|
|
|
|
class FacebookOAuth
|
|
{
|
|
/**
|
|
* Facebook Application ID
|
|
* @var int
|
|
* @access protected
|
|
*/
|
|
protected $_appId;
|
|
|
|
/**
|
|
* Facebook Application Secret
|
|
* @var string
|
|
* @access protected
|
|
*/
|
|
protected $_appSecret;
|
|
|
|
/**
|
|
* Call back URL
|
|
* URL to redirect oAuth requests to after processing at Facebook
|
|
* @var string
|
|
* @access protected
|
|
*/
|
|
protected $_callBackUrl;
|
|
|
|
/**
|
|
* Permissions scope
|
|
* Array containing required permissions
|
|
* @var array
|
|
* @access protected
|
|
*/
|
|
protected $_permsScope = array();
|
|
|
|
/**
|
|
* Form Factor
|
|
* @link http://developers.facebook.com/docs/authentication/
|
|
* @var string
|
|
* @access protected
|
|
*/
|
|
protected $_formFactor = '';
|
|
|
|
/**
|
|
* Last http code (200, 403, etc)
|
|
* @var string
|
|
* @access public
|
|
*/
|
|
public $httpCode;
|
|
|
|
/**
|
|
* Last API call
|
|
* @var string
|
|
* @access public
|
|
*/
|
|
public $lastApiCall;
|
|
|
|
/**
|
|
* Timeout
|
|
* @var int
|
|
* @access public
|
|
*/
|
|
public $timeout = 30;
|
|
|
|
/**
|
|
* Connect timeout
|
|
* @var int
|
|
* @access public
|
|
*/
|
|
public $connectTimeout = 30;
|
|
|
|
/**
|
|
* SSL verify peer
|
|
* @var string
|
|
* @access public
|
|
*/
|
|
public $sslVerifyPeer = FALSE;
|
|
|
|
/**
|
|
* Constant for authorize URL
|
|
*/
|
|
const AUTHORIZE_URL = 'https://graph.facebook.com/oauth/authorize';
|
|
|
|
/**
|
|
* Constant for access token
|
|
*/
|
|
const ACCESS_TOKEN_URL = 'https://graph.facebook.com/oauth/access_token';
|
|
|
|
/**
|
|
* Constructor
|
|
*
|
|
* @access public
|
|
* @param int application id
|
|
* @param string application secret
|
|
* @param string callback URL
|
|
* @param string Form factor
|
|
* @param array Array of permissions array( 'email', 'publish_stream' ), etc
|
|
*/
|
|
public function __construct( $appId, $appSecret, $callBackUrl, $permsScope, $formFactor='page' )
|
|
{
|
|
$this->_appId = $appId;
|
|
$this->_appSecret = $appSecret;
|
|
|
|
$this->setCallBackUrl( $callBackUrl );
|
|
$this->setPermissionsScope( $permsScope );
|
|
$this->setFormFactor( $formFactor );
|
|
}
|
|
|
|
/**
|
|
* Set FormFactor
|
|
* Although we require this in the contructor, the calling class may wish
|
|
* to change it to add other parameters
|
|
*
|
|
* @access public
|
|
* @param string
|
|
*/
|
|
public function setFormFactor( $formFactor )
|
|
{
|
|
if ( $formFactor )
|
|
{
|
|
$this->_formFactor = $formFactor;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Set Call back URL
|
|
* Although we require this in the contructor, the calling class may wish
|
|
* to change it to add other parameters
|
|
*
|
|
* @access public
|
|
* @param string
|
|
*/
|
|
public function setCallBackUrl( $url )
|
|
{
|
|
if ( $url )
|
|
{
|
|
$this->_callBackUrl = $url;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Set Permissions required for auth token
|
|
* Although we require this in the contructor, the calling class may wish
|
|
* to change it to add other parameters
|
|
*
|
|
* @access public
|
|
* @param string
|
|
*/
|
|
public function setPermissionsScope( $permsScope )
|
|
{
|
|
if ( is_array( $permsScope ) )
|
|
{
|
|
$this->_permsScope = $permsScope;
|
|
}
|
|
else if ( strstr( $permsScope, ',' ) )
|
|
{
|
|
$this->_permsScope = explode( ',', str_replace( ' ', '', $permsScope ) );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get Authorize URL
|
|
* Returns a full authorize URL
|
|
*
|
|
* @access public
|
|
* @return string URL
|
|
*/
|
|
public function getAuthorizeUrl()
|
|
{
|
|
$_e = ( count( $this->_permsScope ) ) ? '&scope=' . implode( ',', $this->_permsScope ) : '';
|
|
$_f = ( $this->_formFactor ) ? '&display=' . $this->_formFactor : '';
|
|
|
|
return self::AUTHORIZE_URL . '?client_id=' . $this->_appId . '&redirect_uri=' . urlencode( $this->_callBackUrl ) . $_e . $_f;
|
|
}
|
|
|
|
/**
|
|
* Authorize
|
|
* Accepts a code, uses CURL to return a final access token
|
|
*
|
|
* @access public
|
|
* @param string Code from authorize
|
|
* @return mixed Access token or JSON error
|
|
*/
|
|
public function getAccessToken( $code )
|
|
{
|
|
$url = self::ACCESS_TOKEN_URL . '?client_id=' . $this->_appId . '&redirect_uri=' . urlencode( $this->_callBackUrl ) . '&client_secret=' . $this->_appSecret . '&code=' . rawurlencode( $code );
|
|
|
|
/* Send it and hope to receive access_token=blah */
|
|
$result = $this->_send( $url, 'GET' );
|
|
|
|
if ( preg_match( "#^access_token=(.*)$#", $result, $match ) )
|
|
{
|
|
return $match[1];
|
|
}
|
|
else
|
|
{
|
|
/* Likely to be an error in json */
|
|
return json_decode( $result );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Make an HTTP request
|
|
*
|
|
* @param protected
|
|
* @param string URL
|
|
* @param string Method (post or get)
|
|
* @param array Post data to send
|
|
* @return API results
|
|
*/
|
|
protected function _send($url, $method='POST', $postfields=NULL)
|
|
{
|
|
/* Compress post fields */
|
|
if ( is_array( $postfields ) AND count( $postfields ) )
|
|
{
|
|
$_postfields = $postfields;
|
|
$postfields = '';
|
|
|
|
foreach( $_postfields as $k => $v )
|
|
{
|
|
$postfields .= $k . '=' . $v . '&';
|
|
}
|
|
|
|
$postfields = trim( $postfields, '&' );
|
|
}
|
|
|
|
/* Attempt CURL */
|
|
if ( function_exists( 'curl_init' ) AND function_exists("curl_exec") )
|
|
{
|
|
$ci = curl_init();
|
|
/* Curl settings */
|
|
curl_setopt( $ci, CURLOPT_CONNECTTIMEOUT, $this->connectTimeout );
|
|
curl_setopt( $ci, CURLOPT_TIMEOUT, $this->timeout );
|
|
curl_setopt( $ci, CURLOPT_RETURNTRANSFER, TRUE );
|
|
curl_setopt( $ci, CURLOPT_HTTPHEADER, array('Expect:') );
|
|
curl_setopt( $ci, CURLOPT_SSL_VERIFYPEER, $this->sslVerifyPeer );
|
|
|
|
switch ($method)
|
|
{
|
|
case 'POST':
|
|
curl_setopt($ci, CURLOPT_POST, TRUE);
|
|
if ( ! empty( $postfields) )
|
|
{
|
|
curl_setopt($ci, CURLOPT_POSTFIELDS, $postfields);
|
|
}
|
|
break;
|
|
case 'DELETE':
|
|
curl_setopt($ci, CURLOPT_CUSTOMREQUEST, 'DELETE');
|
|
if ( ! empty( $postfields ) )
|
|
{
|
|
$url = "{$url}?{$postfields}";
|
|
}
|
|
break;
|
|
}
|
|
|
|
curl_setopt( $ci, CURLOPT_URL, $url );
|
|
$response = curl_exec( $ci );
|
|
$this->httpCode = curl_getinfo( $ci, CURLINFO_HTTP_CODE );
|
|
$this->lastApiCall = $url;
|
|
curl_close ($ci);
|
|
|
|
if( $response )
|
|
{
|
|
return $response;
|
|
}
|
|
}
|
|
|
|
$url_parts = @parse_url($url);
|
|
|
|
if ( ! $postfields )
|
|
{
|
|
$postfields = str_replace( '&', '&', $url_parts['query'] );
|
|
}
|
|
|
|
/* Use SSL rather than https */
|
|
$url_parts['scheme'] = ( $url_parts['scheme'] == 'https' ) ? 'ssl' : $url_parts['scheme'];
|
|
|
|
$host = $url_parts['scheme'] . '://' . $url_parts['host'];
|
|
$port = ( isset($url_parts['port']) ) ? $url_parts['port'] : ( $url_parts['scheme'] == 'https' || $url_parts['scheme'] == 'ssl' ? 443 : 80 );
|
|
|
|
if ( !empty( $url_parts["path"] ) )
|
|
{
|
|
$path = $url_parts["path"];
|
|
}
|
|
else
|
|
{
|
|
$path = "/";
|
|
}
|
|
|
|
$header = "POST {$path} HTTP/1.0\r\n";
|
|
$header .= "Host: " . str_replace( array( 'http://', 'https://', 'ssl://' ), '', $host ) . "\r\n";
|
|
$header .= "Content-Type: application/x-www-form-urlencoded\r\n";
|
|
$header .= "Content-Length: " . strlen($postfields) . "\r\n\r\n";
|
|
|
|
if ( $fp = fsockopen( $host, $port, $errno, $errstr, $this->timeout ) )
|
|
{
|
|
socket_set_timeout($fp, $this->timeout);
|
|
|
|
fwrite($fp, $header . $postfields);
|
|
|
|
while( ! feof($fp) && ! $status['timed_out'] )
|
|
{
|
|
$data .= fgets ($fp,8192);
|
|
$status = stream_get_meta_data($fp);
|
|
}
|
|
|
|
fclose($fp);
|
|
}
|
|
|
|
/* Strip headers HTTP/1.1 ### ABCD */
|
|
$this->httpCode = substr( $data, 9, 3 );
|
|
$this->lastApiCall = $url;
|
|
|
|
/* Chuncked? */
|
|
|
|
$_chunked = false;
|
|
|
|
if( preg_match( "/Transfer\-Encoding:\s*chunked/i", $data ) )
|
|
{
|
|
$_chunked = true;
|
|
}
|
|
|
|
$tmp = explode("\r\n\r\n", $data, 2);
|
|
$data = trim($tmp[1]);
|
|
|
|
if( $_chunked )
|
|
{
|
|
$lines = explode( "\n", $data );
|
|
array_pop($lines);
|
|
array_shift($lines);
|
|
$data = implode( "\n", $lines );
|
|
}
|
|
|
|
return $data;
|
|
}
|
|
|
|
|
|
} |