Guest User

Untitled

a guest
Dec 18th, 2011
96
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 30.60 KB | None | 0 0
  1. <?php
  2.  
  3.  
  4. define('FACEBOOK_APP_ID', '136205146437527');
  5. define('FACEBOOK_SECRET', '**************');
  6.  
  7. // Create our Application instance (replace this with your appId and secret).
  8. $facebook = new Facebook(array(
  9. 'appId' => '136205146437527',
  10. 'secret' => '**************',
  11. 'cookie' => true,
  12. ));
  13.  
  14. // We may or may not have this data based on a $_GET or $_COOKIE based session.
  15. //
  16. // If we get a session here, it means we found a correctly signed session using
  17. // the Application Secret only Facebook and the Application know. We dont know
  18. // if it is still valid until we make an API call using the session. A session
  19. // can become invalid if it has already expired (should not be getting the
  20. // session back in this case) or if the user logged out of Facebook.
  21.  
  22. if(isset($_SESSION['fbc']) && !isset($_COOKIE['fbs_136205146437527'])){
  23. $_COOKIE['fbs_136205146437527'] = $_SESSION['fbc'];
  24. // mail("m@sr.dk", "lostcookie", "im lost");
  25. }
  26. $session = $facebook->getSession();
  27.  
  28. $me = null;
  29. // Session based API call.
  30. if ($session) {
  31. try {
  32. $uid = $facebook->getUser();
  33. $me = $facebook->api('/me');
  34. if(!isset($_SESSION['fb']['me'])) {
  35. $_SESSION['fb']['friends'] = $facebook->api('/me/friends');
  36.  
  37.  
  38. $_SESSION['fb']['me'] = $me;
  39. $_SESSION['fb']['session'] = $session;
  40. $_SESSION['fb']['logout'] = $facebook->getLogoutUrl();
  41.  
  42. do_facebooklogin($_SESSION['fb']);
  43. }
  44.  
  45. if($_COOKIE['fbs_136205146437527'] != $_SESSION['fbc']){
  46.  
  47. $_SESSION['fbc'] = $_COOKIE['fbs_136205146437527'];
  48. }
  49. } catch (FacebookApiException $e) {
  50. error_log($e);
  51. }
  52. }
  53.  
  54. // login or logout url will be needed depending on current user state.
  55. if ($me) {
  56. $logoutUrl = $facebook->getLogoutUrl();
  57. } else {
  58. $loginUrl = $facebook->getLoginUrl();
  59. }
  60.  
  61.  
  62. // FACEBOOK DONE
  63.  
  64. function get_facebook_cookie($app_id, $application_secret) {
  65. $args = array();
  66. parse_str(@trim($_COOKIE['fbs_' . $app_id], '\\"'), $args);
  67. ksort($args);
  68. $payload = '';
  69. foreach ($args as $key => $value) {
  70. if ($key != 'sig') {
  71. $payload .= $key . '=' . $value;
  72. }
  73. }
  74. if (isset($args['sig']) && md5($payload . $application_secret) != $args['sig']) {
  75. return null;
  76. }
  77. return $args;
  78. }
  79.  
  80. $cookie = get_facebook_cookie(FACEBOOK_APP_ID, FACEBOOK_SECRET);
  81.  
  82.  
  83. function fb_writeappwall($msg) {
  84. $args = array('grant_type' => 'client_credentials',
  85. 'client_id' => '136205146437527',
  86. 'client_secret' => '************');
  87. $ch = curl_init();
  88. $url = 'https://graph.facebook.com/oauth/access_token';
  89. curl_setopt($ch, CURLOPT_URL, $url);
  90. curl_setopt($ch, CURLOPT_HEADER, false);
  91. curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  92. curl_setopt($ch, CURLOPT_POST, true);
  93. curl_setopt($ch, CURLOPT_POSTFIELDS, $args);
  94. $returnValue = curl_exec($ch);
  95. curl_close($ch);
  96.  
  97. $returnValue = explode("access_token=", $returnValue);
  98. $parms['access_token'] = $returnValue[1];
  99. $parms['message'] = $msg ;
  100. $parms['privacy'] = '{"value": "ALL_FRIENDS"}';
  101.  
  102. $params = '?' . http_build_query($parms, null, '&');
  103. $curl = curl_init();
  104.  
  105. curl_setopt($curl, CURLOPT_POST, true);
  106. curl_setopt($curl, CURLOPT_POSTFIELDS, $params);
  107. curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
  108. curl_setopt($curl, CURLOPT_URL, "https://graph.facebook.com/136205146437527/feed". $params);
  109. $data = curl_exec($curl);
  110.  
  111. adminlog("FB LIKE ". $msg ." - ADMIN - ". $data,"fblike");
  112.  
  113. curl_close($curl);
  114. }
  115.  
  116.  
  117.  
  118.  
  119. if (!function_exists('curl_init')) {
  120. throw new Exception('Facebook needs the CURL PHP extension.');
  121. }
  122. if (!function_exists('json_decode')) {
  123. throw new Exception('Facebook needs the JSON PHP extension.');
  124. }
  125.  
  126. /**
  127. * Thrown when an API call returns an exception.
  128. *
  129. * @author Naitik Shah <naitik@facebook.com>
  130. */
  131. class FacebookApiException extends Exception
  132. {
  133. /**
  134. * The result from the API server that represents the exception information.
  135. */
  136. protected $result;
  137.  
  138. /**
  139. * Make a new API Exception with the given result.
  140. *
  141. * @param Array $result the result from the API server
  142. */
  143. public function __construct($result) {
  144. $this->result = $result;
  145.  
  146. $code = isset($result['error_code']) ? $result['error_code'] : 0;
  147.  
  148. if (isset($result['error_description'])) {
  149. // OAuth 2.0 Draft 10 style
  150. $msg = $result['error_description'];
  151. } else if (isset($result['error']) && is_array($result['error'])) {
  152. // OAuth 2.0 Draft 00 style
  153. $msg = $result['error']['message'];
  154. } else if (isset($result['error_msg'])) {
  155. // Rest server style
  156. $msg = $result['error_msg'];
  157. } else {
  158. $msg = 'Unknown Error. Check getResult()';
  159. }
  160.  
  161. parent::__construct($msg, $code);
  162. }
  163.  
  164. /**
  165. * Return the associated result object returned by the API server.
  166. *
  167. * @returns Array the result from the API server
  168. */
  169. public function getResult() {
  170. return $this->result;
  171. }
  172.  
  173. /**
  174. * Returns the associated type for the error. This will default to
  175. * 'Exception' when a type is not available.
  176. *
  177. * @return String
  178. */
  179. public function getType() {
  180. if (isset($this->result['error'])) {
  181. $error = $this->result['error'];
  182. if (is_string($error)) {
  183. // OAuth 2.0 Draft 10 style
  184. return $error;
  185. } else if (is_array($error)) {
  186. // OAuth 2.0 Draft 00 style
  187. if (isset($error['type'])) {
  188. return $error['type'];
  189. }
  190. }
  191. }
  192. return 'Exception';
  193. }
  194.  
  195. /**
  196. * To make debugging easier.
  197. *
  198. * @returns String the string representation of the error
  199. */
  200. public function __toString() {
  201. $str = $this->getType() . ': ';
  202. if ($this->code != 0) {
  203. $str .= $this->code . ': ';
  204. }
  205. return $str . $this->message;
  206. }
  207. }
  208.  
  209. /**
  210. * Provides access to the Facebook Platform.
  211. *
  212. * @author Naitik Shah <naitik@facebook.com>
  213. */
  214. class Facebook
  215. {
  216. /**
  217. * Version.
  218. */
  219. const VERSION = '2.1.2';
  220.  
  221. /**
  222. * Default options for curl.
  223. */
  224. public static $CURL_OPTS = array(
  225. CURLOPT_CONNECTTIMEOUT => 10,
  226. CURLOPT_RETURNTRANSFER => true,
  227. CURLOPT_TIMEOUT => 60,
  228. CURLOPT_USERAGENT => 'facebook-php-2.0',
  229. );
  230.  
  231. /**
  232. * List of query parameters that get automatically dropped when rebuilding
  233. * the current URL.
  234. */
  235. protected static $DROP_QUERY_PARAMS = array(
  236. 'session',
  237. 'signed_request',
  238. );
  239.  
  240. /**
  241. * Maps aliases to Facebook domains.
  242. */
  243. public static $DOMAIN_MAP = array(
  244. 'api' => 'https://api.facebook.com/',
  245. 'api_read' => 'https://api-read.facebook.com/',
  246. 'graph' => 'https://graph.facebook.com/',
  247. 'www' => 'https://www.facebook.com/',
  248. );
  249.  
  250. /**
  251. * The Application ID.
  252. */
  253. protected $appId;
  254.  
  255. /**
  256. * The Application API Secret.
  257. */
  258. protected $apiSecret;
  259.  
  260. /**
  261. * The active user session, if one is available.
  262. */
  263. protected $session;
  264.  
  265. /**
  266. * The data from the signed_request token.
  267. */
  268. protected $signedRequest;
  269.  
  270. /**
  271. * Indicates that we already loaded the session as best as we could.
  272. */
  273. protected $sessionLoaded = false;
  274.  
  275. /**
  276. * Indicates if Cookie support should be enabled.
  277. */
  278. protected $cookieSupport = true;
  279.  
  280. /**
  281. * Base domain for the Cookie.
  282. */
  283. protected $baseDomain = '';
  284.  
  285. /**
  286. * Indicates if the CURL based @ syntax for file uploads is enabled.
  287. */
  288. protected $fileUploadSupport = false;
  289.  
  290. /**
  291. * Initialize a Facebook Application.
  292. *
  293. * The configuration:
  294. * - appId: the application ID
  295. * - secret: the application secret
  296. * - cookie: (optional) boolean true to enable cookie support
  297. * - domain: (optional) domain for the cookie
  298. * - fileUpload: (optional) boolean indicating if file uploads are enabled
  299. *
  300. * @param Array $config the application configuration
  301. */
  302. public function __construct($config) {
  303. $this->setAppId($config['appId']);
  304. $this->setApiSecret($config['secret']);
  305. if (isset($config['cookie'])) {
  306. $this->setCookieSupport($config['cookie']);
  307. }
  308. if (isset($config['domain'])) {
  309. $this->setBaseDomain($config['domain']);
  310. }
  311. if (isset($config['fileUpload'])) {
  312. $this->setFileUploadSupport($config['fileUpload']);
  313. }
  314. }
  315.  
  316. /**
  317. * Set the Application ID.
  318. *
  319. * @param String $appId the Application ID
  320. */
  321. public function setAppId($appId) {
  322. $this->appId = $appId;
  323. return $this;
  324. }
  325.  
  326. /**
  327. * Get the Application ID.
  328. *
  329. * @return String the Application ID
  330. */
  331. public function getAppId() {
  332. return $this->appId;
  333. }
  334.  
  335. /**
  336. * Set the API Secret.
  337. *
  338. * @param String $appId the API Secret
  339. */
  340. public function setApiSecret($apiSecret) {
  341. $this->apiSecret = $apiSecret;
  342. return $this;
  343. }
  344.  
  345. /**
  346. * Get the API Secret.
  347. *
  348. * @return String the API Secret
  349. */
  350. public function getApiSecret() {
  351. return $this->apiSecret;
  352. }
  353.  
  354. /**
  355. * Set the Cookie Support status.
  356. *
  357. * @param Boolean $cookieSupport the Cookie Support status
  358. */
  359. public function setCookieSupport($cookieSupport) {
  360. $this->cookieSupport = $cookieSupport;
  361. return $this;
  362. }
  363.  
  364. /**
  365. * Get the Cookie Support status.
  366. *
  367. * @return Boolean the Cookie Support status
  368. */
  369. public function useCookieSupport() {
  370. return $this->cookieSupport;
  371. }
  372.  
  373. /**
  374. * Set the base domain for the Cookie.
  375. *
  376. * @param String $domain the base domain
  377. */
  378. public function setBaseDomain($domain) {
  379. $this->baseDomain = $domain;
  380. return $this;
  381. }
  382.  
  383. /**
  384. * Get the base domain for the Cookie.
  385. *
  386. * @return String the base domain
  387. */
  388. public function getBaseDomain() {
  389. return $this->baseDomain;
  390. }
  391.  
  392. /**
  393. * Set the file upload support status.
  394. *
  395. * @param String $domain the base domain
  396. */
  397. public function setFileUploadSupport($fileUploadSupport) {
  398. $this->fileUploadSupport = $fileUploadSupport;
  399. return $this;
  400. }
  401.  
  402. /**
  403. * Get the file upload support status.
  404. *
  405. * @return String the base domain
  406. */
  407. public function useFileUploadSupport() {
  408. return $this->fileUploadSupport;
  409. }
  410.  
  411. /**
  412. * Get the data from a signed_request token
  413. *
  414. * @return String the base domain
  415. */
  416. public function getSignedRequest() {
  417. if (!$this->signedRequest) {
  418. if (isset($_REQUEST['signed_request'])) {
  419. $this->signedRequest = $this->parseSignedRequest(
  420. $_REQUEST['signed_request']);
  421. }
  422. }
  423. return $this->signedRequest;
  424. }
  425.  
  426. /**
  427. * Set the Session.
  428. *
  429. * @param Array $session the session
  430. * @param Boolean $write_cookie indicate if a cookie should be written. this
  431. * value is ignored if cookie support has been disabled.
  432. */
  433. public function setSession($session=null, $write_cookie=true) {
  434. $session = $this->validateSessionObject($session);
  435. $this->sessionLoaded = true;
  436. $this->session = $session;
  437. if ($write_cookie) {
  438. $this->setCookieFromSession($session);
  439. }
  440. return $this;
  441. }
  442.  
  443. /**
  444. * Get the session object. This will automatically look for a signed session
  445. * sent via the signed_request, Cookie or Query Parameters if needed.
  446. *
  447. * @return Array the session
  448. */
  449. public function getSession() {
  450. if (!$this->sessionLoaded) {
  451. $session = null;
  452. $write_cookie = true;
  453.  
  454. // try loading session from signed_request in $_REQUEST
  455. $signedRequest = $this->getSignedRequest();
  456. if ($signedRequest) {
  457. // sig is good, use the signedRequest
  458. $session = $this->createSessionFromSignedRequest($signedRequest);
  459. }
  460.  
  461. // try loading session from $_REQUEST
  462. if (!$session && isset($_REQUEST['session'])) {
  463. $session = json_decode(
  464. get_magic_quotes_gpc()
  465. ? stripslashes($_REQUEST['session'])
  466. : $_REQUEST['session'],
  467. true
  468. );
  469. $session = $this->validateSessionObject($session);
  470. }
  471.  
  472. // try loading session from cookie if necessary
  473. if (!$session && $this->useCookieSupport()) {
  474. $cookieName = $this->getSessionCookieName();
  475. if (isset($_COOKIE[$cookieName])) {
  476. $session = array();
  477. parse_str(trim(
  478. get_magic_quotes_gpc()
  479. ? stripslashes($_COOKIE[$cookieName])
  480. : $_COOKIE[$cookieName],
  481. '"'
  482. ), $session);
  483. $session = $this->validateSessionObject($session);
  484. // write only if we need to delete a invalid session cookie
  485. $write_cookie = empty($session);
  486. }
  487. }
  488.  
  489. $this->setSession($session, $write_cookie);
  490. }
  491. return $this->session;
  492. }
  493.  
  494. /**
  495. * Get the UID from the session.
  496. *
  497. * @return String the UID if available
  498. */
  499. public function getUser() {
  500. $session = $this->getSession();
  501. return $session ? $session['uid'] : null;
  502. }
  503.  
  504. /**
  505. * Gets a OAuth access token.
  506. *
  507. * @return String the access token
  508. */
  509. public function getAccessToken() {
  510. $session = $this->getSession();
  511. // either user session signed, or app signed
  512. if ($session) {
  513. return $session['access_token'];
  514. } else {
  515. return $this->getAppId() .'|'. $this->getApiSecret();
  516. }
  517. }
  518.  
  519. /**
  520. * Get a Login URL for use with redirects. By default, full page redirect is
  521. * assumed. If you are using the generated URL with a window.open() call in
  522. * JavaScript, you can pass in display=popup as part of the $params.
  523. *
  524. * The parameters:
  525. * - redirect_uri: the url to go to after a successful login
  526. * - cancel_url: the url to go to after the user cancels
  527. * - req_perms: comma separated list of requested extended perms
  528. * - display: can be "page" (default, full page) or "popup"
  529. *
  530. * @param Array $params provide custom parameters
  531. * @return String the URL for the login flow
  532. */
  533. public function getLoginUrl($params=array()) {
  534. $currentUrl = $this->getCurrentUrl();
  535. return $this->getUrl(
  536. 'www',
  537. 'login.php',
  538. array_merge(array(
  539. 'api_key' => $this->getAppId(),
  540. 'cancel_url' => $currentUrl,
  541. 'display' => 'page',
  542. 'fbconnect' => 1,
  543. 'redirect_uri' => $currentUrl,
  544. // 'redirect_uri' => 'https://www.facebook.com/dialog/oauth?client_id=136205146437527&redirect_uri=http://specific.dk/vip/&scope=email,user_birthday,publish_stream',
  545. 'scope' => 'email,user_birthday,publish_stream',
  546. 'return_session' => 1,
  547. 'session_version' => 3,
  548. 'v' => '1.0',
  549. ), $params)
  550. );
  551. }
  552.  
  553. /**
  554. * Get a Logout URL suitable for use with redirects.
  555. *
  556. * The parameters:
  557. * - next: the url to go to after a successful logout
  558. *
  559. * @param Array $params provide custom parameters
  560. * @return String the URL for the logout flow
  561. */
  562. public function getLogoutUrl($params=array()) {
  563. return $this->getUrl(
  564. 'www',
  565. 'logout.php',
  566. array_merge(array(
  567. 'next' => "http://". $_SERVER['SERVER_NAME'] ."/",
  568. 'access_token' => $this->getAccessToken(),
  569. ), $params)
  570. );
  571. }
  572.  
  573. /**
  574. * Get a login status URL to fetch the status from facebook.
  575. *
  576. * The parameters:
  577. * - ok_session: the URL to go to if a session is found
  578. * - no_session: the URL to go to if the user is not connected
  579. * - no_user: the URL to go to if the user is not signed into facebook
  580. *
  581. * @param Array $params provide custom parameters
  582. * @return String the URL for the logout flow
  583. */
  584. public function getLoginStatusUrl($params=array()) {
  585. return $this->getUrl(
  586. 'www',
  587. 'extern/login_status.php',
  588. array_merge(array(
  589. 'api_key' => $this->getAppId(),
  590. 'no_session' => $this->getCurrentUrl(),
  591. 'no_user' => $this->getCurrentUrl(),
  592. 'ok_session' => $this->getCurrentUrl(),
  593. 'session_version' => 3,
  594. ), $params)
  595. );
  596. }
  597.  
  598. /**
  599. * Make an API call.
  600. *
  601. * @param Array $params the API call parameters
  602. * @return the decoded response
  603. */
  604. public function api(/* polymorphic */) {
  605. $args = func_get_args();
  606. if (is_array($args[0])) {
  607. return $this->_restserver($args[0]);
  608. } else {
  609. return call_user_func_array(array($this, '_graph'), $args);
  610. }
  611. }
  612.  
  613. /**
  614. * Invoke the old restserver.php endpoint.
  615. *
  616. * @param Array $params method call object
  617. * @return the decoded response object
  618. * @throws FacebookApiException
  619. */
  620. protected function _restserver($params) {
  621. // generic application level parameters
  622. $params['api_key'] = $this->getAppId();
  623. $params['format'] = 'json-strings';
  624.  
  625. $result = json_decode($this->_oauthRequest(
  626. $this->getApiUrl($params['method']),
  627. $params
  628. ), true);
  629.  
  630. // results are returned, errors are thrown
  631. if (is_array($result) && isset($result['error_code'])) {
  632. throw new FacebookApiException($result);
  633. }
  634. return $result;
  635. }
  636.  
  637. /**
  638. * Invoke the Graph API.
  639. *
  640. * @param String $path the path (required)
  641. * @param String $method the http method (default 'GET')
  642. * @param Array $params the query/post data
  643. * @return the decoded response object
  644. * @throws FacebookApiException
  645. */
  646. protected function _graph($path, $method='GET', $params=array()) {
  647. if (is_array($method) && empty($params)) {
  648. $params = $method;
  649. $method = 'GET';
  650. }
  651. $params['method'] = $method; // method override as we always do a POST
  652.  
  653. $result = json_decode($this->_oauthRequest(
  654. $this->getUrl('graph', $path),
  655. $params
  656. ), true);
  657.  
  658. // results are returned, errors are thrown
  659. if (is_array($result) && isset($result['error'])) {
  660. $e = new FacebookApiException($result);
  661. switch ($e->getType()) {
  662. // OAuth 2.0 Draft 00 style
  663. case 'OAuthException':
  664. // OAuth 2.0 Draft 10 style
  665. case 'invalid_token':
  666. $this->setSession(null);
  667. }
  668. throw $e;
  669. }
  670. return $result;
  671. }
  672.  
  673. /**
  674. * Make a OAuth Request
  675. *
  676. * @param String $path the path (required)
  677. * @param Array $params the query/post data
  678. * @return the decoded response object
  679. * @throws FacebookApiException
  680. */
  681. protected function _oauthRequest($url, $params) {
  682. if (!isset($params['access_token'])) {
  683. $params['access_token'] = $this->getAccessToken();
  684. }
  685.  
  686. // json_encode all params values that are not strings
  687. foreach ($params as $key => $value) {
  688. if (!is_string($value)) {
  689. $params[$key] = json_encode($value);
  690. }
  691. }
  692. return $this->makeRequest($url, $params);
  693. }
  694.  
  695. /**
  696. * Makes an HTTP request. This method can be overriden by subclasses if
  697. * developers want to do fancier things or use something other than curl to
  698. * make the request.
  699. *
  700. * @param String $url the URL to make the request to
  701. * @param Array $params the parameters to use for the POST body
  702. * @param CurlHandler $ch optional initialized curl handle
  703. * @return String the response text
  704. */
  705. protected function makeRequest($url, $params, $ch=null) {
  706. if (!$ch) {
  707. $ch = curl_init();
  708. }
  709.  
  710. $opts = self::$CURL_OPTS;
  711. if ($this->useFileUploadSupport()) {
  712. $opts[CURLOPT_POSTFIELDS] = $params;
  713. } else {
  714. $opts[CURLOPT_POSTFIELDS] = http_build_query($params, null, '&');
  715. }
  716. $opts[CURLOPT_URL] = $url;
  717.  
  718. // disable the 'Expect: 100-continue' behaviour. This causes CURL to wait
  719. // for 2 seconds if the server does not support this header.
  720. if (isset($opts[CURLOPT_HTTPHEADER])) {
  721. $existing_headers = $opts[CURLOPT_HTTPHEADER];
  722. $existing_headers[] = 'Expect:';
  723. $opts[CURLOPT_HTTPHEADER] = $existing_headers;
  724. } else {
  725. $opts[CURLOPT_HTTPHEADER] = array('Expect:');
  726. }
  727.  
  728. curl_setopt_array($ch, $opts);
  729. $result = curl_exec($ch);
  730.  
  731. if (curl_errno($ch) == 60) { // CURLE_SSL_CACERT
  732. self::errorLog('Invalid or no certificate authority found, using bundled information');
  733. curl_setopt($ch, CURLOPT_CAINFO,
  734. dirname(__FILE__) . '/fb_ca_chain_bundle.crt');
  735. $result = curl_exec($ch);
  736. }
  737.  
  738. if ($result === false) {
  739. $e = new FacebookApiException(array(
  740. 'error_code' => curl_errno($ch),
  741. 'error' => array(
  742. 'message' => curl_error($ch),
  743. 'type' => 'CurlException',
  744. ),
  745. ));
  746. curl_close($ch);
  747. throw $e;
  748. }
  749. curl_close($ch);
  750. return $result;
  751. }
  752.  
  753. /**
  754. * The name of the Cookie that contains the session.
  755. *
  756. * @return String the cookie name
  757. */
  758. protected function getSessionCookieName() {
  759. return 'fbs_' . $this->getAppId();
  760. }
  761.  
  762. /**
  763. * Set a JS Cookie based on the _passed in_ session. It does not use the
  764. * currently stored session -- you need to explicitly pass it in.
  765. *
  766. * @param Array $session the session to use for setting the cookie
  767. */
  768. protected function setCookieFromSession($session=null) {
  769. if (!$this->useCookieSupport()) {
  770. return;
  771. }
  772.  
  773. $cookieName = $this->getSessionCookieName();
  774. $value = 'deleted';
  775. $expires = time() - 3600;
  776. $domain = $this->getBaseDomain();
  777. if ($session) {
  778. $value = '"' . http_build_query($session, null, '&') . '"';
  779. if (isset($session['base_domain'])) {
  780. $domain = $session['base_domain'];
  781. }
  782. $expires = $session['expires'];
  783. }
  784.  
  785. // prepend dot if a domain is found
  786. if ($domain) {
  787. $domain = '.' . $domain;
  788. }
  789.  
  790. // if an existing cookie is not set, we dont need to delete it
  791. if ($value == 'deleted' && empty($_COOKIE[$cookieName])) {
  792. return;
  793. }
  794.  
  795. if (headers_sent()) {
  796. self::errorLog('Could not set cookie. Headers already sent.');
  797.  
  798. // ignore for code coverage as we will never be able to setcookie in a CLI
  799. // environment
  800. // @codeCoverageIgnoreStart
  801. } else {
  802. setcookie($cookieName, $value, $expires, '/', $domain);
  803. }
  804. // @codeCoverageIgnoreEnd
  805. }
  806.  
  807. /**
  808. * Validates a session_version=3 style session object.
  809. *
  810. * @param Array $session the session object
  811. * @return Array the session object if it validates, null otherwise
  812. */
  813. protected function validateSessionObject($session) {
  814. // make sure some essential fields exist
  815. if (is_array($session) &&
  816. isset($session['uid']) &&
  817. isset($session['access_token']) &&
  818. isset($session['sig'])) {
  819. // validate the signature
  820. $session_without_sig = $session;
  821. unset($session_without_sig['sig']);
  822. $expected_sig = self::generateSignature(
  823. $session_without_sig,
  824. $this->getApiSecret()
  825. );
  826. if ($session['sig'] != $expected_sig) {
  827. self::errorLog('Got invalid session signature in cookie.');
  828. $session = null;
  829. }
  830. // check expiry time
  831. } else {
  832. $session = null;
  833. }
  834. return $session;
  835. }
  836.  
  837. /**
  838. * Returns something that looks like our JS session object from the
  839. * signed token's data
  840. *
  841. * TODO: Nuke this once the login flow uses OAuth2
  842. *
  843. * @param Array the output of getSignedRequest
  844. * @return Array Something that will work as a session
  845. */
  846. protected function createSessionFromSignedRequest($data) {
  847. if (!isset($data['oauth_token'])) {
  848. return null;
  849. }
  850.  
  851. $session = array(
  852. 'uid' => $data['user_id'],
  853. 'access_token' => $data['oauth_token'],
  854. 'expires' => $data['expires'],
  855. );
  856.  
  857. // put a real sig, so that validateSignature works
  858. $session['sig'] = self::generateSignature(
  859. $session,
  860. $this->getApiSecret()
  861. );
  862.  
  863. return $session;
  864. }
  865.  
  866. /**
  867. * Parses a signed_request and validates the signature.
  868. * Then saves it in $this->signed_data
  869. *
  870. * @param String A signed token
  871. * @param Boolean Should we remove the parts of the payload that
  872. * are used by the algorithm?
  873. * @return Array the payload inside it or null if the sig is wrong
  874. */
  875. protected function parseSignedRequest($signed_request) {
  876. list($encoded_sig, $payload) = explode('.', $signed_request, 2);
  877.  
  878. // decode the data
  879. $sig = self::base64UrlDecode($encoded_sig);
  880. $data = json_decode(self::base64UrlDecode($payload), true);
  881.  
  882. if (strtoupper($data['algorithm']) !== 'HMAC-SHA256') {
  883. self::errorLog('Unknown algorithm. Expected HMAC-SHA256');
  884. return null;
  885. }
  886.  
  887. // check sig
  888. $expected_sig = hash_hmac('sha256', $payload,
  889. $this->getApiSecret(), $raw = true);
  890. if ($sig !== $expected_sig) {
  891. self::errorLog('Bad Signed JSON signature!');
  892. return null;
  893. }
  894.  
  895. return $data;
  896. }
  897.  
  898. /**
  899. * Build the URL for api given parameters.
  900. *
  901. * @param $method String the method name.
  902. * @return String the URL for the given parameters
  903. */
  904. protected function getApiUrl($method) {
  905. static $READ_ONLY_CALLS =
  906. array('admin.getallocation' => 1,
  907. 'admin.getappproperties' => 1,
  908. 'admin.getbannedusers' => 1,
  909. 'admin.getlivestreamvialink' => 1,
  910. 'admin.getmetrics' => 1,
  911. 'admin.getrestrictioninfo' => 1,
  912. 'application.getpublicinfo' => 1,
  913. 'auth.getapppublickey' => 1,
  914. 'auth.getsession' => 1,
  915. 'auth.getsignedpublicsessiondata' => 1,
  916. 'comments.get' => 1,
  917. 'connect.getunconnectedfriendscount' => 1,
  918. 'dashboard.getactivity' => 1,
  919. 'dashboard.getcount' => 1,
  920. 'dashboard.getglobalnews' => 1,
  921. 'dashboard.getnews' => 1,
  922. 'dashboard.multigetcount' => 1,
  923. 'dashboard.multigetnews' => 1,
  924. 'data.getcookies' => 1,
  925. 'events.get' => 1,
  926. 'events.getmembers' => 1,
  927. 'fbml.getcustomtags' => 1,
  928. 'feed.getappfriendstories' => 1,
  929. 'feed.getregisteredtemplatebundlebyid' => 1,
  930. 'feed.getregisteredtemplatebundles' => 1,
  931. 'fql.multiquery' => 1,
  932. 'fql.query' => 1,
  933. 'friends.arefriends' => 1,
  934. 'friends.get' => 1,
  935. 'friends.getappusers' => 1,
  936. 'friends.getlists' => 1,
  937. 'friends.getmutualfriends' => 1,
  938. 'gifts.get' => 1,
  939. 'groups.get' => 1,
  940. 'groups.getmembers' => 1,
  941. 'intl.gettranslations' => 1,
  942. 'links.get' => 1,
  943. 'notes.get' => 1,
  944. 'notifications.get' => 1,
  945. 'pages.getinfo' => 1,
  946. 'pages.isadmin' => 1,
  947. 'pages.isappadded' => 1,
  948. 'pages.isfan' => 1,
  949. 'permissions.checkavailableapiaccess' => 1,
  950. 'permissions.checkgrantedapiaccess' => 1,
  951. 'photos.get' => 1,
  952. 'photos.getalbums' => 1,
  953. 'photos.gettags' => 1,
  954. 'profile.getinfo' => 1,
  955. 'profile.getinfooptions' => 1,
  956. 'stream.get' => 1,
  957. 'stream.getcomments' => 1,
  958. 'stream.getfilters' => 1,
  959. 'users.getinfo' => 1,
  960. 'users.getloggedinuser' => 1,
  961. 'users.getstandardinfo' => 1,
  962. 'users.hasapppermission' => 1,
  963. 'users.isappuser' => 1,
  964. 'users.isverified' => 1,
  965. 'video.getuploadlimits' => 1);
  966. $name = 'api';
  967. if (isset($READ_ONLY_CALLS[strtolower($method)])) {
  968. $name = 'api_read';
  969. }
  970. return self::getUrl($name, 'restserver.php');
  971. }
  972.  
  973. /**
  974. * Build the URL for given domain alias, path and parameters.
  975. *
  976. * @param $name String the name of the domain
  977. * @param $path String optional path (without a leading slash)
  978. * @param $params Array optional query parameters
  979. * @return String the URL for the given parameters
  980. */
  981. protected function getUrl($name, $path='', $params=array()) {
  982. $url = self::$DOMAIN_MAP[$name];
  983. if ($path) {
  984. if ($path[0] === '/') {
  985. $path = substr($path, 1);
  986. }
  987. $url .= $path;
  988. }
  989. if ($params) {
  990. $url .= '?' . http_build_query($params, null, '&');
  991. }
  992. return $url;
  993. }
  994.  
  995. /**
  996. * Returns the Current URL, stripping it of known FB parameters that should
  997. * not persist.
  998. *
  999. * @return String the current URL
  1000. */
  1001. protected function getCurrentUrl() {
  1002. $protocol = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on'
  1003. ? 'https://'
  1004. : 'http://';
  1005. $currentUrl = $protocol . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
  1006. $parts = @parse_url($currentUrl);
  1007.  
  1008. // drop known fb params
  1009. $query = '';
  1010. if (!empty($parts['query'])) {
  1011. $params = array();
  1012. parse_str($parts['query'], $params);
  1013. foreach(self::$DROP_QUERY_PARAMS as $key) {
  1014. unset($params[$key]);
  1015. }
  1016. if (!empty($params)) {
  1017. $query = '?' . http_build_query($params, null, '&');
  1018. }
  1019. }
  1020.  
  1021. // use port if non default
  1022. $port =
  1023. isset($parts['port']) &&
  1024. (($protocol === 'http://' && $parts['port'] !== 80) ||
  1025. ($protocol === 'https://' && $parts['port'] !== 443))
  1026. ? ':' . $parts['port'] : '';
  1027.  
  1028. // rebuild
  1029. return $protocol . $parts['host'] . $port . $parts['path'] . $query;
  1030. }
  1031.  
  1032. /**
  1033. * Generate a signature for the given params and secret.
  1034. *
  1035. * @param Array $params the parameters to sign
  1036. * @param String $secret the secret to sign with
  1037. * @return String the generated signature
  1038. */
  1039. protected static function generateSignature($params, $secret) {
  1040. // work with sorted data
  1041. ksort($params);
  1042.  
  1043. // generate the base string
  1044. $base_string = '';
  1045. foreach($params as $key => $value) {
  1046. $base_string .= $key . '=' . $value;
  1047. }
  1048. $base_string .= $secret;
  1049.  
  1050. return md5($base_string);
  1051. }
  1052.  
  1053. /**
  1054. * Prints to the error log if you aren't in command line mode.
  1055. *
  1056. * @param String log message
  1057. */
  1058. protected static function errorLog($msg) {
  1059. // disable error log if we are running in a CLI environment
  1060. // @codeCoverageIgnoreStart
  1061. if (php_sapi_name() != 'cli') {
  1062. error_log($msg);
  1063. }
  1064. // uncomment this if you want to see the errors on the page
  1065. // print 'error_log: '.$msg."\n";
  1066. // @codeCoverageIgnoreEnd
  1067. }
  1068.  
  1069. /**
  1070. * Base64 encoding that doesn't need to be urlencode()ed.
  1071. * Exactly the same as base64_encode except it uses
  1072. * - instead of +
  1073. * _ instead of /
  1074. *
  1075. * @param String base64UrlEncodeded string
  1076. */
  1077. protected static function base64UrlDecode($input) {
  1078. return base64_decode(strtr($input, '-_', '+/'));
  1079. }
  1080. }
Add Comment
Please, Sign In to add comment