161 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			PHP
		
	
	
	
		
		
			
		
	
	
			161 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			PHP
		
	
	
	
|   | <?php | ||
|  | /** | ||
|  |  * Copyright 2011 Facebook, Inc. | ||
|  |  * | ||
|  |  * Licensed under the Apache License, Version 2.0 (the "License"); you may | ||
|  |  * not use this file except in compliance with the License. You may obtain | ||
|  |  * a copy of the License at | ||
|  |  * | ||
|  |  *     http://www.apache.org/licenses/LICENSE-2.0 | ||
|  |  * | ||
|  |  * Unless required by applicable law or agreed to in writing, software | ||
|  |  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||
|  |  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||
|  |  * License for the specific language governing permissions and limitations | ||
|  |  * under the License. | ||
|  |  */ | ||
|  | 
 | ||
|  | require_once "base_facebook.php"; | ||
|  | 
 | ||
|  | /** | ||
|  |  * Extends the BaseFacebook class with the intent of using | ||
|  |  * PHP sessions to store user ids and access tokens. | ||
|  |  */ | ||
|  | class Facebook extends BaseFacebook | ||
|  | { | ||
|  |   const FBSS_COOKIE_NAME = 'fbss'; | ||
|  | 
 | ||
|  |   // We can set this to a high number because the main session
 | ||
|  |   // expiration will trump this.
 | ||
|  |   const FBSS_COOKIE_EXPIRE = 31556926; // 1 year
 | ||
|  | 
 | ||
|  |   // Stores the shared session ID if one is set.
 | ||
|  |   protected $sharedSessionID; | ||
|  | 
 | ||
|  |   /** | ||
|  |    * Identical to the parent constructor, except that | ||
|  |    * we start a PHP session to store the user ID and | ||
|  |    * access token if during the course of execution | ||
|  |    * we discover them. | ||
|  |    * | ||
|  |    * @param Array $config the application configuration. Additionally | ||
|  |    * accepts "sharedSession" as a boolean to turn on a secondary | ||
|  |    * cookie for environments with a shared session (that is, your app | ||
|  |    * shares the domain with other apps). | ||
|  |    * @see BaseFacebook::__construct in facebook.php | ||
|  |    */ | ||
|  |   public function __construct($config) { | ||
|  |     if (!session_id()) { | ||
|  |       session_start(); | ||
|  |     } | ||
|  |     parent::__construct($config); | ||
|  |     if (!empty($config['sharedSession'])) { | ||
|  |       $this->initSharedSession(); | ||
|  |     } | ||
|  |   } | ||
|  | 
 | ||
|  |   protected static $kSupportedKeys = | ||
|  |     array('state', 'code', 'access_token', 'user_id'); | ||
|  | 
 | ||
|  |   protected function initSharedSession() { | ||
|  |     $cookie_name = $this->getSharedSessionCookieName(); | ||
|  |     if (isset($_COOKIE[$cookie_name])) { | ||
|  |       $data = $this->parseSignedRequest($_COOKIE[$cookie_name]); | ||
|  |       if ($data && !empty($data['domain']) && | ||
|  |           self::isAllowedDomain($this->getHttpHost(), $data['domain'])) { | ||
|  |         // good case
 | ||
|  |         $this->sharedSessionID = $data['id']; | ||
|  |         return; | ||
|  |       } | ||
|  |       // ignoring potentially unreachable data
 | ||
|  |     } | ||
|  |     // evil/corrupt/missing case
 | ||
|  |     $base_domain = $this->getBaseDomain(); | ||
|  |     $this->sharedSessionID = md5(uniqid(mt_rand(), true)); | ||
|  |     $cookie_value = $this->makeSignedRequest( | ||
|  |       array( | ||
|  |         'domain' => $base_domain, | ||
|  |         'id' => $this->sharedSessionID, | ||
|  |       ) | ||
|  |     ); | ||
|  |     $_COOKIE[$cookie_name] = $cookie_value; | ||
|  |     if (!headers_sent()) { | ||
|  |       $expire = time() + self::FBSS_COOKIE_EXPIRE; | ||
|  |       setcookie($cookie_name, $cookie_value, $expire, '/', '.'.$base_domain); | ||
|  |     } else { | ||
|  |       // @codeCoverageIgnoreStart
 | ||
|  |       self::errorLog( | ||
|  |         'Shared session ID cookie could not be set! You must ensure you '. | ||
|  |         'create the Facebook instance before headers have been sent. This '. | ||
|  |         'will cause authentication issues after the first request.' | ||
|  |       ); | ||
|  |       // @codeCoverageIgnoreEnd
 | ||
|  |     } | ||
|  |   } | ||
|  | 
 | ||
|  |   /** | ||
|  |    * Provides the implementations of the inherited abstract | ||
|  |    * methods.  The implementation uses PHP sessions to maintain | ||
|  |    * a store for authorization codes, user ids, CSRF states, and | ||
|  |    * access tokens. | ||
|  |    */ | ||
|  |   protected function setPersistentData($key, $value) { | ||
|  |     if (!in_array($key, self::$kSupportedKeys)) { | ||
|  |       self::errorLog('Unsupported key passed to setPersistentData.'); | ||
|  |       return; | ||
|  |     } | ||
|  | 
 | ||
|  |     $session_var_name = $this->constructSessionVariableName($key); | ||
|  |     $_SESSION[$session_var_name] = $value; | ||
|  |   } | ||
|  | 
 | ||
|  |   protected function getPersistentData($key, $default = false) { | ||
|  |     if (!in_array($key, self::$kSupportedKeys)) { | ||
|  |       self::errorLog('Unsupported key passed to getPersistentData.'); | ||
|  |       return $default; | ||
|  |     } | ||
|  | 
 | ||
|  |     $session_var_name = $this->constructSessionVariableName($key); | ||
|  |     return isset($_SESSION[$session_var_name]) ? | ||
|  |       $_SESSION[$session_var_name] : $default; | ||
|  |   } | ||
|  | 
 | ||
|  |   protected function clearPersistentData($key) { | ||
|  |     if (!in_array($key, self::$kSupportedKeys)) { | ||
|  |       self::errorLog('Unsupported key passed to clearPersistentData.'); | ||
|  |       return; | ||
|  |     } | ||
|  | 
 | ||
|  |     $session_var_name = $this->constructSessionVariableName($key); | ||
|  |     unset($_SESSION[$session_var_name]); | ||
|  |   } | ||
|  | 
 | ||
|  |   protected function clearAllPersistentData() { | ||
|  |     foreach (self::$kSupportedKeys as $key) { | ||
|  |       $this->clearPersistentData($key); | ||
|  |     } | ||
|  |     if ($this->sharedSessionID) { | ||
|  |       $this->deleteSharedSessionCookie(); | ||
|  |     } | ||
|  |   } | ||
|  | 
 | ||
|  |   protected function deleteSharedSessionCookie() { | ||
|  |     $cookie_name = $this->getSharedSessionCookieName(); | ||
|  |     unset($_COOKIE[$cookie_name]); | ||
|  |     $base_domain = $this->getBaseDomain(); | ||
|  |     setcookie($cookie_name, '', 1, '/', '.'.$base_domain); | ||
|  |   } | ||
|  | 
 | ||
|  |   protected function getSharedSessionCookieName() { | ||
|  |     return self::FBSS_COOKIE_NAME . '_' . $this->getAppId(); | ||
|  |   } | ||
|  | 
 | ||
|  |   protected function constructSessionVariableName($key) { | ||
|  |     $parts = array('fb', $this->getAppId(), $key); | ||
|  |     if ($this->sharedSessionID) { | ||
|  |       array_unshift($parts, $this->sharedSessionID); | ||
|  |     } | ||
|  |     return implode('_', $parts); | ||
|  |   } | ||
|  | } |