From 61a7199e5dccb0534da5f9a133efc2c21d13f5cb Mon Sep 17 00:00:00 2001 From: mastacheata Date: Fri, 8 Apr 2011 04:12:54 +0200 Subject: [PATCH 1/5] Add get_token and set_token for store and loading access tokens --- application/libraries/facebook.php | 254 ++++++++++++++++------------- 1 file changed, 143 insertions(+), 111 deletions(-) diff --git a/application/libraries/facebook.php b/application/libraries/facebook.php index d24c00b..015438d 100644 --- a/application/libraries/facebook.php +++ b/application/libraries/facebook.php @@ -1,59 +1,59 @@ _obj =& get_instance(); - + $this->_obj->load->library('session'); $this->_obj->load->config('facebook'); $this->_obj->load->helper('url'); $this->_obj->load->helper('facebook'); - + $this->_api_url = $this->_obj->config->item('facebook_api_url'); $this->_api_key = $this->_obj->config->item('facebook_app_id'); $this->_api_secret = $this->_obj->config->item('facebook_api_secret'); - + $this->session = new facebookSession(); $this->connection = new facebookConnection(); } - + public function logged_in() { return $this->session->logged_in(); } - + public function login($scope = NULL) { return $this->session->login($scope); } - + public function login_url($scope = NULL) { return $this->session->login_url($scope); } - + public function logout() { return $this->session->logout(); } - + public function user() { return $this->session->get(); } - + public function call($method, $uri, $data = array()) { $response = FALSE; - + try { switch ( $method ) @@ -61,7 +61,7 @@ public function call($method, $uri, $data = array()) case 'get': $response = $this->connection->get($this->append_token($this->_api_url.$uri)); break; - + case 'post': $response = $this->connection->post($this->append_token($this->_api_url.$uri), $data); break; @@ -70,57 +70,67 @@ public function call($method, $uri, $data = array()) catch (facebookException $e) { $this->_errors[] = $e; - + if ( $this->_enable_debug ) { echo $e; } } - + return $response; } - + public function errors() { return $this->_errors; } - + public function last_error() { if ( count($this->_errors) == 0 ) return NULL; - + return $this->_errors[count($this->_errors) - 1]; } - + public function append_token($url) { return $this->session->append_token($url); } - + + public function get_token() + { + return $this->session->get_token(); + } + + public function set_token($access_token) + { + $this->session->set_token($access_token); + } + public function set_callback($url) { return $this->session->set_callback($url); } - + public function enable_debug($debug = TRUE) { $this->_enable_debug = (bool) $debug; - - + + } } - + class facebookConnection { - + // Allow multi-threading. - + private $_mch = NULL; private $_properties = array(); - + function __construct() { $this->_mch = curl_multi_init(); - + $this->_properties = array( 'code' => CURLINFO_HTTP_CODE, 'time' => CURLINFO_TOTAL_TIME, @@ -128,61 +138,61 @@ function __construct() 'type' => CURLINFO_CONTENT_TYPE ); } - + private function _initConnection($url) { $this->_ch = curl_init($url); curl_setopt($this->_ch, CURLOPT_RETURNTRANSFER, TRUE); } - + public function get($url, $params = array()) { if ( count($params) > 0 ) { $url .= '?'; - + foreach( $params as $k => $v ) { $url .= "{$k}={$v}&"; } - + $url = substr($url, 0, -1); } - + $this->_initConnection($url); $response = $this->_addCurl($url, $params); return $response; } - + public function post($url, $params = array()) { // Todo $post = ''; - + foreach ( $params as $k => $v ) { $post .= "{$k}={$v}&"; } - + $post = substr($post, 0, -1); - + $this->_initConnection($url, $params); curl_setopt($this->_ch, CURLOPT_POST, 1); curl_setopt($this->_ch, CURLOPT_POSTFIELDS, $post); - + $response = $this->_addCurl($url, $params); return $response; } - + private function _addCurl($url, $params = array()) { $ch = $this->_ch; - + $key = (string) $ch; $this->_requests[$key] = $ch; - + $response = curl_multi_add_handle($this->_mch, $ch); if ( $response === CURLM_OK || $response === CURLM_CALL_MULTI_PERFORM ) @@ -190,7 +200,7 @@ private function _addCurl($url, $params = array()) do { $mch = curl_multi_exec($this->_mch, $active); } while ( $mch === CURLM_CALL_MULTI_PERFORM ); - + return $this->_getResponse($key); } else @@ -198,71 +208,71 @@ private function _addCurl($url, $params = array()) return $response; } } - + private function _getResponse($key = NULL) { if ( $key == NULL ) return FALSE; - + if ( isset($this->_responses[$key]) ) { return $this->_responses[$key]; } - + $running = NULL; - + do { $response = curl_multi_exec($this->_mch, $running_curl); - + if ( $running !== NULL && $running_curl != $running ) { $this->_setResponse($key); - + if ( isset($this->_responses[$key]) ) { $response = new facebookResponse( (object) $this->_responses[$key] ); - + if ( $response->__resp->code !== 200 ) { $error = $response->__resp->code.' | Request Failed'; - + if ( isset($response->__resp->data->error->type) ) { $error .= ' - '.$response->__resp->data->error->type.' - '.$response->__resp->data->error->message; } - + throw new facebookException($error); } - + return $response; } } - + $running = $running_curl; - + } while ( $running_curl > 0); - + } - + private function _setResponse($key) { - while( $done = curl_multi_info_read($this->_mch) ) + while( true == ($done = curl_multi_info_read($this->_mch)) ) { $key = (string) $done['handle']; $this->_responses[$key]['data'] = curl_multi_getcontent($done['handle']); - + foreach ( $this->_properties as $curl_key => $value ) { $this->_responses[$key][$curl_key] = curl_getinfo($done['handle'], $value); - + curl_multi_remove_handle($this->_mch, $done['handle']); } } } } - + class facebookResponse { - + private $__construct; public function __construct($resp) @@ -270,7 +280,7 @@ public function __construct($resp) $this->__resp = $resp; $data = json_decode($this->__resp->data); - + if ( $data !== NULL ) { $this->__resp->data = $data; @@ -288,73 +298,73 @@ public function __get($name) parse_str($this->__resp->data, $result); $this->__resp->data = (object) $result; } - + if ( $name === '_result') { return $this->__resp->data; } - + return $this->__resp->data->$name; } } - + class facebookException extends Exception { - + function __construct($string) { parent::__construct($string); } - + public function __toString() { return "exception '".__CLASS__ ."' with message '".$this->getMessage()."' in ".$this->getFile().":".$this->getLine()."\nStack trace:\n".$this->getTraceAsString(); } } - + class facebookSession { - + private $_api_key; private $_api_secret; private $_token_url = 'oauth/access_token'; private $_user_url = 'me'; private $_data = array(); - + function __construct() { $this->_obj =& get_instance(); - + $this->_api_key = $this->_obj->config->item('facebook_app_id'); $this->_api_secret = $this->_obj->config->item('facebook_api_secret'); - + $this->_token_url = $this->_obj->config->item('facebook_api_url').$this->_token_url; $this->_user_url = $this->_obj->config->item('facebook_api_url').$this->_user_url; - + $this->_set('scope', $this->_obj->config->item('facebook_default_scope')); - + $this->connection = new facebookConnection(); - + if ( !$this->logged_in() ) { // Initializes the callback to this page URL. $this->set_callback(); } - + } - + public function logged_in() { return ( $this->get() === NULL ) ? FALSE : TRUE; } - + public function logout() { $this->_unset('token'); $this->_unset('user'); } - + public function login_url($scope = NULL) { $url = "http://www.facebook.com/dialog/oauth?client_id=".$this->_api_key.'&redirect_uri='.urlencode($this->_get('callback')); - + if ( empty($scope) ) { $scope = $this->_get('scope'); @@ -363,35 +373,35 @@ public function login_url($scope = NULL) { $this->_set('scope', $scope); } - + if ( !empty($scope) ) { $url .= '&scope='.$scope; } - + return $url; } - + public function login($scope = NULL) { $this->logout(); - + if ( !$this->_get('callback') ) $this->_set('callback', current_url()); - + $url = $this->login_url($scope); - + return redirect($url); } - + public function get() { $token = $this->_find_token(); if ( empty($token) ) return NULL; - + // $user = $this->_get('user'); // if ( !empty($user) ) return $user; - - try + + try { $user = $this->connection->get($this->_user_url.'?'.$this->_token_string()); } @@ -400,15 +410,15 @@ public function get() $this->logout(); return NULL; } - + // $this->_set('user', $user); return $user; } - + private function _find_token() { $token = $this->_get('token'); - + if ( !empty($token) ) { if ( !empty($token->expires) && intval($token->expires) >= time() ) @@ -416,20 +426,20 @@ private function _find_token() // Problem, token is expired! return $this->logout(); } - + $this->_set('token', $token); return $this->_token_string(); } - + if ( !isset($_GET['code']) ) { return $this->logout(); } - + if ( !$this->_get('callback') ) $this->_set('callback', current_url()); $token_url = $this->_token_url.'?client_id='.$this->_api_key."&client_secret=".$this->_api_secret."&code=".$_GET['code'].'&redirect_uri='.urlencode($this->_get('callback')); - - try + + try { $token = $this->connection->get($token_url); } @@ -439,58 +449,80 @@ private function _find_token() redirect($this->_strip_query()); return NULL; } - + $this->_unset('callback'); - + if ( $token->access_token ) { if ( !empty($token->expires) ) { $token->expires = strval(time() + intval($token->expires)); } - + $this->_set('token', $token); redirect($this->_strip_query()); } - + return $this->_token_string(); } - + private function _get($key) { $key = '_facebook_'.$key; return $this->_obj->session->userdata($key); } - + private function _set($key, $data) { $key = '_facebook_'.$key; $this->_obj->session->set_userdata($key, $data); } - + private function _unset($key) { $key = '_facebook_'.$key; $this->_obj->session->unset_userdata($key); } - + public function set_callback($url = NULL) { $this->_set('callback', $this->_strip_query($url)); } - + private function _token_string() { return 'access_token='.$this->_get('token')->access_token; } - + public function append_token($url) { if ( $this->_get('token') ) $url .= '?'.$this->_token_string(); - + return $url; } - + + public function get_token() + { + $token = $this->_get('token'); + + if ( !empty($token) && (empty($token->expires) || $token->expires == 0 ) ) + { + return $this->_get('token')->access_token; + } + else + { + return ''; + } + } + + public function set_token($access_token) + { + $token = new stdClass(); + $token->expires = 0; + $token->access_token = $access_token; + $this->_set('token', $token); + } + private function _strip_query($url = NULL) { if ( $url === NULL ) @@ -498,7 +530,7 @@ private function _strip_query($url = NULL) $url = ( empty($_SERVER['HTTPS']) ) ? 'http' : 'https'; $url .= '://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']; } - + $parts = explode('?', $url); return $parts[0]; } From 18e4c2d81fec57f974d472fda441fbe107f8b763 Mon Sep 17 00:00:00 2001 From: Nicholas Ruunu Date: Sun, 17 Apr 2011 18:09:04 +0200 Subject: [PATCH 2/5] Stripped down some code in favor of http_build_query --- application/libraries/facebook.php | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/application/libraries/facebook.php b/application/libraries/facebook.php index d24c00b..5114b4a 100644 --- a/application/libraries/facebook.php +++ b/application/libraries/facebook.php @@ -139,14 +139,7 @@ public function get($url, $params = array()) { if ( count($params) > 0 ) { - $url .= '?'; - - foreach( $params as $k => $v ) - { - $url .= "{$k}={$v}&"; - } - - $url = substr($url, 0, -1); + $url .= '?' . http_build_query($params); } $this->_initConnection($url); @@ -157,15 +150,7 @@ public function get($url, $params = array()) public function post($url, $params = array()) { - // Todo - $post = ''; - - foreach ( $params as $k => $v ) - { - $post .= "{$k}={$v}&"; - } - - $post = substr($post, 0, -1); + $post = http_build_query($params); $this->_initConnection($url, $params); curl_setopt($this->_ch, CURLOPT_POST, 1); From 9662ceee430473ad4a2d68f11e9b6d9222220bf8 Mon Sep 17 00:00:00 2001 From: mastacheata Date: Fri, 13 May 2011 20:54:11 +0200 Subject: [PATCH 3/5] Complete rewrite of the codeIgniter library. Native support for background storage of access tokens. Exception handling is still to be completed and an option for multicurl is planned --- application/controllers/facebook_test.php | 21 +- application/libraries/facebook.php | 522 ------------------- application/libraries/facebook_api.php | 381 ++++++++++++++ application/libraries/fb_ca_chain_bundle.crt | 0 application/views/facebook_view.php | 8 +- 5 files changed, 396 insertions(+), 536 deletions(-) delete mode 100644 application/libraries/facebook.php create mode 100644 application/libraries/facebook_api.php create mode 100644 application/libraries/fb_ca_chain_bundle.crt diff --git a/application/controllers/facebook_test.php b/application/controllers/facebook_test.php index d13efc1..f33d390 100644 --- a/application/controllers/facebook_test.php +++ b/application/controllers/facebook_test.php @@ -1,13 +1,14 @@ load->add_package_path('/Users/elliot/github/codeigniter-facebook/application/'); - $this->load->library('facebook'); - $this->facebook->enable_debug(TRUE); + $this->load->library('facebook_api'); + $this->load->helper('facebook'); + $this->facebook_api->enable_debug(TRUE); } function index() @@ -33,27 +34,27 @@ function index() function login() { // This is the easiest way to keep your code up-to-date. Use git to checkout the - // codeigniter-facebook repo to a location outside of your site directory. + // codeigniter-facebook_api repo to a location outside of your site directory. // // Add the 'application' directory from the repo as a package path: // $this->load->add_package_path('/var/www/haughin.com/codeigniter-facebook/application/'); // // Then when you want to grab a fresh copy of the code, you can just run a git pull - // on your codeigniter-facebook directory. + // on your codeigniter-facebook_api directory. - if ( !$this->facebook->logged_in() ) + if ( !$this->facebook_api->logged_in() ) { // From now on, when we call login() or login_url(), the auth // will redirect back to this url. - $this->facebook->set_callback(site_url('facebook_test')); + $this->facebook_api->set_callback(site_url('facebook_test')); // Header redirection to auth. - $this->facebook->login(); + $this->facebook_api->login(); // You can alternatively create links in your HTML using - // $this->facebook->login_url(); as the href parameter. + // $this->facebook_api->login_url(); as the href parameter. } else { @@ -63,7 +64,7 @@ function login() function logout() { - $this->facebook->logout(); + $this->facebook_api->logout(); redirect('facebook_test'); } } \ No newline at end of file diff --git a/application/libraries/facebook.php b/application/libraries/facebook.php deleted file mode 100644 index a330252..0000000 --- a/application/libraries/facebook.php +++ /dev/null @@ -1,522 +0,0 @@ -_obj =& get_instance(); - - $this->_obj->load->library('session'); - $this->_obj->load->config('facebook'); - $this->_obj->load->helper('url'); - $this->_obj->load->helper('facebook'); - - $this->_api_url = $this->_obj->config->item('facebook_api_url'); - $this->_api_key = $this->_obj->config->item('facebook_app_id'); - $this->_api_secret = $this->_obj->config->item('facebook_api_secret'); - - $this->session = new facebookSession(); - $this->connection = new facebookConnection(); - } - - public function logged_in() - { - return $this->session->logged_in(); - } - - public function login($scope = NULL) - { - return $this->session->login($scope); - } - - public function login_url($scope = NULL) - { - return $this->session->login_url($scope); - } - - public function logout() - { - return $this->session->logout(); - } - - public function user() - { - return $this->session->get(); - } - - public function call($method, $uri, $data = array()) - { - $response = FALSE; - - try - { - switch ( $method ) - { - case 'get': - $response = $this->connection->get($this->append_token($this->_api_url.$uri)); - break; - - case 'post': - $response = $this->connection->post($this->append_token($this->_api_url.$uri), $data); - break; - } - } - catch (facebookException $e) - { - $this->_errors[] = $e; - - if ( $this->_enable_debug ) - { - echo $e; - } - } - - return $response; - } - - public function errors() - { - return $this->_errors; - } - - public function last_error() - { - if ( count($this->_errors) == 0 ) return NULL; - - return $this->_errors[count($this->_errors) - 1]; - } - - public function append_token($url) - { - return $this->session->append_token($url); - } - - public function get_token() - { - return $this->session->get_token(); - } - - public function set_token($access_token) - { - $this->session->set_token($access_token); - } - - public function set_callback($url) - { - return $this->session->set_callback($url); - } - - public function enable_debug($debug = TRUE) - { - $this->_enable_debug = (bool) $debug; - - - } - } - - class facebookConnection { - - // Allow multi-threading. - - private $_mch = NULL; - private $_properties = array(); - - function __construct() - { - $this->_mch = curl_multi_init(); - - $this->_properties = array( - 'code' => CURLINFO_HTTP_CODE, - 'time' => CURLINFO_TOTAL_TIME, - 'length' => CURLINFO_CONTENT_LENGTH_DOWNLOAD, - 'type' => CURLINFO_CONTENT_TYPE - ); - } - - private function _initConnection($url) - { - $this->_ch = curl_init($url); - curl_setopt($this->_ch, CURLOPT_RETURNTRANSFER, TRUE); - } - - public function get($url, $params = array()) - { - if ( count($params) > 0 ) - { - $url .= '?' . http_build_query($params); - } - - $this->_initConnection($url); - $response = $this->_addCurl($url, $params); - - return $response; - } - - public function post($url, $params = array()) - { - $post = http_build_query($params); - - $this->_initConnection($url, $params); - curl_setopt($this->_ch, CURLOPT_POST, 1); - curl_setopt($this->_ch, CURLOPT_POSTFIELDS, $post); - - $response = $this->_addCurl($url, $params); - - return $response; - } - - private function _addCurl($url, $params = array()) - { - $ch = $this->_ch; - - $key = (string) $ch; - $this->_requests[$key] = $ch; - - $response = curl_multi_add_handle($this->_mch, $ch); - - if ( $response === CURLM_OK || $response === CURLM_CALL_MULTI_PERFORM ) - { - do { - $mch = curl_multi_exec($this->_mch, $active); - } while ( $mch === CURLM_CALL_MULTI_PERFORM ); - - return $this->_getResponse($key); - } - else - { - return $response; - } - } - - private function _getResponse($key = NULL) - { - if ( $key == NULL ) return FALSE; - - if ( isset($this->_responses[$key]) ) - { - return $this->_responses[$key]; - } - - $running = NULL; - - do - { - $response = curl_multi_exec($this->_mch, $running_curl); - - if ( $running !== NULL && $running_curl != $running ) - { - $this->_setResponse($key); - - if ( isset($this->_responses[$key]) ) - { - $response = new facebookResponse( (object) $this->_responses[$key] ); - - if ( $response->__resp->code !== 200 ) - { - $error = $response->__resp->code.' | Request Failed'; - - if ( isset($response->__resp->data->error->type) ) - { - $error .= ' - '.$response->__resp->data->error->type.' - '.$response->__resp->data->error->message; - } - - throw new facebookException($error); - } - - return $response; - } - } - - $running = $running_curl; - - } while ( $running_curl > 0); - - } - - private function _setResponse($key) - { - while( true == ($done = curl_multi_info_read($this->_mch)) ) - { - $key = (string) $done['handle']; - $this->_responses[$key]['data'] = curl_multi_getcontent($done['handle']); - - foreach ( $this->_properties as $curl_key => $value ) - { - $this->_responses[$key][$curl_key] = curl_getinfo($done['handle'], $value); - - curl_multi_remove_handle($this->_mch, $done['handle']); - } - } - } - } - - class facebookResponse { - - private $__construct; - - public function __construct($resp) - { - $this->__resp = $resp; - - $data = json_decode($this->__resp->data); - - if ( $data !== NULL ) - { - $this->__resp->data = $data; - } - } - - public function __get($name) - { - if ($this->__resp->code < 200 || $this->__resp->code > 299) return FALSE; - - $result = array(); - - if ( is_string($this->__resp->data ) ) - { - parse_str($this->__resp->data, $result); - $this->__resp->data = (object) $result; - } - - if ( $name === '_result') - { - return $this->__resp->data; - } - - return $this->__resp->data->$name; - } - } - - class facebookException extends Exception { - - function __construct($string) - { - parent::__construct($string); - } - - public function __toString() { - return "exception '".__CLASS__ ."' with message '".$this->getMessage()."' in ".$this->getFile().":".$this->getLine()."\nStack trace:\n".$this->getTraceAsString(); - } - } - - class facebookSession { - - private $_api_key; - private $_api_secret; - private $_token_url = 'oauth/access_token'; - private $_user_url = 'me'; - private $_data = array(); - - function __construct() - { - $this->_obj =& get_instance(); - - $this->_api_key = $this->_obj->config->item('facebook_app_id'); - $this->_api_secret = $this->_obj->config->item('facebook_api_secret'); - - $this->_token_url = $this->_obj->config->item('facebook_api_url').$this->_token_url; - $this->_user_url = $this->_obj->config->item('facebook_api_url').$this->_user_url; - - $this->_set('scope', $this->_obj->config->item('facebook_default_scope')); - - $this->connection = new facebookConnection(); - - if ( !$this->logged_in() ) - { - // Initializes the callback to this page URL. - $this->set_callback(); - } - - } - - public function logged_in() - { - return ( $this->get() === NULL ) ? FALSE : TRUE; - } - - public function logout() - { - $this->_unset('token'); - $this->_unset('user'); - } - - public function login_url($scope = NULL) - { - $url = "http://www.facebook.com/dialog/oauth?client_id=".$this->_api_key.'&redirect_uri='.urlencode($this->_get('callback')); - - if ( empty($scope) ) - { - $scope = $this->_get('scope'); - } - else - { - $this->_set('scope', $scope); - } - - if ( !empty($scope) ) - { - $url .= '&scope='.$scope; - } - - return $url; - } - - public function login($scope = NULL) - { - $this->logout(); - - if ( !$this->_get('callback') ) $this->_set('callback', current_url()); - - $url = $this->login_url($scope); - - return redirect($url); - } - - public function get() - { - $token = $this->_find_token(); - if ( empty($token) ) return NULL; - - // $user = $this->_get('user'); - // if ( !empty($user) ) return $user; - - try - { - $user = $this->connection->get($this->_user_url.'?'.$this->_token_string()); - } - catch ( facebookException $e ) - { - $this->logout(); - return NULL; - } - - // $this->_set('user', $user); - return $user; - } - - private function _find_token() - { - $token = $this->_get('token'); - - if ( !empty($token) ) - { - if ( !empty($token->expires) && intval($token->expires) >= time() ) - { - // Problem, token is expired! - return $this->logout(); - } - - $this->_set('token', $token); - return $this->_token_string(); - } - - if ( !isset($_GET['code']) ) - { - return $this->logout(); - } - - if ( !$this->_get('callback') ) $this->_set('callback', current_url()); - $token_url = $this->_token_url.'?client_id='.$this->_api_key."&client_secret=".$this->_api_secret."&code=".$_GET['code'].'&redirect_uri='.urlencode($this->_get('callback')); - - try - { - $token = $this->connection->get($token_url); - } - catch ( facebookException $e ) - { - $this->logout(); - redirect($this->_strip_query()); - return NULL; - } - - $this->_unset('callback'); - - if ( $token->access_token ) - { - if ( !empty($token->expires) ) - { - $token->expires = strval(time() + intval($token->expires)); - } - - $this->_set('token', $token); - redirect($this->_strip_query()); - } - - return $this->_token_string(); - } - - private function _get($key) - { - $key = '_facebook_'.$key; - return $this->_obj->session->userdata($key); - } - - private function _set($key, $data) - { - $key = '_facebook_'.$key; - $this->_obj->session->set_userdata($key, $data); - } - - private function _unset($key) - { - $key = '_facebook_'.$key; - $this->_obj->session->unset_userdata($key); - } - - public function set_callback($url = NULL) - { - $this->_set('callback', $this->_strip_query($url)); - } - - private function _token_string() - { - return 'access_token='.$this->_get('token')->access_token; - } - - public function append_token($url) - { - if ( $this->_get('token') ) $url .= '?'.$this->_token_string(); - - return $url; - } - - public function get_token() - { - $token = $this->_get('token'); - - if ( !empty($token) && (empty($token->expires) || $token->expires == 0 ) ) - { - return $this->_get('token')->access_token; - } - else - { - return ''; - } - } - - public function set_token($access_token) - { - $token = new stdClass(); - $token->expires = 0; - $token->access_token = $access_token; - $this->_set('token', $token); - } - - private function _strip_query($url = NULL) - { - if ( $url === NULL ) - { - $url = ( empty($_SERVER['HTTPS']) ) ? 'http' : 'https'; - $url .= '://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']; - } - - $parts = explode('?', $url); - return $parts[0]; - } - } \ No newline at end of file diff --git a/application/libraries/facebook_api.php b/application/libraries/facebook_api.php new file mode 100644 index 0000000..1717c41 --- /dev/null +++ b/application/libraries/facebook_api.php @@ -0,0 +1,381 @@ + + * @copyright Copyright (c) 2011, Benedikt Bauer + * @license http://dev.sam-song.info/license do what the fuck you want to public license v2 + */ +class Facebook_api +{ + /** + * Internal storage of the access_token + * @var string + */ + private $_token; + + /** + * Internal storage of token expiry + * @var integer + */ + private $_expires = 0; + + /** + * cURL handle + * @var resource + */ + private $_ch = NULL; + + /** + * Callback URL + * @var string + */ + private $_callback; + + /** + * Application ID + * @var string + */ + private $_appId; + + /** + * Application Key + * @var string + */ + private $_appKey; + + /** + * Application Secret + * @var string + */ + private $_appSecret; + + /** + * API Base URL + * @var string + */ + private $_apiURL; + + /** + * Instance of the CodeIgniter Main Class + * @var CodeIgniter + */ + private $_CI = NULL; + + + /** + * Load common config options into variables + * Load session library and URL helper + */ + public function __construct() + { + $this->_CI =& get_instance(); + $this->_CI->load->library('session'); + $this->_CI->load->config('facebook'); + $this->_CI->load->helper('url'); + + $this->_appId = $this->_CI->config->item('facebook_app_id'); + $this->_appKey = $this->_CI->config->item('facebook_app_key'); + $this->_appSecret = $this->_CI->config->item('facebook_app_secret'); + $this->_apiURL = $this->_CI->config->item('facebook_api_url'); + + $this->_token = $this->_CI->session->userdata('fb_token'); + } + + /** + * Initialize cURL with some default options + */ + private function _initCurl() + { + $this->_ch = curl_init(); + $config = array + ( + CURLOPT_CONNECTTIMEOUT => 10, + CURLOPT_RETURNTRANSFER => true, + CURLOPT_TIMEOUT => 60, + CURLOPT_USERAGENT => 'facebook-php-2.0', + CURLOPT_HTTPHEADER => 'Expect:', + ); + curl_setopt_array($this->_ch, $config); + } + + /** + * Get access token from supplied code + * @param string $code + * @return bool + */ + private function _authorize($code) + { + // set parameters for oauth2.0 request + $options = array + ( + 'client_id' => $this->_appId, + 'client_secret' => $this->_appSecret, + 'code' => $code, + 'redirect_uri' => $this->_callback, + ); + + try + { + $token_reply = $this->call('get', 'oauth/access_token', $options); + } + catch (FacebookException $e) + { + //TODO: Exception handling + } + + $token_array = array(); + parse_str($token_reply, $token_array); + + if (array_key_exists('access_token', $token_array)) + { + $this->_token = $token_array['access_token']; + } + else + { + //TODO: Exception handling + } + + $this->_CI->load->helper('array'); + $this->_expires = element('expires', $token_array, 0); + + // set session storage to newly acquired token + $this->_CI->session->set_userdata(array('fb_token' => $this->_token, 'fb_token_expires' => $this->_expires)); + + redirect($this->_callback); + } + + private function _base64UrlDecode($input) + { + return base64_decode(strtr($input, '-_', '+/')); + } + + /** + * If $_GET['code'] is set, get an access token + * ElseIf $_GET['error'] is set, return false + * Else redirect to login URL + * @return bool + */ + public function login() + { + redirect($this->get_loginURL()); + } + + /** + * Unset session data and local token variable + */ + public function logout() + { + $this->_token = ''; + $this->_CI->session->unset_userdata('fb_token'); + $this->_CI->session->unset_userdata('fb_token_expires'); + } + + /** + * Check if token is set + * @return bool + */ + public function logged_in() + { + if (($code = $this->_CI->input->get('code')) !== false) + { + $this->_authorize($code); + } + elseif (($error = $this->_CI->input->get('error')) !== false) + { + throw new FacebookException($this->_CI->input->get('error').$this->_CI->input->get('error_description'), 401); + } + + // get token from cookie + $cookie_token = $this->_CI->session->userdata('fb_token'); + // check if token is empty (both local and cookie) + $empty_token = empty($this->_token) && empty($cookie_token); + // get expiry from cookie + $cookie_expiry = $this->_CI->session->userdata('fb_token_expires'); + // check if token expires at all + $token_expires = $this->_expires > 0 || $cookie_expiry > 0; + + // Token empty, login required + if ($empty_token) + { + return false; + } + elseif ($token_expires) + { + // check if token is still valid + $token_valid = ($this->_expires > time()) || ($cookie_expiry && ($cookie_expiry > time())); + + // return token_valid state + return $token_valid; + } + else + { + // token exists and never expires + return true; + } + } + + /** + * Retrieve Access Token for external storage + * @return string + */ + public function get_token() + { + return $this->_token; + } + + /** + * Set Access Token from external source + * @param string $token + */ + public function set_token($token) + { + $this->_token = $token; + } + + /** + * Issue API call via GET/POST (request_method) + * + * @param string $request_method + * @param string $uri + * @param array $params + * @return mixed + */ + public function call($request_method, $uri, array $params = NULL) + { + $this->_initCurl(); + // Set the Query URL to the requested option + $apiURL = $this->_apiURL.$uri.'?access_token='.$this->_token; + // build a querystring from the parameters array + $paramString = $params === NULL ? '' : http_build_query($params); + + if ($request_method === 'post') + { + curl_setopt($this->_ch, CURLOPT_POST, TRUE); + curl_setopt($this->_ch, CURLOPT_POSTFIELDS, $paramString); + } + else + { + $apiURL .= '&'.$paramString; + } + + + curl_setopt($this->_ch, CURLOPT_URL, $apiURL); + $response = curl_exec($this->_ch); + + // Error validating Certificate Chain, use bundled CA info + if (curl_errno($this->_ch) == CURLE_SSL_CACERT) + { + curl_setopt($this->_ch, CURLOPT_CAINFO, dirname(__FILE__).'/fb_ca_chain_bundle.crt'); + $response = curl_exec($this->_ch); + } + + // cURL Error + if ($response === false) + { + $e = new FacebookException(curl_error($this->_ch, curl_errno($this->_ch))); + curl_close($this->_ch); + + throw $e; + } + + curl_close($this->_ch); + + if (($decoded_response = json_decode($response)) == NULL) + { + return $response; + } + else + { + return $decoded_response; + } + } + + /** + * Retrieve URL to Login dialog + * @return string + */ + public function get_loginURL() + { + return 'https://www.facebook.com/dialog/oauth?client_id='.$this->_appId + .'&redirect_uri='.urlencode($this->_callback) + .'&scope='.$this->_CI->config->item('facebook_default_scope'); + } + + /** + * Set Callback URL + * @param string $url + */ + public function set_callback($url) + { + $this->_callback = $url; + } + + /** + * Log in as the application + */ + public function app_login() + { + $options = array + ( + 'client_id' => $this->_appId, + 'client_secret' => $this->_appSecret, + 'grant_type' => 'client_credentials', + ); + + try + { + $token_response = $this->call('get', 'oauth/access_token', $options); + } + catch(FacebookException $e) + { + //TODO: Exception Handling + } + + // For app login only set local variables, so user experience is not permanently changed + $this->_token = $token_response['access_token']; + $this->_expires = 0; + } + + public function parse_signedRequest($signedRequest) + { + list($encoded_sig, $payload) = explode('.', $signedRequest, 2); + // decode the data + $sig = $this->base64UrlDecode($encoded_sig); + $data = json_decode($this->base64UrlDecode($payload), true); + + if (strtoupper($data['algorithm']) !== 'HMAC-SHA256') + { + log_message('error', 'Unknown algorithm. Expected HMAC-SHA256'); + log_message('debug', 'Bad signature algorithm: '.$data['algorithm']); + return null; + } + + // check sig + $expected_sig = hash_hmac('sha256', $payload, $this->_appSecret, $raw = true); + if ($sig !== $expected_sig) + { + log_message('debug', 'Bad Signed JSON signature!'); + return null; + } + return $data; + } +} + + +/** + * + * Enter description here ... + * @author Benedikt Bauer + * + */ +class FacebookException extends Exception +{ + //TODO - Insert your code here +} + +/* End of File: facebook_api2.php */ +/* Location: ./application/libraries/facebook_api2.php */ \ No newline at end of file diff --git a/application/libraries/fb_ca_chain_bundle.crt b/application/libraries/fb_ca_chain_bundle.crt new file mode 100644 index 0000000..e69de29 diff --git a/application/views/facebook_view.php b/application/views/facebook_view.php index 42845ce..5453a8d 100644 --- a/application/views/facebook_view.php +++ b/application/views/facebook_view.php @@ -50,15 +50,15 @@