mirror of
https://github.com/salesagility/SuiteCRM.git
synced 2024-11-22 16:02:36 +00:00
2533 lines
75 KiB
PHP
2533 lines
75 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 testPersistentCSRFState()
|
|
{
|
|
$facebook = new FBCode(array(
|
|
'appId' => self::APP_ID,
|
|
'secret' => self::SECRET,
|
|
));
|
|
$facebook->setCSRFStateToken();
|
|
$code = $facebook->getCSRFStateToken();
|
|
|
|
$facebook = new FBCode(array(
|
|
'appId' => self::APP_ID,
|
|
'secret' => self::SECRET,
|
|
));
|
|
|
|
$this->assertEquals(
|
|
$code,
|
|
$facebook->publicGetState(),
|
|
'Persisted CSRF state token not loaded correctly'
|
|
);
|
|
}
|
|
|
|
public function testPersistentCSRFStateWithSharedSession()
|
|
{
|
|
$_SERVER['HTTP_HOST'] = 'fbrell.com';
|
|
$facebook = new FBCode(array(
|
|
'appId' => self::APP_ID,
|
|
'secret' => self::SECRET,
|
|
'sharedSession' => true,
|
|
));
|
|
$facebook->setCSRFStateToken();
|
|
$code = $facebook->getCSRFStateToken();
|
|
|
|
$facebook = new FBCode(array(
|
|
'appId' => self::APP_ID,
|
|
'secret' => self::SECRET,
|
|
'sharedSession' => true,
|
|
));
|
|
|
|
$this->assertEquals(
|
|
$code,
|
|
$facebook->publicGetState(),
|
|
'Persisted CSRF state token not loaded correctly with shared session'
|
|
);
|
|
}
|
|
|
|
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 testDisallowSignedRequest()
|
|
{
|
|
$facebook = new TransientFacebook(array(
|
|
'appId' => self::APP_ID,
|
|
'secret' => self::SECRET,
|
|
'allowSignedRequest' => false
|
|
));
|
|
|
|
$_REQUEST['signed_request'] = self::kValidSignedRequest();
|
|
$this->assertEquals(
|
|
0,
|
|
$facebook->getUser(),
|
|
'Should not have received valid user from 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
|
|
));
|
|
$sr = self::kValidSignedRequest();
|
|
$payload = $facebook->publicParseSignedRequest($sr);
|
|
$this->assertNotNull($payload, 'Expected token to parse');
|
|
$this->assertEquals($facebook->getSignedRequest(), null);
|
|
$_REQUEST['signed_request'] = $sr;
|
|
$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 testAppsecretProofNoParams()
|
|
{
|
|
$fb = new FBRecordMakeRequest(array(
|
|
'appId' => self::APP_ID,
|
|
'secret' => self::SECRET,
|
|
));
|
|
$token = $fb->getAccessToken();
|
|
$proof = $fb->publicGetAppSecretProof($token);
|
|
$params = array();
|
|
$fb->api('/mattynoce', $params);
|
|
$requests = $fb->publicGetRequests();
|
|
$this->assertEquals($proof, $requests[0]['params']['appsecret_proof']);
|
|
}
|
|
|
|
public function testAppsecretProofWithParams()
|
|
{
|
|
$fb = new FBRecordMakeRequest(array(
|
|
'appId' => self::APP_ID,
|
|
'secret' => self::SECRET,
|
|
));
|
|
$proof = 'foo';
|
|
$params = array('appsecret_proof' => $proof);
|
|
$fb->api('/mattynoce', $params);
|
|
$requests = $fb->publicGetRequests();
|
|
$this->assertEquals($proof, $requests[0]['params']['appsecret_proof']);
|
|
}
|
|
|
|
public function testExceptionConstructorWithErrorCode()
|
|
{
|
|
$code = 404;
|
|
$e = new FacebookApiException(array('error_code' => $code));
|
|
$this->assertEquals($code, $e->getCode());
|
|
}
|
|
|
|
public function testExceptionConstructorWithInvalidErrorCode()
|
|
{
|
|
$e = new FacebookApiException(array('error_code' => 'not an int'));
|
|
$this->assertEquals(0, $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;
|
|
}
|
|
|
|
public function publicGetAppSecretProof($access_token)
|
|
{
|
|
return $this->getAppSecretProof($access_token);
|
|
}
|
|
}
|
|
|
|
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 publicGetState()
|
|
{
|
|
return $this->state;
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|