Files
firstgarden-web-gnu/plugin/sns/facebook/tests/tests.php

2035 lines
65 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.
*/
class PHPSDKTestCase extends PHPUnit_Framework_TestCase {
const APP_ID = '117743971608120';
const SECRET = '9c8ea2071859659bea1246d33a9207cf';
const MIGRATED_APP_ID = '174236045938435';
const MIGRATED_SECRET = '0073dce2d95c4a5c2922d1827ea0cca6';
const TEST_USER = 499834690;
const TEST_USER_2 = 499835484;
private static $kExpiredAccessToken = 'AAABrFmeaJjgBAIshbq5ZBqZBICsmveZCZBi6O4w9HSTkFI73VMtmkL9jLuWsZBZC9QMHvJFtSulZAqonZBRIByzGooCZC8DWr0t1M4BL9FARdQwPWPnIqCiFQ';
private static function kValidSignedRequest($id = self::TEST_USER, $oauth_token = null) {
$facebook = new FBPublic(array(
'appId' => self::APP_ID,
'secret' => self::SECRET,
));
return $facebook->publicMakeSignedRequest(
array(
'user_id' => $id,
'oauth_token' => $oauth_token
)
);
}
private static function kNonTosedSignedRequest() {
$facebook = new FBPublic(array(
'appId' => self::APP_ID,
'secret' => self::SECRET,
));
return $facebook->publicMakeSignedRequest(array());
}
private static function kSignedRequestWithEmptyValue() {
return '';
}
private static function kSignedRequestWithBogusSignature() {
$facebook = new FBPublic(array(
'appId' => self::APP_ID,
'secret' => 'bogus',
));
return $facebook->publicMakeSignedRequest(
array(
'algorithm' => 'HMAC-SHA256',
)
);
}
private static function kSignedRequestWithWrongAlgo() {
$facebook = new FBPublic(array(
'appId' => self::APP_ID,
'secret' => self::SECRET,
));
$data['algorithm'] = 'foo';
$json = json_encode($data);
$b64 = $facebook->publicBase64UrlEncode($json);
$raw_sig = hash_hmac('sha256', $b64, self::SECRET, $raw = true);
$sig = $facebook->publicBase64UrlEncode($raw_sig);
return $sig.'.'.$b64;
}
public function testConstructor() {
$facebook = new TransientFacebook(array(
'appId' => self::APP_ID,
'secret' => self::SECRET,
));
$this->assertEquals($facebook->getAppId(), self::APP_ID,
'Expect the App ID to be set.');
$this->assertEquals($facebook->getAppSecret(), self::SECRET,
'Expect the API secret to be set.');
}
public function testConstructorWithFileUpload() {
$facebook = new TransientFacebook(array(
'appId' => self::APP_ID,
'secret' => self::SECRET,
'fileUpload' => true,
));
$this->assertEquals($facebook->getAppId(), self::APP_ID,
'Expect the App ID to be set.');
$this->assertEquals($facebook->getAppSecret(), self::SECRET,
'Expect the API secret to be set.');
$this->assertTrue($facebook->getFileUploadSupport(),
'Expect file upload support to be on.');
// alias (depricated) for getFileUploadSupport -- test until removed
$this->assertTrue($facebook->useFileUploadSupport(),
'Expect file upload support to be on.');
}
public function testSetAppId() {
$facebook = new TransientFacebook(array(
'appId' => self::APP_ID,
'secret' => self::SECRET,
));
$facebook->setAppId('dummy');
$this->assertEquals($facebook->getAppId(), 'dummy',
'Expect the App ID to be dummy.');
}
public function testSetAPISecret() {
$facebook = new TransientFacebook(array(
'appId' => self::APP_ID,
'secret' => self::SECRET,
));
$facebook->setApiSecret('dummy');
$this->assertEquals($facebook->getApiSecret(), 'dummy',
'Expect the API secret to be dummy.');
}
public function testSetAPPSecret() {
$facebook = new TransientFacebook(array(
'appId' => self::APP_ID,
'secret' => self::SECRET,
));
$facebook->setAppSecret('dummy');
$this->assertEquals($facebook->getAppSecret(), 'dummy',
'Expect the API secret to be dummy.');
}
public function testSetAccessToken() {
$facebook = new TransientFacebook(array(
'appId' => self::APP_ID,
'secret' => self::SECRET,
));
$facebook->setAccessToken('saltydog');
$this->assertEquals($facebook->getAccessToken(), 'saltydog',
'Expect installed access token to remain \'saltydog\'');
}
public function testSetFileUploadSupport() {
$facebook = new TransientFacebook(array(
'appId' => self::APP_ID,
'secret' => self::SECRET,
));
$this->assertFalse($facebook->getFileUploadSupport(),
'Expect file upload support to be off.');
// alias for getFileUploadSupport (depricated), testing until removed
$this->assertFalse($facebook->useFileUploadSupport(),
'Expect file upload support to be off.');
$facebook->setFileUploadSupport(true);
$this->assertTrue($facebook->getFileUploadSupport(),
'Expect file upload support to be on.');
// alias for getFileUploadSupport (depricated), testing until removed
$this->assertTrue($facebook->useFileUploadSupport(),
'Expect file upload support to be on.');
}
public function testGetCurrentURL() {
$facebook = new FBGetCurrentURLFacebook(array(
'appId' => self::APP_ID,
'secret' => self::SECRET,
));
// fake the HPHP $_SERVER globals
$_SERVER['HTTP_HOST'] = 'www.test.com';
$_SERVER['REQUEST_URI'] = '/unit-tests.php?one=one&two=two&three=three';
$current_url = $facebook->publicGetCurrentUrl();
$this->assertEquals(
'http://www.test.com/unit-tests.php?one=one&two=two&three=three',
$current_url,
'getCurrentUrl function is changing the current URL');
// ensure structure of valueless GET params is retained (sometimes
// an = sign was present, and sometimes it was not)
// first test when equal signs are present
$_SERVER['HTTP_HOST'] = 'www.test.com';
$_SERVER['REQUEST_URI'] = '/unit-tests.php?one=&two=&three=';
$current_url = $facebook->publicGetCurrentUrl();
$this->assertEquals(
'http://www.test.com/unit-tests.php?one=&two=&three=',
$current_url,
'getCurrentUrl function is changing the current URL');
// now confirm that
$_SERVER['HTTP_HOST'] = 'www.test.com';
$_SERVER['REQUEST_URI'] = '/unit-tests.php?one&two&three';
$current_url = $facebook->publicGetCurrentUrl();
$this->assertEquals(
'http://www.test.com/unit-tests.php?one&two&three',
$current_url,
'getCurrentUrl function is changing the current URL');
}
public function testGetLoginURL() {
$facebook = new Facebook(array(
'appId' => self::APP_ID,
'secret' => self::SECRET,
));
// fake the HPHP $_SERVER globals
$_SERVER['HTTP_HOST'] = 'www.test.com';
$_SERVER['REQUEST_URI'] = '/unit-tests.php';
$login_url = parse_url($facebook->getLoginUrl());
$this->assertEquals($login_url['scheme'], 'https');
$this->assertEquals($login_url['host'], 'www.facebook.com');
$this->assertEquals($login_url['path'], '/dialog/oauth');
$expected_login_params =
array('client_id' => self::APP_ID,
'redirect_uri' => 'http://www.test.com/unit-tests.php');
$query_map = array();
parse_str($login_url['query'], $query_map);
$this->assertIsSubset($expected_login_params, $query_map);
// we don't know what the state is, but we know it's an md5 and should
// be 32 characters long.
$this->assertEquals(strlen($query_map['state']), $num_characters = 32);
}
public function testGetLoginURLWithExtraParams() {
$facebook = new Facebook(array(
'appId' => self::APP_ID,
'secret' => self::SECRET,
));
// fake the HPHP $_SERVER globals
$_SERVER['HTTP_HOST'] = 'www.test.com';
$_SERVER['REQUEST_URI'] = '/unit-tests.php';
$extra_params = array('scope' => 'email, sms',
'nonsense' => 'nonsense');
$login_url = parse_url($facebook->getLoginUrl($extra_params));
$this->assertEquals($login_url['scheme'], 'https');
$this->assertEquals($login_url['host'], 'www.facebook.com');
$this->assertEquals($login_url['path'], '/dialog/oauth');
$expected_login_params =
array_merge(
array('client_id' => self::APP_ID,
'redirect_uri' => 'http://www.test.com/unit-tests.php'),
$extra_params);
$query_map = array();
parse_str($login_url['query'], $query_map);
$this->assertIsSubset($expected_login_params, $query_map);
// we don't know what the state is, but we know it's an md5 and should
// be 32 characters long.
$this->assertEquals(strlen($query_map['state']), $num_characters = 32);
}
public function testGetLoginURLWithScopeParamsAsArray() {
$facebook = new Facebook(array(
'appId' => self::APP_ID,
'secret' => self::SECRET,
));
// fake the HPHP $_SERVER globals
$_SERVER['HTTP_HOST'] = 'www.test.com';
$_SERVER['REQUEST_URI'] = '/unit-tests.php';
$scope_params_as_array = array('email','sms','read_stream');
$extra_params = array('scope' => $scope_params_as_array,
'nonsense' => 'nonsense');
$login_url = parse_url($facebook->getLoginUrl($extra_params));
$this->assertEquals($login_url['scheme'], 'https');
$this->assertEquals($login_url['host'], 'www.facebook.com');
$this->assertEquals($login_url['path'], '/dialog/oauth');
// expect api to flatten array params to comma separated list
// should do the same here before asserting to make sure API is behaving
// correctly;
$extra_params['scope'] = implode(',', $scope_params_as_array);
$expected_login_params =
array_merge(
array('client_id' => self::APP_ID,
'redirect_uri' => 'http://www.test.com/unit-tests.php'),
$extra_params);
$query_map = array();
parse_str($login_url['query'], $query_map);
$this->assertIsSubset($expected_login_params, $query_map);
// we don't know what the state is, but we know it's an md5 and should
// be 32 characters long.
$this->assertEquals(strlen($query_map['state']), $num_characters = 32);
}
public function testGetCodeWithValidCSRFState() {
$facebook = new FBCode(array(
'appId' => self::APP_ID,
'secret' => self::SECRET,
));
$facebook->setCSRFStateToken();
$code = $_REQUEST['code'] = $this->generateMD5HashOfRandomValue();
$_REQUEST['state'] = $facebook->getCSRFStateToken();
$this->assertEquals($code,
$facebook->publicGetCode(),
'Expect code to be pulled from $_REQUEST[\'code\']');
}
public function testGetCodeWithInvalidCSRFState() {
$facebook = new FBCode(array(
'appId' => self::APP_ID,
'secret' => self::SECRET,
));
$facebook->setCSRFStateToken();
$code = $_REQUEST['code'] = $this->generateMD5HashOfRandomValue();
$_REQUEST['state'] = $facebook->getCSRFStateToken().'forgery!!!';
$this->assertFalse($facebook->publicGetCode(),
'Expect getCode to fail, CSRF state should not match.');
}
public function testGetCodeWithMissingCSRFState() {
$facebook = new FBCode(array(
'appId' => self::APP_ID,
'secret' => self::SECRET,
));
$code = $_REQUEST['code'] = $this->generateMD5HashOfRandomValue();
// intentionally don't set CSRF token at all
$this->assertFalse($facebook->publicGetCode(),
'Expect getCode to fail, CSRF state not sent back.');
}
public function testGetUserFromSignedRequest() {
$facebook = new TransientFacebook(array(
'appId' => self::APP_ID,
'secret' => self::SECRET,
));
$_REQUEST['signed_request'] = self::kValidSignedRequest();
$this->assertEquals('499834690', $facebook->getUser(),
'Failed to get user ID from a valid signed request.');
}
public function testSignedRequestRewrite(){
$facebook = new FBRewrite(array(
'appId' => self::APP_ID,
'secret' => self::SECRET,
));
$_REQUEST['signed_request'] = self::kValidSignedRequest(self::TEST_USER, 'Hello sweetie');
$this->assertEquals(self::TEST_USER, $facebook->getUser(),
'Failed to get user ID from a valid signed request.');
$this->assertEquals('Hello sweetie', $facebook->getAccessToken(),
'Failed to get access token from signed request');
$facebook->uncache();
$_REQUEST['signed_request'] = self::kValidSignedRequest(self::TEST_USER_2, 'spoilers');
$this->assertEquals(self::TEST_USER_2, $facebook->getUser(),
'Failed to get user ID from a valid signed request.');
$_REQUEST['signed_request'] = null;
$facebook ->uncacheSignedRequest();
$this->assertNotEquals('Hello sweetie', $facebook->getAccessToken(),
'Failed to clear access token');
}
public function testGetSignedRequestFromCookie() {
$facebook = new FBPublicCookie(array(
'appId' => self::APP_ID,
'secret' => self::SECRET,
));
$_COOKIE[$facebook->publicGetSignedRequestCookieName()] =
self::kValidSignedRequest();
$this->assertNotNull($facebook->publicGetSignedRequest());
$this->assertEquals('499834690', $facebook->getUser(),
'Failed to get user ID from a valid signed request.');
}
public function testGetSignedRequestWithIncorrectSignature() {
$facebook = new FBPublicCookie(array(
'appId' => self::APP_ID,
'secret' => self::SECRET,
));
$_COOKIE[$facebook->publicGetSignedRequestCookieName()] =
self::kSignedRequestWithBogusSignature();
$this->assertNull($facebook->publicGetSignedRequest());
}
public function testNonUserAccessToken() {
$facebook = new FBAccessToken(array(
'appId' => self::APP_ID,
'secret' => self::SECRET,
));
// no cookies, and no request params, so no user or code,
// so no user access token (even with cookie support)
$this->assertEquals($facebook->publicGetApplicationAccessToken(),
$facebook->getAccessToken(),
'Access token should be that for logged out users.');
}
public function testMissingMetadataCookie() {
$fb = new FBPublicCookie(array(
'appId' => self::APP_ID,
'secret' => self::SECRET,
));
$this->assertEmpty($fb->publicGetMetadataCookie());
}
public function testEmptyMetadataCookie() {
$fb = new FBPublicCookie(array(
'appId' => self::APP_ID,
'secret' => self::SECRET,
));
$_COOKIE[$fb->publicGetMetadataCookieName()] = '';
$this->assertEmpty($fb->publicGetMetadataCookie());
}
public function testMetadataCookie() {
$fb = new FBPublicCookie(array(
'appId' => self::APP_ID,
'secret' => self::SECRET,
));
$key = 'foo';
$val = '42';
$_COOKIE[$fb->publicGetMetadataCookieName()] = "$key=$val";
$this->assertEquals(array($key => $val), $fb->publicGetMetadataCookie());
}
public function testQuotedMetadataCookie() {
$fb = new FBPublicCookie(array(
'appId' => self::APP_ID,
'secret' => self::SECRET,
));
$key = 'foo';
$val = '42';
$_COOKIE[$fb->publicGetMetadataCookieName()] = "\"$key=$val\"";
$this->assertEquals(array($key => $val), $fb->publicGetMetadataCookie());
}
public function testAPIForLoggedOutUsers() {
$facebook = new TransientFacebook(array(
'appId' => self::APP_ID,
'secret' => self::SECRET,
));
$response = $facebook->api(array(
'method' => 'fql.query',
'query' => 'SELECT name FROM user WHERE uid=4',
));
$this->assertEquals(count($response), 1,
'Expect one row back.');
$this->assertEquals($response[0]['name'], 'Mark Zuckerberg',
'Expect the name back.');
}
public function testAPIWithBogusAccessToken() {
$facebook = new TransientFacebook(array(
'appId' => self::APP_ID,
'secret' => self::SECRET,
));
$facebook->setAccessToken('this-is-not-really-an-access-token');
// if we don't set an access token and there's no way to
// get one, then the FQL query below works beautifully, handing
// over Zuck's public data. But if you specify a bogus access
// token as I have right here, then the FQL query should fail.
// We could return just Zuck's public data, but that wouldn't
// advertise the issue that the access token is at worst broken
// and at best expired.
try {
$response = $facebook->api(array(
'method' => 'fql.query',
'query' => 'SELECT name FROM profile WHERE id=4',
));
$this->fail('Should not get here.');
} catch(FacebookApiException $e) {
$result = $e->getResult();
$this->assertTrue(is_array($result), 'expect a result object');
$this->assertEquals('190', $result['error_code'], 'expect code');
}
}
public function testAPIGraphPublicData() {
$facebook = new TransientFacebook(array(
'appId' => self::APP_ID,
'secret' => self::SECRET,
));
$response = $facebook->api('/jerry');
$this->assertEquals(
$response['id'], '214707', 'should get expected id.');
}
public function testGraphAPIWithBogusAccessToken() {
$facebook = new TransientFacebook(array(
'appId' => self::APP_ID,
'secret' => self::SECRET,
));
$facebook->setAccessToken('this-is-not-really-an-access-token');
try {
$response = $facebook->api('/me');
$this->fail('Should not get here.');
} catch(FacebookApiException $e) {
// means the server got the access token and didn't like it
$msg = 'OAuthException: Invalid OAuth access token.';
$this->assertEquals($msg, (string) $e,
'Expect the invalid OAuth token message.');
}
}
public function testGraphAPIWithExpiredAccessToken() {
$facebook = new TransientFacebook(array(
'appId' => self::APP_ID,
'secret' => self::SECRET,
));
$facebook->setAccessToken(self::$kExpiredAccessToken);
try {
$response = $facebook->api('/me');
$this->fail('Should not get here.');
} catch(FacebookApiException $e) {
// means the server got the access token and didn't like it
$error_msg_start = 'OAuthException: Error validating access token:';
$this->assertTrue(strpos((string) $e, $error_msg_start) === 0,
'Expect the token validation error message.');
}
}
public function testGraphAPIOAuthSpecError() {
$facebook = new TransientFacebook(array(
'appId' => self::MIGRATED_APP_ID,
'secret' => self::MIGRATED_SECRET,
));
try {
$response = $facebook->api('/me', array(
'client_id' => self::MIGRATED_APP_ID));
$this->fail('Should not get here.');
} catch(FacebookApiException $e) {
// means the server got the access token
$msg = 'invalid_request: An active access token must be used '.
'to query information about the current user.';
$this->assertEquals($msg, (string) $e,
'Expect the invalid session message.');
}
}
public function testGraphAPIMethodOAuthSpecError() {
$facebook = new TransientFacebook(array(
'appId' => self::MIGRATED_APP_ID,
'secret' => self::MIGRATED_SECRET,
));
try {
$response = $facebook->api('/daaku.shah', 'DELETE', array(
'client_id' => self::MIGRATED_APP_ID));
$this->fail('Should not get here.');
} catch(FacebookApiException $e) {
$this->assertEquals(strpos($e, 'invalid_request'), 0);
}
}
public function testCurlFailure() {
$facebook = new TransientFacebook(array(
'appId' => self::APP_ID,
'secret' => self::SECRET,
));
if (!defined('CURLOPT_TIMEOUT_MS')) {
// can't test it if we don't have millisecond timeouts
return;
}
$exception = null;
try {
// we dont expect facebook will ever return in 1ms
Facebook::$CURL_OPTS[CURLOPT_TIMEOUT_MS] = 50;
$facebook->api('/naitik');
} catch(FacebookApiException $e) {
$exception = $e;
}
unset(Facebook::$CURL_OPTS[CURLOPT_TIMEOUT_MS]);
if (!$exception) {
$this->fail('no exception was thrown on timeout.');
}
$code = $exception->getCode();
if ($code != CURLE_OPERATION_TIMEOUTED && $code != CURLE_COULDNT_CONNECT) {
$this->fail("Expected curl error code 7 or 28 but got: $code");
}
$this->assertEquals('CurlException', $exception->getType(), 'expect type');
}
public function testGraphAPIWithOnlyParams() {
$facebook = new TransientFacebook(array(
'appId' => self::APP_ID,
'secret' => self::SECRET,
));
$response = $facebook->api('/jerry');
$this->assertTrue(isset($response['id']),
'User ID should be public.');
$this->assertTrue(isset($response['name']),
'User\'s name should be public.');
$this->assertTrue(isset($response['first_name']),
'User\'s first name should be public.');
$this->assertTrue(isset($response['last_name']),
'User\'s last name should be public.');
$this->assertFalse(isset($response['work']),
'User\'s work history should only be available with '.
'a valid access token.');
$this->assertFalse(isset($response['education']),
'User\'s education history should only be '.
'available with a valid access token.');
$this->assertFalse(isset($response['verified']),
'User\'s verification status should only be '.
'available with a valid access token.');
}
public function testLoginURLDefaults() {
$_SERVER['HTTP_HOST'] = 'fbrell.com';
$_SERVER['REQUEST_URI'] = '/examples';
$facebook = new TransientFacebook(array(
'appId' => self::APP_ID,
'secret' => self::SECRET,
));
$encodedUrl = rawurlencode('http://fbrell.com/examples');
$this->assertNotNull(strpos($facebook->getLoginUrl(), $encodedUrl),
'Expect the current url to exist.');
}
public function testLoginURLDefaultsDropStateQueryParam() {
$_SERVER['HTTP_HOST'] = 'fbrell.com';
$_SERVER['REQUEST_URI'] = '/examples?state=xx42xx';
$facebook = new TransientFacebook(array(
'appId' => self::APP_ID,
'secret' => self::SECRET,
));
$expectEncodedUrl = rawurlencode('http://fbrell.com/examples');
$this->assertTrue(strpos($facebook->getLoginUrl(), $expectEncodedUrl) > -1,
'Expect the current url to exist.');
$this->assertFalse(strpos($facebook->getLoginUrl(), 'xx42xx'),
'Expect the session param to be dropped.');
}
public function testLoginURLDefaultsDropCodeQueryParam() {
$_SERVER['HTTP_HOST'] = 'fbrell.com';
$_SERVER['REQUEST_URI'] = '/examples?code=xx42xx';
$facebook = new TransientFacebook(array(
'appId' => self::APP_ID,
'secret' => self::SECRET,
));
$expectEncodedUrl = rawurlencode('http://fbrell.com/examples');
$this->assertTrue(strpos($facebook->getLoginUrl(), $expectEncodedUrl) > -1,
'Expect the current url to exist.');
$this->assertFalse(strpos($facebook->getLoginUrl(), 'xx42xx'),
'Expect the session param to be dropped.');
}
public function testLoginURLDefaultsDropSignedRequestParamButNotOthers() {
$_SERVER['HTTP_HOST'] = 'fbrell.com';
$_SERVER['REQUEST_URI'] =
'/examples?signed_request=xx42xx&do_not_drop=xx43xx';
$facebook = new TransientFacebook(array(
'appId' => self::APP_ID,
'secret' => self::SECRET,
));
$expectEncodedUrl = rawurlencode('http://fbrell.com/examples');
$this->assertFalse(strpos($facebook->getLoginUrl(), 'xx42xx'),
'Expect the session param to be dropped.');
$this->assertTrue(strpos($facebook->getLoginUrl(), 'xx43xx') > -1,
'Expect the do_not_drop param to exist.');
}
public function testLoginURLCustomNext() {
$_SERVER['HTTP_HOST'] = 'fbrell.com';
$_SERVER['REQUEST_URI'] = '/examples';
$facebook = new TransientFacebook(array(
'appId' => self::APP_ID,
'secret' => self::SECRET,
));
$next = 'http://fbrell.com/custom';
$loginUrl = $facebook->getLoginUrl(array(
'redirect_uri' => $next,
'cancel_url' => $next
));
$currentEncodedUrl = rawurlencode('http://fbrell.com/examples');
$expectedEncodedUrl = rawurlencode($next);
$this->assertNotNull(strpos($loginUrl, $expectedEncodedUrl),
'Expect the custom url to exist.');
$this->assertFalse(strpos($loginUrl, $currentEncodedUrl),
'Expect the current url to not exist.');
}
public function testLogoutURLDefaults() {
$_SERVER['HTTP_HOST'] = 'fbrell.com';
$_SERVER['REQUEST_URI'] = '/examples';
$facebook = new TransientFacebook(array(
'appId' => self::APP_ID,
'secret' => self::SECRET,
));
$encodedUrl = rawurlencode('http://fbrell.com/examples');
$this->assertNotNull(strpos($facebook->getLogoutUrl(), $encodedUrl),
'Expect the current url to exist.');
$this->assertFalse(strpos($facebook->getLogoutUrl(), self::SECRET));
}
public function testLoginStatusURLDefaults() {
$_SERVER['HTTP_HOST'] = 'fbrell.com';
$_SERVER['REQUEST_URI'] = '/examples';
$facebook = new TransientFacebook(array(
'appId' => self::APP_ID,
'secret' => self::SECRET,
));
$encodedUrl = rawurlencode('http://fbrell.com/examples');
$this->assertNotNull(strpos($facebook->getLoginStatusUrl(), $encodedUrl),
'Expect the current url to exist.');
}
public function testLoginStatusURLCustom() {
$_SERVER['HTTP_HOST'] = 'fbrell.com';
$_SERVER['REQUEST_URI'] = '/examples';
$facebook = new TransientFacebook(array(
'appId' => self::APP_ID,
'secret' => self::SECRET,
));
$encodedUrl1 = rawurlencode('http://fbrell.com/examples');
$okUrl = 'http://fbrell.com/here1';
$encodedUrl2 = rawurlencode($okUrl);
$loginStatusUrl = $facebook->getLoginStatusUrl(array(
'ok_session' => $okUrl,
));
$this->assertNotNull(strpos($loginStatusUrl, $encodedUrl1),
'Expect the current url to exist.');
$this->assertNotNull(strpos($loginStatusUrl, $encodedUrl2),
'Expect the custom url to exist.');
}
public function testNonDefaultPort() {
$_SERVER['HTTP_HOST'] = 'fbrell.com:8080';
$_SERVER['REQUEST_URI'] = '/examples';
$facebook = new TransientFacebook(array(
'appId' => self::APP_ID,
'secret' => self::SECRET,
));
$encodedUrl = rawurlencode('http://fbrell.com:8080/examples');
$this->assertNotNull(strpos($facebook->getLoginUrl(), $encodedUrl),
'Expect the current url to exist.');
}
public function testSecureCurrentUrl() {
$_SERVER['HTTP_HOST'] = 'fbrell.com';
$_SERVER['REQUEST_URI'] = '/examples';
$_SERVER['HTTPS'] = 'on';
$facebook = new TransientFacebook(array(
'appId' => self::APP_ID,
'secret' => self::SECRET,
));
$encodedUrl = rawurlencode('https://fbrell.com/examples');
$this->assertNotNull(strpos($facebook->getLoginUrl(), $encodedUrl),
'Expect the current url to exist.');
}
public function testSecureCurrentUrlWithNonDefaultPort() {
$_SERVER['HTTP_HOST'] = 'fbrell.com:8080';
$_SERVER['REQUEST_URI'] = '/examples';
$_SERVER['HTTPS'] = 'on';
$facebook = new TransientFacebook(array(
'appId' => self::APP_ID,
'secret' => self::SECRET,
));
$encodedUrl = rawurlencode('https://fbrell.com:8080/examples');
$this->assertNotNull(strpos($facebook->getLoginUrl(), $encodedUrl),
'Expect the current url to exist.');
}
public function testBase64UrlEncode() {
$input = 'Facebook rocks';
$output = 'RmFjZWJvb2sgcm9ja3M';
$this->assertEquals(FBPublic::publicBase64UrlDecode($output), $input);
}
public function testSignedToken() {
$facebook = new FBPublic(array(
'appId' => self::APP_ID,
'secret' => self::SECRET
));
$payload = $facebook->publicParseSignedRequest(self::kValidSignedRequest());
$this->assertNotNull($payload, 'Expected token to parse');
$this->assertEquals($facebook->getSignedRequest(), null);
$_REQUEST['signed_request'] = self::kValidSignedRequest();
$this->assertEquals($facebook->getSignedRequest(), $payload);
}
public function testNonTossedSignedtoken() {
$facebook = new FBPublic(array(
'appId' => self::APP_ID,
'secret' => self::SECRET
));
$payload = $facebook->publicParseSignedRequest(
self::kNonTosedSignedRequest());
$this->assertNotNull($payload, 'Expected token to parse');
$this->assertNull($facebook->getSignedRequest());
$_REQUEST['signed_request'] = self::kNonTosedSignedRequest();
$sr = $facebook->getSignedRequest();
$this->assertTrue(isset($sr['algorithm']));
}
public function testSignedRequestWithEmptyValue() {
$fb = new FBPublicCookie(array(
'appId' => self::APP_ID,
'secret' => self::SECRET
));
$_REQUEST['signed_request'] = self::kSignedRequestWithEmptyValue();
$this->assertNull($fb->getSignedRequest());
$_COOKIE[$fb->publicGetSignedRequestCookieName()] =
self::kSignedRequestWithEmptyValue();
$this->assertNull($fb->getSignedRequest());
}
public function testSignedRequestWithWrongAlgo() {
$fb = new FBPublic(array(
'appId' => self::APP_ID,
'secret' => self::SECRET
));
$payload = $fb->publicParseSignedRequest(
self::kSignedRequestWithWrongAlgo());
$this->assertNull($payload, 'Expected nothing back.');
}
public function testMakeAndParse() {
$fb = new FBPublic(array(
'appId' => self::APP_ID,
'secret' => self::SECRET
));
$data = array('foo' => 42);
$sr = $fb->publicMakeSignedRequest($data);
$decoded = $fb->publicParseSignedRequest($sr);
$this->assertEquals($data['foo'], $decoded['foo']);
}
/**
* @expectedException InvalidArgumentException
*/
public function testMakeSignedRequestExpectsArray() {
$fb = new FBPublic(array(
'appId' => self::APP_ID,
'secret' => self::SECRET
));
$sr = $fb->publicMakeSignedRequest('');
}
public function testBundledCACert() {
$facebook = new TransientFacebook(array(
'appId' => self::APP_ID,
'secret' => self::SECRET
));
// use the bundled cert from the start
Facebook::$CURL_OPTS[CURLOPT_CAINFO] =
dirname(__FILE__) . '/../src/fb_ca_chain_bundle.crt';
$response = $facebook->api('/naitik');
unset(Facebook::$CURL_OPTS[CURLOPT_CAINFO]);
$this->assertEquals(
$response['id'], '5526183', 'should get expected id.');
}
public function testVideoUpload() {
$facebook = new FBRecordURL(array(
'appId' => self::APP_ID,
'secret' => self::SECRET
));
$facebook->api(array('method' => 'video.upload'));
$this->assertContains('//api-video.', $facebook->getRequestedURL(),
'video.upload should go against api-video');
}
public function testVideoUploadGraph() {
$facebook = new FBRecordURL(array(
'appId' => self::APP_ID,
'secret' => self::SECRET
));
$facebook->api('/me/videos', 'POST');
$this->assertContains('//graph-video.', $facebook->getRequestedURL(),
'/me/videos should go against graph-video');
}
public function testGetUserAndAccessTokenFromSession() {
$facebook = new PersistentFBPublic(array(
'appId' => self::APP_ID,
'secret' => self::SECRET
));
$facebook->publicSetPersistentData('access_token',
self::$kExpiredAccessToken);
$facebook->publicSetPersistentData('user_id', 12345);
$this->assertEquals(self::$kExpiredAccessToken,
$facebook->getAccessToken(),
'Get access token from persistent store.');
$this->assertEquals('12345',
$facebook->getUser(),
'Get user id from persistent store.');
}
public function testGetUserAndAccessTokenFromSignedRequestNotSession() {
$facebook = new PersistentFBPublic(array(
'appId' => self::APP_ID,
'secret' => self::SECRET
));
$_REQUEST['signed_request'] = self::kValidSignedRequest();
$facebook->publicSetPersistentData('user_id', 41572);
$facebook->publicSetPersistentData('access_token',
self::$kExpiredAccessToken);
$this->assertNotEquals('41572', $facebook->getUser(),
'Got user from session instead of signed request.');
$this->assertEquals('499834690', $facebook->getUser(),
'Failed to get correct user ID from signed request.');
$this->assertNotEquals(
self::$kExpiredAccessToken,
$facebook->getAccessToken(),
'Got access token from session instead of signed request.');
$this->assertNotEmpty(
$facebook->getAccessToken(),
'Failed to extract an access token from the signed request.');
}
public function testGetUserWithoutCodeOrSignedRequestOrSession() {
$facebook = new PersistentFBPublic(array(
'appId' => self::APP_ID,
'secret' => self::SECRET
));
// deliberately leave $_REQUEST and _$SESSION empty
$this->assertEmpty($_REQUEST,
'GET, POST, and COOKIE params exist even though '.
'they should. Test cannot succeed unless all of '.
'$_REQUEST is empty.');
$this->assertEmpty($_SESSION,
'Session is carrying state and should not be.');
$this->assertEmpty($facebook->getUser(),
'Got a user id, even without a signed request, '.
'access token, or session variable.');
$this->assertEmpty($_SESSION,
'Session superglobal incorrectly populated by getUser.');
}
public function testGetAccessTokenUsingCodeInJsSdkCookie() {
$code = 'code1';
$access_token = 'at1';
$methods_to_stub = array('getSignedRequest', 'getAccessTokenFromCode');
$constructor_args = array(array(
'appId' => self::APP_ID,
'secret' => self::SECRET
));
$stub = $this->getMock(
'TransientFacebook', $methods_to_stub, $constructor_args);
$stub
->expects($this->once())
->method('getSignedRequest')
->will($this->returnValue(array('code' => $code)));
$stub
->expects($this->once())
->method('getAccessTokenFromCode')
->will($this->returnValueMap(array(array($code, '', $access_token))));
$this->assertEquals($stub->getAccessToken(), $access_token);
}
public function testSignedRequestWithoutAuthClearsData() {
$methods_to_stub = array('getSignedRequest', 'clearAllPersistentData');
$constructor_args = array(array(
'appId' => self::APP_ID,
'secret' => self::SECRET
));
$stub = $this->getMock(
'TransientFacebook', $methods_to_stub, $constructor_args);
$stub
->expects($this->once())
->method('getSignedRequest')
->will($this->returnValue(array('foo' => 1)));
$stub
->expects($this->once())
->method('clearAllPersistentData');
$this->assertEquals(self::APP_ID.'|'.self::SECRET, $stub->getAccessToken());
}
public function testInvalidCodeInSignedRequestWillClearData() {
$code = 'code1';
$methods_to_stub = array(
'getSignedRequest',
'getAccessTokenFromCode',
'clearAllPersistentData',
);
$constructor_args = array(array(
'appId' => self::APP_ID,
'secret' => self::SECRET
));
$stub = $this->getMock(
'TransientFacebook', $methods_to_stub, $constructor_args);
$stub
->expects($this->once())
->method('getSignedRequest')
->will($this->returnValue(array('code' => $code)));
$stub
->expects($this->once())
->method('getAccessTokenFromCode')
->will($this->returnValue(null));
$stub
->expects($this->once())
->method('clearAllPersistentData');
$this->assertEquals(self::APP_ID.'|'.self::SECRET, $stub->getAccessToken());
}
public function testInvalidCodeWillClearData() {
$code = 'code1';
$methods_to_stub = array(
'getCode',
'getAccessTokenFromCode',
'clearAllPersistentData',
);
$constructor_args = array(array(
'appId' => self::APP_ID,
'secret' => self::SECRET
));
$stub = $this->getMock(
'TransientFacebook', $methods_to_stub, $constructor_args);
$stub
->expects($this->once())
->method('getCode')
->will($this->returnValue($code));
$stub
->expects($this->once())
->method('getAccessTokenFromCode')
->will($this->returnValue(null));
$stub
->expects($this->once())
->method('clearAllPersistentData');
$this->assertEquals(self::APP_ID.'|'.self::SECRET, $stub->getAccessToken());
}
public function testValidCodeToToken() {
$code = 'code1';
$access_token = 'at1';
$methods_to_stub = array(
'getSignedRequest',
'getCode',
'getAccessTokenFromCode',
);
$constructor_args = array(array(
'appId' => self::APP_ID,
'secret' => self::SECRET
));
$stub = $this->getMock(
'TransientFacebook', $methods_to_stub, $constructor_args);
$stub
->expects($this->once())
->method('getCode')
->will($this->returnValue($code));
$stub
->expects($this->once())
->method('getAccessTokenFromCode')
->will($this->returnValueMap(array(array($code, null, $access_token))));
$this->assertEquals($stub->getAccessToken(), $access_token);
}
public function testSignedRequestWithoutAuthClearsDataInAvailData() {
$methods_to_stub = array('getSignedRequest', 'clearAllPersistentData');
$constructor_args = array(array(
'appId' => self::APP_ID,
'secret' => self::SECRET
));
$stub = $this->getMock(
'TransientFacebook', $methods_to_stub, $constructor_args);
$stub
->expects($this->once())
->method('getSignedRequest')
->will($this->returnValue(array('foo' => 1)));
$stub
->expects($this->once())
->method('clearAllPersistentData');
$this->assertEquals(0, $stub->getUser());
}
public function testFailedToGetUserFromAccessTokenClearsData() {
$methods_to_stub = array(
'getAccessToken',
'getUserFromAccessToken',
'clearAllPersistentData',
);
$constructor_args = array(array(
'appId' => self::APP_ID,
'secret' => self::SECRET
));
$stub = $this->getMock(
'TransientFacebook', $methods_to_stub, $constructor_args);
$stub
->expects($this->once())
->method('getAccessToken')
->will($this->returnValue('at1'));
$stub
->expects($this->once())
->method('getUserFromAccessToken');
$stub
->expects($this->once())
->method('clearAllPersistentData');
$this->assertEquals(0, $stub->getUser());
}
public function testUserFromAccessTokenIsStored() {
$methods_to_stub = array(
'getAccessToken',
'getUserFromAccessToken',
'setPersistentData',
);
$constructor_args = array(array(
'appId' => self::APP_ID,
'secret' => self::SECRET
));
$user = 42;
$stub = $this->getMock(
'TransientFacebook', $methods_to_stub, $constructor_args);
$stub
->expects($this->once())
->method('getAccessToken')
->will($this->returnValue('at1'));
$stub
->expects($this->once())
->method('getUserFromAccessToken')
->will($this->returnValue($user));
$stub
->expects($this->once())
->method('setPersistentData');
$this->assertEquals($user, $stub->getUser());
}
public function testUserFromAccessTokenPullsID() {
$methods_to_stub = array(
'getAccessToken',
'api',
);
$constructor_args = array(array(
'appId' => self::APP_ID,
'secret' => self::SECRET
));
$user = 42;
$stub = $this->getMock(
'TransientFacebook', $methods_to_stub, $constructor_args);
$stub
->expects($this->once())
->method('getAccessToken')
->will($this->returnValue('at1'));
$stub
->expects($this->once())
->method('api')
->will($this->returnValue(array('id' => $user)));
$this->assertEquals($user, $stub->getUser());
}
public function testUserFromAccessTokenResetsOnApiException() {
$methods_to_stub = array(
'getAccessToken',
'clearAllPersistentData',
'api',
);
$constructor_args = array(array(
'appId' => self::APP_ID,
'secret' => self::SECRET
));
$stub = $this->getMock(
'TransientFacebook', $methods_to_stub, $constructor_args);
$stub
->expects($this->once())
->method('getAccessToken')
->will($this->returnValue('at1'));
$stub
->expects($this->once())
->method('api')
->will($this->throwException(new FacebookApiException(false)));
$stub
->expects($this->once())
->method('clearAllPersistentData');
$this->assertEquals(0, $stub->getUser());
}
public function testEmptyCodeReturnsFalse() {
$fb = new FBPublicGetAccessTokenFromCode(array(
'appId' => self::APP_ID,
'secret' => self::SECRET
));
$this->assertFalse($fb->publicGetAccessTokenFromCode(''));
$this->assertFalse($fb->publicGetAccessTokenFromCode(null));
$this->assertFalse($fb->publicGetAccessTokenFromCode(false));
}
public function testNullRedirectURIUsesCurrentURL() {
$methods_to_stub = array(
'_oauthRequest',
'getCurrentUrl',
);
$constructor_args = array(array(
'appId' => self::APP_ID,
'secret' => self::SECRET
));
$access_token = 'at1';
$stub = $this->getMock(
'FBPublicGetAccessTokenFromCode', $methods_to_stub, $constructor_args);
$stub
->expects($this->once())
->method('_oauthRequest')
->will($this->returnValue("access_token=$access_token"));
$stub
->expects($this->once())
->method('getCurrentUrl');
$this->assertEquals(
$access_token, $stub->publicGetAccessTokenFromCode('c'));
}
public function testNullRedirectURIAllowsEmptyStringForCookie() {
$methods_to_stub = array(
'_oauthRequest',
'getCurrentUrl',
);
$constructor_args = array(array(
'appId' => self::APP_ID,
'secret' => self::SECRET
));
$access_token = 'at1';
$stub = $this->getMock(
'FBPublicGetAccessTokenFromCode', $methods_to_stub, $constructor_args);
$stub
->expects($this->once())
->method('_oauthRequest')
->will($this->returnValue("access_token=$access_token"));
$stub
->expects($this->never())
->method('getCurrentUrl');
$this->assertEquals(
$access_token, $stub->publicGetAccessTokenFromCode('c', ''));
}
public function testAPIExceptionDuringCodeExchangeIsIgnored() {
$methods_to_stub = array(
'_oauthRequest',
);
$constructor_args = array(array(
'appId' => self::APP_ID,
'secret' => self::SECRET
));
$stub = $this->getMock(
'FBPublicGetAccessTokenFromCode', $methods_to_stub, $constructor_args);
$stub
->expects($this->once())
->method('_oauthRequest')
->will($this->throwException(new FacebookApiException(false)));
$this->assertFalse($stub->publicGetAccessTokenFromCode('c', ''));
}
public function testEmptyResponseInCodeExchangeIsIgnored() {
$methods_to_stub = array(
'_oauthRequest',
);
$constructor_args = array(array(
'appId' => self::APP_ID,
'secret' => self::SECRET
));
$stub = $this->getMock(
'FBPublicGetAccessTokenFromCode', $methods_to_stub, $constructor_args);
$stub
->expects($this->once())
->method('_oauthRequest')
->will($this->returnValue(''));
$this->assertFalse($stub->publicGetAccessTokenFromCode('c', ''));
}
public function testExistingStateRestoredInConstructor() {
$fb = new FBPublicState(array(
'appId' => self::APP_ID,
'secret' => self::SECRET
));
$this->assertEquals(FBPublicState::STATE, $fb->publicGetState());
}
public function testMissingAccessTokenInCodeExchangeIsIgnored() {
$methods_to_stub = array(
'_oauthRequest',
);
$constructor_args = array(array(
'appId' => self::APP_ID,
'secret' => self::SECRET
));
$stub = $this->getMock(
'FBPublicGetAccessTokenFromCode', $methods_to_stub, $constructor_args);
$stub
->expects($this->once())
->method('_oauthRequest')
->will($this->returnValue('foo=1'));
$this->assertFalse($stub->publicGetAccessTokenFromCode('c', ''));
}
public function testExceptionConstructorWithErrorCode() {
$code = 404;
$e = new FacebookApiException(array('error_code' => $code));
$this->assertEquals($code, $e->getCode());
}
// this happens often despite the fact that it is useless
public function testExceptionTypeFalse() {
$e = new FacebookApiException(false);
$this->assertEquals('Exception', $e->getType());
}
public function testExceptionTypeMixedDraft00() {
$e = new FacebookApiException(array('error' => array('message' => 'foo')));
$this->assertEquals('Exception', $e->getType());
}
public function testExceptionTypeDraft00() {
$error = 'foo';
$e = new FacebookApiException(
array('error' => array('type' => $error, 'message' => 'hello world')));
$this->assertEquals($error, $e->getType());
}
public function testExceptionTypeDraft10() {
$error = 'foo';
$e = new FacebookApiException(array('error' => $error));
$this->assertEquals($error, $e->getType());
}
public function testExceptionTypeDefault() {
$e = new FacebookApiException(array('error' => false));
$this->assertEquals('Exception', $e->getType());
}
public function testExceptionToString() {
$e = new FacebookApiException(array(
'error_code' => 1,
'error_description' => 'foo',
));
$this->assertEquals('Exception: 1: foo', (string) $e);
}
public function testDestroyClearsCookie() {
$fb = new FBPublicCookie(array(
'appId' => self::APP_ID,
'secret' => self::SECRET,
));
$_COOKIE[$fb->publicGetSignedRequestCookieName()] = 'foo';
$_COOKIE[$fb->publicGetMetadataCookieName()] = 'base_domain=fbrell.com';
$_SERVER['HTTP_HOST'] = 'fbrell.com';
$fb->destroySession();
$this->assertFalse(
array_key_exists($fb->publicGetSignedRequestCookieName(), $_COOKIE));
}
public function testAuthExpireSessionDestroysSession() {
$methods_to_stub = array(
'_oauthRequest',
'destroySession',
);
$constructor_args = array(array(
'appId' => self::APP_ID,
'secret' => self::SECRET
));
$key = 'foo';
$val = 42;
$stub = $this->getMock(
'TransientFacebook', $methods_to_stub, $constructor_args);
$stub
->expects($this->once())
->method('_oauthRequest')
->will($this->returnValue("{\"$key\":$val}"));
$stub
->expects($this->once())
->method('destroySession');
$this->assertEquals(
array($key => $val),
$stub->api(array('method' => 'auth.expireSession'))
);
}
public function testLowercaseAuthRevokeAuthDestroysSession() {
$methods_to_stub = array(
'_oauthRequest',
'destroySession',
);
$constructor_args = array(array(
'appId' => self::APP_ID,
'secret' => self::SECRET
));
$key = 'foo';
$val = 42;
$stub = $this->getMock(
'TransientFacebook', $methods_to_stub, $constructor_args);
$stub
->expects($this->once())
->method('_oauthRequest')
->will($this->returnValue("{\"$key\":$val}"));
$stub
->expects($this->once())
->method('destroySession');
$this->assertEquals(
array($key => $val),
$stub->api(array('method' => 'auth.revokeauthorization'))
);
}
/**
* @expectedException FacebookAPIException
*/
public function testErrorCodeFromRestAPIThrowsException() {
$methods_to_stub = array(
'_oauthRequest',
);
$constructor_args = array(array(
'appId' => self::APP_ID,
'secret' => self::SECRET
));
$stub = $this->getMock(
'TransientFacebook', $methods_to_stub, $constructor_args);
$stub
->expects($this->once())
->method('_oauthRequest')
->will($this->returnValue('{"error_code": 500}'));
$stub->api(array('method' => 'foo'));
}
public function testJsonEncodeOfNonStringParams() {
$foo = array(1, 2);
$params = array(
'method' => 'get',
'foo' => $foo,
);
$fb = new FBRecordMakeRequest(array(
'appId' => self::APP_ID,
'secret' => self::SECRET,
));
$fb->api('/naitik', $params);
$requests = $fb->publicGetRequests();
$this->assertEquals(json_encode($foo), $requests[0]['params']['foo']);
}
public function testSessionBackedFacebook() {
$fb = new PersistentFBPublic(array(
'appId' => self::APP_ID,
'secret' => self::SECRET,
));
$key = 'state';
$val = 'foo';
$fb->publicSetPersistentData($key, $val);
$this->assertEquals(
$val,
$_SESSION[sprintf('fb_%s_%s', self::APP_ID, $key)]
);
$this->assertEquals(
$val,
$fb->publicGetPersistentData($key)
);
}
public function testSessionBackedFacebookIgnoresUnsupportedKey() {
$fb = new PersistentFBPublic(array(
'appId' => self::APP_ID,
'secret' => self::SECRET,
));
$key = '--invalid--';
$val = 'foo';
$fb->publicSetPersistentData($key, $val);
$this->assertFalse(
array_key_exists(
sprintf('fb_%s_%s', self::APP_ID, $key),
$_SESSION
)
);
$this->assertFalse($fb->publicGetPersistentData($key));
}
public function testClearSessionBackedFacebook() {
$fb = new PersistentFBPublic(array(
'appId' => self::APP_ID,
'secret' => self::SECRET,
));
$key = 'state';
$val = 'foo';
$fb->publicSetPersistentData($key, $val);
$this->assertEquals(
$val,
$_SESSION[sprintf('fb_%s_%s', self::APP_ID, $key)]
);
$this->assertEquals(
$val,
$fb->publicGetPersistentData($key)
);
$fb->publicClearPersistentData($key);
$this->assertFalse(
array_key_exists(
sprintf('fb_%s_%s', self::APP_ID, $key),
$_SESSION
)
);
$this->assertFalse($fb->publicGetPersistentData($key));
}
public function testSessionBackedFacebookIgnoresUnsupportedKeyInClear() {
$fb = new PersistentFBPublic(array(
'appId' => self::APP_ID,
'secret' => self::SECRET,
));
$key = '--invalid--';
$val = 'foo';
$session_var_name = sprintf('fb_%s_%s', self::APP_ID, $key);
$_SESSION[$session_var_name] = $val;
$fb->publicClearPersistentData($key);
$this->assertTrue(array_key_exists($session_var_name, $_SESSION));
$this->assertFalse($fb->publicGetPersistentData($key));
}
public function testClearAllSessionBackedFacebook() {
$fb = new PersistentFBPublic(array(
'appId' => self::APP_ID,
'secret' => self::SECRET,
));
$key = 'state';
$val = 'foo';
$session_var_name = sprintf('fb_%s_%s', self::APP_ID, $key);
$fb->publicSetPersistentData($key, $val);
$this->assertEquals($val, $_SESSION[$session_var_name]);
$this->assertEquals($val, $fb->publicGetPersistentData($key));
$fb->publicClearAllPersistentData();
$this->assertFalse(array_key_exists($session_var_name, $_SESSION));
$this->assertFalse($fb->publicGetPersistentData($key));
}
public function testSharedSessionBackedFacebook() {
$_SERVER['HTTP_HOST'] = 'fbrell.com';
$fb = new PersistentFBPublic(array(
'appId' => self::APP_ID,
'secret' => self::SECRET,
'sharedSession' => true,
));
$key = 'state';
$val = 'foo';
$session_var_name = sprintf(
'%s_fb_%s_%s',
$fb->publicGetSharedSessionID(),
self::APP_ID,
$key
);
$fb->publicSetPersistentData($key, $val);
$this->assertEquals($val, $_SESSION[$session_var_name]);
$this->assertEquals($val, $fb->publicGetPersistentData($key));
}
public function testSharedSessionBackedFacebookIgnoresUnsupportedKey() {
$_SERVER['HTTP_HOST'] = 'fbrell.com';
$fb = new PersistentFBPublic(array(
'appId' => self::APP_ID,
'secret' => self::SECRET,
'sharedSession' => true,
));
$key = '--invalid--';
$val = 'foo';
$session_var_name = sprintf(
'%s_fb_%s_%s',
$fb->publicGetSharedSessionID(),
self::APP_ID,
$key
);
$fb->publicSetPersistentData($key, $val);
$this->assertFalse(array_key_exists($session_var_name, $_SESSION));
$this->assertFalse($fb->publicGetPersistentData($key));
}
public function testSharedClearSessionBackedFacebook() {
$_SERVER['HTTP_HOST'] = 'fbrell.com';
$fb = new PersistentFBPublic(array(
'appId' => self::APP_ID,
'secret' => self::SECRET,
'sharedSession' => true,
));
$key = 'state';
$val = 'foo';
$session_var_name = sprintf(
'%s_fb_%s_%s',
$fb->publicGetSharedSessionID(),
self::APP_ID,
$key
);
$fb->publicSetPersistentData($key, $val);
$this->assertEquals($val, $_SESSION[$session_var_name]);
$this->assertEquals($val, $fb->publicGetPersistentData($key));
$fb->publicClearPersistentData($key);
$this->assertFalse(array_key_exists($session_var_name, $_SESSION));
$this->assertFalse($fb->publicGetPersistentData($key));
}
public function testSharedSessionBackedFacebookIgnoresUnsupportedKeyInClear() {
$_SERVER['HTTP_HOST'] = 'fbrell.com';
$fb = new PersistentFBPublic(array(
'appId' => self::APP_ID,
'secret' => self::SECRET,
'sharedSession' => true,
));
$key = '--invalid--';
$val = 'foo';
$session_var_name = sprintf(
'%s_fb_%s_%s',
$fb->publicGetSharedSessionID(),
self::APP_ID,
$key
);
$_SESSION[$session_var_name] = $val;
$fb->publicClearPersistentData($key);
$this->assertTrue(array_key_exists($session_var_name, $_SESSION));
$this->assertFalse($fb->publicGetPersistentData($key));
}
public function testSharedClearAllSessionBackedFacebook() {
$_SERVER['HTTP_HOST'] = 'fbrell.com';
$fb = new PersistentFBPublic(array(
'appId' => self::APP_ID,
'secret' => self::SECRET,
'sharedSession' => true,
));
$key = 'state';
$val = 'foo';
$session_var_name = sprintf(
'%s_fb_%s_%s',
$fb->publicGetSharedSessionID(),
self::APP_ID,
$key
);
$fb->publicSetPersistentData($key, $val);
$this->assertEquals($val, $_SESSION[$session_var_name]);
$this->assertEquals($val, $fb->publicGetPersistentData($key));
$fb->publicClearAllPersistentData();
$this->assertFalse(array_key_exists($session_var_name, $_SESSION));
$this->assertFalse($fb->publicGetPersistentData($key));
}
public function testSharedSessionBackedFacebookIsRestored() {
$_SERVER['HTTP_HOST'] = 'fbrell.com';
$fb = new PersistentFBPublic(array(
'appId' => self::APP_ID,
'secret' => self::SECRET,
'sharedSession' => true,
));
$key = 'state';
$val = 'foo';
$shared_session_id = $fb->publicGetSharedSessionID();
$session_var_name = sprintf(
'%s_fb_%s_%s',
$shared_session_id,
self::APP_ID,
$key
);
$fb->publicSetPersistentData($key, $val);
$this->assertEquals($val, $_SESSION[$session_var_name]);
$this->assertEquals($val, $fb->publicGetPersistentData($key));
// check the new instance has the same data
$fb = new PersistentFBPublic(array(
'appId' => self::APP_ID,
'secret' => self::SECRET,
'sharedSession' => true,
));
$this->assertEquals(
$shared_session_id,
$fb->publicGetSharedSessionID()
);
$this->assertEquals($val, $fb->publicGetPersistentData($key));
}
public function testSharedSessionBackedFacebookIsNotRestoredWhenCorrupt() {
$_SERVER['HTTP_HOST'] = 'fbrell.com';
$fb = new PersistentFBPublic(array(
'appId' => self::APP_ID,
'secret' => self::SECRET,
'sharedSession' => true,
));
$key = 'state';
$val = 'foo';
$shared_session_id = $fb->publicGetSharedSessionID();
$session_var_name = sprintf(
'%s_fb_%s_%s',
$shared_session_id,
self::APP_ID,
$key
);
$fb->publicSetPersistentData($key, $val);
$this->assertEquals($val, $_SESSION[$session_var_name]);
$this->assertEquals($val, $fb->publicGetPersistentData($key));
// break the cookie
$cookie_name = $fb->publicGetSharedSessionCookieName();
$_COOKIE[$cookie_name] = substr($_COOKIE[$cookie_name], 1);
// check the new instance does not have the data
$fb = new PersistentFBPublic(array(
'appId' => self::APP_ID,
'secret' => self::SECRET,
'sharedSession' => true,
));
$this->assertFalse($fb->publicGetPersistentData($key));
$this->assertNotEquals(
$shared_session_id,
$fb->publicGetSharedSessionID()
);
}
public function testHttpHost() {
$real = 'foo.com';
$_SERVER['HTTP_HOST'] = $real;
$_SERVER['HTTP_X_FORWARDED_HOST'] = 'evil.com';
$fb = new PersistentFBPublic(array(
'appId' => self::APP_ID,
'secret' => self::SECRET,
));
$this->assertEquals($real, $fb->publicGetHttpHost());
}
public function testHttpProtocol() {
$_SERVER['HTTPS'] = 'on';
$_SERVER['HTTP_X_FORWARDED_PROTO'] = 'http';
$fb = new PersistentFBPublic(array(
'appId' => self::APP_ID,
'secret' => self::SECRET,
));
$this->assertEquals('https', $fb->publicGetHttpProtocol());
}
public function testHttpHostForwarded() {
$real = 'foo.com';
$_SERVER['HTTP_HOST'] = 'localhost';
$_SERVER['HTTP_X_FORWARDED_HOST'] = $real;
$fb = new PersistentFBPublic(array(
'appId' => self::APP_ID,
'secret' => self::SECRET,
'trustForwarded' => true,
));
$this->assertEquals($real, $fb->publicGetHttpHost());
}
public function testHttpProtocolForwarded() {
$_SERVER['HTTPS'] = 'on';
$_SERVER['HTTP_X_FORWARDED_PROTO'] = 'http';
$fb = new PersistentFBPublic(array(
'appId' => self::APP_ID,
'secret' => self::SECRET,
'trustForwarded' => true,
));
$this->assertEquals('http', $fb->publicGetHttpProtocol());
}
public function testHttpProtocolForwardedSecure() {
$_SERVER['HTTPS'] = 'on';
$_SERVER['HTTP_X_FORWARDED_PROTO'] = 'https';
$fb = new PersistentFBPublic(array(
'appId' => self::APP_ID,
'secret' => self::SECRET,
'trustForwarded' => true,
));
$this->assertEquals('https', $fb->publicGetHttpProtocol());
}
/**
* @dataProvider provideEndsWith
*/
public function testEndsWith($big, $small, $result) {
$this->assertEquals(
$result,
PersistentFBPublic::publicEndsWith($big, $small)
);
}
public function provideEndsWith() {
return array(
array('', '', true),
array('', 'a', false),
array('a', '', true),
array('a', 'b', false),
array('a', 'a', true),
array('aa', 'a', true),
array('ab', 'a', false),
array('ba', 'a', true),
);
}
/**
* @dataProvider provideIsAllowedDomain
*/
public function testIsAllowedDomain($big, $small, $result) {
$this->assertEquals(
$result,
PersistentFBPublic::publicIsAllowedDomain($big, $small)
);
}
public function provideIsAllowedDomain() {
return array(
array('fbrell.com', 'fbrell.com', true),
array('foo.fbrell.com', 'fbrell.com', true),
array('foofbrell.com', 'fbrell.com', false),
array('evil.com', 'fbrell.com', false),
array('foo.fbrell.com', 'bar.fbrell.com', false),
);
}
protected function generateMD5HashOfRandomValue() {
return md5(uniqid(mt_rand(), true));
}
protected function setUp() {
parent::setUp();
}
protected function tearDown() {
$this->clearSuperGlobals();
parent::tearDown();
}
protected function clearSuperGlobals() {
unset($_SERVER['HTTPS']);
unset($_SERVER['HTTP_HOST']);
unset($_SERVER['REQUEST_URI']);
$_SESSION = array();
$_COOKIE = array();
$_REQUEST = array();
$_POST = array();
$_GET = array();
if (session_id()) {
session_destroy();
}
}
/**
* Checks that the correct args are a subset of the returned obj
* @param array $correct The correct array values
* @param array $actual The values in practice
* @param string $message to be shown on failure
*/
protected function assertIsSubset($correct, $actual, $msg='') {
foreach ($correct as $key => $value) {
$actual_value = $actual[$key];
$newMsg = (strlen($msg) ? ($msg.' ') : '').'Key: '.$key;
$this->assertEquals($value, $actual_value, $newMsg);
}
}
}
class TransientFacebook extends BaseFacebook {
protected function setPersistentData($key, $value) {}
protected function getPersistentData($key, $default = false) {
return $default;
}
protected function clearPersistentData($key) {}
protected function clearAllPersistentData() {}
}
class FBRecordURL extends TransientFacebook {
private $url;
protected function _oauthRequest($url, $params) {
$this->url = $url;
}
public function getRequestedURL() {
return $this->url;
}
}
class FBRecordMakeRequest extends TransientFacebook {
private $requests = array();
protected function makeRequest($url, $params, $ch=null) {
$this->requests[] = array(
'url' => $url,
'params' => $params,
);
return parent::makeRequest($url, $params, $ch);
}
public function publicGetRequests() {
return $this->requests;
}
}
class FBPublic extends TransientFacebook {
public static function publicBase64UrlDecode($input) {
return self::base64UrlDecode($input);
}
public static function publicBase64UrlEncode($input) {
return self::base64UrlEncode($input);
}
public function publicParseSignedRequest($input) {
return $this->parseSignedRequest($input);
}
public function publicMakeSignedRequest($data) {
return $this->makeSignedRequest($data);
}
}
class PersistentFBPublic extends Facebook {
public function publicParseSignedRequest($input) {
return $this->parseSignedRequest($input);
}
public function publicSetPersistentData($key, $value) {
$this->setPersistentData($key, $value);
}
public function publicGetPersistentData($key, $default = false) {
return $this->getPersistentData($key, $default);
}
public function publicClearPersistentData($key) {
return $this->clearPersistentData($key);
}
public function publicClearAllPersistentData() {
return $this->clearAllPersistentData();
}
public function publicGetSharedSessionID() {
return $this->sharedSessionID;
}
public static function publicIsAllowedDomain($big, $small) {
return self::isAllowedDomain($big, $small);
}
public static function publicEndsWith($big, $small) {
return self::endsWith($big, $small);
}
public function publicGetSharedSessionCookieName() {
return $this->getSharedSessionCookieName();
}
public function publicGetHttpHost() {
return $this->getHttpHost();
}
public function publicGetHttpProtocol() {
return $this->getHttpProtocol();
}
}
class FBCode extends Facebook {
public function publicGetCode() {
return $this->getCode();
}
public function setCSRFStateToken() {
$this->establishCSRFTokenState();
}
public function getCSRFStateToken() {
return $this->getPersistentData('state');
}
}
class FBAccessToken extends TransientFacebook {
public function publicGetApplicationAccessToken() {
return $this->getApplicationAccessToken();
}
}
class FBGetCurrentURLFacebook extends TransientFacebook {
public function publicGetCurrentUrl() {
return $this->getCurrentUrl();
}
}
class FBPublicCookie extends TransientFacebook {
public function publicGetSignedRequest() {
return $this->getSignedRequest();
}
public function publicGetSignedRequestCookieName() {
return $this->getSignedRequestCookieName();
}
public function publicGetMetadataCookie() {
return $this->getMetadataCookie();
}
public function publicGetMetadataCookieName() {
return $this->getMetadataCookieName();
}
}
class FBRewrite extends Facebook{
public function uncacheSignedRequest(){
$this->signedRequest = null;
}
public function uncache()
{
$this->user = null;
$this->signedRequest = null;
$this->accessToken = null;
}
}
class FBPublicGetAccessTokenFromCode extends TransientFacebook {
public function publicGetAccessTokenFromCode($code, $redirect_uri = null) {
return $this->getAccessTokenFromCode($code, $redirect_uri);
}
}
class FBPublicState extends TransientFacebook {
const STATE = 'foo';
protected function getPersistentData($key, $default = false) {
if ($key === 'state') {
return self::STATE;
}
return parent::getPersistentData($key, $default);
}
public function publicGetState() {
return $this->state;
}
}