diff options
author | emkael <emkael@tlen.pl> | 2018-04-26 01:00:12 +0200 |
---|---|---|
committer | emkael <emkael@tlen.pl> | 2018-04-26 01:00:12 +0200 |
commit | 4b8a9a5189a625bf99fedec7fd31f6e146410a14 (patch) | |
tree | a29759d5f0f0c29f07c89c59f6b5cf38407d1470 /lib/facebook-graph-sdk/src/Facebook | |
parent | ab82beef33f4c196383a81213dcdff4ebe9447ae (diff) |
Update FB API library
Diffstat (limited to 'lib/facebook-graph-sdk/src/Facebook')
76 files changed, 1258 insertions, 355 deletions
diff --git a/lib/facebook-graph-sdk/src/Facebook/Authentication/AccessToken.php b/lib/facebook-graph-sdk/src/Facebook/Authentication/AccessToken.php index 582ea61..5d70073 100644 --- a/lib/facebook-graph-sdk/src/Facebook/Authentication/AccessToken.php +++ b/lib/facebook-graph-sdk/src/Facebook/Authentication/AccessToken.php @@ -1,6 +1,6 @@ <?php /** - * Copyright 2014 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * You are hereby granted a non-exclusive, worldwide, royalty-free license to * use, copy, modify, and distribute this software in source code or binary diff --git a/lib/facebook-graph-sdk/src/Facebook/Authentication/AccessTokenMetadata.php b/lib/facebook-graph-sdk/src/Facebook/Authentication/AccessTokenMetadata.php index f302a6d..165433c 100644 --- a/lib/facebook-graph-sdk/src/Facebook/Authentication/AccessTokenMetadata.php +++ b/lib/facebook-graph-sdk/src/Facebook/Authentication/AccessTokenMetadata.php @@ -1,6 +1,6 @@ <?php /** - * Copyright 2014 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * You are hereby granted a non-exclusive, worldwide, royalty-free license to * use, copy, modify, and distribute this software in source code or binary @@ -382,7 +382,7 @@ class AccessTokenMetadata private function castTimestampsToDateTime() { foreach (static::$dateProperties as $key) { - if (isset($this->metadata[$key])) { + if (isset($this->metadata[$key]) && $this->metadata[$key] !== 0) { $this->metadata[$key] = $this->convertTimestampToDateTime($this->metadata[$key]); } } diff --git a/lib/facebook-graph-sdk/src/Facebook/Authentication/OAuth2Client.php b/lib/facebook-graph-sdk/src/Facebook/Authentication/OAuth2Client.php index 8e364ec..94df9b7 100644 --- a/lib/facebook-graph-sdk/src/Facebook/Authentication/OAuth2Client.php +++ b/lib/facebook-graph-sdk/src/Facebook/Authentication/OAuth2Client.php @@ -1,6 +1,6 @@ <?php /** - * Copyright 2014 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * You are hereby granted a non-exclusive, worldwide, royalty-free license to * use, copy, modify, and distribute this software in source code or binary @@ -125,8 +125,8 @@ class OAuth2Client * Generates an authorization URL to begin the process of authenticating a user. * * @param string $redirectUrl The callback URL to redirect to. - * @param array $scope An array of permissions to request. * @param string $state The CSPRNG-generated CSRF value. + * @param array $scope An array of permissions to request. * @param array $params An array of parameters to generate URL. * @param string $separator The separator to use in http_build_query(). * @@ -250,9 +250,9 @@ class OAuth2Client /** * Send a request to Graph with an app access token. * - * @param string $endpoint - * @param array $params - * @param string|null $accessToken + * @param string $endpoint + * @param array $params + * @param AccessToken|string|null $accessToken * * @return FacebookResponse * diff --git a/lib/facebook-graph-sdk/src/Facebook/Exceptions/FacebookAuthenticationException.php b/lib/facebook-graph-sdk/src/Facebook/Exceptions/FacebookAuthenticationException.php index 449cf93..c5e45fa 100644 --- a/lib/facebook-graph-sdk/src/Facebook/Exceptions/FacebookAuthenticationException.php +++ b/lib/facebook-graph-sdk/src/Facebook/Exceptions/FacebookAuthenticationException.php @@ -1,6 +1,6 @@ <?php /** - * Copyright 2014 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * You are hereby granted a non-exclusive, worldwide, royalty-free license to * use, copy, modify, and distribute this software in source code or binary diff --git a/lib/facebook-graph-sdk/src/Facebook/Exceptions/FacebookAuthorizationException.php b/lib/facebook-graph-sdk/src/Facebook/Exceptions/FacebookAuthorizationException.php index 4938c42..3a7f557 100644 --- a/lib/facebook-graph-sdk/src/Facebook/Exceptions/FacebookAuthorizationException.php +++ b/lib/facebook-graph-sdk/src/Facebook/Exceptions/FacebookAuthorizationException.php @@ -1,6 +1,6 @@ <?php /** - * Copyright 2014 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * You are hereby granted a non-exclusive, worldwide, royalty-free license to * use, copy, modify, and distribute this software in source code or binary diff --git a/lib/facebook-graph-sdk/src/Facebook/Exceptions/FacebookClientException.php b/lib/facebook-graph-sdk/src/Facebook/Exceptions/FacebookClientException.php index b006283..6a899b7 100644 --- a/lib/facebook-graph-sdk/src/Facebook/Exceptions/FacebookClientException.php +++ b/lib/facebook-graph-sdk/src/Facebook/Exceptions/FacebookClientException.php @@ -1,6 +1,6 @@ <?php /** - * Copyright 2014 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * You are hereby granted a non-exclusive, worldwide, royalty-free license to * use, copy, modify, and distribute this software in source code or binary diff --git a/lib/facebook-graph-sdk/src/Facebook/Exceptions/FacebookOtherException.php b/lib/facebook-graph-sdk/src/Facebook/Exceptions/FacebookOtherException.php index 9cc94a5..06a33ac 100644 --- a/lib/facebook-graph-sdk/src/Facebook/Exceptions/FacebookOtherException.php +++ b/lib/facebook-graph-sdk/src/Facebook/Exceptions/FacebookOtherException.php @@ -1,6 +1,6 @@ <?php /** - * Copyright 2014 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * You are hereby granted a non-exclusive, worldwide, royalty-free license to * use, copy, modify, and distribute this software in source code or binary diff --git a/lib/facebook-graph-sdk/src/Facebook/Exceptions/FacebookResponseException.php b/lib/facebook-graph-sdk/src/Facebook/Exceptions/FacebookResponseException.php index c1b19f9..4a135db 100644 --- a/lib/facebook-graph-sdk/src/Facebook/Exceptions/FacebookResponseException.php +++ b/lib/facebook-graph-sdk/src/Facebook/Exceptions/FacebookResponseException.php @@ -1,6 +1,6 @@ <?php /** - * Copyright 2014 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * You are hereby granted a non-exclusive, worldwide, royalty-free license to * use, copy, modify, and distribute this software in source code or binary @@ -77,8 +77,6 @@ class FacebookResponseException extends FacebookSDKException $code = isset($data['error']['code']) ? $data['error']['code'] : null; $message = isset($data['error']['message']) ? $data['error']['message'] : 'Unknown error from Graph.'; - $previousException = null; - if (isset($data['error']['error_subcode'])) { switch ($data['error']['error_subcode']) { // Other authentication issues @@ -89,6 +87,14 @@ class FacebookResponseException extends FacebookSDKException case 464: case 467: return new static($response, new FacebookAuthenticationException($message, $code)); + // Video upload resumable error + case 1363030: + case 1363019: + case 1363037: + case 1363033: + case 1363021: + case 1363041: + return new static($response, new FacebookResumableUploadException($message, $code)); } } @@ -107,7 +113,9 @@ class FacebookResponseException extends FacebookSDKException // API Throttling case 4: case 17: + case 32: case 341: + case 613: return new static($response, new FacebookThrottleException($message, $code)); // Duplicate Post diff --git a/lib/facebook-graph-sdk/src/Facebook/Exceptions/FacebookResumableUploadException.php b/lib/facebook-graph-sdk/src/Facebook/Exceptions/FacebookResumableUploadException.php new file mode 100644 index 0000000..6f47066 --- /dev/null +++ b/lib/facebook-graph-sdk/src/Facebook/Exceptions/FacebookResumableUploadException.php @@ -0,0 +1,33 @@ +<?php +/** + * Copyright 2017 Facebook, Inc. + * + * You are hereby granted a non-exclusive, worldwide, royalty-free license to + * use, copy, modify, and distribute this software in source code or binary + * form for use in connection with the web services and APIs provided by + * Facebook. + * + * As with any software that integrates with the Facebook platform, your use + * of this software is subject to the Facebook Developer Principles and + * Policies [http://developers.facebook.com/policy/]. This copyright notice + * shall be included in all copies or substantial portions of the software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ +namespace Facebook\Exceptions; + +/** + * Class FacebookResumableUploadException + * + * @package Facebook + */ +class FacebookResumableUploadException extends FacebookSDKException +{ +} diff --git a/lib/facebook-graph-sdk/src/Facebook/Exceptions/FacebookSDKException.php b/lib/facebook-graph-sdk/src/Facebook/Exceptions/FacebookSDKException.php index 03219b0..d8bef1a 100644 --- a/lib/facebook-graph-sdk/src/Facebook/Exceptions/FacebookSDKException.php +++ b/lib/facebook-graph-sdk/src/Facebook/Exceptions/FacebookSDKException.php @@ -1,6 +1,6 @@ <?php /** - * Copyright 2014 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * You are hereby granted a non-exclusive, worldwide, royalty-free license to * use, copy, modify, and distribute this software in source code or binary diff --git a/lib/facebook-graph-sdk/src/Facebook/Exceptions/FacebookServerException.php b/lib/facebook-graph-sdk/src/Facebook/Exceptions/FacebookServerException.php index 0790b08..5e0b625 100644 --- a/lib/facebook-graph-sdk/src/Facebook/Exceptions/FacebookServerException.php +++ b/lib/facebook-graph-sdk/src/Facebook/Exceptions/FacebookServerException.php @@ -1,6 +1,6 @@ <?php /** - * Copyright 2014 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * You are hereby granted a non-exclusive, worldwide, royalty-free license to * use, copy, modify, and distribute this software in source code or binary diff --git a/lib/facebook-graph-sdk/src/Facebook/Exceptions/FacebookThrottleException.php b/lib/facebook-graph-sdk/src/Facebook/Exceptions/FacebookThrottleException.php index 6d1e825..47fec0e 100644 --- a/lib/facebook-graph-sdk/src/Facebook/Exceptions/FacebookThrottleException.php +++ b/lib/facebook-graph-sdk/src/Facebook/Exceptions/FacebookThrottleException.php @@ -1,6 +1,6 @@ <?php /** - * Copyright 2014 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * You are hereby granted a non-exclusive, worldwide, royalty-free license to * use, copy, modify, and distribute this software in source code or binary diff --git a/lib/facebook-graph-sdk/src/Facebook/Facebook.php b/lib/facebook-graph-sdk/src/Facebook/Facebook.php index 227a166..bf93119 100644 --- a/lib/facebook-graph-sdk/src/Facebook/Facebook.php +++ b/lib/facebook-graph-sdk/src/Facebook/Facebook.php @@ -1,6 +1,6 @@ <?php /** - * Copyright 2014 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * You are hereby granted a non-exclusive, worldwide, royalty-free license to * use, copy, modify, and distribute this software in source code or binary @@ -26,21 +26,17 @@ namespace Facebook; use Facebook\Authentication\AccessToken; use Facebook\Authentication\OAuth2Client; use Facebook\FileUpload\FacebookFile; +use Facebook\FileUpload\FacebookResumableUploader; +use Facebook\FileUpload\FacebookTransferChunk; use Facebook\FileUpload\FacebookVideo; use Facebook\GraphNodes\GraphEdge; use Facebook\Url\UrlDetectionInterface; use Facebook\Url\FacebookUrlDetectionHandler; +use Facebook\PseudoRandomString\PseudoRandomStringGeneratorFactory; use Facebook\PseudoRandomString\PseudoRandomStringGeneratorInterface; -use Facebook\PseudoRandomString\McryptPseudoRandomStringGenerator; -use Facebook\PseudoRandomString\OpenSslPseudoRandomStringGenerator; -use Facebook\PseudoRandomString\UrandomPseudoRandomStringGenerator; -use Facebook\HttpClients\FacebookHttpClientInterface; -use Facebook\HttpClients\FacebookCurlHttpClient; -use Facebook\HttpClients\FacebookStreamHttpClient; -use Facebook\HttpClients\FacebookGuzzleHttpClient; +use Facebook\HttpClients\HttpClientsFactory; +use Facebook\PersistentData\PersistentDataFactory; use Facebook\PersistentData\PersistentDataInterface; -use Facebook\PersistentData\FacebookSessionPersistentDataHandler; -use Facebook\PersistentData\FacebookMemoryPersistentDataHandler; use Facebook\Helpers\FacebookCanvasHelper; use Facebook\Helpers\FacebookJavaScriptHelper; use Facebook\Helpers\FacebookPageTabHelper; @@ -57,12 +53,12 @@ class Facebook /** * @const string Version number of the Facebook PHP SDK. */ - const VERSION = '5.0.0'; + const VERSION = '5.6.2'; /** * @const string Default Graph API version for requests. */ - const DEFAULT_GRAPH_VERSION = 'v2.4'; + const DEFAULT_GRAPH_VERSION = 'v2.10'; /** * @const string The name of the environment variable that contains the app ID. @@ -128,80 +124,43 @@ class Facebook */ public function __construct(array $config = []) { - $appId = isset($config['app_id']) ? $config['app_id'] : getenv(static::APP_ID_ENV_NAME); - if (!$appId) { + $config = array_merge([ + 'app_id' => getenv(static::APP_ID_ENV_NAME), + 'app_secret' => getenv(static::APP_SECRET_ENV_NAME), + 'default_graph_version' => static::DEFAULT_GRAPH_VERSION, + 'enable_beta_mode' => false, + 'http_client_handler' => null, + 'persistent_data_handler' => null, + 'pseudo_random_string_generator' => null, + 'url_detection_handler' => null, + ], $config); + + if (!$config['app_id']) { throw new FacebookSDKException('Required "app_id" key not supplied in config and could not find fallback environment variable "' . static::APP_ID_ENV_NAME . '"'); } - - $appSecret = isset($config['app_secret']) ? $config['app_secret'] : getenv(static::APP_SECRET_ENV_NAME); - if (!$appSecret) { + if (!$config['app_secret']) { throw new FacebookSDKException('Required "app_secret" key not supplied in config and could not find fallback environment variable "' . static::APP_SECRET_ENV_NAME . '"'); } - $this->app = new FacebookApp($appId, $appSecret); - - $httpClientHandler = null; - if (isset($config['http_client_handler'])) { - if ($config['http_client_handler'] instanceof FacebookHttpClientInterface) { - $httpClientHandler = $config['http_client_handler']; - } elseif ($config['http_client_handler'] === 'curl') { - $httpClientHandler = new FacebookCurlHttpClient(); - } elseif ($config['http_client_handler'] === 'stream') { - $httpClientHandler = new FacebookStreamHttpClient(); - } elseif ($config['http_client_handler'] === 'guzzle') { - $httpClientHandler = new FacebookGuzzleHttpClient(); - } else { - throw new \InvalidArgumentException('The http_client_handler must be set to "curl", "stream", "guzzle", or be an instance of Facebook\HttpClients\FacebookHttpClientInterface'); - } - } - - $enableBeta = isset($config['enable_beta_mode']) && $config['enable_beta_mode'] === true; - $this->client = new FacebookClient($httpClientHandler, $enableBeta); - - if (isset($config['url_detection_handler'])) { - if ($config['url_detection_handler'] instanceof UrlDetectionInterface) { - $this->urlDetectionHandler = $config['url_detection_handler']; - } else { - throw new \InvalidArgumentException('The url_detection_handler must be an instance of Facebook\Url\UrlDetectionInterface'); - } - } - - if (isset($config['pseudo_random_string_generator'])) { - if ($config['pseudo_random_string_generator'] instanceof PseudoRandomStringGeneratorInterface) { - $this->pseudoRandomStringGenerator = $config['pseudo_random_string_generator']; - } elseif ($config['pseudo_random_string_generator'] === 'mcrypt') { - $this->pseudoRandomStringGenerator = new McryptPseudoRandomStringGenerator(); - } elseif ($config['pseudo_random_string_generator'] === 'openssl') { - $this->pseudoRandomStringGenerator = new OpenSslPseudoRandomStringGenerator(); - } elseif ($config['pseudo_random_string_generator'] === 'urandom') { - $this->pseudoRandomStringGenerator = new UrandomPseudoRandomStringGenerator(); - } else { - throw new \InvalidArgumentException('The pseudo_random_string_generator must be set to "mcrypt", "openssl", or "urandom", or be an instance of Facebook\PseudoRandomString\PseudoRandomStringGeneratorInterface'); - } - } - - if (isset($config['persistent_data_handler'])) { - if ($config['persistent_data_handler'] instanceof PersistentDataInterface) { - $this->persistentDataHandler = $config['persistent_data_handler']; - } elseif ($config['persistent_data_handler'] === 'session') { - $this->persistentDataHandler = new FacebookSessionPersistentDataHandler(); - } elseif ($config['persistent_data_handler'] === 'memory') { - $this->persistentDataHandler = new FacebookMemoryPersistentDataHandler(); - } else { - throw new \InvalidArgumentException('The persistent_data_handler must be set to "session", "memory", or be an instance of Facebook\PersistentData\PersistentDataInterface'); - } - } + $this->app = new FacebookApp($config['app_id'], $config['app_secret']); + $this->client = new FacebookClient( + HttpClientsFactory::createHttpClient($config['http_client_handler']), + $config['enable_beta_mode'] + ); + $this->pseudoRandomStringGenerator = PseudoRandomStringGeneratorFactory::createPseudoRandomStringGenerator( + $config['pseudo_random_string_generator'] + ); + $this->setUrlDetectionHandler($config['url_detection_handler'] ?: new FacebookUrlDetectionHandler()); + $this->persistentDataHandler = PersistentDataFactory::createPersistentDataHandler( + $config['persistent_data_handler'] + ); if (isset($config['default_access_token'])) { $this->setDefaultAccessToken($config['default_access_token']); } - if (isset($config['default_graph_version'])) { - $this->defaultGraphVersion = $config['default_graph_version']; - } else { - // @todo v6: Throw an InvalidArgumentException if "default_graph_version" is not set - $this->defaultGraphVersion = static::DEFAULT_GRAPH_VERSION; - } + // @todo v6: Throw an InvalidArgumentException if "default_graph_version" is not set + $this->defaultGraphVersion = $config['default_graph_version']; } /** @@ -257,14 +216,20 @@ class Facebook */ public function getUrlDetectionHandler() { - if (!$this->urlDetectionHandler instanceof UrlDetectionInterface) { - $this->urlDetectionHandler = new FacebookUrlDetectionHandler(); - } - return $this->urlDetectionHandler; } /** + * Changes the URL detection handler. + * + * @param UrlDetectionInterface $urlDetectionHandler + */ + private function setUrlDetectionHandler(UrlDetectionInterface $urlDetectionHandler) + { + $this->urlDetectionHandler = $urlDetectionHandler; + } + + /** * Returns the default AccessToken entity. * * @return AccessToken|null @@ -530,6 +495,27 @@ class Facebook } /** + * Instantiates an empty FacebookBatchRequest entity. + * + * @param AccessToken|string|null $accessToken The top-level access token. Requests with no access token + * will fallback to this. + * @param string|null $graphVersion The Graph API version to use. + * @return FacebookBatchRequest + */ + public function newBatchRequest($accessToken = null, $graphVersion = null) + { + $accessToken = $accessToken ?: $this->defaultAccessToken; + $graphVersion = $graphVersion ?: $this->defaultGraphVersion; + + return new FacebookBatchRequest( + $this->app, + [], + $accessToken, + $graphVersion + ); + } + + /** * Instantiates a new FacebookRequest entity. * * @param string $method @@ -586,4 +572,64 @@ class Facebook { return new FacebookVideo($pathToFile); } + + /** + * Upload a video in chunks. + * + * @param int $target The id of the target node before the /videos edge. + * @param string $pathToFile The full path to the file. + * @param array $metadata The metadata associated with the video file. + * @param string|null $accessToken The access token. + * @param int $maxTransferTries The max times to retry a failed upload chunk. + * @param string|null $graphVersion The Graph API version to use. + * + * @return array + * + * @throws FacebookSDKException + */ + public function uploadVideo($target, $pathToFile, $metadata = [], $accessToken = null, $maxTransferTries = 5, $graphVersion = null) + { + $accessToken = $accessToken ?: $this->defaultAccessToken; + $graphVersion = $graphVersion ?: $this->defaultGraphVersion; + + $uploader = new FacebookResumableUploader($this->app, $this->client, $accessToken, $graphVersion); + $endpoint = '/'.$target.'/videos'; + $file = $this->videoToUpload($pathToFile); + $chunk = $uploader->start($endpoint, $file); + + do { + $chunk = $this->maxTriesTransfer($uploader, $endpoint, $chunk, $maxTransferTries); + } while (!$chunk->isLastChunk()); + + return [ + 'video_id' => $chunk->getVideoId(), + 'success' => $uploader->finish($endpoint, $chunk->getUploadSessionId(), $metadata), + ]; + } + + /** + * Attempts to upload a chunk of a file in $retryCountdown tries. + * + * @param FacebookResumableUploader $uploader + * @param string $endpoint + * @param FacebookTransferChunk $chunk + * @param int $retryCountdown + * + * @return FacebookTransferChunk + * + * @throws FacebookSDKException + */ + private function maxTriesTransfer(FacebookResumableUploader $uploader, $endpoint, FacebookTransferChunk $chunk, $retryCountdown) + { + $newChunk = $uploader->transfer($endpoint, $chunk, $retryCountdown < 1); + + if ($newChunk !== $chunk) { + return $newChunk; + } + + $retryCountdown--; + + // If transfer() returned the same chunk entity, the transfer failed but is resumable. + return $this->maxTriesTransfer($uploader, $endpoint, $chunk, $retryCountdown); + } } diff --git a/lib/facebook-graph-sdk/src/Facebook/FacebookApp.php b/lib/facebook-graph-sdk/src/Facebook/FacebookApp.php index 84956ce..804c9bb 100644 --- a/lib/facebook-graph-sdk/src/Facebook/FacebookApp.php +++ b/lib/facebook-graph-sdk/src/Facebook/FacebookApp.php @@ -1,6 +1,6 @@ <?php /** - * Copyright 2014 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * You are hereby granted a non-exclusive, worldwide, royalty-free license to * use, copy, modify, and distribute this software in source code or binary @@ -24,6 +24,7 @@ namespace Facebook; use Facebook\Authentication\AccessToken; +use Facebook\Exceptions\FacebookSDKException; class FacebookApp implements \Serializable { @@ -40,10 +41,18 @@ class FacebookApp implements \Serializable /** * @param string $id * @param string $secret + * + * @throws FacebookSDKException */ public function __construct($id, $secret) { - $this->id = $id; + if (!is_string($id) + // Keeping this for BC. Integers greater than PHP_INT_MAX will make is_int() return false + && !is_int($id)) { + throw new FacebookSDKException('The "app_id" must be formatted as a string since many app ID\'s are greater than PHP_INT_MAX on some systems.'); + } + // We cast as a string in case a valid int was set on a 64-bit system and this is unserialised on a 32-bit system + $this->id = (string) $id; $this->secret = $secret; } @@ -84,7 +93,7 @@ class FacebookApp implements \Serializable */ public function serialize() { - return serialize([$this->id, $this->secret]); + return implode('|', [$this->id, $this->secret]); } /** @@ -94,7 +103,7 @@ class FacebookApp implements \Serializable */ public function unserialize($serialized) { - list($id, $secret) = unserialize($serialized); + list($id, $secret) = explode('|', $serialized); $this->__construct($id, $secret); } diff --git a/lib/facebook-graph-sdk/src/Facebook/FacebookBatchRequest.php b/lib/facebook-graph-sdk/src/Facebook/FacebookBatchRequest.php index 33c489c..3d5d5d5 100644 --- a/lib/facebook-graph-sdk/src/Facebook/FacebookBatchRequest.php +++ b/lib/facebook-graph-sdk/src/Facebook/FacebookBatchRequest.php @@ -1,6 +1,6 @@ <?php /** - * Copyright 2014 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * You are hereby granted a non-exclusive, worldwide, royalty-free license to * use, copy, modify, and distribute this software in source code or binary @@ -62,16 +62,17 @@ class FacebookBatchRequest extends FacebookRequest implements IteratorAggregate, } /** - * A a new request to the array. + * Adds a new request to the array. * * @param FacebookRequest|array $request - * @param string|null $name + * @param string|null|array $options Array of batch request options e.g. 'name', 'omit_response_on_success'. + * If a string is given, it is the value of the 'name' option. * * @return FacebookBatchRequest * * @throws \InvalidArgumentException */ - public function add($request, $name = null) + public function add($request, $options = null) { if (is_array($request)) { foreach ($request as $key => $req) { @@ -85,17 +86,28 @@ class FacebookBatchRequest extends FacebookRequest implements IteratorAggregate, throw new \InvalidArgumentException('Argument for add() must be of type array or FacebookRequest.'); } + if (null === $options) { + $options = []; + } elseif (!is_array($options)) { + $options = ['name' => $options]; + } + $this->addFallbackDefaults($request); + + // File uploads + $attachedFiles = $this->extractFileAttachments($request); + + $name = isset($options['name']) ? $options['name'] : null; + + unset($options['name']); + $requestToAdd = [ 'name' => $name, 'request' => $request, + 'options' => $options, + 'attached_files' => $attachedFiles, ]; - // File uploads - $attachedFiles = $this->extractFileAttachments($request); - if ($attachedFiles) { - $requestToAdd['attached_files'] = $attachedFiles; - } $this->requests[] = $requestToAdd; return $this; @@ -168,8 +180,6 @@ class FacebookBatchRequest extends FacebookRequest implements IteratorAggregate, /** * Prepares the requests to be sent as a batch request. - * - * @return string */ public function prepareRequestsForBatch() { @@ -191,8 +201,15 @@ class FacebookBatchRequest extends FacebookRequest implements IteratorAggregate, { $requests = []; foreach ($this->requests as $request) { - $attachedFiles = isset($request['attached_files']) ? $request['attached_files'] : null; - $requests[] = $this->requestEntityToBatchArray($request['request'], $request['name'], $attachedFiles); + $options = []; + + if (null !== $request['name']) { + $options['name'] = $request['name']; + } + + $options += $request['options']; + + $requests[] = $this->requestEntityToBatchArray($request['request'], $options, $request['attached_files']); } return json_encode($requests); @@ -217,14 +234,22 @@ class FacebookBatchRequest extends FacebookRequest implements IteratorAggregate, /** * Converts a Request entity into an array that is batch-friendly. * - * @param FacebookRequest $request The request entity to convert. - * @param string|null $requestName The name of the request. - * @param string|null $attachedFiles Names of files associated with the request. + * @param FacebookRequest $request The request entity to convert. + * @param string|null|array $options Array of batch request options e.g. 'name', 'omit_response_on_success'. + * If a string is given, it is the value of the 'name' option. + * @param string|null $attachedFiles Names of files associated with the request. * * @return array */ - public function requestEntityToBatchArray(FacebookRequest $request, $requestName = null, $attachedFiles = null) + public function requestEntityToBatchArray(FacebookRequest $request, $options = null, $attachedFiles = null) { + + if (null === $options) { + $options = []; + } elseif (!is_array($options)) { + $options = ['name' => $options]; + } + $compiledHeaders = []; $headers = $request->getHeaders(); foreach ($headers as $name => $value) { @@ -244,18 +269,12 @@ class FacebookBatchRequest extends FacebookRequest implements IteratorAggregate, $batch['body'] = $body; } - if (isset($requestName)) { - $batch['name'] = $requestName; - } + $batch += $options; - if (isset($attachedFiles)) { + if (null !== $attachedFiles) { $batch['attached_files'] = $attachedFiles; } - // @TODO Add support for "omit_response_on_success" - // @TODO Add support for "depends_on" - // @TODO Add support for JSONP with "callback" - return $batch; } diff --git a/lib/facebook-graph-sdk/src/Facebook/FacebookBatchResponse.php b/lib/facebook-graph-sdk/src/Facebook/FacebookBatchResponse.php index 5ea765e..8e1464c 100644 --- a/lib/facebook-graph-sdk/src/Facebook/FacebookBatchResponse.php +++ b/lib/facebook-graph-sdk/src/Facebook/FacebookBatchResponse.php @@ -1,6 +1,6 @@ <?php /** - * Copyright 2014 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * You are hereby granted a non-exclusive, worldwide, royalty-free license to * use, copy, modify, and distribute this software in source code or binary @@ -102,7 +102,8 @@ class FacebookBatchResponse extends FacebookResponse implements IteratorAggregat $httpResponseBody = isset($response['body']) ? $response['body'] : null; $httpResponseCode = isset($response['code']) ? $response['code'] : null; - $httpResponseHeaders = isset($response['headers']) ? $response['headers'] : []; + // @TODO With PHP 5.5 support, this becomes array_column($response['headers'], 'value', 'name') + $httpResponseHeaders = isset($response['headers']) ? $this->normalizeBatchHeaders($response['headers']) : []; $this->responses[$originalRequestName] = new FacebookResponse( $originalRequest, @@ -151,4 +152,23 @@ class FacebookBatchResponse extends FacebookResponse implements IteratorAggregat { return isset($this->responses[$offset]) ? $this->responses[$offset] : null; } + + /** + * Converts the batch header array into a standard format. + * @TODO replace with array_column() when PHP 5.5 is supported. + * + * @param array $batchHeaders + * + * @return array + */ + private function normalizeBatchHeaders(array $batchHeaders) + { + $headers = []; + + foreach ($batchHeaders as $header) { + $headers[$header['name']] = $header['value']; + } + + return $headers; + } } diff --git a/lib/facebook-graph-sdk/src/Facebook/FacebookClient.php b/lib/facebook-graph-sdk/src/Facebook/FacebookClient.php index b10762f..dbf7592 100644 --- a/lib/facebook-graph-sdk/src/Facebook/FacebookClient.php +++ b/lib/facebook-graph-sdk/src/Facebook/FacebookClient.php @@ -1,6 +1,6 @@ <?php /** - * Copyright 2014 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * You are hereby granted a non-exclusive, worldwide, royalty-free license to * use, copy, modify, and distribute this software in source code or binary @@ -124,7 +124,7 @@ class FacebookClient */ public function detectHttpClientHandler() { - return function_exists('curl_init') ? new FacebookCurlHttpClient() : new FacebookStreamHttpClient(); + return extension_loaded('curl') ? new FacebookCurlHttpClient() : new FacebookStreamHttpClient(); } /** @@ -197,7 +197,7 @@ class FacebookClient */ public function sendRequest(FacebookRequest $request) { - if (get_class($request) === 'FacebookRequest') { + if (get_class($request) === 'Facebook\FacebookRequest') { $request->validateAccessToken(); } diff --git a/lib/facebook-graph-sdk/src/Facebook/FacebookRequest.php b/lib/facebook-graph-sdk/src/Facebook/FacebookRequest.php index 5e4083f..2b10089 100644 --- a/lib/facebook-graph-sdk/src/Facebook/FacebookRequest.php +++ b/lib/facebook-graph-sdk/src/Facebook/FacebookRequest.php @@ -1,6 +1,6 @@ <?php /** - * Copyright 2014 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * You are hereby granted a non-exclusive, worldwide, royalty-free license to * use, copy, modify, and distribute this software in source code or binary @@ -108,7 +108,7 @@ class FacebookRequest /** * Set the access token for this request. * - * @param AccessToken|string + * @param AccessToken|string|null * * @return FacebookRequest */ @@ -154,7 +154,7 @@ class FacebookRequest } /** - * Return the access token for this request an an AccessToken entity. + * Return the access token for this request as an AccessToken entity. * * @return AccessToken|null */ @@ -214,8 +214,6 @@ class FacebookRequest * Set the HTTP method for this request. * * @param string - * - * @return FacebookRequest */ public function setMethod($method) { @@ -273,7 +271,7 @@ class FacebookRequest } /** - * Return the HTTP method for this request. + * Return the endpoint for this request. * * @return string */ diff --git a/lib/facebook-graph-sdk/src/Facebook/FacebookResponse.php b/lib/facebook-graph-sdk/src/Facebook/FacebookResponse.php index ce55b14..251ca2f 100644 --- a/lib/facebook-graph-sdk/src/Facebook/FacebookResponse.php +++ b/lib/facebook-graph-sdk/src/Facebook/FacebookResponse.php @@ -1,6 +1,6 @@ <?php /** - * Copyright 2014 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * You are hereby granted a non-exclusive, worldwide, royalty-free license to * use, copy, modify, and distribute this software in source code or binary @@ -213,7 +213,7 @@ class FacebookResponse /** * Returns the exception that was thrown for this request. * - * @return FacebookSDKException|null + * @return FacebookResponseException|null */ public function getThrownException() { @@ -225,7 +225,7 @@ class FacebookResponse * * Graph will return 2 types of responses: * - JSON(P) - * Most responses from Grpah are JSON(P) + * Most responses from Graph are JSON(P) * - application/x-www-form-urlencoded key/value pairs * Happens on the `/oauth/access_token` endpoint when exchanging * a short-lived access token for a long-lived access token @@ -259,7 +259,7 @@ class FacebookResponse /** * Instantiate a new GraphObject from response. * - * @param string|null $subclassName The GraphNode sub class to cast to. + * @param string|null $subclassName The GraphNode subclass to cast to. * * @return \Facebook\GraphNodes\GraphObject * @@ -276,7 +276,7 @@ class FacebookResponse /** * Instantiate a new GraphNode from response. * - * @param string|null $subclassName The GraphNode sub class to cast to. + * @param string|null $subclassName The GraphNode subclass to cast to. * * @return \Facebook\GraphNodes\GraphNode * @@ -376,7 +376,7 @@ class FacebookResponse /** * Instantiate a new GraphList from response. * - * @param string|null $subclassName The GraphNode sub class to cast list items to. + * @param string|null $subclassName The GraphNode subclass to cast list items to. * @param boolean $auto_prefix Toggle to auto-prefix the subclass name. * * @return \Facebook\GraphNodes\GraphList @@ -394,7 +394,7 @@ class FacebookResponse /** * Instantiate a new GraphEdge from response. * - * @param string|null $subclassName The GraphNode sub class to cast list items to. + * @param string|null $subclassName The GraphNode subclass to cast list items to. * @param boolean $auto_prefix Toggle to auto-prefix the subclass name. * * @return \Facebook\GraphNodes\GraphEdge diff --git a/lib/facebook-graph-sdk/src/Facebook/FileUpload/FacebookFile.php b/lib/facebook-graph-sdk/src/Facebook/FileUpload/FacebookFile.php index f8b9905..3c1536d 100644 --- a/lib/facebook-graph-sdk/src/Facebook/FileUpload/FacebookFile.php +++ b/lib/facebook-graph-sdk/src/Facebook/FileUpload/FacebookFile.php @@ -1,6 +1,6 @@ <?php /** - * Copyright 2014 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * You are hereby granted a non-exclusive, worldwide, royalty-free license to * use, copy, modify, and distribute this software in source code or binary @@ -38,6 +38,16 @@ class FacebookFile protected $path; /** + * @var int The maximum bytes to read. Defaults to -1 (read all the remaining buffer). + */ + private $maxLength; + + /** + * @var int Seek to the specified offset before reading. If this number is negative, no seeking will occur and reading will start from the current position. + */ + private $offset; + + /** * @var resource The stream pointing to the file. */ protected $stream; @@ -46,12 +56,16 @@ class FacebookFile * Creates a new FacebookFile entity. * * @param string $filePath + * @param int $maxLength + * @param int $offset * * @throws FacebookSDKException */ - public function __construct($filePath) + public function __construct($filePath, $maxLength = -1, $offset = -1) { $this->path = $filePath; + $this->maxLength = $maxLength; + $this->offset = $offset; $this->open(); } @@ -98,7 +112,7 @@ class FacebookFile */ public function getContents() { - return stream_get_contents($this->stream); + return stream_get_contents($this->stream, $this->maxLength, $this->offset); } /** @@ -112,6 +126,26 @@ class FacebookFile } /** + * Return the path of the file. + * + * @return string + */ + public function getFilePath() + { + return $this->path; + } + + /** + * Return the size of the file. + * + * @return int + */ + public function getSize() + { + return filesize($this->path); + } + + /** * Return the mimetype of the file. * * @return string diff --git a/lib/facebook-graph-sdk/src/Facebook/FileUpload/FacebookResumableUploader.php b/lib/facebook-graph-sdk/src/Facebook/FileUpload/FacebookResumableUploader.php new file mode 100644 index 0000000..92a22f1 --- /dev/null +++ b/lib/facebook-graph-sdk/src/Facebook/FileUpload/FacebookResumableUploader.php @@ -0,0 +1,167 @@ +<?php +/** + * Copyright 2017 Facebook, Inc. + * + * You are hereby granted a non-exclusive, worldwide, royalty-free license to + * use, copy, modify, and distribute this software in source code or binary + * form for use in connection with the web services and APIs provided by + * Facebook. + * + * As with any software that integrates with the Facebook platform, your use + * of this software is subject to the Facebook Developer Principles and + * Policies [http://developers.facebook.com/policy/]. This copyright notice + * shall be included in all copies or substantial portions of the software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ +namespace Facebook\FileUpload; + +use Facebook\Authentication\AccessToken; +use Facebook\Exceptions\FacebookResponseException; +use Facebook\Exceptions\FacebookResumableUploadException; +use Facebook\Exceptions\FacebookSDKException; +use Facebook\FacebookApp; +use Facebook\FacebookClient; +use Facebook\FacebookRequest; + +/** + * Class FacebookResumableUploader + * + * @package Facebook + */ +class FacebookResumableUploader +{ + /** + * @var FacebookApp + */ + protected $app; + + /** + * @var string + */ + protected $accessToken; + + /** + * @var FacebookClient The Facebook client service. + */ + protected $client; + + /** + * @var string Graph version to use for this request. + */ + protected $graphVersion; + + /** + * @param FacebookApp $app + * @param FacebookClient $client + * @param AccessToken|string|null $accessToken + * @param string $graphVersion + */ + public function __construct(FacebookApp $app, FacebookClient $client, $accessToken, $graphVersion) + { + $this->app = $app; + $this->client = $client; + $this->accessToken = $accessToken; + $this->graphVersion = $graphVersion; + } + + /** + * Upload by chunks - start phase + * + * @param string $endpoint + * @param FacebookFile $file + * + * @return FacebookTransferChunk + * + * @throws FacebookSDKException + */ + public function start($endpoint, FacebookFile $file) + { + $params = [ + 'upload_phase' => 'start', + 'file_size' => $file->getSize(), + ]; + $response = $this->sendUploadRequest($endpoint, $params); + + return new FacebookTransferChunk($file, $response['upload_session_id'], $response['video_id'], $response['start_offset'], $response['end_offset']); + } + + /** + * Upload by chunks - transfer phase + * + * @param string $endpoint + * @param FacebookTransferChunk $chunk + * @param boolean $allowToThrow + * + * @return FacebookTransferChunk + * + * @throws FacebookResponseException + */ + public function transfer($endpoint, FacebookTransferChunk $chunk, $allowToThrow = false) + { + $params = [ + 'upload_phase' => 'transfer', + 'upload_session_id' => $chunk->getUploadSessionId(), + 'start_offset' => $chunk->getStartOffset(), + 'video_file_chunk' => $chunk->getPartialFile(), + ]; + + try { + $response = $this->sendUploadRequest($endpoint, $params); + } catch (FacebookResponseException $e) { + $preException = $e->getPrevious(); + if ($allowToThrow || !$preException instanceof FacebookResumableUploadException) { + throw $e; + } + + // Return the same chunk entity so it can be retried. + return $chunk; + } + + return new FacebookTransferChunk($chunk->getFile(), $chunk->getUploadSessionId(), $chunk->getVideoId(), $response['start_offset'], $response['end_offset']); + } + + /** + * Upload by chunks - finish phase + * + * @param string $endpoint + * @param string $uploadSessionId + * @param array $metadata The metadata associated with the file. + * + * @return boolean + * + * @throws FacebookSDKException + */ + public function finish($endpoint, $uploadSessionId, $metadata = []) + { + $params = array_merge($metadata, [ + 'upload_phase' => 'finish', + 'upload_session_id' => $uploadSessionId, + ]); + $response = $this->sendUploadRequest($endpoint, $params); + + return $response['success']; + } + + /** + * Helper to make a FacebookRequest and send it. + * + * @param string $endpoint The endpoint to POST to. + * @param array $params The params to send with the request. + * + * @return array + */ + private function sendUploadRequest($endpoint, $params = []) + { + $request = new FacebookRequest($this->app, $this->accessToken, 'POST', $endpoint, $params, null, $this->graphVersion); + + return $this->client->sendRequest($request)->getDecodedBody(); + } +} diff --git a/lib/facebook-graph-sdk/src/Facebook/FileUpload/FacebookTransferChunk.php b/lib/facebook-graph-sdk/src/Facebook/FileUpload/FacebookTransferChunk.php new file mode 100644 index 0000000..a909e87 --- /dev/null +++ b/lib/facebook-graph-sdk/src/Facebook/FileUpload/FacebookTransferChunk.php @@ -0,0 +1,133 @@ +<?php +/** + * Copyright 2017 Facebook, Inc. + * + * You are hereby granted a non-exclusive, worldwide, royalty-free license to + * use, copy, modify, and distribute this software in source code or binary + * form for use in connection with the web services and APIs provided by + * Facebook. + * + * As with any software that integrates with the Facebook platform, your use + * of this software is subject to the Facebook Developer Principles and + * Policies [http://developers.facebook.com/policy/]. This copyright notice + * shall be included in all copies or substantial portions of the software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ +namespace Facebook\FileUpload; + +/** + * Class FacebookTransferChunk + * + * @package Facebook + */ +class FacebookTransferChunk +{ + /** + * @var FacebookFile The file to chunk during upload. + */ + private $file; + + /** + * @var int The ID of the upload session. + */ + private $uploadSessionId; + + /** + * @var int Start byte position of the next file chunk. + */ + private $startOffset; + + /** + * @var int End byte position of the next file chunk. + */ + private $endOffset; + + /** + * @var int The ID of the video. + */ + private $videoId; + + /** + * @param FacebookFile $file + * @param int $uploadSessionId + * @param int $videoId + * @param int $startOffset + * @param int $endOffset + */ + public function __construct(FacebookFile $file, $uploadSessionId, $videoId, $startOffset, $endOffset) + { + $this->file = $file; + $this->uploadSessionId = $uploadSessionId; + $this->videoId = $videoId; + $this->startOffset = $startOffset; + $this->endOffset = $endOffset; + } + + /** + * Return the file entity. + * + * @return FacebookFile + */ + public function getFile() + { + return $this->file; + } + + /** + * Return a FacebookFile entity with partial content. + * + * @return FacebookFile + */ + public function getPartialFile() + { + $maxLength = $this->endOffset - $this->startOffset; + + return new FacebookFile($this->file->getFilePath(), $maxLength, $this->startOffset); + } + + /** + * Return upload session Id + * + * @return int + */ + public function getUploadSessionId() + { + return $this->uploadSessionId; + } + + /** + * Check whether is the last chunk + * + * @return bool + */ + public function isLastChunk() + { + return $this->startOffset === $this->endOffset; + } + + /** + * @return int + */ + public function getStartOffset() + { + return $this->startOffset; + } + + /** + * Get uploaded video Id + * + * @return int + */ + public function getVideoId() + { + return $this->videoId; + } +} diff --git a/lib/facebook-graph-sdk/src/Facebook/FileUpload/FacebookVideo.php b/lib/facebook-graph-sdk/src/Facebook/FileUpload/FacebookVideo.php index 1e8c55a..ee6dd53 100644 --- a/lib/facebook-graph-sdk/src/Facebook/FileUpload/FacebookVideo.php +++ b/lib/facebook-graph-sdk/src/Facebook/FileUpload/FacebookVideo.php @@ -1,6 +1,6 @@ <?php /** - * Copyright 2014 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * You are hereby granted a non-exclusive, worldwide, royalty-free license to * use, copy, modify, and distribute this software in source code or binary diff --git a/lib/facebook-graph-sdk/src/Facebook/FileUpload/Mimetypes.php b/lib/facebook-graph-sdk/src/Facebook/FileUpload/Mimetypes.php index f8b7e36..95d3992 100644 --- a/lib/facebook-graph-sdk/src/Facebook/FileUpload/Mimetypes.php +++ b/lib/facebook-graph-sdk/src/Facebook/FileUpload/Mimetypes.php @@ -1,6 +1,6 @@ <?php /** - * Copyright 2014 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * You are hereby granted a non-exclusive, worldwide, royalty-free license to * use, copy, modify, and distribute this software in source code or binary @@ -724,6 +724,7 @@ class Mimetypes 'spq' => 'application/scvp-vp-request', 'spx' => 'audio/ogg', 'src' => 'application/x-wais-source', + 'srt' => 'application/octet-stream', 'sru' => 'application/sru+xml', 'srx' => 'application/sparql-results+xml', 'sse' => 'application/vnd.kodak-descriptor', diff --git a/lib/facebook-graph-sdk/src/Facebook/GraphNodes/Birthday.php b/lib/facebook-graph-sdk/src/Facebook/GraphNodes/Birthday.php new file mode 100644 index 0000000..4338b65 --- /dev/null +++ b/lib/facebook-graph-sdk/src/Facebook/GraphNodes/Birthday.php @@ -0,0 +1,85 @@ +<?php +/** + * Copyright 2017 Facebook, Inc. + * + * You are hereby granted a non-exclusive, worldwide, royalty-free license to + * use, copy, modify, and distribute this software in source code or binary + * form for use in connection with the web services and APIs provided by + * Facebook. + * + * As with any software that integrates with the Facebook platform, your use + * of this software is subject to the Facebook Developer Principles and + * Policies [http://developers.facebook.com/policy/]. This copyright notice + * shall be included in all copies or substantial portions of the software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ +namespace Facebook\GraphNodes; + +use DateTime; + +/** + * Birthday object to handle various Graph return formats + * + * @package Facebook + */ +class Birthday extends DateTime +{ + /** + * @var bool + */ + private $hasDate = false; + + /** + * @var bool + */ + private $hasYear = false; + + /** + * Parses Graph birthday format to set indication flags, possible values: + * + * MM/DD/YYYY + * MM/DD + * YYYY + * + * @link https://developers.facebook.com/docs/graph-api/reference/user + * + * @param string $date + */ + public function __construct($date) + { + $parts = explode('/', $date); + + $this->hasYear = count($parts) === 3 || count($parts) === 1; + $this->hasDate = count($parts) === 3 || count($parts) === 2; + + parent::__construct($date); + } + + /** + * Returns whether date object contains birth day and month + * + * @return bool + */ + public function hasDate() + { + return $this->hasDate; + } + + /** + * Returns whether date object contains birth year + * + * @return bool + */ + public function hasYear() + { + return $this->hasYear; + } +} diff --git a/lib/facebook-graph-sdk/src/Facebook/GraphNodes/Collection.php b/lib/facebook-graph-sdk/src/Facebook/GraphNodes/Collection.php index cac010b..424b7cf 100644 --- a/lib/facebook-graph-sdk/src/Facebook/GraphNodes/Collection.php +++ b/lib/facebook-graph-sdk/src/Facebook/GraphNodes/Collection.php @@ -1,6 +1,6 @@ <?php /** - * Copyright 2014 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * You are hereby granted a non-exclusive, worldwide, royalty-free license to * use, copy, modify, and distribute this software in source code or binary @@ -69,7 +69,7 @@ class Collection implements ArrayAccess, Countable, IteratorAggregate return $this->items[$name]; } - return $default ?: null; + return $default; } /** diff --git a/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphAchievement.php b/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphAchievement.php index 3fba815..31508ee 100644 --- a/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphAchievement.php +++ b/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphAchievement.php @@ -1,6 +1,6 @@ <?php /** - * Copyright 2014 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * You are hereby granted a non-exclusive, worldwide, royalty-free license to * use, copy, modify, and distribute this software in source code or binary @@ -28,7 +28,6 @@ namespace Facebook\GraphNodes; * * @package Facebook */ - class GraphAchievement extends GraphNode { /** @@ -92,7 +91,7 @@ class GraphAchievement extends GraphNode /** * Returns the type of achievement. * - * @see https://developers.facebook.com/docs/graph-api/reference/v2.2/achievement + * @see https://developers.facebook.com/docs/graph-api/reference/achievement * * @return string */ diff --git a/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphAlbum.php b/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphAlbum.php index 50d1f2c..52f19b5 100644 --- a/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphAlbum.php +++ b/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphAlbum.php @@ -1,6 +1,6 @@ <?php /** - * Copyright 2014 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * You are hereby granted a non-exclusive, worldwide, royalty-free license to * use, copy, modify, and distribute this software in source code or binary diff --git a/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphApplication.php b/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphApplication.php index 69b09bb..aa07c82 100644 --- a/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphApplication.php +++ b/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphApplication.php @@ -1,6 +1,6 @@ <?php /** - * Copyright 2014 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * You are hereby granted a non-exclusive, worldwide, royalty-free license to * use, copy, modify, and distribute this software in source code or binary diff --git a/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphCoverPhoto.php b/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphCoverPhoto.php index ee60750..824275b 100644 --- a/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphCoverPhoto.php +++ b/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphCoverPhoto.php @@ -1,6 +1,6 @@ <?php /** - * Copyright 2014 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * You are hereby granted a non-exclusive, worldwide, royalty-free license to * use, copy, modify, and distribute this software in source code or binary diff --git a/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphEdge.php b/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphEdge.php index 95f3284..f6f4970 100644 --- a/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphEdge.php +++ b/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphEdge.php @@ -1,6 +1,6 @@ <?php /** - * Copyright 2014 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * You are hereby granted a non-exclusive, worldwide, royalty-free license to * use, copy, modify, and distribute this software in source code or binary @@ -153,35 +153,13 @@ class GraphEdge extends Collection $this->validateForPagination(); // Do we have a paging URL? - if (isset($this->metaData['paging'][$direction])) { - // Graph returns the full URL with all the original params. - // We just want the endpoint though. - $pageUrl = $this->metaData['paging'][$direction]; - - return FacebookUrlManipulator::baseGraphUrlEndpoint($pageUrl); - } - - // Do we have a cursor to work with? - $cursorDirection = $direction === 'next' ? 'after' : 'before'; - $cursor = $this->getCursor($cursorDirection); - if (!$cursor) { - return null; - } - - // If we don't know the ID of the parent node, this ain't gonna work. - if (!$this->parentEdgeEndpoint) { + if (!isset($this->metaData['paging'][$direction])) { return null; } - // We have the parent node ID, paging cursor & original request. - // These were the ingredients chosen to create the perfect little URL. - $pageUrl = $this->parentEdgeEndpoint . '?' . $cursorDirection . '=' . urlencode($cursor); + $pageUrl = $this->metaData['paging'][$direction]; - // Pull in the original params - $originalUrl = $this->request->getUrl(); - $pageUrl = FacebookUrlManipulator::mergeUrlParams($originalUrl, $pageUrl); - - return FacebookUrlManipulator::forceSlashPrefix($pageUrl); + return FacebookUrlManipulator::baseGraphUrlEndpoint($pageUrl); } /** @@ -257,4 +235,18 @@ class GraphEdge extends Collection return null; } + + /** + * @inheritDoc + */ + public function map(\Closure $callback) + { + return new static( + $this->request, + array_map($callback, $this->items, array_keys($this->items)), + $this->metaData, + $this->parentEdgeEndpoint, + $this->subclassName + ); + } } diff --git a/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphEvent.php b/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphEvent.php index 19ff2fb..a470d89 100644 --- a/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphEvent.php +++ b/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphEvent.php @@ -1,6 +1,6 @@ <?php /** - * Copyright 2014 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * You are hereby granted a non-exclusive, worldwide, royalty-free license to * use, copy, modify, and distribute this software in source code or binary diff --git a/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphGroup.php b/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphGroup.php index 07a4dbd..6217bd4 100644 --- a/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphGroup.php +++ b/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphGroup.php @@ -1,6 +1,6 @@ <?php /** - * Copyright 2014 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * You are hereby granted a non-exclusive, worldwide, royalty-free license to * use, copy, modify, and distribute this software in source code or binary @@ -167,5 +167,4 @@ class GraphGroup extends GraphNode { return $this->getField('venue'); } - } diff --git a/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphList.php b/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphList.php index a60a07a..3dfbd49 100644 --- a/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphList.php +++ b/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphList.php @@ -1,6 +1,6 @@ <?php /** - * Copyright 2014 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * You are hereby granted a non-exclusive, worldwide, royalty-free license to * use, copy, modify, and distribute this software in source code or binary diff --git a/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphLocation.php b/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphLocation.php index 187a399..29215aa 100644 --- a/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphLocation.php +++ b/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphLocation.php @@ -1,6 +1,6 @@ <?php /** - * Copyright 2014 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * You are hereby granted a non-exclusive, worldwide, royalty-free license to * use, copy, modify, and distribute this software in source code or binary diff --git a/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphNode.php b/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphNode.php index 0d2f504..061e744 100644 --- a/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphNode.php +++ b/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphNode.php @@ -1,6 +1,6 @@ <?php /** - * Copyright 2014 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * You are hereby granted a non-exclusive, worldwide, royalty-free license to * use, copy, modify, and distribute this software in source code or binary @@ -62,10 +62,11 @@ class GraphNode extends Collection foreach ($data as $k => $v) { if ($this->shouldCastAsDateTime($k) && (is_numeric($v) - || $k === 'birthday' || $this->isIso8601DateString($v)) ) { $items[$k] = $this->castToDateTime($v); + } elseif ($k === 'birthday') { + $items[$k] = $this->castToBirthday($v); } else { $items[$k] = $v; } @@ -149,7 +150,6 @@ class GraphNode extends Collection 'backdated_time', 'issued_at', 'expires_at', - 'birthday', 'publish_time' ], true); } @@ -174,6 +174,18 @@ class GraphNode extends Collection } /** + * Casts a birthday value from Graph to Birthday + * + * @param string $value + * + * @return Birthday + */ + public function castToBirthday($value) + { + return new Birthday($value); + } + + /** * Getter for $graphObjectMap. * * @return array diff --git a/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphNodeFactory.php b/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphNodeFactory.php index e1bedd9..6a37091 100644 --- a/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphNodeFactory.php +++ b/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphNodeFactory.php @@ -1,6 +1,6 @@ <?php /** - * Copyright 2014 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * You are hereby granted a non-exclusive, worldwide, royalty-free license to * use, copy, modify, and distribute this software in source code or binary @@ -331,7 +331,7 @@ class GraphNodeFactory $dataList = []; foreach ($data['data'] as $graphNode) { - $dataList[] = $this->safelyMakeGraphNode($graphNode, $subclassName, $parentKey, $parentNodeId); + $dataList[] = $this->safelyMakeGraphNode($graphNode, $subclassName); } $metaData = $this->getMetaData($data); diff --git a/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphObject.php b/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphObject.php index bb8f8e4..0633c40 100644 --- a/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphObject.php +++ b/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphObject.php @@ -1,6 +1,6 @@ <?php /** - * Copyright 2014 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * You are hereby granted a non-exclusive, worldwide, royalty-free license to * use, copy, modify, and distribute this software in source code or binary diff --git a/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphObjectFactory.php b/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphObjectFactory.php index 94963a0..c0f6e04 100644 --- a/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphObjectFactory.php +++ b/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphObjectFactory.php @@ -1,6 +1,6 @@ <?php /** - * Copyright 2014 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * You are hereby granted a non-exclusive, worldwide, royalty-free license to * use, copy, modify, and distribute this software in source code or binary @@ -23,6 +23,8 @@ */ namespace Facebook\GraphNodes; +use Facebook\Exceptions\FacebookSDKException; + /** * Class GraphObjectFactory * @@ -56,7 +58,7 @@ class GraphObjectFactory extends GraphNodeFactory { return $this->makeGraphNode($subclassName); } - + /** * Convenience method for creating a GraphEvent collection. * @@ -66,7 +68,7 @@ class GraphObjectFactory extends GraphNodeFactory */ public function makeGraphEvent() { - return $this->makeGraphObject(static::BASE_GRAPH_OBJECT_PREFIX . 'GraphEvent'); + return $this->makeGraphNode(static::BASE_GRAPH_OBJECT_PREFIX . 'GraphEvent'); } /** diff --git a/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphPage.php b/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphPage.php index ab8e31a..3dfb0e0 100644 --- a/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphPage.php +++ b/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphPage.php @@ -1,6 +1,6 @@ <?php /** - * Copyright 2014 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * You are hereby granted a non-exclusive, worldwide, royalty-free license to * use, copy, modify, and distribute this software in source code or binary @@ -37,6 +37,8 @@ class GraphPage extends GraphNode 'best_page' => '\Facebook\GraphNodes\GraphPage', 'global_brand_parent_page' => '\Facebook\GraphNodes\GraphPage', 'location' => '\Facebook\GraphNodes\GraphLocation', + 'cover' => '\Facebook\GraphNodes\GraphCoverPhoto', + 'picture' => '\Facebook\GraphNodes\GraphPicture', ]; /** @@ -100,6 +102,26 @@ class GraphPage extends GraphNode } /** + * Returns CoverPhoto of the Page. + * + * @return GraphCoverPhoto|null + */ + public function getCover() + { + return $this->getField('cover'); + } + + /** + * Returns Picture of the Page. + * + * @return GraphPicture|null + */ + public function getPicture() + { + return $this->getField('picture'); + } + + /** * Returns the page access token for the admin user. * * Only available in the `/me/accounts` context. diff --git a/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphPicture.php b/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphPicture.php index bfd37fa..10274ec 100644 --- a/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphPicture.php +++ b/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphPicture.php @@ -1,6 +1,6 @@ <?php /** - * Copyright 2014 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * You are hereby granted a non-exclusive, worldwide, royalty-free license to * use, copy, modify, and distribute this software in source code or binary diff --git a/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphSessionInfo.php b/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphSessionInfo.php index 3c9e2ff..df8dd35 100644 --- a/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphSessionInfo.php +++ b/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphSessionInfo.php @@ -1,6 +1,6 @@ <?php /** - * Copyright 2014 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * You are hereby granted a non-exclusive, worldwide, royalty-free license to * use, copy, modify, and distribute this software in source code or binary diff --git a/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphUser.php b/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphUser.php index cb9ddbb..6e1ed8f 100644 --- a/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphUser.php +++ b/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphUser.php @@ -1,6 +1,6 @@ <?php /** - * Copyright 2014 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * You are hereby granted a non-exclusive, worldwide, royalty-free license to * use, copy, modify, and distribute this software in source code or binary @@ -91,6 +91,16 @@ class GraphUser extends GraphNode } /** + * Returns the email for the user as a string if present. + * + * @return string|null + */ + public function getEmail() + { + return $this->getField('email'); + } + + /** * Returns the gender for the user as a string if present. * * @return string|null @@ -113,7 +123,7 @@ class GraphUser extends GraphNode /** * Returns the users birthday, if available. * - * @return \DateTime|null + * @return Birthday|null */ public function getBirthday() { diff --git a/lib/facebook-graph-sdk/src/Facebook/Helpers/FacebookCanvasHelper.php b/lib/facebook-graph-sdk/src/Facebook/Helpers/FacebookCanvasHelper.php index 8068526..7f3466f 100644 --- a/lib/facebook-graph-sdk/src/Facebook/Helpers/FacebookCanvasHelper.php +++ b/lib/facebook-graph-sdk/src/Facebook/Helpers/FacebookCanvasHelper.php @@ -1,6 +1,6 @@ <?php /** - * Copyright 2014 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * You are hereby granted a non-exclusive, worldwide, royalty-free license to * use, copy, modify, and distribute this software in source code or binary diff --git a/lib/facebook-graph-sdk/src/Facebook/Helpers/FacebookJavaScriptHelper.php b/lib/facebook-graph-sdk/src/Facebook/Helpers/FacebookJavaScriptHelper.php index 5d406b5..01a76b8 100644 --- a/lib/facebook-graph-sdk/src/Facebook/Helpers/FacebookJavaScriptHelper.php +++ b/lib/facebook-graph-sdk/src/Facebook/Helpers/FacebookJavaScriptHelper.php @@ -1,6 +1,6 @@ <?php /** - * Copyright 2014 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * You are hereby granted a non-exclusive, worldwide, royalty-free license to * use, copy, modify, and distribute this software in source code or binary diff --git a/lib/facebook-graph-sdk/src/Facebook/Helpers/FacebookPageTabHelper.php b/lib/facebook-graph-sdk/src/Facebook/Helpers/FacebookPageTabHelper.php index ee43f5e..da2c356 100644 --- a/lib/facebook-graph-sdk/src/Facebook/Helpers/FacebookPageTabHelper.php +++ b/lib/facebook-graph-sdk/src/Facebook/Helpers/FacebookPageTabHelper.php @@ -1,6 +1,6 @@ <?php /** - * Copyright 2014 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * You are hereby granted a non-exclusive, worldwide, royalty-free license to * use, copy, modify, and distribute this software in source code or binary diff --git a/lib/facebook-graph-sdk/src/Facebook/Helpers/FacebookRedirectLoginHelper.php b/lib/facebook-graph-sdk/src/Facebook/Helpers/FacebookRedirectLoginHelper.php index 144a5b4..3240ba8 100644 --- a/lib/facebook-graph-sdk/src/Facebook/Helpers/FacebookRedirectLoginHelper.php +++ b/lib/facebook-graph-sdk/src/Facebook/Helpers/FacebookRedirectLoginHelper.php @@ -1,6 +1,6 @@ <?php /** - * Copyright 2014 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * You are hereby granted a non-exclusive, worldwide, royalty-free license to * use, copy, modify, and distribute this software in source code or binary @@ -25,16 +25,14 @@ namespace Facebook\Helpers; use Facebook\Authentication\AccessToken; use Facebook\Authentication\OAuth2Client; -use Facebook\Url\UrlDetectionInterface; -use Facebook\Url\FacebookUrlDetectionHandler; -use Facebook\Url\FacebookUrlManipulator; -use Facebook\PersistentData\PersistentDataInterface; +use Facebook\Exceptions\FacebookSDKException; use Facebook\PersistentData\FacebookSessionPersistentDataHandler; +use Facebook\PersistentData\PersistentDataInterface; +use Facebook\PseudoRandomString\PseudoRandomStringGeneratorFactory; use Facebook\PseudoRandomString\PseudoRandomStringGeneratorInterface; -use Facebook\PseudoRandomString\McryptPseudoRandomStringGenerator; -use Facebook\PseudoRandomString\OpenSslPseudoRandomStringGenerator; -use Facebook\PseudoRandomString\UrandomPseudoRandomStringGenerator; -use Facebook\Exceptions\FacebookSDKException; +use Facebook\Url\FacebookUrlDetectionHandler; +use Facebook\Url\FacebookUrlManipulator; +use Facebook\Url\UrlDetectionInterface; /** * Class FacebookRedirectLoginHelper @@ -79,7 +77,7 @@ class FacebookRedirectLoginHelper $this->oAuth2Client = $oAuth2Client; $this->persistentDataHandler = $persistentDataHandler ?: new FacebookSessionPersistentDataHandler(); $this->urlDetectionHandler = $urlHandler ?: new FacebookUrlDetectionHandler(); - $this->pseudoRandomStringGenerator = $prsg ?: $this->detectPseudoRandomStringGenerator(); + $this->pseudoRandomStringGenerator = PseudoRandomStringGeneratorFactory::createPseudoRandomStringGenerator($prsg); } /** @@ -113,32 +111,6 @@ class FacebookRedirectLoginHelper } /** - * Detects which pseudo-random string generator to use. - * - * @return PseudoRandomStringGeneratorInterface - * - * @throws FacebookSDKException - */ - public function detectPseudoRandomStringGenerator() - { - // Since openssl_random_pseudo_bytes() can sometimes return non-cryptographically - // secure pseudo-random strings (in rare cases), we check for mcrypt_create_iv() first. - if (function_exists('mcrypt_create_iv')) { - return new McryptPseudoRandomStringGenerator(); - } - - if (function_exists('openssl_random_pseudo_bytes')) { - return new OpenSslPseudoRandomStringGenerator(); - } - - if (!ini_get('open_basedir') && is_readable('/dev/urandom')) { - return new UrandomPseudoRandomStringGenerator(); - } - - throw new FacebookSDKException('Unable to detect a cryptographically secure pseudo-random string generator.'); - } - - /** * Stores CSRF state and returns a URL to which the user should be sent to in order to continue the login process with Facebook. * * @param string $redirectUrl The URL Facebook should redirect users to after login. @@ -150,7 +122,7 @@ class FacebookRedirectLoginHelper */ private function makeUrl($redirectUrl, array $scope, array $params = [], $separator = '&') { - $state = $this->pseudoRandomStringGenerator->getPseudoRandomString(static::CSRF_LENGTH); + $state = $this->persistentDataHandler->get('state') ?: $this->pseudoRandomStringGenerator->getPseudoRandomString(static::CSRF_LENGTH); $this->persistentDataHandler->set('state', $state); return $this->oAuth2Client->getAuthorizationUrl($redirectUrl, $state, $scope, $params, $separator); @@ -247,10 +219,11 @@ class FacebookRedirectLoginHelper } $this->validateCsrf(); + $this->resetCsrf(); $redirectUrl = $redirectUrl ?: $this->urlDetectionHandler->getCurrentUrl(); - // At minimum we need to remove the state param - $redirectUrl = FacebookUrlManipulator::removeParamsFromUrl($redirectUrl, ['state']); + // At minimum we need to remove the 'state' and 'code' params + $redirectUrl = FacebookUrlManipulator::removeParamsFromUrl($redirectUrl, ['code', 'state']); return $this->oAuth2Client->getAccessTokenFromCode($code, $redirectUrl); } @@ -263,27 +236,27 @@ class FacebookRedirectLoginHelper protected function validateCsrf() { $state = $this->getState(); + if (!$state) { + throw new FacebookSDKException('Cross-site request forgery validation failed. Required GET param "state" missing.'); + } $savedState = $this->persistentDataHandler->get('state'); - - if (!$state || !$savedState) { - throw new FacebookSDKException('Cross-site request forgery validation failed. Required param "state" missing.'); + if (!$savedState) { + throw new FacebookSDKException('Cross-site request forgery validation failed. Required param "state" missing from persistent data.'); } - $savedLen = strlen($savedState); - $givenLen = strlen($state); - - if ($savedLen !== $givenLen) { - throw new FacebookSDKException('Cross-site request forgery validation failed. The "state" param from the URL and session do not match.'); + if (\hash_equals($savedState, $state)) { + return; } - $result = 0; - for ($i = 0; $i < $savedLen; $i++) { - $result |= ord($state[$i]) ^ ord($savedState[$i]); - } + throw new FacebookSDKException('Cross-site request forgery validation failed. The "state" param from the URL and session do not match.'); + } - if ($result !== 0) { - throw new FacebookSDKException('Cross-site request forgery validation failed. The "state" param from the URL and session do not match.'); - } + /** + * Resets the CSRF so that it doesn't get reused. + */ + private function resetCsrf() + { + $this->persistentDataHandler->set('state', null); } /** diff --git a/lib/facebook-graph-sdk/src/Facebook/Helpers/FacebookSignedRequestFromInputHelper.php b/lib/facebook-graph-sdk/src/Facebook/Helpers/FacebookSignedRequestFromInputHelper.php index aafa246..4044da1 100644 --- a/lib/facebook-graph-sdk/src/Facebook/Helpers/FacebookSignedRequestFromInputHelper.php +++ b/lib/facebook-graph-sdk/src/Facebook/Helpers/FacebookSignedRequestFromInputHelper.php @@ -1,6 +1,6 @@ <?php /** - * Copyright 2014 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * You are hereby granted a non-exclusive, worldwide, royalty-free license to * use, copy, modify, and distribute this software in source code or binary diff --git a/lib/facebook-graph-sdk/src/Facebook/Http/GraphRawResponse.php b/lib/facebook-graph-sdk/src/Facebook/Http/GraphRawResponse.php index 583d303..d1a7241 100644 --- a/lib/facebook-graph-sdk/src/Facebook/Http/GraphRawResponse.php +++ b/lib/facebook-graph-sdk/src/Facebook/Http/GraphRawResponse.php @@ -1,6 +1,6 @@ <?php /** - * Copyright 2014 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * You are hereby granted a non-exclusive, worldwide, royalty-free license to * use, copy, modify, and distribute this software in source code or binary @@ -129,7 +129,7 @@ class GraphRawResponse if (strpos($line, ': ') === false) { $this->setHttpResponseCodeFromHeader($line); } else { - list($key, $value) = explode(': ', $line); + list($key, $value) = explode(': ', $line, 2); $this->headers[$key] = $value; } } diff --git a/lib/facebook-graph-sdk/src/Facebook/Http/RequestBodyInterface.php b/lib/facebook-graph-sdk/src/Facebook/Http/RequestBodyInterface.php index 97e0a2e..1c03f4f 100644 --- a/lib/facebook-graph-sdk/src/Facebook/Http/RequestBodyInterface.php +++ b/lib/facebook-graph-sdk/src/Facebook/Http/RequestBodyInterface.php @@ -1,6 +1,6 @@ <?php /** - * Copyright 2014 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * You are hereby granted a non-exclusive, worldwide, royalty-free license to * use, copy, modify, and distribute this software in source code or binary diff --git a/lib/facebook-graph-sdk/src/Facebook/Http/RequestBodyMultipart.php b/lib/facebook-graph-sdk/src/Facebook/Http/RequestBodyMultipart.php index 82f1438..e43695a 100644 --- a/lib/facebook-graph-sdk/src/Facebook/Http/RequestBodyMultipart.php +++ b/lib/facebook-graph-sdk/src/Facebook/Http/RequestBodyMultipart.php @@ -1,6 +1,6 @@ <?php /** - * Copyright 2014 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * You are hereby granted a non-exclusive, worldwide, royalty-free license to * use, copy, modify, and distribute this software in source code or binary diff --git a/lib/facebook-graph-sdk/src/Facebook/Http/RequestBodyUrlEncoded.php b/lib/facebook-graph-sdk/src/Facebook/Http/RequestBodyUrlEncoded.php index 77c2b64..c1e35f4 100644 --- a/lib/facebook-graph-sdk/src/Facebook/Http/RequestBodyUrlEncoded.php +++ b/lib/facebook-graph-sdk/src/Facebook/Http/RequestBodyUrlEncoded.php @@ -1,6 +1,6 @@ <?php /** - * Copyright 2014 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * You are hereby granted a non-exclusive, worldwide, royalty-free license to * use, copy, modify, and distribute this software in source code or binary diff --git a/lib/facebook-graph-sdk/src/Facebook/HttpClients/FacebookCurl.php b/lib/facebook-graph-sdk/src/Facebook/HttpClients/FacebookCurl.php index e5d124a..28e4ba5 100644 --- a/lib/facebook-graph-sdk/src/Facebook/HttpClients/FacebookCurl.php +++ b/lib/facebook-graph-sdk/src/Facebook/HttpClients/FacebookCurl.php @@ -1,6 +1,6 @@ <?php /** - * Copyright 2014 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * You are hereby granted a non-exclusive, worldwide, royalty-free license to * use, copy, modify, and distribute this software in source code or binary diff --git a/lib/facebook-graph-sdk/src/Facebook/HttpClients/FacebookCurlHttpClient.php b/lib/facebook-graph-sdk/src/Facebook/HttpClients/FacebookCurlHttpClient.php index 955ac06..9516cc8 100644 --- a/lib/facebook-graph-sdk/src/Facebook/HttpClients/FacebookCurlHttpClient.php +++ b/lib/facebook-graph-sdk/src/Facebook/HttpClients/FacebookCurlHttpClient.php @@ -1,6 +1,6 @@ <?php /** - * Copyright 2014 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * You are hereby granted a non-exclusive, worldwide, royalty-free license to * use, copy, modify, and distribute this software in source code or binary @@ -54,16 +54,6 @@ class FacebookCurlHttpClient implements FacebookHttpClientInterface protected $facebookCurl; /** - * @const Curl Version which is unaffected by the proxy header length error. - */ - const CURL_PROXY_QUIRK_VER = 0x071E00; - - /** - * @const "Connection Established" header text - */ - const CONNECTION_ESTABLISHED = "HTTP/1.0 200 Connection established\r\n\r\n"; - - /** * @param FacebookCurl|null Procedural curl as object */ public function __construct(FacebookCurl $facebookCurl = null) @@ -108,7 +98,7 @@ class FacebookCurlHttpClient implements FacebookHttpClientInterface CURLOPT_URL => $url, CURLOPT_CONNECTTIMEOUT => 10, CURLOPT_TIMEOUT => $timeOut, - CURLOPT_RETURNTRANSFER => true, // Follow 301 redirects + CURLOPT_RETURNTRANSFER => true, // Return response as string CURLOPT_HEADER => true, // Enable header processing CURLOPT_SSL_VERIFYHOST => 2, CURLOPT_SSL_VERIFYPEER => true, @@ -164,47 +154,10 @@ class FacebookCurlHttpClient implements FacebookHttpClientInterface */ public function extractResponseHeadersAndBody() { - $headerSize = $this->getHeaderSize(); - - $rawHeaders = mb_substr($this->rawResponse, 0, $headerSize); - $rawBody = mb_substr($this->rawResponse, $headerSize); + $parts = explode("\r\n\r\n", $this->rawResponse); + $rawBody = array_pop($parts); + $rawHeaders = implode("\r\n\r\n", $parts); return [trim($rawHeaders), trim($rawBody)]; } - - /** - * Return proper header size - * - * @return integer - */ - private function getHeaderSize() - { - $headerSize = $this->facebookCurl->getinfo(CURLINFO_HEADER_SIZE); - // This corrects a Curl bug where header size does not account - // for additional Proxy headers. - if ($this->needsCurlProxyFix()) { - // Additional way to calculate the request body size. - if (preg_match('/Content-Length: (\d+)/', $this->rawResponse, $m)) { - $headerSize = mb_strlen($this->rawResponse) - $m[1]; - } elseif (stripos($this->rawResponse, self::CONNECTION_ESTABLISHED) !== false) { - $headerSize += mb_strlen(self::CONNECTION_ESTABLISHED); - } - } - - return $headerSize; - } - - /** - * Detect versions of Curl which report incorrect header lengths when - * using Proxies. - * - * @return boolean - */ - private function needsCurlProxyFix() - { - $ver = $this->facebookCurl->version(); - $version = $ver['version_number']; - - return $version < self::CURL_PROXY_QUIRK_VER; - } } diff --git a/lib/facebook-graph-sdk/src/Facebook/HttpClients/FacebookGuzzleHttpClient.php b/lib/facebook-graph-sdk/src/Facebook/HttpClients/FacebookGuzzleHttpClient.php index 6f2a1c6..8feb7cb 100644 --- a/lib/facebook-graph-sdk/src/Facebook/HttpClients/FacebookGuzzleHttpClient.php +++ b/lib/facebook-graph-sdk/src/Facebook/HttpClients/FacebookGuzzleHttpClient.php @@ -1,6 +1,6 @@ <?php /** - * Copyright 2014 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * You are hereby granted a non-exclusive, worldwide, royalty-free license to * use, copy, modify, and distribute this software in source code or binary diff --git a/lib/facebook-graph-sdk/src/Facebook/HttpClients/FacebookHttpClientInterface.php b/lib/facebook-graph-sdk/src/Facebook/HttpClients/FacebookHttpClientInterface.php index 0029bc0..1fbf953 100644 --- a/lib/facebook-graph-sdk/src/Facebook/HttpClients/FacebookHttpClientInterface.php +++ b/lib/facebook-graph-sdk/src/Facebook/HttpClients/FacebookHttpClientInterface.php @@ -1,6 +1,6 @@ <?php /** - * Copyright 2014 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * You are hereby granted a non-exclusive, worldwide, royalty-free license to * use, copy, modify, and distribute this software in source code or binary diff --git a/lib/facebook-graph-sdk/src/Facebook/HttpClients/FacebookStream.php b/lib/facebook-graph-sdk/src/Facebook/HttpClients/FacebookStream.php index 95aa22e..3f39988 100644 --- a/lib/facebook-graph-sdk/src/Facebook/HttpClients/FacebookStream.php +++ b/lib/facebook-graph-sdk/src/Facebook/HttpClients/FacebookStream.php @@ -1,6 +1,6 @@ <?php /** - * Copyright 2014 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * You are hereby granted a non-exclusive, worldwide, royalty-free license to * use, copy, modify, and distribute this software in source code or binary @@ -41,7 +41,7 @@ class FacebookStream /** * @var array Response headers from the stream wrapper */ - protected $responseHeaders; + protected $responseHeaders = []; /** * Make a new context stream reference instance @@ -56,7 +56,7 @@ class FacebookStream /** * The response headers from the stream wrapper * - * @return array|null + * @return array */ public function getResponseHeaders() { @@ -73,7 +73,7 @@ class FacebookStream public function fileGetContents($url) { $rawResponse = file_get_contents($url, false, $this->stream); - $this->responseHeaders = $http_response_header; + $this->responseHeaders = $http_response_header ?: []; return $rawResponse; } diff --git a/lib/facebook-graph-sdk/src/Facebook/HttpClients/FacebookStreamHttpClient.php b/lib/facebook-graph-sdk/src/Facebook/HttpClients/FacebookStreamHttpClient.php index b157514..1cdfd53 100644 --- a/lib/facebook-graph-sdk/src/Facebook/HttpClients/FacebookStreamHttpClient.php +++ b/lib/facebook-graph-sdk/src/Facebook/HttpClients/FacebookStreamHttpClient.php @@ -1,6 +1,6 @@ <?php /** - * Copyright 2014 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * You are hereby granted a non-exclusive, worldwide, royalty-free license to * use, copy, modify, and distribute this software in source code or binary @@ -66,7 +66,7 @@ class FacebookStreamHttpClient implements FacebookHttpClientInterface $rawBody = $this->facebookStream->fileGetContents($url); $rawHeaders = $this->facebookStream->getResponseHeaders(); - if ($rawBody === false || !$rawHeaders) { + if ($rawBody === false || empty($rawHeaders)) { throw new FacebookSDKException('Stream returned an empty response', 660); } diff --git a/lib/facebook-graph-sdk/src/Facebook/HttpClients/HttpClientsFactory.php b/lib/facebook-graph-sdk/src/Facebook/HttpClients/HttpClientsFactory.php new file mode 100644 index 0000000..d9f2a8d --- /dev/null +++ b/lib/facebook-graph-sdk/src/Facebook/HttpClients/HttpClientsFactory.php @@ -0,0 +1,99 @@ +<?php +/** + * Copyright 2017 Facebook, Inc. + * + * You are hereby granted a non-exclusive, worldwide, royalty-free license to + * use, copy, modify, and distribute this software in source code or binary + * form for use in connection with the web services and APIs provided by + * Facebook. + * + * As with any software that integrates with the Facebook platform, your use + * of this software is subject to the Facebook Developer Principles and + * Policies [http://developers.facebook.com/policy/]. This copyright notice + * shall be included in all copies or substantial portions of the software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ +namespace Facebook\HttpClients; + +use GuzzleHttp\Client; +use InvalidArgumentException; +use Exception; + +class HttpClientsFactory +{ + private function __construct() + { + // a factory constructor should never be invoked + } + + /** + * HTTP client generation. + * + * @param FacebookHttpClientInterface|Client|string|null $handler + * + * @throws Exception If the cURL extension or the Guzzle client aren't available (if required). + * @throws InvalidArgumentException If the http client handler isn't "curl", "stream", "guzzle", or an instance of Facebook\HttpClients\FacebookHttpClientInterface. + * + * @return FacebookHttpClientInterface + */ + public static function createHttpClient($handler) + { + if (!$handler) { + return self::detectDefaultClient(); + } + + if ($handler instanceof FacebookHttpClientInterface) { + return $handler; + } + + if ('stream' === $handler) { + return new FacebookStreamHttpClient(); + } + if ('curl' === $handler) { + if (!extension_loaded('curl')) { + throw new Exception('The cURL extension must be loaded in order to use the "curl" handler.'); + } + + return new FacebookCurlHttpClient(); + } + + if ('guzzle' === $handler && !class_exists('GuzzleHttp\Client')) { + throw new Exception('The Guzzle HTTP client must be included in order to use the "guzzle" handler.'); + } + + if ($handler instanceof Client) { + return new FacebookGuzzleHttpClient($handler); + } + if ('guzzle' === $handler) { + return new FacebookGuzzleHttpClient(); + } + + throw new InvalidArgumentException('The http client handler must be set to "curl", "stream", "guzzle", be an instance of GuzzleHttp\Client or an instance of Facebook\HttpClients\FacebookHttpClientInterface'); + } + + /** + * Detect default HTTP client. + * + * @return FacebookHttpClientInterface + */ + private static function detectDefaultClient() + { + if (extension_loaded('curl')) { + return new FacebookCurlHttpClient(); + } + + if (class_exists('GuzzleHttp\Client')) { + return new FacebookGuzzleHttpClient(); + } + + return new FacebookStreamHttpClient(); + } +} diff --git a/lib/facebook-graph-sdk/src/Facebook/PersistentData/FacebookMemoryPersistentDataHandler.php b/lib/facebook-graph-sdk/src/Facebook/PersistentData/FacebookMemoryPersistentDataHandler.php index 93a6686..4b7c87e 100644 --- a/lib/facebook-graph-sdk/src/Facebook/PersistentData/FacebookMemoryPersistentDataHandler.php +++ b/lib/facebook-graph-sdk/src/Facebook/PersistentData/FacebookMemoryPersistentDataHandler.php @@ -1,6 +1,6 @@ <?php /** - * Copyright 2014 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * You are hereby granted a non-exclusive, worldwide, royalty-free license to * use, copy, modify, and distribute this software in source code or binary diff --git a/lib/facebook-graph-sdk/src/Facebook/PersistentData/FacebookSessionPersistentDataHandler.php b/lib/facebook-graph-sdk/src/Facebook/PersistentData/FacebookSessionPersistentDataHandler.php index 698bfd0..9123e3d 100644 --- a/lib/facebook-graph-sdk/src/Facebook/PersistentData/FacebookSessionPersistentDataHandler.php +++ b/lib/facebook-graph-sdk/src/Facebook/PersistentData/FacebookSessionPersistentDataHandler.php @@ -1,6 +1,6 @@ <?php /** - * Copyright 2014 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * You are hereby granted a non-exclusive, worldwide, royalty-free license to * use, copy, modify, and distribute this software in source code or binary diff --git a/lib/facebook-graph-sdk/src/Facebook/PersistentData/PersistentDataFactory.php b/lib/facebook-graph-sdk/src/Facebook/PersistentData/PersistentDataFactory.php new file mode 100644 index 0000000..18fb8fd --- /dev/null +++ b/lib/facebook-graph-sdk/src/Facebook/PersistentData/PersistentDataFactory.php @@ -0,0 +1,65 @@ +<?php +/** + * Copyright 2017 Facebook, Inc. + * + * You are hereby granted a non-exclusive, worldwide, royalty-free license to + * use, copy, modify, and distribute this software in source code or binary + * form for use in connection with the web services and APIs provided by + * Facebook. + * + * As with any software that integrates with the Facebook platform, your use + * of this software is subject to the Facebook Developer Principles and + * Policies [http://developers.facebook.com/policy/]. This copyright notice + * shall be included in all copies or substantial portions of the software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ +namespace Facebook\PersistentData; + +use InvalidArgumentException; + +class PersistentDataFactory +{ + private function __construct() + { + // a factory constructor should never be invoked + } + + /** + * PersistentData generation. + * + * @param PersistentDataInterface|string|null $handler + * + * @throws InvalidArgumentException If the persistent data handler isn't "session", "memory", or an instance of Facebook\PersistentData\PersistentDataInterface. + * + * @return PersistentDataInterface + */ + public static function createPersistentDataHandler($handler) + { + if (!$handler) { + return session_status() === PHP_SESSION_ACTIVE + ? new FacebookSessionPersistentDataHandler() + : new FacebookMemoryPersistentDataHandler(); + } + + if ($handler instanceof PersistentDataInterface) { + return $handler; + } + + if ('session' === $handler) { + return new FacebookSessionPersistentDataHandler(); + } + if ('memory' === $handler) { + return new FacebookMemoryPersistentDataHandler(); + } + + throw new InvalidArgumentException('The persistent data handler must be set to "session", "memory", or be an instance of Facebook\PersistentData\PersistentDataInterface'); + } +} diff --git a/lib/facebook-graph-sdk/src/Facebook/PersistentData/PersistentDataInterface.php b/lib/facebook-graph-sdk/src/Facebook/PersistentData/PersistentDataInterface.php index bd7e072..3517ee1 100644 --- a/lib/facebook-graph-sdk/src/Facebook/PersistentData/PersistentDataInterface.php +++ b/lib/facebook-graph-sdk/src/Facebook/PersistentData/PersistentDataInterface.php @@ -1,6 +1,6 @@ <?php /** - * Copyright 2014 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * You are hereby granted a non-exclusive, worldwide, royalty-free license to * use, copy, modify, and distribute this software in source code or binary diff --git a/lib/facebook-graph-sdk/src/Facebook/PseudoRandomString/McryptPseudoRandomStringGenerator.php b/lib/facebook-graph-sdk/src/Facebook/PseudoRandomString/McryptPseudoRandomStringGenerator.php index 63c271f..bf57374 100644 --- a/lib/facebook-graph-sdk/src/Facebook/PseudoRandomString/McryptPseudoRandomStringGenerator.php +++ b/lib/facebook-graph-sdk/src/Facebook/PseudoRandomString/McryptPseudoRandomStringGenerator.php @@ -1,6 +1,6 @@ <?php /** - * Copyright 2014 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * You are hereby granted a non-exclusive, worldwide, royalty-free license to * use, copy, modify, and distribute this software in source code or binary diff --git a/lib/facebook-graph-sdk/src/Facebook/PseudoRandomString/OpenSslPseudoRandomStringGenerator.php b/lib/facebook-graph-sdk/src/Facebook/PseudoRandomString/OpenSslPseudoRandomStringGenerator.php index f4ea6b8..4b4276d 100644 --- a/lib/facebook-graph-sdk/src/Facebook/PseudoRandomString/OpenSslPseudoRandomStringGenerator.php +++ b/lib/facebook-graph-sdk/src/Facebook/PseudoRandomString/OpenSslPseudoRandomStringGenerator.php @@ -1,6 +1,6 @@ <?php /** - * Copyright 2014 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * You are hereby granted a non-exclusive, worldwide, royalty-free license to * use, copy, modify, and distribute this software in source code or binary diff --git a/lib/facebook-graph-sdk/src/Facebook/PseudoRandomString/PseudoRandomStringGeneratorFactory.php b/lib/facebook-graph-sdk/src/Facebook/PseudoRandomString/PseudoRandomStringGeneratorFactory.php new file mode 100644 index 0000000..412f481 --- /dev/null +++ b/lib/facebook-graph-sdk/src/Facebook/PseudoRandomString/PseudoRandomStringGeneratorFactory.php @@ -0,0 +1,101 @@ +<?php +/** + * Copyright 2017 Facebook, Inc. + * + * You are hereby granted a non-exclusive, worldwide, royalty-free license to + * use, copy, modify, and distribute this software in source code or binary + * form for use in connection with the web services and APIs provided by + * Facebook. + * + * As with any software that integrates with the Facebook platform, your use + * of this software is subject to the Facebook Developer Principles and + * Policies [http://developers.facebook.com/policy/]. This copyright notice + * shall be included in all copies or substantial portions of the software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ +namespace Facebook\PseudoRandomString; + +use Facebook\Exceptions\FacebookSDKException; +use InvalidArgumentException; + +class PseudoRandomStringGeneratorFactory +{ + private function __construct() + { + // a factory constructor should never be invoked + } + + /** + * Pseudo random string generator creation. + * + * @param PseudoRandomStringGeneratorInterface|string|null $generator + * + * @throws InvalidArgumentException If the pseudo random string generator must be set to "random_bytes", "mcrypt", "openssl", or "urandom", or be an instance of Facebook\PseudoRandomString\PseudoRandomStringGeneratorInterface. + * + * @return PseudoRandomStringGeneratorInterface + */ + public static function createPseudoRandomStringGenerator($generator) + { + if (!$generator) { + return self::detectDefaultPseudoRandomStringGenerator(); + } + + if ($generator instanceof PseudoRandomStringGeneratorInterface) { + return $generator; + } + + if ('random_bytes' === $generator) { + return new RandomBytesPseudoRandomStringGenerator(); + } + if ('mcrypt' === $generator) { + return new McryptPseudoRandomStringGenerator(); + } + if ('openssl' === $generator) { + return new OpenSslPseudoRandomStringGenerator(); + } + if ('urandom' === $generator) { + return new UrandomPseudoRandomStringGenerator(); + } + + throw new InvalidArgumentException('The pseudo random string generator must be set to "random_bytes", "mcrypt", "openssl", or "urandom", or be an instance of Facebook\PseudoRandomString\PseudoRandomStringGeneratorInterface'); + } + + /** + * Detects which pseudo-random string generator to use. + * + * @throws FacebookSDKException If unable to detect a cryptographically secure pseudo-random string generator. + * + * @return PseudoRandomStringGeneratorInterface + */ + private static function detectDefaultPseudoRandomStringGenerator() + { + // Check for PHP 7's CSPRNG first to keep mcrypt deprecation messages from appearing in PHP 7.1. + if (function_exists('random_bytes')) { + return new RandomBytesPseudoRandomStringGenerator(); + } + + // Since openssl_random_pseudo_bytes() can sometimes return non-cryptographically + // secure pseudo-random strings (in rare cases), we check for mcrypt_create_iv() next. + if (function_exists('mcrypt_create_iv')) { + return new McryptPseudoRandomStringGenerator(); + } + + if (function_exists('openssl_random_pseudo_bytes')) { + return new OpenSslPseudoRandomStringGenerator(); + } + + if (!ini_get('open_basedir') && is_readable('/dev/urandom')) { + return new UrandomPseudoRandomStringGenerator(); + } + + throw new FacebookSDKException('Unable to detect a cryptographically secure pseudo-random string generator.'); + } +} diff --git a/lib/facebook-graph-sdk/src/Facebook/PseudoRandomString/PseudoRandomStringGeneratorInterface.php b/lib/facebook-graph-sdk/src/Facebook/PseudoRandomString/PseudoRandomStringGeneratorInterface.php index 970330c..914ee3c 100644 --- a/lib/facebook-graph-sdk/src/Facebook/PseudoRandomString/PseudoRandomStringGeneratorInterface.php +++ b/lib/facebook-graph-sdk/src/Facebook/PseudoRandomString/PseudoRandomStringGeneratorInterface.php @@ -1,6 +1,6 @@ <?php /** - * Copyright 2014 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * You are hereby granted a non-exclusive, worldwide, royalty-free license to * use, copy, modify, and distribute this software in source code or binary diff --git a/lib/facebook-graph-sdk/src/Facebook/PseudoRandomString/PseudoRandomStringGeneratorTrait.php b/lib/facebook-graph-sdk/src/Facebook/PseudoRandomString/PseudoRandomStringGeneratorTrait.php index a41ce59..0f587ea 100644 --- a/lib/facebook-graph-sdk/src/Facebook/PseudoRandomString/PseudoRandomStringGeneratorTrait.php +++ b/lib/facebook-graph-sdk/src/Facebook/PseudoRandomString/PseudoRandomStringGeneratorTrait.php @@ -1,6 +1,6 @@ <?php /** - * Copyright 2014 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * You are hereby granted a non-exclusive, worldwide, royalty-free license to * use, copy, modify, and distribute this software in source code or binary @@ -53,6 +53,6 @@ trait PseudoRandomStringGeneratorTrait */ public function binToHex($binaryData, $length) { - return mb_substr(bin2hex($binaryData), 0, $length); + return \substr(\bin2hex($binaryData), 0, $length); } } diff --git a/lib/facebook-graph-sdk/src/Facebook/PseudoRandomString/RandomBytesPseudoRandomStringGenerator.php b/lib/facebook-graph-sdk/src/Facebook/PseudoRandomString/RandomBytesPseudoRandomStringGenerator.php new file mode 100644 index 0000000..b5943f6 --- /dev/null +++ b/lib/facebook-graph-sdk/src/Facebook/PseudoRandomString/RandomBytesPseudoRandomStringGenerator.php @@ -0,0 +1,59 @@ +<?php +/** + * Copyright 2017 Facebook, Inc. + * + * You are hereby granted a non-exclusive, worldwide, royalty-free license to + * use, copy, modify, and distribute this software in source code or binary + * form for use in connection with the web services and APIs provided by + * Facebook. + * + * As with any software that integrates with the Facebook platform, your use + * of this software is subject to the Facebook Developer Principles and + * Policies [http://developers.facebook.com/policy/]. This copyright notice + * shall be included in all copies or substantial portions of the software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ +namespace Facebook\PseudoRandomString; + +use Facebook\Exceptions\FacebookSDKException; + +class RandomBytesPseudoRandomStringGenerator implements PseudoRandomStringGeneratorInterface +{ + use PseudoRandomStringGeneratorTrait; + + /** + * @const string The error message when generating the string fails. + */ + const ERROR_MESSAGE = 'Unable to generate a cryptographically secure pseudo-random string from random_bytes(). '; + + /** + * @throws FacebookSDKException + */ + public function __construct() + { + if (!function_exists('random_bytes')) { + throw new FacebookSDKException( + static::ERROR_MESSAGE . + 'The function random_bytes() does not exist.' + ); + } + } + + /** + * @inheritdoc + */ + public function getPseudoRandomString($length) + { + $this->validateLength($length); + + return $this->binToHex(random_bytes($length), $length); + } +} diff --git a/lib/facebook-graph-sdk/src/Facebook/PseudoRandomString/UrandomPseudoRandomStringGenerator.php b/lib/facebook-graph-sdk/src/Facebook/PseudoRandomString/UrandomPseudoRandomStringGenerator.php index 0f9cacd..5ab434e 100644 --- a/lib/facebook-graph-sdk/src/Facebook/PseudoRandomString/UrandomPseudoRandomStringGenerator.php +++ b/lib/facebook-graph-sdk/src/Facebook/PseudoRandomString/UrandomPseudoRandomStringGenerator.php @@ -1,6 +1,6 @@ <?php /** - * Copyright 2014 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * You are hereby granted a non-exclusive, worldwide, royalty-free license to * use, copy, modify, and distribute this software in source code or binary diff --git a/lib/facebook-graph-sdk/src/Facebook/SignedRequest.php b/lib/facebook-graph-sdk/src/Facebook/SignedRequest.php index 77099a3..6a175a0 100644 --- a/lib/facebook-graph-sdk/src/Facebook/SignedRequest.php +++ b/lib/facebook-graph-sdk/src/Facebook/SignedRequest.php @@ -1,6 +1,6 @@ <?php /** - * Copyright 2014 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * You are hereby granted a non-exclusive, worldwide, royalty-free license to * use, copy, modify, and distribute this software in source code or binary @@ -164,7 +164,7 @@ class SignedRequest /** * Splits a raw signed request into signature and payload. * - * @returns array + * @return array * * @throws FacebookSDKException */ @@ -182,7 +182,7 @@ class SignedRequest * * @param string $encodedSig * - * @returns string + * @return string * * @throws FacebookSDKException */ @@ -202,7 +202,7 @@ class SignedRequest * * @param string $encodedPayload * - * @returns array + * @return array * * @throws FacebookSDKException */ @@ -268,14 +268,8 @@ class SignedRequest */ protected function validateSignature($hashedSig, $sig) { - if (mb_strlen($hashedSig) === mb_strlen($sig)) { - $validate = 0; - for ($i = 0; $i < mb_strlen($sig); $i++) { - $validate |= ord($hashedSig[$i]) ^ ord($sig[$i]); - } - if ($validate === 0) { - return; - } + if (\hash_equals($hashedSig, $sig)) { + return; } throw new FacebookSDKException('Signed request has an invalid signature.', 602); diff --git a/lib/facebook-graph-sdk/src/Facebook/Url/FacebookUrlDetectionHandler.php b/lib/facebook-graph-sdk/src/Facebook/Url/FacebookUrlDetectionHandler.php index 5fbb9ce..1d134dd 100644 --- a/lib/facebook-graph-sdk/src/Facebook/Url/FacebookUrlDetectionHandler.php +++ b/lib/facebook-graph-sdk/src/Facebook/Url/FacebookUrlDetectionHandler.php @@ -1,6 +1,6 @@ <?php /** - * Copyright 2014 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * You are hereby granted a non-exclusive, worldwide, royalty-free license to * use, copy, modify, and distribute this software in source code or binary @@ -95,8 +95,9 @@ class FacebookUrlDetectionHandler implements UrlDetectionInterface protected function getHostName() { // Check for proxy first - if ($host = $this->getHeader('X_FORWARDED_HOST')) { - $elements = explode(',', $host); + $header = $this->getHeader('X_FORWARDED_HOST'); + if ($header && $this->isValidForwardedHost($header)) { + $elements = explode(',', $header); $host = $elements[count($elements) - 1]; } elseif (!$host = $this->getHeader('HOST')) { if (!$host = $this->getServerVar('SERVER_NAME')) { @@ -160,4 +161,22 @@ class FacebookUrlDetectionHandler implements UrlDetectionInterface { return $this->getServerVar('HTTP_' . $key); } + + /** + * Checks if the value in X_FORWARDED_HOST is a valid hostname + * Could prevent unintended redirections + * + * @param string $header + * + * @return boolean + */ + protected function isValidForwardedHost($header) + { + $elements = explode(',', $header); + $host = $elements[count($elements) - 1]; + + return preg_match("/^([a-z\d](-*[a-z\d])*)(\.([a-z\d](-*[a-z\d])*))*$/i", $host) //valid chars check + && 0 < strlen($host) && strlen($host) < 254 //overall length check + && preg_match("/^[^\.]{1,63}(\.[^\.]{1,63})*$/", $host); //length of each label + } } diff --git a/lib/facebook-graph-sdk/src/Facebook/Url/FacebookUrlManipulator.php b/lib/facebook-graph-sdk/src/Facebook/Url/FacebookUrlManipulator.php index 20a0299..daeab9c 100644 --- a/lib/facebook-graph-sdk/src/Facebook/Url/FacebookUrlManipulator.php +++ b/lib/facebook-graph-sdk/src/Facebook/Url/FacebookUrlManipulator.php @@ -1,6 +1,6 @@ <?php /** - * Copyright 2014 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * You are hereby granted a non-exclusive, worldwide, royalty-free license to * use, copy, modify, and distribute this software in source code or binary @@ -76,7 +76,7 @@ class FacebookUrlManipulator */ public static function appendParamsToUrl($url, array $newParams = []) { - if (!$newParams) { + if (empty($newParams)) { return $url; } diff --git a/lib/facebook-graph-sdk/src/Facebook/Url/UrlDetectionInterface.php b/lib/facebook-graph-sdk/src/Facebook/Url/UrlDetectionInterface.php index 764a606..dca38a0 100644 --- a/lib/facebook-graph-sdk/src/Facebook/Url/UrlDetectionInterface.php +++ b/lib/facebook-graph-sdk/src/Facebook/Url/UrlDetectionInterface.php @@ -1,6 +1,6 @@ <?php /** - * Copyright 2014 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * You are hereby granted a non-exclusive, worldwide, royalty-free license to * use, copy, modify, and distribute this software in source code or binary diff --git a/lib/facebook-graph-sdk/src/Facebook/autoload.php b/lib/facebook-graph-sdk/src/Facebook/autoload.php index 6fcd39a..e0dd21c 100644 --- a/lib/facebook-graph-sdk/src/Facebook/autoload.php +++ b/lib/facebook-graph-sdk/src/Facebook/autoload.php @@ -1,6 +1,6 @@ <?php /** - * Copyright 2014 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * You are hereby granted a non-exclusive, worldwide, royalty-free license to * use, copy, modify, and distribute this software in source code or binary @@ -32,6 +32,8 @@ if (version_compare(PHP_VERSION, '5.4.0', '<')) { throw new Exception('The Facebook SDK requires PHP version 5.4 or higher.'); } +require_once __DIR__ . '/polyfills.php'; + /** * Register the autoloader for the Facebook SDK classes. * diff --git a/lib/facebook-graph-sdk/src/Facebook/polyfills.php b/lib/facebook-graph-sdk/src/Facebook/polyfills.php new file mode 100644 index 0000000..4a67d86 --- /dev/null +++ b/lib/facebook-graph-sdk/src/Facebook/polyfills.php @@ -0,0 +1,49 @@ +<?php +/** + * Copyright 2017 Facebook, Inc. + * + * You are hereby granted a non-exclusive, worldwide, royalty-free license to + * use, copy, modify, and distribute this software in source code or binary + * form for use in connection with the web services and APIs provided by + * Facebook. + * + * As with any software that integrates with the Facebook platform, your use + * of this software is subject to the Facebook Developer Principles and + * Policies [http://developers.facebook.com/policy/]. This copyright notice + * shall be included in all copies or substantial portions of the software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ + +/** + * @see https://github.com/sarciszewski/php-future/blob/master/src/Security.php#L37-L51 + */ +if (!function_exists('hash_equals')) { + function hash_equals($knownString, $userString) + { + if (function_exists('mb_strlen')) { + $kLen = mb_strlen($knownString, '8bit'); + $uLen = mb_strlen($userString, '8bit'); + } else { + $kLen = strlen($knownString); + $uLen = strlen($userString); + } + if ($kLen !== $uLen) { + return false; + } + $result = 0; + for ($i = 0; $i < $kLen; $i++) { + $result |= (ord($knownString[$i]) ^ ord($userString[$i])); + } + + // They are only identical strings if $result is exactly 0... + return 0 === $result; + } +} |