Social Login WordPress Plugin – AccessPress Social Login Lite - Version 3.3.5

Version Description

  • Issue with social login with facebok since our last update resolved
Download this release

Release Info

Developer Access Keys
Plugin Icon 128x128 Social Login WordPress Plugin – AccessPress Social Login Lite
Version 3.3.5
Comparing to
See all releases

Code changes from version 3.3.4 to 3.3.5

Files changed (89) hide show
  1. accesspress-social-login-lite.php +192 -205
  2. facebook/Exceptions/FacebookResumableUploadException.php +33 -0
  3. facebook/FileUpload/FacebookResumableUploader.php +167 -0
  4. facebook/FileUpload/FacebookTransferChunk.php +133 -0
  5. facebook/GraphNodes/Birthday.php +85 -0
  6. facebook/HttpClients/HttpClientsFactory.php +99 -0
  7. facebook/PersistentData/PersistentDataFactory.php +65 -0
  8. facebook/PseudoRandomString/PseudoRandomStringGeneratorFactory.php +101 -0
  9. facebook/PseudoRandomString/RandomBytesPseudoRandomStringGenerator.php +59 -0
  10. facebook/facebook/Authentication/AccessToken.php +160 -0
  11. facebook/facebook/Authentication/AccessTokenMetadata.php +390 -0
  12. facebook/facebook/Authentication/OAuth2Client.php +292 -0
  13. facebook/facebook/Exceptions/FacebookAuthenticationException.php +33 -0
  14. facebook/facebook/Exceptions/FacebookAuthorizationException.php +33 -0
  15. facebook/facebook/Exceptions/FacebookClientException.php +33 -0
  16. facebook/facebook/Exceptions/FacebookOtherException.php +33 -0
  17. facebook/facebook/Exceptions/FacebookResponseException.php +216 -0
  18. facebook/facebook/Exceptions/FacebookResumableUploadException.php +33 -0
  19. facebook/facebook/Exceptions/FacebookSDKException.php +33 -0
  20. facebook/facebook/Exceptions/FacebookServerException.php +33 -0
  21. facebook/facebook/Exceptions/FacebookThrottleException.php +33 -0
  22. facebook/facebook/Facebook.php +635 -0
  23. facebook/facebook/FacebookApp.php +110 -0
  24. facebook/facebook/FacebookBatchRequest.php +322 -0
  25. facebook/facebook/FacebookBatchResponse.php +174 -0
  26. facebook/facebook/FacebookClient.php +250 -0
  27. facebook/facebook/FacebookRequest.php +534 -0
  28. facebook/facebook/FacebookResponse.php +410 -0
  29. facebook/facebook/FileUpload/FacebookFile.php +169 -0
  30. facebook/facebook/FileUpload/FacebookResumableUploader.php +167 -0
  31. facebook/facebook/FileUpload/FacebookTransferChunk.php +133 -0
  32. facebook/facebook/FileUpload/FacebookVideo.php +33 -0
  33. facebook/facebook/FileUpload/Mimetypes.php +988 -0
  34. facebook/facebook/GraphNodes/Birthday.php +85 -0
  35. facebook/facebook/GraphNodes/Collection.php +242 -0
  36. facebook/facebook/GraphNodes/GraphAchievement.php +112 -0
  37. facebook/facebook/GraphNodes/GraphAlbum.php +183 -0
  38. facebook/facebook/GraphNodes/GraphApplication.php +43 -0
  39. facebook/facebook/GraphNodes/GraphCoverPhoto.php +72 -0
  40. facebook/facebook/GraphNodes/GraphEdge.php +252 -0
  41. facebook/facebook/GraphNodes/GraphEvent.php +242 -0
  42. facebook/facebook/GraphNodes/GraphGroup.php +170 -0
  43. facebook/facebook/GraphNodes/GraphList.php +36 -0
  44. facebook/facebook/GraphNodes/GraphLocation.php +102 -0
  45. facebook/facebook/GraphNodes/GraphNode.php +197 -0
  46. facebook/facebook/GraphNodes/GraphNodeFactory.php +392 -0
  47. facebook/facebook/GraphNodes/GraphObject.php +36 -0
  48. facebook/facebook/GraphNodes/GraphObjectFactory.php +88 -0
  49. facebook/facebook/GraphNodes/GraphPage.php +147 -0
  50. facebook/facebook/GraphNodes/GraphPicture.php +72 -0
  51. facebook/facebook/GraphNodes/GraphSessionInfo.php +102 -0
  52. facebook/facebook/GraphNodes/GraphUser.php +172 -0
  53. facebook/facebook/Helpers/FacebookCanvasHelper.php +52 -0
  54. facebook/facebook/Helpers/FacebookJavaScriptHelper.php +42 -0
  55. facebook/facebook/Helpers/FacebookPageTabHelper.php +95 -0
  56. facebook/facebook/Helpers/FacebookRedirectLoginHelper.php +333 -0
  57. facebook/facebook/Helpers/FacebookSignedRequestFromInputHelper.php +166 -0
  58. facebook/facebook/Http/GraphRawResponse.php +137 -0
  59. facebook/facebook/Http/RequestBodyInterface.php +39 -0
  60. facebook/facebook/Http/RequestBodyMultipart.php +170 -0
  61. facebook/facebook/Http/RequestBodyUrlEncoded.php +55 -0
  62. facebook/facebook/HttpClients/FacebookCurl.php +129 -0
  63. facebook/facebook/HttpClients/FacebookCurlHttpClient.php +163 -0
  64. facebook/facebook/HttpClients/FacebookGuzzleHttpClient.php +97 -0
  65. facebook/facebook/HttpClients/FacebookHttpClientInterface.php +47 -0
  66. facebook/facebook/HttpClients/FacebookStream.php +80 -0
  67. facebook/facebook/HttpClients/FacebookStreamHttpClient.php +94 -0
  68. facebook/facebook/HttpClients/HttpClientsFactory.php +99 -0
  69. facebook/facebook/HttpClients/certs/DigiCertHighAssuranceEVRootCA.pem +23 -0
  70. facebook/facebook/PersistentData/FacebookMemoryPersistentDataHandler.php +53 -0
  71. facebook/facebook/PersistentData/FacebookSessionPersistentDataHandler.php +76 -0
  72. facebook/facebook/PersistentData/PersistentDataFactory.php +65 -0
  73. facebook/facebook/PersistentData/PersistentDataInterface.php +49 -0
  74. facebook/facebook/PseudoRandomString/McryptPseudoRandomStringGenerator.php +68 -0
  75. facebook/facebook/PseudoRandomString/OpenSslPseudoRandomStringGenerator.php +67 -0
  76. facebook/facebook/PseudoRandomString/PseudoRandomStringGeneratorFactory.php +101 -0
  77. facebook/facebook/PseudoRandomString/PseudoRandomStringGeneratorInterface.php +45 -0
  78. facebook/facebook/PseudoRandomString/PseudoRandomStringGeneratorTrait.php +58 -0
  79. facebook/facebook/PseudoRandomString/RandomBytesPseudoRandomStringGenerator.php +59 -0
  80. facebook/facebook/PseudoRandomString/UrandomPseudoRandomStringGenerator.php +89 -0
  81. facebook/facebook/SignedRequest.php +326 -0
  82. facebook/facebook/Url/FacebookUrlDetectionHandler.php +182 -0
  83. facebook/facebook/Url/FacebookUrlManipulator.php +167 -0
  84. facebook/facebook/Url/UrlDetectionInterface.php +39 -0
  85. facebook/facebook/autoload.php +81 -0
  86. facebook/facebook/polyfills.php +49 -0
  87. facebook/polyfills.php +49 -0
  88. inc/frontend/login_check.php +361 -345
  89. readme.txt +5 -1
accesspress-social-login-lite.php CHANGED
@@ -1,48 +1,46 @@
1
- <?php
2
-
3
- defined('ABSPATH') or die("No script kiddies please!");
4
  /*
5
  Plugin name: Social Login WordPress Plugin - AccessPress Social Login Lite
6
  Plugin URI: https://accesspressthemes.com/wordpress-plugins/accesspress-social-login-lite/
7
  Description: A plugin to add various social logins to a site.
8
- version: 3.3.4
9
  Author: AccessPress Themes
10
  Author URI: https://accesspressthemes.com/
11
  Text Domain: accesspress-social-login-lite
12
  Domain Path: /languages/
13
  License: GPLv2 or later
14
- */
15
  //Declearation of the necessary constants for plugin
16
- if (!defined('APSL_VERSION')) {
17
- define('APSL_VERSION', '3.3.4');
18
  }
19
 
20
- if (!defined('APSL_IMAGE_DIR')) {
21
- define('APSL_IMAGE_DIR', plugin_dir_url(__FILE__) . 'images');
22
  }
23
 
24
- if (!defined('APSL_JS_DIR')) {
25
- define('APSL_JS_DIR', plugin_dir_url(__FILE__) . 'js');
26
  }
27
 
28
- if (!defined('APSL_CSS_DIR')) {
29
- define('APSL_CSS_DIR', plugin_dir_url(__FILE__) . 'css');
30
  }
31
 
32
- if (!defined('APSL_LANG_DIR')) {
33
- define('APSL_LANG_DIR', basename(dirname(__FILE__)) . '/languages/');
34
  }
35
 
36
- if (!defined('APSL_TEXT_DOMAIN')) {
37
- define('APSL_TEXT_DOMAIN', 'accesspress-social-login-lite');
38
  }
39
 
40
- if (!defined('APSL_SETTINGS')) {
41
- define('APSL_SETTINGS', 'apsl-lite-settings');
42
  }
43
 
44
- if (!defined('APSL_PLUGIN_DIR')) {
45
- define('APSL_PLUGIN_DIR', plugin_dir_path(__FILE__));
46
  }
47
  /**
48
  * Register a widget
@@ -50,163 +48,163 @@ if (!defined('APSL_PLUGIN_DIR')) {
50
  */
51
  include_once( 'inc/backend/widget.php' );
52
 
53
- if (version_compare(get_bloginfo('version'), '4.3.1', '>=')) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
54
  // Redefine user notification function
55
- if (!function_exists('wp_new_user_notification')) {
56
-
57
- function wp_new_user_notification($user_id, $deprecated = null, $notify = 'both') {
58
- if ($deprecated !== null) {
59
- _deprecated_argument(__FUNCTION__, '4.3.1');
60
- }
61
-
62
- global $wpdb, $wp_hasher;
63
- $user = get_userdata($user_id);
64
- if (empty($user))
65
- return;
66
-
67
- // The blogname option is escaped with esc_html on the way into the database in sanitize_option
68
- // we want to reverse this for the plain text arena of emails.
69
- $blogname = wp_specialchars_decode(get_option('blogname'), ENT_QUOTES);
70
-
71
- $message = sprintf(__('New user registration on your site %s:'), $blogname) . "\r\n\r\n";
72
- $message .= sprintf(__('Username: %s'), $user->user_login) . "\r\n\r\n";
73
- $message .= sprintf(__('E-mail: %s'), $user->user_email) . "\r\n";
74
 
75
- @wp_mail(get_option('admin_email'), sprintf(__('[%s] New User Registration'), $blogname), $message);
 
76
 
77
- if ('admin' === $notify || empty($notify)) {
78
- return;
79
- }
80
-
81
- // Generate something random for a password reset key.
82
- $key = wp_generate_password(20, false);
83
 
84
- /** This action is documented in wp-login.php */
85
- do_action('retrieve_password_key', $user->user_login, $key);
86
-
87
- // Now insert the key, hashed, into the DB.
88
- if (empty($wp_hasher)) {
89
- require_once ABSPATH . WPINC . '/class-phpass.php';
90
- $wp_hasher = new PasswordHash(8, true);
91
- }
92
- $hashed = time() . ':' . $wp_hasher->HashPassword($key);
93
- $wpdb->update($wpdb->users, array('user_activation_key' => $hashed), array('user_login' => $user->user_login));
94
 
95
- $message = sprintf(__('Username: %s'), $user->user_login) . "\r\n\r\n";
96
- $message .= __('To set your password, visit the following address:') . "\r\n\r\n";
97
- $message .= '<' . network_site_url("wp-login.php?action=rp&key=$key&login=" . rawurlencode($user->user_login), 'login') . ">\r\n\r\n";
98
 
99
- $message .= wp_login_url() . "\r\n\r\n";
100
- $message .= sprintf(__('If you have any problems, please contact us at %s.'), get_option('admin_email')) . "\r\n\r\n";
101
- $message .= __('Adios!') . "\r\n\r\n";
 
 
 
 
102
 
103
- wp_mail($user->user_email, sprintf(__('[%s] Your username and password info'), $blogname), $message);
104
- }
105
-
106
- }
107
- } else {
108
- // for wordpress version less than 4.3.1
109
- // Redefine user notification function
110
- if (!function_exists('wp_new_user_notification')) {
111
 
112
- function wp_new_user_notification($user_id, $plaintext_pass = '') {
113
- $user = new WP_User($user_id);
114
 
115
- $user_login = stripslashes($user->user_login);
116
- $user_email = stripslashes($user->user_email);
117
-
118
- $message = sprintf(__('New user registration on your site %s:'), get_option('blogname')) . "\r\n\r\n";
119
- $message .= sprintf(__('Username: %s'), $user_login) . "\r\n\r\n";
120
- $message .= sprintf(__('E-mail: %s'), $user_email) . "\r\n";
121
- $message .= __('Thanks!');
122
-
123
- $headers = 'From:' . get_option('blogname') . ' <' . get_option('admin_email') . '>' . "\r\n";
124
- @wp_mail(get_option('admin_email'), sprintf(__('[%s] New User Registration'), get_option('blogname')), $message, $headers);
125
-
126
- if (empty($plaintext_pass))
127
- return;
128
-
129
- $message = __('Hi there,') . "\r\n\r\n";
130
- $message .= sprintf(__("Welcome to %s! Here's how to log in:"), get_option('blogname')) . "\r\n\r\n";
131
- $message .= wp_login_url() . "\r\n";
132
- $message .= sprintf(__('Username: %s'), $user_login) . "\r\n";
133
- $message .= sprintf(__('Password: %s'), $plaintext_pass) . "\r\n\r\n";
134
- $message .= sprintf(__('If you have any problems, please contact me at %s.'), get_option('admin_email')) . "\r\n\r\n";
135
- $message .= __('Thanks!');
136
-
137
- $headers = 'From:' . get_option('blogname') . ' <' . get_option('admin_email') . '>' . "\r\n";
138
-
139
- wp_mail($user_email, sprintf(__('[%s] Your username and password'), get_option('blogname')), $message, $headers);
140
- }
141
-
142
- }
143
  }
144
 
145
 
146
  // Declaration of the class
147
- if (!class_exists('APSL_Lite_Class')) {
148
-
149
  class APSL_Lite_Class {
150
-
151
  var $apsl_settings;
152
-
153
  function __construct() {
154
- $this->apsl_settings = get_option(APSL_SETTINGS);
155
- add_action('init', array($this, 'session_init')); //start the session if not started yet.
156
- register_activation_hook(__FILE__, array($this, 'plugin_activation')); //load the default setting for the plugin while activating
157
- add_action('init', array($this, 'plugin_text_domain')); //load the plugin text domain
158
- add_action('admin_menu', array($this, 'add_apsl_menu')); //register the plugin menu in backend
159
- add_action('admin_enqueue_scripts', array($this, 'register_admin_assets')); //registers all the assets required for wp-admin
160
- add_action('wp_enqueue_scripts', array($this, 'register_frontend_assets')); // registers all the assets required for the frontend
161
- add_action('admin_post_apsl_save_options', array($this, 'save_settings')); //save settings of a plugin
162
-
163
- $options = get_option(APSL_SETTINGS);
164
- if ($options['apsl_enable_disable_plugin'] == 'yes') {
165
- if (in_array("login_form", $options['apsl_display_options'])) {
166
- add_action('login_form', array($this, 'add_social_login')); // add the social logins to the login form
167
- add_action('woocommerce_login_form', array($this, 'add_social_login_form_to_comment'));
 
168
  }
169
-
170
- if (in_array("register_form", $options['apsl_display_options'])) {
171
- add_action('register_form', array($this, 'add_social_login')); //add the social logins to the registration form
172
- add_action('after_signup_form', array($this, 'add_social_login'));
173
  }
174
-
175
- if (in_array("comment_form", $options['apsl_display_options'])) {
176
- add_action('comment_form_top', array($this, 'add_social_login_form_to_comment')); //add the social logins to the comment form
177
- add_action('comment_form_must_log_in_after', array($this, 'add_social_login_form_to_comment')); // add the social login buttons if “Users must be registered and logged in to comment” checked in the discussions settings.
 
178
  }
179
  }
180
-
181
- add_shortcode('apsl-login-lite', array($this, 'apsl_shortcode')); //adds a shortcode
182
- add_action('init', array($this, 'login_check')); //check for the social logins
183
- add_action('widgets_init', array($this, 'register_apsl_widget')); //register the widget of a plugin
184
- add_action('login_enqueue_scripts', array($this, 'apsl_login_form_enqueue_style'), 10);
185
- add_action('login_enqueue_scripts', array($this, 'apsl_login_form__enqueue_script'), 1);
186
- add_action('admin_post_apsl_restore_default_settings', array($this, 'apsl_restore_default_settings')); //restores default settings.
187
-
188
-
189
  /**
190
  * Hook to display custom avatars
191
  */
192
- add_filter('get_avatar', array($this, 'apsl_social_login_custom_avatar'), 10, 5);
193
 
194
  //add delete action when user is deleted from wordpress backend.
195
- add_action('delete_user', array($this, 'apsl_delete_user'));
196
  }
197
-
198
- function apsl_social_login_custom_avatar($avatar, $mixed, $size, $default, $alt = '') {
199
- $options = get_option(APSL_SETTINGS);
200
  //Check if we have an user identifier
201
- if (is_numeric($mixed) AND $mixed > 0) {
202
  $user_id = $mixed;
203
  }
204
  //Check if we have an user email
205
- elseif (is_string($mixed) AND ( $user = get_user_by('email', $mixed) )) {
206
  $user_id = $user->ID;
207
  }
208
  //Check if we have an user object
209
- elseif (is_object($mixed) AND property_exists($mixed, 'user_id') AND is_numeric($mixed->user_id)) {
210
  $user_id = $mixed->user_id;
211
  }
212
  //None found
@@ -214,35 +212,33 @@ if (!class_exists('APSL_Lite_Class')) {
214
  $user_id = null;
215
  }
216
  //User found?
217
- if (!empty($user_id)) {
218
  //Override current avatar ?
219
  $override_avatar = true;
220
  //Read the avatar
221
- $user_meta_thumbnail = get_user_meta($user_id, 'deuimage', true);
222
  //read user details
223
- $user_meta_name = get_user_meta($user_id, 'first_name', true);
224
-
225
- if ($options['apsl_user_avatar_options'] == 'social') {
226
- $user_picture = (!empty($user_meta_thumbnail) ? $user_meta_thumbnail : '' );
227
  //Avatar found?
228
- if ($user_picture !== false AND strlen(trim($user_picture)) > 0) {
229
  return '<img alt="' . $user_meta_name . '" src="' . $user_picture . '" class="avatar apsl-avatar-social-login avatar-' . $size . ' photo" height="' . $size . '" width="' . $size . '" />';
230
  }
231
  }
232
  }
233
  return $avatar;
234
  }
235
-
236
  //starts the session with the call of init hook
237
  function session_init() {
238
- if (!session_id() && !headers_sent()) {
239
  session_start();
240
  }
241
  }
242
-
243
  //load the default settings of the plugin
244
  function plugin_activation() {
245
- if (!get_option(APSL_SETTINGS)) {
246
  include( 'inc/backend/activation.php' );
247
  }
248
  self:: apsl_database_install();
@@ -287,124 +283,115 @@ if (!class_exists('APSL_Lite_Class')) {
287
  KEY user_id (user_id),
288
  KEY provider_name (provider_name)
289
  )";
290
- dbDelta($sql);
291
  }
292
 
293
  //loads the text domain for translation
294
  function plugin_text_domain() {
295
- load_plugin_textdomain('accesspress-social-login-lite', false, APSL_LANG_DIR);
296
  }
297
-
298
  //register the plugin menu for backend.
299
  function add_apsl_menu() {
300
- add_menu_page('AccessPress Social Login Lite', 'AccessPress Social Login Lite', 'manage_options', 'accesspress-social-login-lite', array($this, 'main_page'), APSL_IMAGE_DIR . '/icon.png');
301
  }
302
-
303
  //menu page
304
  function main_page() {
305
  include( 'inc/backend/main-page.php' );
306
  }
307
-
308
  //registration of the backend assets
309
  function register_admin_assets() {
310
- wp_enqueue_style('fontawsome-css', APSL_CSS_DIR . '/font-awesome/font-awesome.min.css', '', APSL_VERSION);
311
- if (isset($_GET['page']) && $_GET['page'] == 'accesspress-social-login-lite') {
312
  //backend scripts
313
- wp_enqueue_script('jquery-ui-sortable');
314
- wp_enqueue_script('apsl-admin-js', APSL_JS_DIR . '/backend.js', array('jquery', 'jquery-ui-sortable'), APSL_VERSION); //registering plugin's admin js
315
  //register backend css
316
- wp_enqueue_style('apsl-backend-css', APSL_CSS_DIR . '/backend.css', '', APSL_VERSION);
317
  }
318
  }
319
-
320
  //registration of the plugins frontend assets
321
  function register_frontend_assets() {
322
  //register frontend scripts
323
- wp_enqueue_script('apsl-frontend-js', APSL_JS_DIR . '/frontend.js', array('jquery'), APSL_VERSION);
324
-
325
  //register frontend css
326
  // wp_enqueue_style( 'fontawsome-css', '//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css', '', APSL_VERSION );
327
- wp_enqueue_style('fontawsome-css', APSL_CSS_DIR . '/font-awesome/font-awesome.min.css', '', APSL_VERSION);
328
 
329
- wp_enqueue_style('apsl-frontend-css', APSL_CSS_DIR . '/frontend.css', '', APSL_VERSION);
330
  }
331
-
332
  //save the settings of a plugin
333
  function save_settings() {
334
- if (isset($_POST['apsl_save_settings']) && $_POST['apsl_settings_action'] && wp_verify_nonce($_POST['apsl_settings_action'], 'apsl_nonce_save_settings')) {
335
  include( 'inc/backend/save-settings.php' );
336
- } else {
337
- die('No script kiddies please!');
 
338
  }
339
  }
340
-
341
  //function to add the social login in the login and registration form.
342
  function add_social_login() {
343
- if (!is_user_logged_in()) {
344
  include( 'inc/frontend/login_integration.php' );
345
  }
346
  }
347
-
348
  //function to add the social login in the comment form.
349
  function add_social_login_form_to_comment() {
350
- $options = get_option(APSL_SETTINGS);
351
  $login_text = $options['apsl_title_text_field'];
352
- if (!is_user_logged_in()) {
353
- echo do_shortcode("[apsl-login-lite login_text='{$login_text}']");
354
  }
355
  }
356
-
357
  //function for adding shortcode of a plugin
358
- function apsl_shortcode($attr) {
359
  ob_start();
360
  include( 'inc/frontend/shortcode.php' );
361
  $html = ob_get_contents();
362
  ob_get_clean();
363
  return $html;
364
  }
365
-
366
  //checking of the login
367
  function login_check() {
368
  include( 'inc/frontend/login_check.php' );
369
  }
370
-
371
  //registration of the social login widget
372
  function register_apsl_widget() {
373
- register_widget('APSL_Lite_Widget');
374
  }
375
-
376
  function apsl_login_form_enqueue_style() {
377
- wp_enqueue_style('fontawsome-css', '//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css', '', APSL_VERSION);
378
- wp_enqueue_style('apsl-backend-css', APSL_CSS_DIR . '/backend.css', '', APSL_VERSION);
379
- wp_enqueue_style('apsl-frontend-css', APSL_CSS_DIR . '/frontend.css', '', APSL_VERSION);
380
  }
381
-
382
  function apsl_login_form__enqueue_script() {
383
- wp_enqueue_script('apsl-admin-js', APSL_JS_DIR . '/backend.js', array('jquery', 'jquery-ui-sortable'), APSL_VERSION); //registering plugin's admin js
 
384
  }
385
-
386
  function apsl_restore_default_settings() {
387
  $nonce = $_REQUEST['_wpnonce'];
388
- if (!empty($_GET) && wp_verify_nonce($nonce, 'apsl-restore-default-settings-nonce')) {
389
  //restore the default plugin activation settings from the activation page.
390
  include( 'inc/backend/activation.php' );
391
- $_SESSION['apsl_message'] = __('Settings restored Successfully.', 'accesspress-social-login-lite');
392
- wp_redirect(admin_url() . 'admin.php?page=' . 'accesspress-social-login-lite');
393
  exit;
394
- } else {
395
- die('No script kiddies please!');
 
396
  }
397
  }
398
 
399
- function apsl_delete_user($user_id) {
400
  global $wpdb;
401
  $table_name = $apsl_userdetails = "{$wpdb->prefix}apsl_users_social_profile_details";
402
- $user_obj = get_userdata($user_id);
403
- $result = $wpdb->delete($table_name, array('user_id' => $user_id));
404
  }
 
405
 
406
- }
407
-
408
- //class termination
409
  }
410
  $apsl_object = new APSL_Lite_Class();
1
+ <?php defined( 'ABSPATH' ) or die( "No script kiddies please!" );
 
 
2
  /*
3
  Plugin name: Social Login WordPress Plugin - AccessPress Social Login Lite
4
  Plugin URI: https://accesspressthemes.com/wordpress-plugins/accesspress-social-login-lite/
5
  Description: A plugin to add various social logins to a site.
6
+ version: 3.3.5
7
  Author: AccessPress Themes
8
  Author URI: https://accesspressthemes.com/
9
  Text Domain: accesspress-social-login-lite
10
  Domain Path: /languages/
11
  License: GPLv2 or later
12
+ */
13
  //Declearation of the necessary constants for plugin
14
+ if( !defined( 'APSL_VERSION' ) ) {
15
+ define( 'APSL_VERSION', '3.3.5' );
16
  }
17
 
18
+ if( !defined( 'APSL_IMAGE_DIR' ) ) {
19
+ define( 'APSL_IMAGE_DIR', plugin_dir_url( __FILE__ ) . 'images' );
20
  }
21
 
22
+ if( !defined( 'APSL_JS_DIR' ) ) {
23
+ define( 'APSL_JS_DIR', plugin_dir_url( __FILE__ ) . 'js' );
24
  }
25
 
26
+ if( !defined( 'APSL_CSS_DIR' ) ) {
27
+ define( 'APSL_CSS_DIR', plugin_dir_url( __FILE__ ) . 'css' );
28
  }
29
 
30
+ if( !defined( 'APSL_LANG_DIR' ) ) {
31
+ define( 'APSL_LANG_DIR', basename( dirname( __FILE__ ) ) . '/languages/' );
32
  }
33
 
34
+ if( !defined( 'APSL_TEXT_DOMAIN' ) ) {
35
+ define( 'APSL_TEXT_DOMAIN', 'accesspress-social-login-lite' );
36
  }
37
 
38
+ if( !defined( 'APSL_SETTINGS' ) ) {
39
+ define( 'APSL_SETTINGS', 'apsl-lite-settings' );
40
  }
41
 
42
+ if( !defined( 'APSL_PLUGIN_DIR' ) ) {
43
+ define( 'APSL_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
44
  }
45
  /**
46
  * Register a widget
48
  */
49
  include_once( 'inc/backend/widget.php' );
50
 
51
+ if (version_compare(get_bloginfo('version'), '4.3.1', '>=')){
52
+ // Redefine user notification function
53
+ if ( !function_exists('wp_new_user_notification') ) {
54
+
55
+ function wp_new_user_notification( $user_id, $deprecated = null, $notify = 'both' ) {
56
+ if ( $deprecated !== null ) {
57
+ _deprecated_argument( __FUNCTION__, '4.3.1' );
58
+ }
59
+
60
+ global $wpdb, $wp_hasher;
61
+ $user = get_userdata( $user_id );
62
+ if ( empty ( $user ) )
63
+ return;
64
+
65
+ // The blogname option is escaped with esc_html on the way into the database in sanitize_option
66
+ // we want to reverse this for the plain text arena of emails.
67
+ $blogname = wp_specialchars_decode(get_option('blogname'), ENT_QUOTES);
68
+
69
+ $message = sprintf(__('New user registration on your site %s:'), $blogname) . "\r\n\r\n";
70
+ $message .= sprintf(__('Username: %s'), $user->user_login) . "\r\n\r\n";
71
+ $message .= sprintf(__('E-mail: %s'), $user->user_email) . "\r\n";
72
+
73
+ @wp_mail(get_option('admin_email'), sprintf(__('[%s] New User Registration'), $blogname), $message);
74
+
75
+ if ( 'admin' === $notify || empty( $notify ) ) {
76
+ return;
77
+ }
78
+
79
+ // Generate something random for a password reset key.
80
+ $key = wp_generate_password( 20, false );
81
+
82
+ /** This action is documented in wp-login.php */
83
+ do_action( 'retrieve_password_key', $user->user_login, $key );
84
+
85
+ // Now insert the key, hashed, into the DB.
86
+ if ( empty( $wp_hasher ) ) {
87
+ require_once ABSPATH . WPINC . '/class-phpass.php';
88
+ $wp_hasher = new PasswordHash( 8, true );
89
+ }
90
+ $hashed = time() . ':' . $wp_hasher->HashPassword( $key );
91
+ $wpdb->update( $wpdb->users, array( 'user_activation_key' => $hashed ), array( 'user_login' => $user->user_login ) );
92
+
93
+ $message = sprintf(__('Username: %s'), $user->user_login) . "\r\n\r\n";
94
+ $message .= __('To set your password, visit the following address:') . "\r\n\r\n";
95
+ $message .= '<' . network_site_url("wp-login.php?action=rp&key=$key&login=" . rawurlencode($user->user_login), 'login') . ">\r\n\r\n";
96
+
97
+ $message .= wp_login_url() . "\r\n\r\n";
98
+ $message .= sprintf( __('If you have any problems, please contact us at %s.'), get_option('admin_email') ) . "\r\n\r\n";
99
+ $message .= __('Adios!') . "\r\n\r\n";
100
+
101
+ wp_mail($user->user_email, sprintf(__('[%s] Your username and password info'), $blogname), $message);
102
+ }
103
+ }
104
+ }else{
105
+ // for wordpress version less than 4.3.1
106
  // Redefine user notification function
107
+ if(!function_exists( 'wp_new_user_notification' )){
108
+ function wp_new_user_notification( $user_id, $plaintext_pass = '' ) {
109
+ $user = new WP_User($user_id);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
110
 
111
+ $user_login = stripslashes($user->user_login);
112
+ $user_email = stripslashes($user->user_email);
113
 
114
+ $message = sprintf(__('New user registration on your site %s:'), get_option('blogname')) . "\r\n\r\n";
115
+ $message .= sprintf(__('Username: %s'), $user_login) . "\r\n\r\n";
116
+ $message .= sprintf(__('E-mail: %s'), $user_email) . "\r\n";
117
+ $message .= __('Thanks!');
 
 
118
 
119
+ $headers = 'From:'.get_option('blogname').' <'.get_option('admin_email').'>' . "\r\n";
120
+ @wp_mail(get_option('admin_email'), sprintf(__('[%s] New User Registration'), get_option('blogname')), $message, $headers);
 
 
 
 
 
 
 
 
121
 
122
+ if ( empty($plaintext_pass) )
123
+ return;
 
124
 
125
+ $message = __('Hi there,') . "\r\n\r\n";
126
+ $message .= sprintf(__("Welcome to %s! Here's how to log in:"), get_option('blogname')) . "\r\n\r\n";
127
+ $message .= wp_login_url() . "\r\n";
128
+ $message .= sprintf(__('Username: %s'), $user_login) . "\r\n";
129
+ $message .= sprintf(__('Password: %s'), $plaintext_pass) . "\r\n\r\n";
130
+ $message .= sprintf(__('If you have any problems, please contact me at %s.'), get_option('admin_email')) . "\r\n\r\n";
131
+ $message .= __('Thanks!');
132
 
133
+ $headers = 'From:'.get_option('blogname').' <'.get_option('admin_email').'>' . "\r\n";
 
 
 
 
 
 
 
134
 
135
+ wp_mail($user_email, sprintf(__('[%s] Your username and password'), get_option('blogname')), $message, $headers);
 
136
 
137
+ }
138
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
139
  }
140
 
141
 
142
  // Declaration of the class
143
+ if( !class_exists( 'APSL_Lite_Class' ) ) {
144
+
145
  class APSL_Lite_Class {
146
+
147
  var $apsl_settings;
148
+
149
  function __construct() {
150
+ $this->apsl_settings = get_option( APSL_SETTINGS );
151
+ add_action( 'init', array($this, 'session_init') ); //start the session if not started yet.
152
+ register_activation_hook( __FILE__, array($this, 'plugin_activation') ); //load the default setting for the plugin while activating
153
+ add_action( 'init', array($this, 'plugin_text_domain') ); //load the plugin text domain
154
+ add_action( 'admin_menu', array($this, 'add_apsl_menu') ); //register the plugin menu in backend
155
+ add_action( 'admin_enqueue_scripts', array($this, 'register_admin_assets') ); //registers all the assets required for wp-admin
156
+ add_action( 'wp_enqueue_scripts', array($this, 'register_frontend_assets') ); // registers all the assets required for the frontend
157
+ add_action( 'admin_post_apsl_save_options', array($this, 'save_settings') ); //save settings of a plugin
158
+
159
+ $options = get_option( APSL_SETTINGS );
160
+ if( $options['apsl_enable_disable_plugin'] == 'yes' ) {
161
+ if( in_array( "login_form", $options['apsl_display_options'] ) ) {
162
+ add_action( 'login_form', array($this, 'add_social_login') ); // add the social logins to the login form
163
+ add_action( 'woocommerce_login_form', array($this, 'add_social_login_form_to_comment') );
164
+
165
  }
166
+
167
+ if( in_array( "register_form", $options['apsl_display_options'] ) ) {
168
+ add_action( 'register_form', array($this, 'add_social_login') ); //add the social logins to the registration form
169
+ add_action( 'after_signup_form', array($this, 'add_social_login') );
170
  }
171
+
172
+ if( in_array( "comment_form", $options['apsl_display_options'] ) ) {
173
+ add_action( 'comment_form_top', array($this, 'add_social_login_form_to_comment') ); //add the social logins to the comment form
174
+ add_action( 'comment_form_must_log_in_after', array($this, 'add_social_login_form_to_comment') ); // add the social login buttons if “Users must be registered and logged in to comment” checked in the discussions settings.
175
+
176
  }
177
  }
178
+
179
+ add_shortcode( 'apsl-login-lite', array($this, 'apsl_shortcode') ); //adds a shortcode
180
+ add_action( 'init', array($this, 'login_check') ); //check for the social logins
181
+ add_action( 'widgets_init', array($this, 'register_apsl_widget') ); //register the widget of a plugin
182
+ add_action( 'login_enqueue_scripts', array($this, 'apsl_login_form_enqueue_style'), 10 );
183
+ add_action( 'login_enqueue_scripts', array($this, 'apsl_login_form__enqueue_script'), 1 );
184
+ add_action( 'admin_post_apsl_restore_default_settings', array($this, 'apsl_restore_default_settings') ); //restores default settings.
185
+
186
+
187
  /**
188
  * Hook to display custom avatars
189
  */
190
+ add_filter( 'get_avatar', array($this, 'apsl_social_login_custom_avatar'), 10, 5 );
191
 
192
  //add delete action when user is deleted from wordpress backend.
193
+ add_action( 'delete_user', array ($this, 'apsl_delete_user') );
194
  }
195
+
196
+ function apsl_social_login_custom_avatar( $avatar, $mixed, $size, $default, $alt = '' ) {
197
+ $options = get_option( APSL_SETTINGS );
198
  //Check if we have an user identifier
199
+ if( is_numeric( $mixed ) AND $mixed > 0 ) {
200
  $user_id = $mixed;
201
  }
202
  //Check if we have an user email
203
+ elseif( is_string( $mixed ) AND( $user = get_user_by( 'email', $mixed ) ) ) {
204
  $user_id = $user->ID;
205
  }
206
  //Check if we have an user object
207
+ elseif( is_object( $mixed ) AND property_exists( $mixed, 'user_id' ) AND is_numeric( $mixed->user_id ) ) {
208
  $user_id = $mixed->user_id;
209
  }
210
  //None found
212
  $user_id = null;
213
  }
214
  //User found?
215
+ if( !empty( $user_id ) ) {
216
  //Override current avatar ?
217
  $override_avatar = true;
218
  //Read the avatar
219
+ $user_meta_thumbnail = get_user_meta( $user_id, 'deuimage', true );
220
  //read user details
221
+ $user_meta_name = get_user_meta( $user_id, 'first_name', true );
222
+
223
+ if( $options['apsl_user_avatar_options'] == 'social' ) {
224
+ $user_picture =( !empty( $user_meta_thumbnail ) ? $user_meta_thumbnail : '' );
225
  //Avatar found?
226
+ if( $user_picture !== false AND strlen( trim( $user_picture ) ) > 0 ) {
227
  return '<img alt="' . $user_meta_name . '" src="' . $user_picture . '" class="avatar apsl-avatar-social-login avatar-' . $size . ' photo" height="' . $size . '" width="' . $size . '" />';
228
  }
229
  }
230
  }
231
  return $avatar;
232
  }
 
233
  //starts the session with the call of init hook
234
  function session_init() {
235
+ if( !session_id() && !headers_sent() ) {
236
  session_start();
237
  }
238
  }
 
239
  //load the default settings of the plugin
240
  function plugin_activation() {
241
+ if( !get_option( APSL_SETTINGS ) ) {
242
  include( 'inc/backend/activation.php' );
243
  }
244
  self:: apsl_database_install();
283
  KEY user_id (user_id),
284
  KEY provider_name (provider_name)
285
  )";
286
+ dbDelta( $sql );
287
  }
288
 
289
  //loads the text domain for translation
290
  function plugin_text_domain() {
291
+ load_plugin_textdomain( 'accesspress-social-login-lite', false, APSL_LANG_DIR );
292
  }
 
293
  //register the plugin menu for backend.
294
  function add_apsl_menu() {
295
+ add_menu_page( 'AccessPress Social Login Lite', 'AccessPress Social Login Lite', 'manage_options', 'accesspress-social-login-lite', array($this, 'main_page'), APSL_IMAGE_DIR . '/icon.png' );
296
  }
 
297
  //menu page
298
  function main_page() {
299
  include( 'inc/backend/main-page.php' );
300
  }
 
301
  //registration of the backend assets
302
  function register_admin_assets() {
303
+ wp_enqueue_style( 'fontawsome-css', APSL_CSS_DIR .'/font-awesome/font-awesome.min.css', '', APSL_VERSION );
304
+ if( isset( $_GET['page'] ) && $_GET['page'] == 'accesspress-social-login-lite' ) {
305
  //backend scripts
306
+ wp_enqueue_script( 'jquery-ui-sortable' );
307
+ wp_enqueue_script( 'apsl-admin-js', APSL_JS_DIR . '/backend.js', array('jquery', 'jquery-ui-sortable'), APSL_VERSION ); //registering plugin's admin js
308
  //register backend css
309
+ wp_enqueue_style( 'apsl-backend-css', APSL_CSS_DIR . '/backend.css', '', APSL_VERSION );
310
  }
311
  }
 
312
  //registration of the plugins frontend assets
313
  function register_frontend_assets() {
314
  //register frontend scripts
315
+ wp_enqueue_script( 'apsl-frontend-js', APSL_JS_DIR . '/frontend.js', array('jquery'), APSL_VERSION );
316
+
317
  //register frontend css
318
  // wp_enqueue_style( 'fontawsome-css', '//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css', '', APSL_VERSION );
319
+ wp_enqueue_style( 'fontawsome-css', APSL_CSS_DIR .'/font-awesome/font-awesome.min.css', '', APSL_VERSION );
320
 
321
+ wp_enqueue_style( 'apsl-frontend-css', APSL_CSS_DIR . '/frontend.css', '', APSL_VERSION );
322
  }
 
323
  //save the settings of a plugin
324
  function save_settings() {
325
+ if( isset( $_POST['apsl_save_settings'] ) && $_POST['apsl_settings_action'] && wp_verify_nonce( $_POST['apsl_settings_action'], 'apsl_nonce_save_settings' ) ) {
326
  include( 'inc/backend/save-settings.php' );
327
+ }
328
+ else {
329
+ die( 'No script kiddies please!' );
330
  }
331
  }
 
332
  //function to add the social login in the login and registration form.
333
  function add_social_login() {
334
+ if( !is_user_logged_in() ) {
335
  include( 'inc/frontend/login_integration.php' );
336
  }
337
  }
 
338
  //function to add the social login in the comment form.
339
  function add_social_login_form_to_comment() {
340
+ $options = get_option( APSL_SETTINGS );
341
  $login_text = $options['apsl_title_text_field'];
342
+ if( !is_user_logged_in() ) {
343
+ echo do_shortcode( "[apsl-login-lite login_text='{$login_text}']" );
344
  }
345
  }
 
346
  //function for adding shortcode of a plugin
347
+ function apsl_shortcode( $attr ) {
348
  ob_start();
349
  include( 'inc/frontend/shortcode.php' );
350
  $html = ob_get_contents();
351
  ob_get_clean();
352
  return $html;
353
  }
 
354
  //checking of the login
355
  function login_check() {
356
  include( 'inc/frontend/login_check.php' );
357
  }
 
358
  //registration of the social login widget
359
  function register_apsl_widget() {
360
+ register_widget( 'APSL_Lite_Widget' );
361
  }
362
+
363
  function apsl_login_form_enqueue_style() {
364
+ wp_enqueue_style( 'fontawsome-css', '//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css', '', APSL_VERSION );
365
+ wp_enqueue_style( 'apsl-backend-css', APSL_CSS_DIR . '/backend.css', '', APSL_VERSION );
366
+ wp_enqueue_style( 'apsl-frontend-css', APSL_CSS_DIR . '/frontend.css', '', APSL_VERSION );
367
  }
368
+
369
  function apsl_login_form__enqueue_script() {
370
+ wp_enqueue_script( 'apsl-admin-js', APSL_JS_DIR . '/backend.js', array('jquery', 'jquery-ui-sortable'), APSL_VERSION ); //registering plugin's admin js
371
+
372
  }
373
+
374
  function apsl_restore_default_settings() {
375
  $nonce = $_REQUEST['_wpnonce'];
376
+ if( !empty( $_GET ) && wp_verify_nonce( $nonce, 'apsl-restore-default-settings-nonce' ) ) {
377
  //restore the default plugin activation settings from the activation page.
378
  include( 'inc/backend/activation.php' );
379
+ $_SESSION['apsl_message'] = __( 'Settings restored Successfully.', 'accesspress-social-login-lite' );
380
+ wp_redirect( admin_url() . 'admin.php?page=' . 'accesspress-social-login-lite' );
381
  exit;
382
+ }
383
+ else {
384
+ die( 'No script kiddies please!' );
385
  }
386
  }
387
 
388
+ function apsl_delete_user( $user_id ) {
389
  global $wpdb;
390
  $table_name = $apsl_userdetails = "{$wpdb->prefix}apsl_users_social_profile_details";
391
+ $user_obj = get_userdata( $user_id );
392
+ $result = $wpdb->delete( $table_name, array( 'user_id' => $user_id ) );
393
  }
394
+ } //class termination
395
 
 
 
 
396
  }
397
  $apsl_object = new APSL_Lite_Class();
facebook/Exceptions/FacebookResumableUploadException.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook\Exceptions;
25
+
26
+ /**
27
+ * Class FacebookResumableUploadException
28
+ *
29
+ * @package Facebook
30
+ */
31
+ class FacebookResumableUploadException extends FacebookSDKException
32
+ {
33
+ }
facebook/FileUpload/FacebookResumableUploader.php ADDED
@@ -0,0 +1,167 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook\FileUpload;
25
+
26
+ use Facebook\Authentication\AccessToken;
27
+ use Facebook\Exceptions\FacebookResponseException;
28
+ use Facebook\Exceptions\FacebookResumableUploadException;
29
+ use Facebook\Exceptions\FacebookSDKException;
30
+ use Facebook\FacebookApp;
31
+ use Facebook\FacebookClient;
32
+ use Facebook\FacebookRequest;
33
+
34
+ /**
35
+ * Class FacebookResumableUploader
36
+ *
37
+ * @package Facebook
38
+ */
39
+ class FacebookResumableUploader
40
+ {
41
+ /**
42
+ * @var FacebookApp
43
+ */
44
+ protected $app;
45
+
46
+ /**
47
+ * @var string
48
+ */
49
+ protected $accessToken;
50
+
51
+ /**
52
+ * @var FacebookClient The Facebook client service.
53
+ */
54
+ protected $client;
55
+
56
+ /**
57
+ * @var string Graph version to use for this request.
58
+ */
59
+ protected $graphVersion;
60
+
61
+ /**
62
+ * @param FacebookApp $app
63
+ * @param FacebookClient $client
64
+ * @param AccessToken|string|null $accessToken
65
+ * @param string $graphVersion
66
+ */
67
+ public function __construct(FacebookApp $app, FacebookClient $client, $accessToken, $graphVersion)
68
+ {
69
+ $this->app = $app;
70
+ $this->client = $client;
71
+ $this->accessToken = $accessToken;
72
+ $this->graphVersion = $graphVersion;
73
+ }
74
+
75
+ /**
76
+ * Upload by chunks - start phase
77
+ *
78
+ * @param string $endpoint
79
+ * @param FacebookFile $file
80
+ *
81
+ * @return FacebookTransferChunk
82
+ *
83
+ * @throws FacebookSDKException
84
+ */
85
+ public function start($endpoint, FacebookFile $file)
86
+ {
87
+ $params = [
88
+ 'upload_phase' => 'start',
89
+ 'file_size' => $file->getSize(),
90
+ ];
91
+ $response = $this->sendUploadRequest($endpoint, $params);
92
+
93
+ return new FacebookTransferChunk($file, $response['upload_session_id'], $response['video_id'], $response['start_offset'], $response['end_offset']);
94
+ }
95
+
96
+ /**
97
+ * Upload by chunks - transfer phase
98
+ *
99
+ * @param string $endpoint
100
+ * @param FacebookTransferChunk $chunk
101
+ * @param boolean $allowToThrow
102
+ *
103
+ * @return FacebookTransferChunk
104
+ *
105
+ * @throws FacebookResponseException
106
+ */
107
+ public function transfer($endpoint, FacebookTransferChunk $chunk, $allowToThrow = false)
108
+ {
109
+ $params = [
110
+ 'upload_phase' => 'transfer',
111
+ 'upload_session_id' => $chunk->getUploadSessionId(),
112
+ 'start_offset' => $chunk->getStartOffset(),
113
+ 'video_file_chunk' => $chunk->getPartialFile(),
114
+ ];
115
+
116
+ try {
117
+ $response = $this->sendUploadRequest($endpoint, $params);
118
+ } catch (FacebookResponseException $e) {
119
+ $preException = $e->getPrevious();
120
+ if ($allowToThrow || !$preException instanceof FacebookResumableUploadException) {
121
+ throw $e;
122
+ }
123
+
124
+ // Return the same chunk entity so it can be retried.
125
+ return $chunk;
126
+ }
127
+
128
+ return new FacebookTransferChunk($chunk->getFile(), $chunk->getUploadSessionId(), $chunk->getVideoId(), $response['start_offset'], $response['end_offset']);
129
+ }
130
+
131
+ /**
132
+ * Upload by chunks - finish phase
133
+ *
134
+ * @param string $endpoint
135
+ * @param string $uploadSessionId
136
+ * @param array $metadata The metadata associated with the file.
137
+ *
138
+ * @return boolean
139
+ *
140
+ * @throws FacebookSDKException
141
+ */
142
+ public function finish($endpoint, $uploadSessionId, $metadata = [])
143
+ {
144
+ $params = array_merge($metadata, [
145
+ 'upload_phase' => 'finish',
146
+ 'upload_session_id' => $uploadSessionId,
147
+ ]);
148
+ $response = $this->sendUploadRequest($endpoint, $params);
149
+
150
+ return $response['success'];
151
+ }
152
+
153
+ /**
154
+ * Helper to make a FacebookRequest and send it.
155
+ *
156
+ * @param string $endpoint The endpoint to POST to.
157
+ * @param array $params The params to send with the request.
158
+ *
159
+ * @return array
160
+ */
161
+ private function sendUploadRequest($endpoint, $params = [])
162
+ {
163
+ $request = new FacebookRequest($this->app, $this->accessToken, 'POST', $endpoint, $params, null, $this->graphVersion);
164
+
165
+ return $this->client->sendRequest($request)->getDecodedBody();
166
+ }
167
+ }
facebook/FileUpload/FacebookTransferChunk.php ADDED
@@ -0,0 +1,133 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook\FileUpload;
25
+
26
+ /**
27
+ * Class FacebookTransferChunk
28
+ *
29
+ * @package Facebook
30
+ */
31
+ class FacebookTransferChunk
32
+ {
33
+ /**
34
+ * @var FacebookFile The file to chunk during upload.
35
+ */
36
+ private $file;
37
+
38
+ /**
39
+ * @var int The ID of the upload session.
40
+ */
41
+ private $uploadSessionId;
42
+
43
+ /**
44
+ * @var int Start byte position of the next file chunk.
45
+ */
46
+ private $startOffset;
47
+
48
+ /**
49
+ * @var int End byte position of the next file chunk.
50
+ */
51
+ private $endOffset;
52
+
53
+ /**
54
+ * @var int The ID of the video.
55
+ */
56
+ private $videoId;
57
+
58
+ /**
59
+ * @param FacebookFile $file
60
+ * @param int $uploadSessionId
61
+ * @param int $videoId
62
+ * @param int $startOffset
63
+ * @param int $endOffset
64
+ */
65
+ public function __construct(FacebookFile $file, $uploadSessionId, $videoId, $startOffset, $endOffset)
66
+ {
67
+ $this->file = $file;
68
+ $this->uploadSessionId = $uploadSessionId;
69
+ $this->videoId = $videoId;
70
+ $this->startOffset = $startOffset;
71
+ $this->endOffset = $endOffset;
72
+ }
73
+
74
+ /**
75
+ * Return the file entity.
76
+ *
77
+ * @return FacebookFile
78
+ */
79
+ public function getFile()
80
+ {
81
+ return $this->file;
82
+ }
83
+
84
+ /**
85
+ * Return a FacebookFile entity with partial content.
86
+ *
87
+ * @return FacebookFile
88
+ */
89
+ public function getPartialFile()
90
+ {
91
+ $maxLength = $this->endOffset - $this->startOffset;
92
+
93
+ return new FacebookFile($this->file->getFilePath(), $maxLength, $this->startOffset);
94
+ }
95
+
96
+ /**
97
+ * Return upload session Id
98
+ *
99
+ * @return int
100
+ */
101
+ public function getUploadSessionId()
102
+ {
103
+ return $this->uploadSessionId;
104
+ }
105
+
106
+ /**
107
+ * Check whether is the last chunk
108
+ *
109
+ * @return bool
110
+ */
111
+ public function isLastChunk()
112
+ {
113
+ return $this->startOffset === $this->endOffset;
114
+ }
115
+
116
+ /**
117
+ * @return int
118
+ */
119
+ public function getStartOffset()
120
+ {
121
+ return $this->startOffset;
122
+ }
123
+
124
+ /**
125
+ * Get uploaded video Id
126
+ *
127
+ * @return int
128
+ */
129
+ public function getVideoId()
130
+ {
131
+ return $this->videoId;
132
+ }
133
+ }
facebook/GraphNodes/Birthday.php ADDED
@@ -0,0 +1,85 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook\GraphNodes;
25
+
26
+ use DateTime;
27
+
28
+ /**
29
+ * Birthday object to handle various Graph return formats
30
+ *
31
+ * @package Facebook
32
+ */
33
+ class Birthday extends DateTime
34
+ {
35
+ /**
36
+ * @var bool
37
+ */
38
+ private $hasDate = false;
39
+
40
+ /**
41
+ * @var bool
42
+ */
43
+ private $hasYear = false;
44
+
45
+ /**
46
+ * Parses Graph birthday format to set indication flags, possible values:
47
+ *
48
+ * MM/DD/YYYY
49
+ * MM/DD
50
+ * YYYY
51
+ *
52
+ * @link https://developers.facebook.com/docs/graph-api/reference/user
53
+ *
54
+ * @param string $date
55
+ */
56
+ public function __construct($date)
57
+ {
58
+ $parts = explode('/', $date);
59
+
60
+ $this->hasYear = count($parts) === 3 || count($parts) === 1;
61
+ $this->hasDate = count($parts) === 3 || count($parts) === 2;
62
+
63
+ parent::__construct($date);
64
+ }
65
+
66
+ /**
67
+ * Returns whether date object contains birth day and month
68
+ *
69
+ * @return bool
70
+ */
71
+ public function hasDate()
72
+ {
73
+ return $this->hasDate;
74
+ }
75
+
76
+ /**
77
+ * Returns whether date object contains birth year
78
+ *
79
+ * @return bool
80
+ */
81
+ public function hasYear()
82
+ {
83
+ return $this->hasYear;
84
+ }
85
+ }
facebook/HttpClients/HttpClientsFactory.php ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook\HttpClients;
25
+
26
+ use GuzzleHttp\Client;
27
+ use InvalidArgumentException;
28
+ use Exception;
29
+
30
+ class HttpClientsFactory
31
+ {
32
+ private function __construct()
33
+ {
34
+ // a factory constructor should never be invoked
35
+ }
36
+
37
+ /**
38
+ * HTTP client generation.
39
+ *
40
+ * @param FacebookHttpClientInterface|Client|string|null $handler
41
+ *
42
+ * @throws Exception If the cURL extension or the Guzzle client aren't available (if required).
43
+ * @throws InvalidArgumentException If the http client handler isn't "curl", "stream", "guzzle", or an instance of Facebook\HttpClients\FacebookHttpClientInterface.
44
+ *
45
+ * @return FacebookHttpClientInterface
46
+ */
47
+ public static function createHttpClient($handler)
48
+ {
49
+ if (!$handler) {
50
+ return self::detectDefaultClient();
51
+ }
52
+
53
+ if ($handler instanceof FacebookHttpClientInterface) {
54
+ return $handler;
55
+ }
56
+
57
+ if ('stream' === $handler) {
58
+ return new FacebookStreamHttpClient();
59
+ }
60
+ if ('curl' === $handler) {
61
+ if (!extension_loaded('curl')) {
62
+ throw new Exception('The cURL extension must be loaded in order to use the "curl" handler.');
63
+ }
64
+
65
+ return new FacebookCurlHttpClient();
66
+ }
67
+
68
+ if ('guzzle' === $handler && !class_exists('GuzzleHttp\Client')) {
69
+ throw new Exception('The Guzzle HTTP client must be included in order to use the "guzzle" handler.');
70
+ }
71
+
72
+ if ($handler instanceof Client) {
73
+ return new FacebookGuzzleHttpClient($handler);
74
+ }
75
+ if ('guzzle' === $handler) {
76
+ return new FacebookGuzzleHttpClient();
77
+ }
78
+
79
+ 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');
80
+ }
81
+
82
+ /**
83
+ * Detect default HTTP client.
84
+ *
85
+ * @return FacebookHttpClientInterface
86
+ */
87
+ private static function detectDefaultClient()
88
+ {
89
+ if (extension_loaded('curl')) {
90
+ return new FacebookCurlHttpClient();
91
+ }
92
+
93
+ if (class_exists('GuzzleHttp\Client')) {
94
+ return new FacebookGuzzleHttpClient();
95
+ }
96
+
97
+ return new FacebookStreamHttpClient();
98
+ }
99
+ }
facebook/PersistentData/PersistentDataFactory.php ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook\PersistentData;
25
+
26
+ use InvalidArgumentException;
27
+
28
+ class PersistentDataFactory
29
+ {
30
+ private function __construct()
31
+ {
32
+ // a factory constructor should never be invoked
33
+ }
34
+
35
+ /**
36
+ * PersistentData generation.
37
+ *
38
+ * @param PersistentDataInterface|string|null $handler
39
+ *
40
+ * @throws InvalidArgumentException If the persistent data handler isn't "session", "memory", or an instance of Facebook\PersistentData\PersistentDataInterface.
41
+ *
42
+ * @return PersistentDataInterface
43
+ */
44
+ public static function createPersistentDataHandler($handler)
45
+ {
46
+ if (!$handler) {
47
+ return session_status() === PHP_SESSION_ACTIVE
48
+ ? new FacebookSessionPersistentDataHandler()
49
+ : new FacebookMemoryPersistentDataHandler();
50
+ }
51
+
52
+ if ($handler instanceof PersistentDataInterface) {
53
+ return $handler;
54
+ }
55
+
56
+ if ('session' === $handler) {
57
+ return new FacebookSessionPersistentDataHandler();
58
+ }
59
+ if ('memory' === $handler) {
60
+ return new FacebookMemoryPersistentDataHandler();
61
+ }
62
+
63
+ throw new InvalidArgumentException('The persistent data handler must be set to "session", "memory", or be an instance of Facebook\PersistentData\PersistentDataInterface');
64
+ }
65
+ }
facebook/PseudoRandomString/PseudoRandomStringGeneratorFactory.php ADDED
@@ -0,0 +1,101 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook\PseudoRandomString;
25
+
26
+ use Facebook\Exceptions\FacebookSDKException;
27
+ use InvalidArgumentException;
28
+
29
+ class PseudoRandomStringGeneratorFactory
30
+ {
31
+ private function __construct()
32
+ {
33
+ // a factory constructor should never be invoked
34
+ }
35
+
36
+ /**
37
+ * Pseudo random string generator creation.
38
+ *
39
+ * @param PseudoRandomStringGeneratorInterface|string|null $generator
40
+ *
41
+ * @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.
42
+ *
43
+ * @return PseudoRandomStringGeneratorInterface
44
+ */
45
+ public static function createPseudoRandomStringGenerator($generator)
46
+ {
47
+ if (!$generator) {
48
+ return self::detectDefaultPseudoRandomStringGenerator();
49
+ }
50
+
51
+ if ($generator instanceof PseudoRandomStringGeneratorInterface) {
52
+ return $generator;
53
+ }
54
+
55
+ if ('random_bytes' === $generator) {
56
+ return new RandomBytesPseudoRandomStringGenerator();
57
+ }
58
+ if ('mcrypt' === $generator) {
59
+ return new McryptPseudoRandomStringGenerator();
60
+ }
61
+ if ('openssl' === $generator) {
62
+ return new OpenSslPseudoRandomStringGenerator();
63
+ }
64
+ if ('urandom' === $generator) {
65
+ return new UrandomPseudoRandomStringGenerator();
66
+ }
67
+
68
+ 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');
69
+ }
70
+
71
+ /**
72
+ * Detects which pseudo-random string generator to use.
73
+ *
74
+ * @throws FacebookSDKException If unable to detect a cryptographically secure pseudo-random string generator.
75
+ *
76
+ * @return PseudoRandomStringGeneratorInterface
77
+ */
78
+ private static function detectDefaultPseudoRandomStringGenerator()
79
+ {
80
+ // Check for PHP 7's CSPRNG first to keep mcrypt deprecation messages from appearing in PHP 7.1.
81
+ if (function_exists('random_bytes')) {
82
+ return new RandomBytesPseudoRandomStringGenerator();
83
+ }
84
+
85
+ // Since openssl_random_pseudo_bytes() can sometimes return non-cryptographically
86
+ // secure pseudo-random strings (in rare cases), we check for mcrypt_create_iv() next.
87
+ if (function_exists('mcrypt_create_iv')) {
88
+ return new McryptPseudoRandomStringGenerator();
89
+ }
90
+
91
+ if (function_exists('openssl_random_pseudo_bytes')) {
92
+ return new OpenSslPseudoRandomStringGenerator();
93
+ }
94
+
95
+ if (!ini_get('open_basedir') && is_readable('/dev/urandom')) {
96
+ return new UrandomPseudoRandomStringGenerator();
97
+ }
98
+
99
+ throw new FacebookSDKException('Unable to detect a cryptographically secure pseudo-random string generator.');
100
+ }
101
+ }
facebook/PseudoRandomString/RandomBytesPseudoRandomStringGenerator.php ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook\PseudoRandomString;
25
+
26
+ use Facebook\Exceptions\FacebookSDKException;
27
+
28
+ class RandomBytesPseudoRandomStringGenerator implements PseudoRandomStringGeneratorInterface
29
+ {
30
+ use PseudoRandomStringGeneratorTrait;
31
+
32
+ /**
33
+ * @const string The error message when generating the string fails.
34
+ */
35
+ const ERROR_MESSAGE = 'Unable to generate a cryptographically secure pseudo-random string from random_bytes(). ';
36
+
37
+ /**
38
+ * @throws FacebookSDKException
39
+ */
40
+ public function __construct()
41
+ {
42
+ if (!function_exists('random_bytes')) {
43
+ throw new FacebookSDKException(
44
+ static::ERROR_MESSAGE .
45
+ 'The function random_bytes() does not exist.'
46
+ );
47
+ }
48
+ }
49
+
50
+ /**
51
+ * @inheritdoc
52
+ */
53
+ public function getPseudoRandomString($length)
54
+ {
55
+ $this->validateLength($length);
56
+
57
+ return $this->binToHex(random_bytes($length), $length);
58
+ }
59
+ }
facebook/facebook/Authentication/AccessToken.php ADDED
@@ -0,0 +1,160 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook\Authentication;
25
+
26
+ /**
27
+ * Class AccessToken
28
+ *
29
+ * @package Facebook
30
+ */
31
+ class AccessToken
32
+ {
33
+ /**
34
+ * The access token value.
35
+ *
36
+ * @var string
37
+ */
38
+ protected $value = '';
39
+
40
+ /**
41
+ * Date when token expires.
42
+ *
43
+ * @var \DateTime|null
44
+ */
45
+ protected $expiresAt;
46
+
47
+ /**
48
+ * Create a new access token entity.
49
+ *
50
+ * @param string $accessToken
51
+ * @param int $expiresAt
52
+ */
53
+ public function __construct($accessToken, $expiresAt = 0)
54
+ {
55
+ $this->value = $accessToken;
56
+ if ($expiresAt) {
57
+ $this->setExpiresAtFromTimeStamp($expiresAt);
58
+ }
59
+ }
60
+
61
+ /**
62
+ * Generate an app secret proof to sign a request to Graph.
63
+ *
64
+ * @param string $appSecret The app secret.
65
+ *
66
+ * @return string
67
+ */
68
+ public function getAppSecretProof($appSecret)
69
+ {
70
+ return hash_hmac('sha256', $this->value, $appSecret);
71
+ }
72
+
73
+ /**
74
+ * Getter for expiresAt.
75
+ *
76
+ * @return \DateTime|null
77
+ */
78
+ public function getExpiresAt()
79
+ {
80
+ return $this->expiresAt;
81
+ }
82
+
83
+ /**
84
+ * Determines whether or not this is an app access token.
85
+ *
86
+ * @return bool
87
+ */
88
+ public function isAppAccessToken()
89
+ {
90
+ return strpos($this->value, '|') !== false;
91
+ }
92
+
93
+ /**
94
+ * Determines whether or not this is a long-lived token.
95
+ *
96
+ * @return bool
97
+ */
98
+ public function isLongLived()
99
+ {
100
+ if ($this->expiresAt) {
101
+ return $this->expiresAt->getTimestamp() > time() + (60 * 60 * 2);
102
+ }
103
+
104
+ if ($this->isAppAccessToken()) {
105
+ return true;
106
+ }
107
+
108
+ return false;
109
+ }
110
+
111
+ /**
112
+ * Checks the expiration of the access token.
113
+ *
114
+ * @return boolean|null
115
+ */
116
+ public function isExpired()
117
+ {
118
+ if ($this->getExpiresAt() instanceof \DateTime) {
119
+ return $this->getExpiresAt()->getTimestamp() < time();
120
+ }
121
+
122
+ if ($this->isAppAccessToken()) {
123
+ return false;
124
+ }
125
+
126
+ return null;
127
+ }
128
+
129
+ /**
130
+ * Returns the access token as a string.
131
+ *
132
+ * @return string
133
+ */
134
+ public function getValue()
135
+ {
136
+ return $this->value;
137
+ }
138
+
139
+ /**
140
+ * Returns the access token as a string.
141
+ *
142
+ * @return string
143
+ */
144
+ public function __toString()
145
+ {
146
+ return $this->getValue();
147
+ }
148
+
149
+ /**
150
+ * Setter for expires_at.
151
+ *
152
+ * @param int $timeStamp
153
+ */
154
+ protected function setExpiresAtFromTimeStamp($timeStamp)
155
+ {
156
+ $dt = new \DateTime();
157
+ $dt->setTimestamp($timeStamp);
158
+ $this->expiresAt = $dt;
159
+ }
160
+ }
facebook/facebook/Authentication/AccessTokenMetadata.php ADDED
@@ -0,0 +1,390 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook\Authentication;
25
+
26
+ use Facebook\Exceptions\FacebookSDKException;
27
+
28
+ /**
29
+ * Class AccessTokenMetadata
30
+ *
31
+ * Represents metadata from an access token.
32
+ *
33
+ * @package Facebook
34
+ * @see https://developers.facebook.com/docs/graph-api/reference/debug_token
35
+ */
36
+ class AccessTokenMetadata
37
+ {
38
+ /**
39
+ * The access token metadata.
40
+ *
41
+ * @var array
42
+ */
43
+ protected $metadata = [];
44
+
45
+ /**
46
+ * Properties that should be cast as DateTime objects.
47
+ *
48
+ * @var array
49
+ */
50
+ protected static $dateProperties = ['expires_at', 'issued_at'];
51
+
52
+ /**
53
+ * @param array $metadata
54
+ *
55
+ * @throws FacebookSDKException
56
+ */
57
+ public function __construct(array $metadata)
58
+ {
59
+ if (!isset($metadata['data'])) {
60
+ throw new FacebookSDKException('Unexpected debug token response data.', 401);
61
+ }
62
+
63
+ $this->metadata = $metadata['data'];
64
+
65
+ $this->castTimestampsToDateTime();
66
+ }
67
+
68
+ /**
69
+ * Returns a value from the metadata.
70
+ *
71
+ * @param string $field The property to retrieve.
72
+ * @param mixed $default The default to return if the property doesn't exist.
73
+ *
74
+ * @return mixed
75
+ */
76
+ public function getField($field, $default = null)
77
+ {
78
+ if (isset($this->metadata[$field])) {
79
+ return $this->metadata[$field];
80
+ }
81
+
82
+ return $default;
83
+ }
84
+
85
+ /**
86
+ * Returns a value from the metadata.
87
+ *
88
+ * @param string $field The property to retrieve.
89
+ * @param mixed $default The default to return if the property doesn't exist.
90
+ *
91
+ * @return mixed
92
+ *
93
+ * @deprecated 5.0.0 getProperty() has been renamed to getField()
94
+ * @todo v6: Remove this method
95
+ */
96
+ public function getProperty($field, $default = null)
97
+ {
98
+ return $this->getField($field, $default);
99
+ }
100
+
101
+ /**
102
+ * Returns a value from a child property in the metadata.
103
+ *
104
+ * @param string $parentField The parent property.
105
+ * @param string $field The property to retrieve.
106
+ * @param mixed $default The default to return if the property doesn't exist.
107
+ *
108
+ * @return mixed
109
+ */
110
+ public function getChildProperty($parentField, $field, $default = null)
111
+ {
112
+ if (!isset($this->metadata[$parentField])) {
113
+ return $default;
114
+ }
115
+
116
+ if (!isset($this->metadata[$parentField][$field])) {
117
+ return $default;
118
+ }
119
+
120
+ return $this->metadata[$parentField][$field];
121
+ }
122
+
123
+ /**
124
+ * Returns a value from the error metadata.
125
+ *
126
+ * @param string $field The property to retrieve.
127
+ * @param mixed $default The default to return if the property doesn't exist.
128
+ *
129
+ * @return mixed
130
+ */
131
+ public function getErrorProperty($field, $default = null)
132
+ {
133
+ return $this->getChildProperty('error', $field, $default);
134
+ }
135
+
136
+ /**
137
+ * Returns a value from the "metadata" metadata. *Brain explodes*
138
+ *
139
+ * @param string $field The property to retrieve.
140
+ * @param mixed $default The default to return if the property doesn't exist.
141
+ *
142
+ * @return mixed
143
+ */
144
+ public function getMetadataProperty($field, $default = null)
145
+ {
146
+ return $this->getChildProperty('metadata', $field, $default);
147
+ }
148
+
149
+ /**
150
+ * The ID of the application this access token is for.
151
+ *
152
+ * @return string|null
153
+ */
154
+ public function getAppId()
155
+ {
156
+ return $this->getField('app_id');
157
+ }
158
+
159
+ /**
160
+ * Name of the application this access token is for.
161
+ *
162
+ * @return string|null
163
+ */
164
+ public function getApplication()
165
+ {
166
+ return $this->getField('application');
167
+ }
168
+
169
+ /**
170
+ * Any error that a request to the graph api
171
+ * would return due to the access token.
172
+ *
173
+ * @return bool|null
174
+ */
175
+ public function isError()
176
+ {
177
+ return $this->getField('error') !== null;
178
+ }
179
+
180
+ /**
181
+ * The error code for the error.
182
+ *
183
+ * @return int|null
184
+ */
185
+ public function getErrorCode()
186
+ {
187
+ return $this->getErrorProperty('code');
188
+ }
189
+
190
+ /**
191
+ * The error message for the error.
192
+ *
193
+ * @return string|null
194
+ */
195
+ public function getErrorMessage()
196
+ {
197
+ return $this->getErrorProperty('message');
198
+ }
199
+
200
+ /**
201
+ * The error subcode for the error.
202
+ *
203
+ * @return int|null
204
+ */
205
+ public function getErrorSubcode()
206
+ {
207
+ return $this->getErrorProperty('subcode');
208
+ }
209
+
210
+ /**
211
+ * DateTime when this access token expires.
212
+ *
213
+ * @return \DateTime|null
214
+ */
215
+ public function getExpiresAt()
216
+ {
217
+ return $this->getField('expires_at');
218
+ }
219
+
220
+ /**
221
+ * Whether the access token is still valid or not.
222
+ *
223
+ * @return boolean|null
224
+ */
225
+ public function getIsValid()
226
+ {
227
+ return $this->getField('is_valid');
228
+ }
229
+
230
+ /**
231
+ * DateTime when this access token was issued.
232
+ *
233
+ * Note that the issued_at field is not returned
234
+ * for short-lived access tokens.
235
+ *
236
+ * @see https://developers.facebook.com/docs/facebook-login/access-tokens#debug
237
+ *
238
+ * @return \DateTime|null
239
+ */
240
+ public function getIssuedAt()
241
+ {
242
+ return $this->getField('issued_at');
243
+ }
244
+
245
+ /**
246
+ * General metadata associated with the access token.
247
+ * Can contain data like 'sso', 'auth_type', 'auth_nonce'.
248
+ *
249
+ * @return array|null
250
+ */
251
+ public function getMetadata()
252
+ {
253
+ return $this->getField('metadata');
254
+ }
255
+
256
+ /**
257
+ * The 'sso' child property from the 'metadata' parent property.
258
+ *
259
+ * @return string|null
260
+ */
261
+ public function getSso()
262
+ {
263
+ return $this->getMetadataProperty('sso');
264
+ }
265
+
266
+ /**
267
+ * The 'auth_type' child property from the 'metadata' parent property.
268
+ *
269
+ * @return string|null
270
+ */
271
+ public function getAuthType()
272
+ {
273
+ return $this->getMetadataProperty('auth_type');
274
+ }
275
+
276
+ /**
277
+ * The 'auth_nonce' child property from the 'metadata' parent property.
278
+ *
279
+ * @return string|null
280
+ */
281
+ public function getAuthNonce()
282
+ {
283
+ return $this->getMetadataProperty('auth_nonce');
284
+ }
285
+
286
+ /**
287
+ * For impersonated access tokens, the ID of
288
+ * the page this token contains.
289
+ *
290
+ * @return string|null
291
+ */
292
+ public function getProfileId()
293
+ {
294
+ return $this->getField('profile_id');
295
+ }
296
+
297
+ /**
298
+ * List of permissions that the user has granted for
299
+ * the app in this access token.
300
+ *
301
+ * @return array
302
+ */
303
+ public function getScopes()
304
+ {
305
+ return $this->getField('scopes');
306
+ }
307
+
308
+ /**
309
+ * The ID of the user this access token is for.
310
+ *
311
+ * @return string|null
312
+ */
313
+ public function getUserId()
314
+ {
315
+ return $this->getField('user_id');
316
+ }
317
+
318
+ /**
319
+ * Ensures the app ID from the access token
320
+ * metadata is what we expect.
321
+ *
322
+ * @param string $appId
323
+ *
324
+ * @throws FacebookSDKException
325
+ */
326
+ public function validateAppId($appId)
327
+ {
328
+ if ($this->getAppId() !== $appId) {
329
+ throw new FacebookSDKException('Access token metadata contains unexpected app ID.', 401);
330
+ }
331
+ }
332
+
333
+ /**
334
+ * Ensures the user ID from the access token
335
+ * metadata is what we expect.
336
+ *
337
+ * @param string $userId
338
+ *
339
+ * @throws FacebookSDKException
340
+ */
341
+ public function validateUserId($userId)
342
+ {
343
+ if ($this->getUserId() !== $userId) {
344
+ throw new FacebookSDKException('Access token metadata contains unexpected user ID.', 401);
345
+ }
346
+ }
347
+
348
+ /**
349
+ * Ensures the access token has not expired yet.
350
+ *
351
+ * @throws FacebookSDKException
352
+ */
353
+ public function validateExpiration()
354
+ {
355
+ if (!$this->getExpiresAt() instanceof \DateTime) {
356
+ return;
357
+ }
358
+
359
+ if ($this->getExpiresAt()->getTimestamp() < time()) {
360
+ throw new FacebookSDKException('Inspection of access token metadata shows that the access token has expired.', 401);
361
+ }
362
+ }
363
+
364
+ /**
365
+ * Converts a unix timestamp into a DateTime entity.
366
+ *
367
+ * @param int $timestamp
368
+ *
369
+ * @return \DateTime
370
+ */
371
+ private function convertTimestampToDateTime($timestamp)
372
+ {
373
+ $dt = new \DateTime();
374
+ $dt->setTimestamp($timestamp);
375
+
376
+ return $dt;
377
+ }
378
+
379
+ /**
380
+ * Casts the unix timestamps as DateTime entities.
381
+ */
382
+ private function castTimestampsToDateTime()
383
+ {
384
+ foreach (static::$dateProperties as $key) {
385
+ if (isset($this->metadata[$key]) && $this->metadata[$key] !== 0) {
386
+ $this->metadata[$key] = $this->convertTimestampToDateTime($this->metadata[$key]);
387
+ }
388
+ }
389
+ }
390
+ }
facebook/facebook/Authentication/OAuth2Client.php ADDED
@@ -0,0 +1,292 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook\Authentication;
25
+
26
+ use Facebook\Facebook;
27
+ use Facebook\FacebookApp;
28
+ use Facebook\FacebookRequest;
29
+ use Facebook\FacebookResponse;
30
+ use Facebook\FacebookClient;
31
+ use Facebook\Exceptions\FacebookResponseException;
32
+ use Facebook\Exceptions\FacebookSDKException;
33
+
34
+ /**
35
+ * Class OAuth2Client
36
+ *
37
+ * @package Facebook
38
+ */
39
+ class OAuth2Client
40
+ {
41
+ /**
42
+ * @const string The base authorization URL.
43
+ */
44
+ const BASE_AUTHORIZATION_URL = 'https://www.facebook.com';
45
+
46
+ /**
47
+ * The FacebookApp entity.
48
+ *
49
+ * @var FacebookApp
50
+ */
51
+ protected $app;
52
+
53
+ /**
54
+ * The Facebook client.
55
+ *
56
+ * @var FacebookClient
57
+ */
58
+ protected $client;
59
+
60
+ /**
61
+ * The version of the Graph API to use.
62
+ *
63
+ * @var string
64
+ */
65
+ protected $graphVersion;
66
+
67
+ /**
68
+ * The last request sent to Graph.
69
+ *
70
+ * @var FacebookRequest|null
71
+ */
72
+ protected $lastRequest;
73
+
74
+ /**
75
+ * @param FacebookApp $app
76
+ * @param FacebookClient $client
77
+ * @param string|null $graphVersion The version of the Graph API to use.
78
+ */
79
+ public function __construct(FacebookApp $app, FacebookClient $client, $graphVersion = null)
80
+ {
81
+ $this->app = $app;
82
+ $this->client = $client;
83
+ $this->graphVersion = $graphVersion ?: Facebook::DEFAULT_GRAPH_VERSION;
84
+ }
85
+
86
+ /**
87
+ * Returns the last FacebookRequest that was sent.
88
+ * Useful for debugging and testing.
89
+ *
90
+ * @return FacebookRequest|null
91
+ */
92
+ public function getLastRequest()
93
+ {
94
+ return $this->lastRequest;
95
+ }
96
+
97
+ /**
98
+ * Get the metadata associated with the access token.
99
+ *
100
+ * @param AccessToken|string $accessToken The access token to debug.
101
+ *
102
+ * @return AccessTokenMetadata
103
+ */
104
+ public function debugToken($accessToken)
105
+ {
106
+ $accessToken = $accessToken instanceof AccessToken ? $accessToken->getValue() : $accessToken;
107
+ $params = ['input_token' => $accessToken];
108
+
109
+ $this->lastRequest = new FacebookRequest(
110
+ $this->app,
111
+ $this->app->getAccessToken(),
112
+ 'GET',
113
+ '/debug_token',
114
+ $params,
115
+ null,
116
+ $this->graphVersion
117
+ );
118
+ $response = $this->client->sendRequest($this->lastRequest);
119
+ $metadata = $response->getDecodedBody();
120
+
121
+ return new AccessTokenMetadata($metadata);
122
+ }
123
+
124
+ /**
125
+ * Generates an authorization URL to begin the process of authenticating a user.
126
+ *
127
+ * @param string $redirectUrl The callback URL to redirect to.
128
+ * @param string $state The CSPRNG-generated CSRF value.
129
+ * @param array $scope An array of permissions to request.
130
+ * @param array $params An array of parameters to generate URL.
131
+ * @param string $separator The separator to use in http_build_query().
132
+ *
133
+ * @return string
134
+ */
135
+ public function getAuthorizationUrl($redirectUrl, $state, array $scope = [], array $params = [], $separator = '&')
136
+ {
137
+ $params += [
138
+ 'client_id' => $this->app->getId(),
139
+ 'state' => $state,
140
+ 'response_type' => 'code',
141
+ 'sdk' => 'php-sdk-' . Facebook::VERSION,
142
+ 'redirect_uri' => $redirectUrl,
143
+ 'scope' => implode(',', $scope)
144
+ ];
145
+
146
+ return static::BASE_AUTHORIZATION_URL . '/' . $this->graphVersion . '/dialog/oauth?' . http_build_query($params, null, $separator);
147
+ }
148
+
149
+ /**
150
+ * Get a valid access token from a code.
151
+ *
152
+ * @param string $code
153
+ * @param string $redirectUri
154
+ *
155
+ * @return AccessToken
156
+ *
157
+ * @throws FacebookSDKException
158
+ */
159
+ public function getAccessTokenFromCode($code, $redirectUri = '')
160
+ {
161
+ $params = [
162
+ 'code' => $code,
163
+ 'redirect_uri' => $redirectUri,
164
+ ];
165
+
166
+ return $this->requestAnAccessToken($params);
167
+ }
168
+
169
+ /**
170
+ * Exchanges a short-lived access token with a long-lived access token.
171
+ *
172
+ * @param AccessToken|string $accessToken
173
+ *
174
+ * @return AccessToken
175
+ *
176
+ * @throws FacebookSDKException
177
+ */
178
+ public function getLongLivedAccessToken($accessToken)
179
+ {
180
+ $accessToken = $accessToken instanceof AccessToken ? $accessToken->getValue() : $accessToken;
181
+ $params = [
182
+ 'grant_type' => 'fb_exchange_token',
183
+ 'fb_exchange_token' => $accessToken,
184
+ ];
185
+
186
+ return $this->requestAnAccessToken($params);
187
+ }
188
+
189
+ /**
190
+ * Get a valid code from an access token.
191
+ *
192
+ * @param AccessToken|string $accessToken
193
+ * @param string $redirectUri
194
+ *
195
+ * @return AccessToken
196
+ *
197
+ * @throws FacebookSDKException
198
+ */
199
+ public function getCodeFromLongLivedAccessToken($accessToken, $redirectUri = '')
200
+ {
201
+ $params = [
202
+ 'redirect_uri' => $redirectUri,
203
+ ];
204
+
205
+ $response = $this->sendRequestWithClientParams('/oauth/client_code', $params, $accessToken);
206
+ $data = $response->getDecodedBody();
207
+
208
+ if (!isset($data['code'])) {
209
+ throw new FacebookSDKException('Code was not returned from Graph.', 401);
210
+ }
211
+
212
+ return $data['code'];
213
+ }
214
+
215
+ /**
216
+ * Send a request to the OAuth endpoint.
217
+ *
218
+ * @param array $params
219
+ *
220
+ * @return AccessToken
221
+ *
222
+ * @throws FacebookSDKException
223
+ */
224
+ protected function requestAnAccessToken(array $params)
225
+ {
226
+ $response = $this->sendRequestWithClientParams('/oauth/access_token', $params);
227
+ $data = $response->getDecodedBody();
228
+
229
+ if (!isset($data['access_token'])) {
230
+ throw new FacebookSDKException('Access token was not returned from Graph.', 401);
231
+ }
232
+
233
+ // Graph returns two different key names for expiration time
234
+ // on the same endpoint. Doh! :/
235
+ $expiresAt = 0;
236
+ if (isset($data['expires'])) {
237
+ // For exchanging a short lived token with a long lived token.
238
+ // The expiration time in seconds will be returned as "expires".
239
+ $expiresAt = time() + $data['expires'];
240
+ } elseif (isset($data['expires_in'])) {
241
+ // For exchanging a code for a short lived access token.
242
+ // The expiration time in seconds will be returned as "expires_in".
243
+ // See: https://developers.facebook.com/docs/facebook-login/access-tokens#long-via-code
244
+ $expiresAt = time() + $data['expires_in'];
245
+ }
246
+
247
+ return new AccessToken($data['access_token'], $expiresAt);
248
+ }
249
+
250
+ /**
251
+ * Send a request to Graph with an app access token.
252
+ *
253
+ * @param string $endpoint
254
+ * @param array $params
255
+ * @param AccessToken|string|null $accessToken
256
+ *
257
+ * @return FacebookResponse
258
+ *
259
+ * @throws FacebookResponseException
260
+ */
261
+ protected function sendRequestWithClientParams($endpoint, array $params, $accessToken = null)
262
+ {
263
+ $params += $this->getClientParams();
264
+
265
+ $accessToken = $accessToken ?: $this->app->getAccessToken();
266
+
267
+ $this->lastRequest = new FacebookRequest(
268
+ $this->app,
269
+ $accessToken,
270
+ 'GET',
271
+ $endpoint,
272
+ $params,
273
+ null,
274
+ $this->graphVersion
275
+ );
276
+
277
+ return $this->client->sendRequest($this->lastRequest);
278
+ }
279
+
280
+ /**
281
+ * Returns the client_* params for OAuth requests.
282
+ *
283
+ * @return array
284
+ */
285
+ protected function getClientParams()
286
+ {
287
+ return [
288
+ 'client_id' => $this->app->getId(),
289
+ 'client_secret' => $this->app->getSecret(),
290
+ ];
291
+ }
292
+ }
facebook/facebook/Exceptions/FacebookAuthenticationException.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook\Exceptions;
25
+
26
+ /**
27
+ * Class FacebookAuthenticationException
28
+ *
29
+ * @package Facebook
30
+ */
31
+ class FacebookAuthenticationException extends FacebookSDKException
32
+ {
33
+ }
facebook/facebook/Exceptions/FacebookAuthorizationException.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook\Exceptions;
25
+
26
+ /**
27
+ * Class FacebookAuthorizationException
28
+ *
29
+ * @package Facebook
30
+ */
31
+ class FacebookAuthorizationException extends FacebookSDKException
32
+ {
33
+ }
facebook/facebook/Exceptions/FacebookClientException.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook\Exceptions;
25
+
26
+ /**
27
+ * Class FacebookClientException
28
+ *
29
+ * @package Facebook
30
+ */
31
+ class FacebookClientException extends FacebookSDKException
32
+ {
33
+ }
facebook/facebook/Exceptions/FacebookOtherException.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook\Exceptions;
25
+
26
+ /**
27
+ * Class FacebookOtherException
28
+ *
29
+ * @package Facebook
30
+ */
31
+ class FacebookOtherException extends FacebookSDKException
32
+ {
33
+ }
facebook/facebook/Exceptions/FacebookResponseException.php ADDED
@@ -0,0 +1,216 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook\Exceptions;
25
+
26
+ use Facebook\FacebookResponse;
27
+
28
+ /**
29
+ * Class FacebookResponseException
30
+ *
31
+ * @package Facebook
32
+ */
33
+ class FacebookResponseException extends FacebookSDKException
34
+ {
35
+ /**
36
+ * @var FacebookResponse The response that threw the exception.
37
+ */
38
+ protected $response;
39
+
40
+ /**
41
+ * @var array Decoded response.
42
+ */
43
+ protected $responseData;
44
+
45
+ /**
46
+ * Creates a FacebookResponseException.
47
+ *
48
+ * @param FacebookResponse $response The response that threw the exception.
49
+ * @param FacebookSDKException $previousException The more detailed exception.
50
+ */
51
+ public function __construct(FacebookResponse $response, FacebookSDKException $previousException = null)
52
+ {
53
+ $this->response = $response;
54
+ $this->responseData = $response->getDecodedBody();
55
+
56
+ $errorMessage = $this->get('message', 'Unknown error from Graph.');
57
+ $errorCode = $this->get('code', -1);
58
+
59
+ parent::__construct($errorMessage, $errorCode, $previousException);
60
+ }
61
+
62
+ /**
63
+ * A factory for creating the appropriate exception based on the response from Graph.
64
+ *
65
+ * @param FacebookResponse $response The response that threw the exception.
66
+ *
67
+ * @return FacebookResponseException
68
+ */
69
+ public static function create(FacebookResponse $response)
70
+ {
71
+ $data = $response->getDecodedBody();
72
+
73
+ if (!isset($data['error']['code']) && isset($data['code'])) {
74
+ $data = ['error' => $data];
75
+ }
76
+
77
+ $code = isset($data['error']['code']) ? $data['error']['code'] : null;
78
+ $message = isset($data['error']['message']) ? $data['error']['message'] : 'Unknown error from Graph.';
79
+
80
+ if (isset($data['error']['error_subcode'])) {
81
+ switch ($data['error']['error_subcode']) {
82
+ // Other authentication issues
83
+ case 458:
84
+ case 459:
85
+ case 460:
86
+ case 463:
87
+ case 464:
88
+ case 467:
89
+ return new static($response, new FacebookAuthenticationException($message, $code));
90
+ // Video upload resumable error
91
+ case 1363030:
92
+ case 1363019:
93
+ case 1363037:
94
+ case 1363033:
95
+ case 1363021:
96
+ case 1363041:
97
+ return new static($response, new FacebookResumableUploadException($message, $code));
98
+ }
99
+ }
100
+
101
+ switch ($code) {
102
+ // Login status or token expired, revoked, or invalid
103
+ case 100:
104
+ case 102:
105
+ case 190:
106
+ return new static($response, new FacebookAuthenticationException($message, $code));
107
+
108
+ // Server issue, possible downtime
109
+ case 1:
110
+ case 2:
111
+ return new static($response, new FacebookServerException($message, $code));
112
+
113
+ // API Throttling
114
+ case 4:
115
+ case 17:
116
+ case 32:
117
+ case 341:
118
+ case 613:
119
+ return new static($response, new FacebookThrottleException($message, $code));
120
+
121
+ // Duplicate Post
122
+ case 506:
123
+ return new static($response, new FacebookClientException($message, $code));
124
+ }
125
+
126
+ // Missing Permissions
127
+ if ($code == 10 || ($code >= 200 && $code <= 299)) {
128
+ return new static($response, new FacebookAuthorizationException($message, $code));
129
+ }
130
+
131
+ // OAuth authentication error
132
+ if (isset($data['error']['type']) && $data['error']['type'] === 'OAuthException') {
133
+ return new static($response, new FacebookAuthenticationException($message, $code));
134
+ }
135
+
136
+ // All others
137
+ return new static($response, new FacebookOtherException($message, $code));
138
+ }
139
+
140
+ /**
141
+ * Checks isset and returns that or a default value.
142
+ *
143
+ * @param string $key
144
+ * @param mixed $default
145
+ *
146
+ * @return mixed
147
+ */
148
+ private function get($key, $default = null)
149
+ {
150
+ if (isset($this->responseData['error'][$key])) {
151
+ return $this->responseData['error'][$key];
152
+ }
153
+
154
+ return $default;
155
+ }
156
+
157
+ /**
158
+ * Returns the HTTP status code
159
+ *
160
+ * @return int
161
+ */
162
+ public function getHttpStatusCode()
163
+ {
164
+ return $this->response->getHttpStatusCode();
165
+ }
166
+
167
+ /**
168
+ * Returns the sub-error code
169
+ *
170
+ * @return int
171
+ */
172
+ public function getSubErrorCode()
173
+ {
174
+ return $this->get('error_subcode', -1);
175
+ }
176
+
177
+ /**
178
+ * Returns the error type
179
+ *
180
+ * @return string
181
+ */
182
+ public function getErrorType()
183
+ {
184
+ return $this->get('type', '');
185
+ }
186
+
187
+ /**
188
+ * Returns the raw response used to create the exception.
189
+ *
190
+ * @return string
191
+ */
192
+ public function getRawResponse()
193
+ {
194
+ return $this->response->getBody();
195
+ }
196
+
197
+ /**
198
+ * Returns the decoded response used to create the exception.
199
+ *
200
+ * @return array
201
+ */
202
+ public function getResponseData()
203
+ {
204
+ return $this->responseData;
205
+ }
206
+
207
+ /**
208
+ * Returns the response entity used to create the exception.
209
+ *
210
+ * @return FacebookResponse
211
+ */
212
+ public function getResponse()
213
+ {
214
+ return $this->response;
215
+ }
216
+ }
facebook/facebook/Exceptions/FacebookResumableUploadException.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook\Exceptions;
25
+
26
+ /**
27
+ * Class FacebookResumableUploadException
28
+ *
29
+ * @package Facebook
30
+ */
31
+ class FacebookResumableUploadException extends FacebookSDKException
32
+ {
33
+ }
facebook/facebook/Exceptions/FacebookSDKException.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook\Exceptions;
25
+
26
+ /**
27
+ * Class FacebookSDKException
28
+ *
29
+ * @package Facebook
30
+ */
31
+ class FacebookSDKException extends \Exception
32
+ {
33
+ }
facebook/facebook/Exceptions/FacebookServerException.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook\Exceptions;
25
+
26
+ /**
27
+ * Class FacebookServerException
28
+ *
29
+ * @package Facebook
30
+ */
31
+ class FacebookServerException extends FacebookSDKException
32
+ {
33
+ }
facebook/facebook/Exceptions/FacebookThrottleException.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook\Exceptions;
25
+
26
+ /**
27
+ * Class FacebookThrottleException
28
+ *
29
+ * @package Facebook
30
+ */
31
+ class FacebookThrottleException extends FacebookSDKException
32
+ {
33
+ }
facebook/facebook/Facebook.php ADDED
@@ -0,0 +1,635 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook;
25
+
26
+ use Facebook\Authentication\AccessToken;
27
+ use Facebook\Authentication\OAuth2Client;
28
+ use Facebook\FileUpload\FacebookFile;
29
+ use Facebook\FileUpload\FacebookResumableUploader;
30
+ use Facebook\FileUpload\FacebookTransferChunk;
31
+ use Facebook\FileUpload\FacebookVideo;
32
+ use Facebook\GraphNodes\GraphEdge;
33
+ use Facebook\Url\UrlDetectionInterface;
34
+ use Facebook\Url\FacebookUrlDetectionHandler;
35
+ use Facebook\PseudoRandomString\PseudoRandomStringGeneratorFactory;
36
+ use Facebook\PseudoRandomString\PseudoRandomStringGeneratorInterface;
37
+ use Facebook\HttpClients\HttpClientsFactory;
38
+ use Facebook\PersistentData\PersistentDataFactory;
39
+ use Facebook\PersistentData\PersistentDataInterface;
40
+ use Facebook\Helpers\FacebookCanvasHelper;
41
+ use Facebook\Helpers\FacebookJavaScriptHelper;
42
+ use Facebook\Helpers\FacebookPageTabHelper;
43
+ use Facebook\Helpers\FacebookRedirectLoginHelper;
44
+ use Facebook\Exceptions\FacebookSDKException;
45
+
46
+ /**
47
+ * Class Facebook
48
+ *
49
+ * @package Facebook
50
+ */
51
+ class Facebook
52
+ {
53
+ /**
54
+ * @const string Version number of the Facebook PHP SDK.
55
+ */
56
+ const VERSION = '5.6.1';
57
+
58
+ /**
59
+ * @const string Default Graph API version for requests.
60
+ */
61
+ const DEFAULT_GRAPH_VERSION = 'v2.10';
62
+
63
+ /**
64
+ * @const string The name of the environment variable that contains the app ID.
65
+ */
66
+ const APP_ID_ENV_NAME = 'FACEBOOK_APP_ID';
67
+
68
+ /**
69
+ * @const string The name of the environment variable that contains the app secret.
70
+ */
71
+ const APP_SECRET_ENV_NAME = 'FACEBOOK_APP_SECRET';
72
+
73
+ /**
74
+ * @var FacebookApp The FacebookApp entity.
75
+ */
76
+ protected $app;
77
+
78
+ /**
79
+ * @var FacebookClient The Facebook client service.
80
+ */
81
+ protected $client;
82
+
83
+ /**
84
+ * @var OAuth2Client The OAuth 2.0 client service.
85
+ */
86
+ protected $oAuth2Client;
87
+
88
+ /**
89
+ * @var UrlDetectionInterface|null The URL detection handler.
90
+ */
91
+ protected $urlDetectionHandler;
92
+
93
+ /**
94
+ * @var PseudoRandomStringGeneratorInterface|null The cryptographically secure pseudo-random string generator.
95
+ */
96
+ protected $pseudoRandomStringGenerator;
97
+
98
+ /**
99
+ * @var AccessToken|null The default access token to use with requests.
100
+ */
101
+ protected $defaultAccessToken;
102
+
103
+ /**
104
+ * @var string|null The default Graph version we want to use.
105
+ */
106
+ protected $defaultGraphVersion;
107
+
108
+ /**
109
+ * @var PersistentDataInterface|null The persistent data handler.
110
+ */
111
+ protected $persistentDataHandler;
112
+
113
+ /**
114
+ * @var FacebookResponse|FacebookBatchResponse|null Stores the last request made to Graph.
115
+ */
116
+ protected $lastResponse;
117
+
118
+ /**
119
+ * Instantiates a new Facebook super-class object.
120
+ *
121
+ * @param array $config
122
+ *
123
+ * @throws FacebookSDKException
124
+ */
125
+ public function __construct(array $config = [])
126
+ {
127
+ $config = array_merge([
128
+ 'app_id' => getenv(static::APP_ID_ENV_NAME),
129
+ 'app_secret' => getenv(static::APP_SECRET_ENV_NAME),
130
+ 'default_graph_version' => static::DEFAULT_GRAPH_VERSION,
131
+ 'enable_beta_mode' => false,
132
+ 'http_client_handler' => null,
133
+ 'persistent_data_handler' => null,
134
+ 'pseudo_random_string_generator' => null,
135
+ 'url_detection_handler' => null,
136
+ ], $config);
137
+
138
+ if (!$config['app_id']) {
139
+ throw new FacebookSDKException('Required "app_id" key not supplied in config and could not find fallback environment variable "' . static::APP_ID_ENV_NAME . '"');
140
+ }
141
+ if (!$config['app_secret']) {
142
+ throw new FacebookSDKException('Required "app_secret" key not supplied in config and could not find fallback environment variable "' . static::APP_SECRET_ENV_NAME . '"');
143
+ }
144
+
145
+ $this->app = new FacebookApp($config['app_id'], $config['app_secret']);
146
+ $this->client = new FacebookClient(
147
+ HttpClientsFactory::createHttpClient($config['http_client_handler']),
148
+ $config['enable_beta_mode']
149
+ );
150
+ $this->pseudoRandomStringGenerator = PseudoRandomStringGeneratorFactory::createPseudoRandomStringGenerator(
151
+ $config['pseudo_random_string_generator']
152
+ );
153
+ $this->setUrlDetectionHandler($config['url_detection_handler'] ?: new FacebookUrlDetectionHandler());
154
+ $this->persistentDataHandler = PersistentDataFactory::createPersistentDataHandler(
155
+ $config['persistent_data_handler']
156
+ );
157
+
158
+ if (isset($config['default_access_token'])) {
159
+ $this->setDefaultAccessToken($config['default_access_token']);
160
+ }
161
+
162
+ // @todo v6: Throw an InvalidArgumentException if "default_graph_version" is not set
163
+ $this->defaultGraphVersion = $config['default_graph_version'];
164
+ }
165
+
166
+ /**
167
+ * Returns the FacebookApp entity.
168
+ *
169
+ * @return FacebookApp
170
+ */
171
+ public function getApp()
172
+ {
173
+ return $this->app;
174
+ }
175
+
176
+ /**
177
+ * Returns the FacebookClient service.
178
+ *
179
+ * @return FacebookClient
180
+ */
181
+ public function getClient()
182
+ {
183
+ return $this->client;
184
+ }
185
+
186
+ /**
187
+ * Returns the OAuth 2.0 client service.
188
+ *
189
+ * @return OAuth2Client
190
+ */
191
+ public function getOAuth2Client()
192
+ {
193
+ if (!$this->oAuth2Client instanceof OAuth2Client) {
194
+ $app = $this->getApp();
195
+ $client = $this->getClient();
196
+ $this->oAuth2Client = new OAuth2Client($app, $client, $this->defaultGraphVersion);
197
+ }
198
+
199
+ return $this->oAuth2Client;
200
+ }
201
+
202
+ /**
203
+ * Returns the last response returned from Graph.
204
+ *
205
+ * @return FacebookResponse|FacebookBatchResponse|null
206
+ */
207
+ public function getLastResponse()
208
+ {
209
+ return $this->lastResponse;
210
+ }
211
+
212
+ /**
213
+ * Returns the URL detection handler.
214
+ *
215
+ * @return UrlDetectionInterface
216
+ */
217
+ public function getUrlDetectionHandler()
218
+ {
219
+ return $this->urlDetectionHandler;
220
+ }
221
+
222
+ /**
223
+ * Changes the URL detection handler.
224
+ *
225
+ * @param UrlDetectionInterface $urlDetectionHandler
226
+ */
227
+ private function setUrlDetectionHandler(UrlDetectionInterface $urlDetectionHandler)
228
+ {
229
+ $this->urlDetectionHandler = $urlDetectionHandler;
230
+ }
231
+
232
+ /**
233
+ * Returns the default AccessToken entity.
234
+ *
235
+ * @return AccessToken|null
236
+ */
237
+ public function getDefaultAccessToken()
238
+ {
239
+ return $this->defaultAccessToken;
240
+ }
241
+
242
+ /**
243
+ * Sets the default access token to use with requests.
244
+ *
245
+ * @param AccessToken|string $accessToken The access token to save.
246
+ *
247
+ * @throws \InvalidArgumentException
248
+ */
249
+ public function setDefaultAccessToken($accessToken)
250
+ {
251
+ if (is_string($accessToken)) {
252
+ $this->defaultAccessToken = new AccessToken($accessToken);
253
+
254
+ return;
255
+ }
256
+
257
+ if ($accessToken instanceof AccessToken) {
258
+ $this->defaultAccessToken = $accessToken;
259
+
260
+ return;
261
+ }
262
+
263
+ throw new \InvalidArgumentException('The default access token must be of type "string" or Facebook\AccessToken');
264
+ }
265
+
266
+ /**
267
+ * Returns the default Graph version.
268
+ *
269
+ * @return string
270
+ */
271
+ public function getDefaultGraphVersion()
272
+ {
273
+ return $this->defaultGraphVersion;
274
+ }
275
+
276
+ /**
277
+ * Returns the redirect login helper.
278
+ *
279
+ * @return FacebookRedirectLoginHelper
280
+ */
281
+ public function getRedirectLoginHelper()
282
+ {
283
+ return new FacebookRedirectLoginHelper(
284
+ $this->getOAuth2Client(),
285
+ $this->persistentDataHandler,
286
+ $this->urlDetectionHandler,
287
+ $this->pseudoRandomStringGenerator
288
+ );
289
+ }
290
+
291
+ /**
292
+ * Returns the JavaScript helper.
293
+ *
294
+ * @return FacebookJavaScriptHelper
295
+ */
296
+ public function getJavaScriptHelper()
297
+ {
298
+ return new FacebookJavaScriptHelper($this->app, $this->client, $this->defaultGraphVersion);
299
+ }
300
+
301
+ /**
302
+ * Returns the canvas helper.
303
+ *
304
+ * @return FacebookCanvasHelper
305
+ */
306
+ public function getCanvasHelper()
307
+ {
308
+ return new FacebookCanvasHelper($this->app, $this->client, $this->defaultGraphVersion);
309
+ }
310
+
311
+ /**
312
+ * Returns the page tab helper.
313
+ *
314
+ * @return FacebookPageTabHelper
315
+ */
316
+ public function getPageTabHelper()
317
+ {
318
+ return new FacebookPageTabHelper($this->app, $this->client, $this->defaultGraphVersion);
319
+ }
320
+
321
+ /**
322
+ * Sends a GET request to Graph and returns the result.
323
+ *
324
+ * @param string $endpoint
325
+ * @param AccessToken|string|null $accessToken
326
+ * @param string|null $eTag
327
+ * @param string|null $graphVersion
328
+ *
329
+ * @return FacebookResponse
330
+ *
331
+ * @throws FacebookSDKException
332
+ */
333
+ public function get($endpoint, $accessToken = null, $eTag = null, $graphVersion = null)
334
+ {
335
+ return $this->sendRequest(
336
+ 'GET',
337
+ $endpoint,
338
+ $params = [],
339
+ $accessToken,
340
+ $eTag,
341
+ $graphVersion
342
+ );
343
+ }
344
+
345
+ /**
346
+ * Sends a POST request to Graph and returns the result.
347
+ *
348
+ * @param string $endpoint
349
+ * @param array $params
350
+ * @param AccessToken|string|null $accessToken
351
+ * @param string|null $eTag
352
+ * @param string|null $graphVersion
353
+ *
354
+ * @return FacebookResponse
355
+ *
356
+ * @throws FacebookSDKException
357
+ */
358
+ public function post($endpoint, array $params = [], $accessToken = null, $eTag = null, $graphVersion = null)
359
+ {
360
+ return $this->sendRequest(
361
+ 'POST',
362
+ $endpoint,
363
+ $params,
364
+ $accessToken,
365
+ $eTag,
366
+ $graphVersion
367
+ );
368
+ }
369
+
370
+ /**
371
+ * Sends a DELETE request to Graph and returns the result.
372
+ *
373
+ * @param string $endpoint
374
+ * @param array $params
375
+ * @param AccessToken|string|null $accessToken
376
+ * @param string|null $eTag
377
+ * @param string|null $graphVersion
378
+ *
379
+ * @return FacebookResponse
380
+ *
381
+ * @throws FacebookSDKException
382
+ */
383
+ public function delete($endpoint, array $params = [], $accessToken = null, $eTag = null, $graphVersion = null)
384
+ {
385
+ return $this->sendRequest(
386
+ 'DELETE',
387
+ $endpoint,
388
+ $params,
389
+ $accessToken,
390
+ $eTag,
391
+ $graphVersion
392
+ );
393
+ }
394
+
395
+ /**
396
+ * Sends a request to Graph for the next page of results.
397
+ *
398
+ * @param GraphEdge $graphEdge The GraphEdge to paginate over.
399
+ *
400
+ * @return GraphEdge|null
401
+ *
402
+ * @throws FacebookSDKException
403
+ */
404
+ public function next(GraphEdge $graphEdge)
405
+ {
406
+ return $this->getPaginationResults($graphEdge, 'next');
407
+ }
408
+
409
+ /**
410
+ * Sends a request to Graph for the previous page of results.
411
+ *
412
+ * @param GraphEdge $graphEdge The GraphEdge to paginate over.
413
+ *
414
+ * @return GraphEdge|null
415
+ *
416
+ * @throws FacebookSDKException
417
+ */
418
+ public function previous(GraphEdge $graphEdge)
419
+ {
420
+ return $this->getPaginationResults($graphEdge, 'previous');
421
+ }
422
+
423
+ /**
424
+ * Sends a request to Graph for the next page of results.
425
+ *
426
+ * @param GraphEdge $graphEdge The GraphEdge to paginate over.
427
+ * @param string $direction The direction of the pagination: next|previous.
428
+ *
429
+ * @return GraphEdge|null
430
+ *
431
+ * @throws FacebookSDKException
432
+ */
433
+ public function getPaginationResults(GraphEdge $graphEdge, $direction)
434
+ {
435
+ $paginationRequest = $graphEdge->getPaginationRequest($direction);
436
+ if (!$paginationRequest) {
437
+ return null;
438
+ }
439
+
440
+ $this->lastResponse = $this->client->sendRequest($paginationRequest);
441
+
442
+ // Keep the same GraphNode subclass
443
+ $subClassName = $graphEdge->getSubClassName();
444
+ $graphEdge = $this->lastResponse->getGraphEdge($subClassName, false);
445
+
446
+ return count($graphEdge) > 0 ? $graphEdge : null;
447
+ }
448
+
449
+ /**
450
+ * Sends a request to Graph and returns the result.
451
+ *
452
+ * @param string $method
453
+ * @param string $endpoint
454
+ * @param array $params
455
+ * @param AccessToken|string|null $accessToken
456
+ * @param string|null $eTag
457
+ * @param string|null $graphVersion
458
+ *
459
+ * @return FacebookResponse
460
+ *
461
+ * @throws FacebookSDKException
462
+ */
463
+ public function sendRequest($method, $endpoint, array $params = [], $accessToken = null, $eTag = null, $graphVersion = null)
464
+ {
465
+ $accessToken = $accessToken ?: $this->defaultAccessToken;
466
+ $graphVersion = $graphVersion ?: $this->defaultGraphVersion;
467
+ $request = $this->request($method, $endpoint, $params, $accessToken, $eTag, $graphVersion);
468
+
469
+ return $this->lastResponse = $this->client->sendRequest($request);
470
+ }
471
+
472
+ /**
473
+ * Sends a batched request to Graph and returns the result.
474
+ *
475
+ * @param array $requests
476
+ * @param AccessToken|string|null $accessToken
477
+ * @param string|null $graphVersion
478
+ *
479
+ * @return FacebookBatchResponse
480
+ *
481
+ * @throws FacebookSDKException
482
+ */
483
+ public function sendBatchRequest(array $requests, $accessToken = null, $graphVersion = null)
484
+ {
485
+ $accessToken = $accessToken ?: $this->defaultAccessToken;
486
+ $graphVersion = $graphVersion ?: $this->defaultGraphVersion;
487
+ $batchRequest = new FacebookBatchRequest(
488
+ $this->app,
489
+ $requests,
490
+ $accessToken,
491
+ $graphVersion
492
+ );
493
+
494
+ return $this->lastResponse = $this->client->sendBatchRequest($batchRequest);
495
+ }
496
+
497
+ /**
498
+ * Instantiates an empty FacebookBatchRequest entity.
499
+ *
500
+ * @param AccessToken|string|null $accessToken The top-level access token. Requests with no access token
501
+ * will fallback to this.
502
+ * @param string|null $graphVersion The Graph API version to use.
503
+ * @return FacebookBatchRequest
504
+ */
505
+ public function newBatchRequest($accessToken = null, $graphVersion = null)
506
+ {
507
+ $accessToken = $accessToken ?: $this->defaultAccessToken;
508
+ $graphVersion = $graphVersion ?: $this->defaultGraphVersion;
509
+
510
+ return new FacebookBatchRequest(
511
+ $this->app,
512
+ [],
513
+ $accessToken,
514
+ $graphVersion
515
+ );
516
+ }
517
+
518
+ /**
519
+ * Instantiates a new FacebookRequest entity.
520
+ *
521
+ * @param string $method
522
+ * @param string $endpoint
523
+ * @param array $params
524
+ * @param AccessToken|string|null $accessToken
525
+ * @param string|null $eTag
526
+ * @param string|null $graphVersion
527
+ *
528
+ * @return FacebookRequest
529
+ *
530
+ * @throws FacebookSDKException
531
+ */
532
+ public function request($method, $endpoint, array $params = [], $accessToken = null, $eTag = null, $graphVersion = null)
533
+ {
534
+ $accessToken = $accessToken ?: $this->defaultAccessToken;
535
+ $graphVersion = $graphVersion ?: $this->defaultGraphVersion;
536
+
537
+ return new FacebookRequest(
538
+ $this->app,
539
+ $accessToken,
540
+ $method,
541
+ $endpoint,
542
+ $params,
543
+ $eTag,
544
+ $graphVersion
545
+ );
546
+ }
547
+
548
+ /**
549
+ * Factory to create FacebookFile's.
550
+ *
551
+ * @param string $pathToFile
552
+ *
553
+ * @return FacebookFile
554
+ *
555
+ * @throws FacebookSDKException
556
+ */
557
+ public function fileToUpload($pathToFile)
558
+ {
559
+ return new FacebookFile($pathToFile);
560
+ }
561
+
562
+ /**
563
+ * Factory to create FacebookVideo's.
564
+ *
565
+ * @param string $pathToFile
566
+ *
567
+ * @return FacebookVideo
568
+ *
569
+ * @throws FacebookSDKException
570
+ */
571
+ public function videoToUpload($pathToFile)
572
+ {
573
+ return new FacebookVideo($pathToFile);
574
+ }
575
+
576
+ /**
577
+ * Upload a video in chunks.
578
+ *
579
+ * @param int $target The id of the target node before the /videos edge.
580
+ * @param string $pathToFile The full path to the file.
581
+ * @param array $metadata The metadata associated with the video file.
582
+ * @param string|null $accessToken The access token.
583
+ * @param int $maxTransferTries The max times to retry a failed upload chunk.
584
+ * @param string|null $graphVersion The Graph API version to use.
585
+ *
586
+ * @return array
587
+ *
588
+ * @throws FacebookSDKException
589
+ */
590
+ public function uploadVideo($target, $pathToFile, $metadata = [], $accessToken = null, $maxTransferTries = 5, $graphVersion = null)
591
+ {
592
+ $accessToken = $accessToken ?: $this->defaultAccessToken;
593
+ $graphVersion = $graphVersion ?: $this->defaultGraphVersion;
594
+
595
+ $uploader = new FacebookResumableUploader($this->app, $this->client, $accessToken, $graphVersion);
596
+ $endpoint = '/'.$target.'/videos';
597
+ $file = $this->videoToUpload($pathToFile);
598
+ $chunk = $uploader->start($endpoint, $file);
599
+
600
+ do {
601
+ $chunk = $this->maxTriesTransfer($uploader, $endpoint, $chunk, $maxTransferTries);
602
+ } while (!$chunk->isLastChunk());
603
+
604
+ return [
605
+ 'video_id' => $chunk->getVideoId(),
606
+ 'success' => $uploader->finish($endpoint, $chunk->getUploadSessionId(), $metadata),
607
+ ];
608
+ }
609
+
610
+ /**
611
+ * Attempts to upload a chunk of a file in $retryCountdown tries.
612
+ *
613
+ * @param FacebookResumableUploader $uploader
614
+ * @param string $endpoint
615
+ * @param FacebookTransferChunk $chunk
616
+ * @param int $retryCountdown
617
+ *
618
+ * @return FacebookTransferChunk
619
+ *
620
+ * @throws FacebookSDKException
621
+ */
622
+ private function maxTriesTransfer(FacebookResumableUploader $uploader, $endpoint, FacebookTransferChunk $chunk, $retryCountdown)
623
+ {
624
+ $newChunk = $uploader->transfer($endpoint, $chunk, $retryCountdown < 1);
625
+
626
+ if ($newChunk !== $chunk) {
627
+ return $newChunk;
628
+ }
629
+
630
+ $retryCountdown--;
631
+
632
+ // If transfer() returned the same chunk entity, the transfer failed but is resumable.
633
+ return $this->maxTriesTransfer($uploader, $endpoint, $chunk, $retryCountdown);
634
+ }
635
+ }
facebook/facebook/FacebookApp.php ADDED
@@ -0,0 +1,110 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook;
25
+
26
+ use Facebook\Authentication\AccessToken;
27
+ use Facebook\Exceptions\FacebookSDKException;
28
+
29
+ class FacebookApp implements \Serializable
30
+ {
31
+ /**
32
+ * @var string The app ID.
33
+ */
34
+ protected $id;
35
+
36
+ /**
37
+ * @var string The app secret.
38
+ */
39
+ protected $secret;
40
+
41
+ /**
42
+ * @param string $id
43
+ * @param string $secret
44
+ *
45
+ * @throws FacebookSDKException
46
+ */
47
+ public function __construct($id, $secret)
48
+ {
49
+ if (!is_string($id)
50
+ // Keeping this for BC. Integers greater than PHP_INT_MAX will make is_int() return false
51
+ && !is_int($id)) {
52
+ 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.');
53
+ }
54
+ // 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
55
+ $this->id = (string) $id;
56
+ $this->secret = $secret;
57
+ }
58
+
59
+ /**
60
+ * Returns the app ID.
61
+ *
62
+ * @return string
63
+ */
64
+ public function getId()
65
+ {
66
+ return $this->id;
67
+ }
68
+
69
+ /**
70
+ * Returns the app secret.
71
+ *
72
+ * @return string
73
+ */
74
+ public function getSecret()
75
+ {
76
+ return $this->secret;
77
+ }
78
+
79
+ /**
80
+ * Returns an app access token.
81
+ *
82
+ * @return AccessToken
83
+ */
84
+ public function getAccessToken()
85
+ {
86
+ return new AccessToken($this->id . '|' . $this->secret);
87
+ }
88
+
89
+ /**
90
+ * Serializes the FacebookApp entity as a string.
91
+ *
92
+ * @return string
93
+ */
94
+ public function serialize()
95
+ {
96
+ return implode('|', [$this->id, $this->secret]);
97
+ }
98
+
99
+ /**
100
+ * Unserializes a string as a FacebookApp entity.
101
+ *
102
+ * @param string $serialized
103
+ */
104
+ public function unserialize($serialized)
105
+ {
106
+ list($id, $secret) = explode('|', $serialized);
107
+
108
+ $this->__construct($id, $secret);
109
+ }
110
+ }
facebook/facebook/FacebookBatchRequest.php ADDED
@@ -0,0 +1,322 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook;
25
+
26
+ use ArrayIterator;
27
+ use IteratorAggregate;
28
+ use ArrayAccess;
29
+ use Facebook\Authentication\AccessToken;
30
+ use Facebook\Exceptions\FacebookSDKException;
31
+
32
+ /**
33
+ * Class BatchRequest
34
+ *
35
+ * @package Facebook
36
+ */
37
+ class FacebookBatchRequest extends FacebookRequest implements IteratorAggregate, ArrayAccess
38
+ {
39
+ /**
40
+ * @var array An array of FacebookRequest entities to send.
41
+ */
42
+ protected $requests;
43
+
44
+ /**
45
+ * @var array An array of files to upload.
46
+ */
47
+ protected $attachedFiles;
48
+
49
+ /**
50
+ * Creates a new Request entity.
51
+ *
52
+ * @param FacebookApp|null $app
53
+ * @param array $requests
54
+ * @param AccessToken|string|null $accessToken
55
+ * @param string|null $graphVersion
56
+ */
57
+ public function __construct(FacebookApp $app = null, array $requests = [], $accessToken = null, $graphVersion = null)
58
+ {
59
+ parent::__construct($app, $accessToken, 'POST', '', [], null, $graphVersion);
60
+
61
+ $this->add($requests);
62
+ }
63
+
64
+ /**
65
+ * Adds a new request to the array.
66
+ *
67
+ * @param FacebookRequest|array $request
68
+ * @param string|null|array $options Array of batch request options e.g. 'name', 'omit_response_on_success'.
69
+ * If a string is given, it is the value of the 'name' option.
70
+ *
71
+ * @return FacebookBatchRequest
72
+ *
73
+ * @throws \InvalidArgumentException
74
+ */
75
+ public function add($request, $options = null)
76
+ {
77
+ if (is_array($request)) {
78
+ foreach ($request as $key => $req) {
79
+ $this->add($req, $key);
80
+ }
81
+
82
+ return $this;
83
+ }
84
+
85
+ if (!$request instanceof FacebookRequest) {
86
+ throw new \InvalidArgumentException('Argument for add() must be of type array or FacebookRequest.');
87
+ }
88
+
89
+ if (null === $options) {
90
+ $options = [];
91
+ } elseif (!is_array($options)) {
92
+ $options = ['name' => $options];
93
+ }
94
+
95
+ $this->addFallbackDefaults($request);
96
+
97
+ // File uploads
98
+ $attachedFiles = $this->extractFileAttachments($request);
99
+
100
+ $name = isset($options['name']) ? $options['name'] : null;
101
+
102
+ unset($options['name']);
103
+
104
+ $requestToAdd = [
105
+ 'name' => $name,
106
+ 'request' => $request,
107
+ 'options' => $options,
108
+ 'attached_files' => $attachedFiles,
109
+ ];
110
+
111
+ $this->requests[] = $requestToAdd;
112
+
113
+ return $this;
114
+ }
115
+
116
+ /**
117
+ * Ensures that the FacebookApp and access token fall back when missing.
118
+ *
119
+ * @param FacebookRequest $request
120
+ *
121
+ * @throws FacebookSDKException
122
+ */
123
+ public function addFallbackDefaults(FacebookRequest $request)
124
+ {
125
+ if (!$request->getApp()) {
126
+ $app = $this->getApp();
127
+ if (!$app) {
128
+ throw new FacebookSDKException('Missing FacebookApp on FacebookRequest and no fallback detected on FacebookBatchRequest.');
129
+ }
130
+ $request->setApp($app);
131
+ }
132
+
133
+ if (!$request->getAccessToken()) {
134
+ $accessToken = $this->getAccessToken();
135
+ if (!$accessToken) {
136
+ throw new FacebookSDKException('Missing access token on FacebookRequest and no fallback detected on FacebookBatchRequest.');
137
+ }
138
+ $request->setAccessToken($accessToken);
139
+ }
140
+ }
141
+
142
+ /**
143
+ * Extracts the files from a request.
144
+ *
145
+ * @param FacebookRequest $request
146
+ *
147
+ * @return string|null
148
+ *
149
+ * @throws FacebookSDKException
150
+ */
151
+ public function extractFileAttachments(FacebookRequest $request)
152
+ {
153
+ if (!$request->containsFileUploads()) {
154
+ return null;
155
+ }
156
+
157
+ $files = $request->getFiles();
158
+ $fileNames = [];
159
+ foreach ($files as $file) {
160
+ $fileName = uniqid();
161
+ $this->addFile($fileName, $file);
162
+ $fileNames[] = $fileName;
163
+ }
164
+
165
+ $request->resetFiles();
166
+
167
+ // @TODO Does Graph support multiple uploads on one endpoint?
168
+ return implode(',', $fileNames);
169
+ }
170
+
171
+ /**
172
+ * Return the FacebookRequest entities.
173
+ *
174
+ * @return array
175
+ */
176
+ public function getRequests()
177
+ {
178
+ return $this->requests;
179
+ }
180
+
181
+ /**
182
+ * Prepares the requests to be sent as a batch request.
183
+ */
184
+ public function prepareRequestsForBatch()
185
+ {
186
+ $this->validateBatchRequestCount();
187
+
188
+ $params = [
189
+ 'batch' => $this->convertRequestsToJson(),
190
+ 'include_headers' => true,
191
+ ];
192
+ $this->setParams($params);
193
+ }
194
+
195
+ /**
196
+ * Converts the requests into a JSON(P) string.
197
+ *
198
+ * @return string
199
+ */
200
+ public function convertRequestsToJson()
201
+ {
202
+ $requests = [];
203
+ foreach ($this->requests as $request) {
204
+ $options = [];
205
+
206
+ if (null !== $request['name']) {
207
+ $options['name'] = $request['name'];
208
+ }
209
+
210
+ $options += $request['options'];
211
+
212
+ $requests[] = $this->requestEntityToBatchArray($request['request'], $options, $request['attached_files']);
213
+ }
214
+
215
+ return json_encode($requests);
216
+ }
217
+
218
+ /**
219
+ * Validate the request count before sending them as a batch.
220
+ *
221
+ * @throws FacebookSDKException
222
+ */
223
+ public function validateBatchRequestCount()
224
+ {
225
+ $batchCount = count($this->requests);
226
+ if ($batchCount === 0) {
227
+ throw new FacebookSDKException('There are no batch requests to send.');
228
+ } elseif ($batchCount > 50) {
229
+ // Per: https://developers.facebook.com/docs/graph-api/making-multiple-requests#limits
230
+ throw new FacebookSDKException('You cannot send more than 50 batch requests at a time.');
231
+ }
232
+ }
233
+
234
+ /**
235
+ * Converts a Request entity into an array that is batch-friendly.
236
+ *
237
+ * @param FacebookRequest $request The request entity to convert.
238
+ * @param string|null|array $options Array of batch request options e.g. 'name', 'omit_response_on_success'.
239
+ * If a string is given, it is the value of the 'name' option.
240
+ * @param string|null $attachedFiles Names of files associated with the request.
241
+ *
242
+ * @return array
243
+ */
244
+ public function requestEntityToBatchArray(FacebookRequest $request, $options = null, $attachedFiles = null)
245
+ {
246
+
247
+ if (null === $options) {
248
+ $options = [];
249
+ } elseif (!is_array($options)) {
250
+ $options = ['name' => $options];
251
+ }
252
+
253
+ $compiledHeaders = [];
254
+ $headers = $request->getHeaders();
255
+ foreach ($headers as $name => $value) {
256
+ $compiledHeaders[] = $name . ': ' . $value;
257
+ }
258
+
259
+ $batch = [
260
+ 'headers' => $compiledHeaders,
261
+ 'method' => $request->getMethod(),
262
+ 'relative_url' => $request->getUrl(),
263
+ ];
264
+
265
+ // Since file uploads are moved to the root request of a batch request,
266
+ // the child requests will always be URL-encoded.
267
+ $body = $request->getUrlEncodedBody()->getBody();
268
+ if ($body) {
269
+ $batch['body'] = $body;
270
+ }
271
+
272
+ $batch += $options;
273
+
274
+ if (null !== $attachedFiles) {
275
+ $batch['attached_files'] = $attachedFiles;
276
+ }
277
+
278
+ return $batch;
279
+ }
280
+
281
+ /**
282
+ * Get an iterator for the items.
283
+ *
284
+ * @return ArrayIterator
285
+ */
286
+ public function getIterator()
287
+ {
288
+ return new ArrayIterator($this->requests);
289
+ }
290
+
291
+ /**
292
+ * @inheritdoc
293
+ */
294
+ public function offsetSet($offset, $value)
295
+ {
296
+ $this->add($value, $offset);
297
+ }
298
+
299
+ /**
300
+ * @inheritdoc
301
+ */
302
+ public function offsetExists($offset)
303
+ {
304
+ return isset($this->requests[$offset]);
305
+ }
306
+
307
+ /**
308
+ * @inheritdoc
309
+ */
310
+ public function offsetUnset($offset)
311
+ {
312
+ unset($this->requests[$offset]);
313
+ }
314
+
315
+ /**
316
+ * @inheritdoc
317
+ */
318
+ public function offsetGet($offset)
319
+ {
320
+ return isset($this->requests[$offset]) ? $this->requests[$offset] : null;
321
+ }
322
+ }
facebook/facebook/FacebookBatchResponse.php ADDED
@@ -0,0 +1,174 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook;
25
+
26
+ use ArrayIterator;
27
+ use IteratorAggregate;
28
+ use ArrayAccess;
29
+
30
+ /**
31
+ * Class FacebookBatchResponse
32
+ *
33
+ * @package Facebook
34
+ */
35
+ class FacebookBatchResponse extends FacebookResponse implements IteratorAggregate, ArrayAccess
36
+ {
37
+ /**
38
+ * @var FacebookBatchRequest The original entity that made the batch request.
39
+ */
40
+ protected $batchRequest;
41
+
42
+ /**
43
+ * @var array An array of FacebookResponse entities.
44
+ */
45
+ protected $responses = [];
46
+
47
+ /**
48
+ * Creates a new Response entity.
49
+ *
50
+ * @param FacebookBatchRequest $batchRequest
51
+ * @param FacebookResponse $response
52
+ */
53
+ public function __construct(FacebookBatchRequest $batchRequest, FacebookResponse $response)
54
+ {
55
+ $this->batchRequest = $batchRequest;
56
+
57
+ $request = $response->getRequest();
58
+ $body = $response->getBody();
59
+ $httpStatusCode = $response->getHttpStatusCode();
60
+ $headers = $response->getHeaders();
61
+ parent::__construct($request, $body, $httpStatusCode, $headers);
62
+
63
+ $responses = $response->getDecodedBody();
64
+ $this->setResponses($responses);
65
+ }
66
+
67
+ /**
68
+ * Returns an array of FacebookResponse entities.
69
+ *
70
+ * @return array
71
+ */
72
+ public function getResponses()
73
+ {
74
+ return $this->responses;
75
+ }
76
+
77
+ /**
78
+ * The main batch response will be an array of requests so
79
+ * we need to iterate over all the responses.
80
+ *
81
+ * @param array $responses
82
+ */
83
+ public function setResponses(array $responses)
84
+ {
85
+ $this->responses = [];
86
+
87
+ foreach ($responses as $key => $graphResponse) {
88
+ $this->addResponse($key, $graphResponse);
89
+ }
90
+ }
91
+
92
+ /**
93
+ * Add a response to the list.
94
+ *
95
+ * @param int $key
96
+ * @param array|null $response
97
+ */
98
+ public function addResponse($key, $response)
99
+ {
100
+ $originalRequestName = isset($this->batchRequest[$key]['name']) ? $this->batchRequest[$key]['name'] : $key;
101
+ $originalRequest = isset($this->batchRequest[$key]['request']) ? $this->batchRequest[$key]['request'] : null;
102
+
103
+ $httpResponseBody = isset($response['body']) ? $response['body'] : null;
104
+ $httpResponseCode = isset($response['code']) ? $response['code'] : null;
105
+ // @TODO With PHP 5.5 support, this becomes array_column($response['headers'], 'value', 'name')
106
+ $httpResponseHeaders = isset($response['headers']) ? $this->normalizeBatchHeaders($response['headers']) : [];
107
+
108
+ $this->responses[$originalRequestName] = new FacebookResponse(
109
+ $originalRequest,
110
+ $httpResponseBody,
111
+ $httpResponseCode,
112
+ $httpResponseHeaders
113
+ );
114
+ }
115
+
116
+ /**
117
+ * @inheritdoc
118
+ */
119
+ public function getIterator()
120
+ {
121
+ return new ArrayIterator($this->responses);
122
+ }
123
+
124
+ /**
125
+ * @inheritdoc
126
+ */
127
+ public function offsetSet($offset, $value)
128
+ {
129
+ $this->addResponse($offset, $value);
130
+ }
131
+
132
+ /**
133
+ * @inheritdoc
134
+ */
135
+ public function offsetExists($offset)
136
+ {
137
+ return isset($this->responses[$offset]);
138
+ }
139
+
140
+ /**
141
+ * @inheritdoc
142
+ */
143
+ public function offsetUnset($offset)
144
+ {
145
+ unset($this->responses[$offset]);
146
+ }
147
+
148
+ /**
149
+ * @inheritdoc
150
+ */
151
+ public function offsetGet($offset)
152
+ {
153
+ return isset($this->responses[$offset]) ? $this->responses[$offset] : null;
154
+ }
155
+
156
+ /**
157
+ * Converts the batch header array into a standard format.
158
+ * @TODO replace with array_column() when PHP 5.5 is supported.
159
+ *
160
+ * @param array $batchHeaders
161
+ *
162
+ * @return array
163
+ */
164
+ private function normalizeBatchHeaders(array $batchHeaders)
165
+ {
166
+ $headers = [];
167
+
168
+ foreach ($batchHeaders as $header) {
169
+ $headers[$header['name']] = $header['value'];
170
+ }
171
+
172
+ return $headers;
173
+ }
174
+ }
facebook/facebook/FacebookClient.php ADDED
@@ -0,0 +1,250 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook;
25
+
26
+ use Facebook\HttpClients\FacebookHttpClientInterface;
27
+ use Facebook\HttpClients\FacebookCurlHttpClient;
28
+ use Facebook\HttpClients\FacebookStreamHttpClient;
29
+ use Facebook\Exceptions\FacebookSDKException;
30
+
31
+ /**
32
+ * Class FacebookClient
33
+ *
34
+ * @package Facebook
35
+ */
36
+ class FacebookClient
37
+ {
38
+ /**
39
+ * @const string Production Graph API URL.
40
+ */
41
+ const BASE_GRAPH_URL = 'https://graph.facebook.com';
42
+
43
+ /**
44
+ * @const string Graph API URL for video uploads.
45
+ */
46
+ const BASE_GRAPH_VIDEO_URL = 'https://graph-video.facebook.com';
47
+
48
+ /**
49
+ * @const string Beta Graph API URL.
50
+ */
51
+ const BASE_GRAPH_URL_BETA = 'https://graph.beta.facebook.com';
52
+
53
+ /**
54
+ * @const string Beta Graph API URL for video uploads.
55
+ */
56
+ const BASE_GRAPH_VIDEO_URL_BETA = 'https://graph-video.beta.facebook.com';
57
+
58
+ /**
59
+ * @const int The timeout in seconds for a normal request.
60
+ */
61
+ const DEFAULT_REQUEST_TIMEOUT = 60;
62
+
63
+ /**
64
+ * @const int The timeout in seconds for a request that contains file uploads.
65
+ */
66
+ const DEFAULT_FILE_UPLOAD_REQUEST_TIMEOUT = 3600;
67
+
68
+ /**
69
+ * @const int The timeout in seconds for a request that contains video uploads.
70
+ */
71
+ const DEFAULT_VIDEO_UPLOAD_REQUEST_TIMEOUT = 7200;
72
+
73
+ /**
74
+ * @var bool Toggle to use Graph beta url.
75
+ */
76
+ protected $enableBetaMode = false;
77
+
78
+ /**
79
+ * @var FacebookHttpClientInterface HTTP client handler.
80
+ */
81
+ protected $httpClientHandler;
82
+
83
+ /**
84
+ * @var int The number of calls that have been made to Graph.
85
+ */
86
+ public static $requestCount = 0;
87
+
88
+ /**
89
+ * Instantiates a new FacebookClient object.
90
+ *
91
+ * @param FacebookHttpClientInterface|null $httpClientHandler
92
+ * @param boolean $enableBeta
93
+ */
94
+ public function __construct(FacebookHttpClientInterface $httpClientHandler = null, $enableBeta = false)
95
+ {
96
+ $this->httpClientHandler = $httpClientHandler ?: $this->detectHttpClientHandler();
97
+ $this->enableBetaMode = $enableBeta;
98
+ }
99
+
100
+ /**
101
+ * Sets the HTTP client handler.
102
+ *
103
+ * @param FacebookHttpClientInterface $httpClientHandler
104
+ */
105
+ public function setHttpClientHandler(FacebookHttpClientInterface $httpClientHandler)
106
+ {
107
+ $this->httpClientHandler = $httpClientHandler;
108
+ }
109
+
110
+ /**
111
+ * Returns the HTTP client handler.
112
+ *
113
+ * @return FacebookHttpClientInterface
114
+ */
115
+ public function getHttpClientHandler()
116
+ {
117
+ return $this->httpClientHandler;
118
+ }
119
+
120
+ /**
121
+ * Detects which HTTP client handler to use.
122
+ *
123
+ * @return FacebookHttpClientInterface
124
+ */
125
+ public function detectHttpClientHandler()
126
+ {
127
+ return extension_loaded('curl') ? new FacebookCurlHttpClient() : new FacebookStreamHttpClient();
128
+ }
129
+
130
+ /**
131
+ * Toggle beta mode.
132
+ *
133
+ * @param boolean $betaMode
134
+ */
135
+ public function enableBetaMode($betaMode = true)
136
+ {
137
+ $this->enableBetaMode = $betaMode;
138
+ }
139
+
140
+ /**
141
+ * Returns the base Graph URL.
142
+ *
143
+ * @param boolean $postToVideoUrl Post to the video API if videos are being uploaded.
144
+ *
145
+ * @return string
146
+ */
147
+ public function getBaseGraphUrl($postToVideoUrl = false)
148
+ {
149
+ if ($postToVideoUrl) {
150
+ return $this->enableBetaMode ? static::BASE_GRAPH_VIDEO_URL_BETA : static::BASE_GRAPH_VIDEO_URL;
151
+ }
152
+
153
+ return $this->enableBetaMode ? static::BASE_GRAPH_URL_BETA : static::BASE_GRAPH_URL;
154
+ }
155
+
156
+ /**
157
+ * Prepares the request for sending to the client handler.
158
+ *
159
+ * @param FacebookRequest $request
160
+ *
161
+ * @return array
162
+ */
163
+ public function prepareRequestMessage(FacebookRequest $request)
164
+ {
165
+ $postToVideoUrl = $request->containsVideoUploads();
166
+ $url = $this->getBaseGraphUrl($postToVideoUrl) . $request->getUrl();
167
+
168
+ // If we're sending files they should be sent as multipart/form-data
169
+ if ($request->containsFileUploads()) {
170
+ $requestBody = $request->getMultipartBody();
171
+ $request->setHeaders([
172
+ 'Content-Type' => 'multipart/form-data; boundary=' . $requestBody->getBoundary(),
173
+ ]);
174
+ } else {
175
+ $requestBody = $request->getUrlEncodedBody();
176
+ $request->setHeaders([
177
+ 'Content-Type' => 'application/x-www-form-urlencoded',
178
+ ]);
179
+ }
180
+
181
+ return [
182
+ $url,
183
+ $request->getMethod(),
184
+ $request->getHeaders(),
185
+ $requestBody->getBody(),
186
+ ];
187
+ }
188
+
189
+ /**
190
+ * Makes the request to Graph and returns the result.
191
+ *
192
+ * @param FacebookRequest $request
193
+ *
194
+ * @return FacebookResponse
195
+ *
196
+ * @throws FacebookSDKException
197
+ */
198
+ public function sendRequest(FacebookRequest $request)
199
+ {
200
+ if (get_class($request) === 'Facebook\FacebookRequest') {
201
+ $request->validateAccessToken();
202
+ }
203
+
204
+ list($url, $method, $headers, $body) = $this->prepareRequestMessage($request);
205
+
206
+ // Since file uploads can take a while, we need to give more time for uploads
207
+ $timeOut = static::DEFAULT_REQUEST_TIMEOUT;
208
+ if ($request->containsFileUploads()) {
209
+ $timeOut = static::DEFAULT_FILE_UPLOAD_REQUEST_TIMEOUT;
210
+ } elseif ($request->containsVideoUploads()) {
211
+ $timeOut = static::DEFAULT_VIDEO_UPLOAD_REQUEST_TIMEOUT;
212
+ }
213
+
214
+ // Should throw `FacebookSDKException` exception on HTTP client error.
215
+ // Don't catch to allow it to bubble up.
216
+ $rawResponse = $this->httpClientHandler->send($url, $method, $body, $headers, $timeOut);
217
+
218
+ static::$requestCount++;
219
+
220
+ $returnResponse = new FacebookResponse(
221
+ $request,
222
+ $rawResponse->getBody(),
223
+ $rawResponse->getHttpResponseCode(),
224
+ $rawResponse->getHeaders()
225
+ );
226
+
227
+ if ($returnResponse->isError()) {
228
+ throw $returnResponse->getThrownException();
229
+ }
230
+
231
+ return $returnResponse;
232
+ }
233
+
234
+ /**
235
+ * Makes a batched request to Graph and returns the result.
236
+ *
237
+ * @param FacebookBatchRequest $request
238
+ *
239
+ * @return FacebookBatchResponse
240
+ *
241
+ * @throws FacebookSDKException
242
+ */
243
+ public function sendBatchRequest(FacebookBatchRequest $request)
244
+ {
245
+ $request->prepareRequestsForBatch();
246
+ $facebookResponse = $this->sendRequest($request);
247
+
248
+ return new FacebookBatchResponse($request, $facebookResponse);
249
+ }
250
+ }
facebook/facebook/FacebookRequest.php ADDED
@@ -0,0 +1,534 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook;
25
+
26
+ use Facebook\Authentication\AccessToken;
27
+ use Facebook\Url\FacebookUrlManipulator;
28
+ use Facebook\FileUpload\FacebookFile;
29
+ use Facebook\FileUpload\FacebookVideo;
30
+ use Facebook\Http\RequestBodyMultipart;
31
+ use Facebook\Http\RequestBodyUrlEncoded;
32
+ use Facebook\Exceptions\FacebookSDKException;
33
+
34
+ /**
35
+ * Class Request
36
+ *
37
+ * @package Facebook
38
+ */
39
+ class FacebookRequest
40
+ {
41
+ /**
42
+ * @var FacebookApp The Facebook app entity.
43
+ */
44
+ protected $app;
45
+
46
+ /**
47
+ * @var string|null The access token to use for this request.
48
+ */
49
+ protected $accessToken;
50
+
51
+ /**
52
+ * @var string The HTTP method for this request.
53
+ */
54
+ protected $method;
55
+
56
+ /**
57
+ * @var string The Graph endpoint for this request.
58
+ */
59
+ protected $endpoint;
60
+
61
+ /**
62
+ * @var array The headers to send with this request.
63
+ */
64
+ protected $headers = [];
65
+
66
+ /**
67
+ * @var array The parameters to send with this request.
68
+ */
69
+ protected $params = [];
70
+
71
+ /**
72
+ * @var array The files to send with this request.
73
+ */
74
+ protected $files = [];
75
+
76
+ /**
77
+ * @var string ETag to send with this request.
78
+ */
79
+ protected $eTag;
80
+
81
+ /**
82
+ * @var string Graph version to use for this request.
83
+ */
84
+ protected $graphVersion;
85
+
86
+ /**
87
+ * Creates a new Request entity.
88
+ *
89
+ * @param FacebookApp|null $app
90
+ * @param AccessToken|string|null $accessToken
91
+ * @param string|null $method
92
+ * @param string|null $endpoint
93
+ * @param array|null $params
94
+ * @param string|null $eTag
95
+ * @param string|null $graphVersion
96
+ */
97
+ public function __construct(FacebookApp $app = null, $accessToken = null, $method = null, $endpoint = null, array $params = [], $eTag = null, $graphVersion = null)
98
+ {
99
+ $this->setApp($app);
100
+ $this->setAccessToken($accessToken);
101
+ $this->setMethod($method);
102
+ $this->setEndpoint($endpoint);
103
+ $this->setParams($params);
104
+ $this->setETag($eTag);
105
+ $this->graphVersion = $graphVersion ?: Facebook::DEFAULT_GRAPH_VERSION;
106
+ }
107
+
108
+ /**
109
+ * Set the access token for this request.
110
+ *
111
+ * @param AccessToken|string|null
112
+ *
113
+ * @return FacebookRequest
114
+ */
115
+ public function setAccessToken($accessToken)
116
+ {
117
+ $this->accessToken = $accessToken;
118
+ if ($accessToken instanceof AccessToken) {
119
+ $this->accessToken = $accessToken->getValue();
120
+ }
121
+
122
+ return $this;
123
+ }
124
+
125
+ /**
126
+ * Sets the access token with one harvested from a URL or POST params.
127
+ *
128
+ * @param string $accessToken The access token.
129
+ *
130
+ * @return FacebookRequest
131
+ *
132
+ * @throws FacebookSDKException
133
+ */
134
+ public function setAccessTokenFromParams($accessToken)
135
+ {
136
+ $existingAccessToken = $this->getAccessToken();
137
+ if (!$existingAccessToken) {
138
+ $this->setAccessToken($accessToken);
139
+ } elseif ($accessToken !== $existingAccessToken) {
140
+ throw new FacebookSDKException('Access token mismatch. The access token provided in the FacebookRequest and the one provided in the URL or POST params do not match.');
141
+ }
142
+
143
+ return $this;
144
+ }
145
+
146
+ /**
147
+ * Return the access token for this request.
148
+ *
149
+ * @return string|null
150
+ */
151
+ public function getAccessToken()
152
+ {
153
+ return $this->accessToken;
154
+ }
155
+
156
+ /**
157
+ * Return the access token for this request as an AccessToken entity.
158
+ *
159
+ * @return AccessToken|null
160
+ */
161
+ public function getAccessTokenEntity()
162
+ {
163
+ return $this->accessToken ? new AccessToken($this->accessToken) : null;
164
+ }
165
+
166
+ /**
167
+ * Set the FacebookApp entity used for this request.
168
+ *
169
+ * @param FacebookApp|null $app
170
+ */
171
+ public function setApp(FacebookApp $app = null)
172
+ {
173
+ $this->app = $app;
174
+ }
175
+
176
+ /**
177
+ * Return the FacebookApp entity used for this request.
178
+ *
179
+ * @return FacebookApp
180
+ */
181
+ public function getApp()
182
+ {
183
+ return $this->app;
184
+ }
185
+
186
+ /**
187
+ * Generate an app secret proof to sign this request.
188
+ *
189
+ * @return string|null
190
+ */
191
+ public function getAppSecretProof()
192
+ {
193
+ if (!$accessTokenEntity = $this->getAccessTokenEntity()) {
194
+ return null;
195
+ }
196
+
197
+ return $accessTokenEntity->getAppSecretProof($this->app->getSecret());
198
+ }
199
+
200
+ /**
201
+ * Validate that an access token exists for this request.
202
+ *
203
+ * @throws FacebookSDKException
204
+ */
205
+ public function validateAccessToken()
206
+ {
207
+ $accessToken = $this->getAccessToken();
208
+ if (!$accessToken) {
209
+ throw new FacebookSDKException('You must provide an access token.');
210
+ }
211
+ }
212
+
213
+ /**
214
+ * Set the HTTP method for this request.
215
+ *
216
+ * @param string
217
+ */
218
+ public function setMethod($method)
219
+ {
220
+ $this->method = strtoupper($method);
221
+ }
222
+
223
+ /**
224
+ * Return the HTTP method for this request.
225
+ *
226
+ * @return string
227
+ */
228
+ public function getMethod()
229
+ {
230
+ return $this->method;
231
+ }
232
+
233
+ /**
234
+ * Validate that the HTTP method is set.
235
+ *
236
+ * @throws FacebookSDKException
237
+ */
238
+ public function validateMethod()
239
+ {
240
+ if (!$this->method) {
241
+ throw new FacebookSDKException('HTTP method not specified.');
242
+ }
243
+
244
+ if (!in_array($this->method, ['GET', 'POST', 'DELETE'])) {
245
+ throw new FacebookSDKException('Invalid HTTP method specified.');
246
+ }
247
+ }
248
+
249
+ /**
250
+ * Set the endpoint for this request.
251
+ *
252
+ * @param string
253
+ *
254
+ * @return FacebookRequest
255
+ *
256
+ * @throws FacebookSDKException
257
+ */
258
+ public function setEndpoint($endpoint)
259
+ {
260
+ // Harvest the access token from the endpoint to keep things in sync
261
+ $params = FacebookUrlManipulator::getParamsAsArray($endpoint);
262
+ if (isset($params['access_token'])) {
263
+ $this->setAccessTokenFromParams($params['access_token']);
264
+ }
265
+
266
+ // Clean the token & app secret proof from the endpoint.
267
+ $filterParams = ['access_token', 'appsecret_proof'];
268
+ $this->endpoint = FacebookUrlManipulator::removeParamsFromUrl($endpoint, $filterParams);
269
+
270
+ return $this;
271
+ }
272
+
273
+ /**
274
+ * Return the endpoint for this request.
275
+ *
276
+ * @return string
277
+ */
278
+ public function getEndpoint()
279
+ {
280
+ // For batch requests, this will be empty
281
+ return $this->endpoint;
282
+ }
283
+
284
+ /**
285
+ * Generate and return the headers for this request.
286
+ *
287
+ * @return array
288
+ */
289
+ public function getHeaders()
290
+ {
291
+ $headers = static::getDefaultHeaders();
292
+
293
+ if ($this->eTag) {
294
+ $headers['If-None-Match'] = $this->eTag;
295
+ }
296
+
297
+ return array_merge($this->headers, $headers);
298
+ }
299
+
300
+ /**
301
+ * Set the headers for this request.
302
+ *
303
+ * @param array $headers
304
+ */
305
+ public function setHeaders(array $headers)
306
+ {
307
+ $this->headers = array_merge($this->headers, $headers);
308
+ }
309
+
310
+ /**
311
+ * Sets the eTag value.
312
+ *
313
+ * @param string $eTag
314
+ */
315
+ public function setETag($eTag)
316
+ {
317
+ $this->eTag = $eTag;
318
+ }
319
+
320
+ /**
321
+ * Set the params for this request.
322
+ *
323
+ * @param array $params
324
+ *
325
+ * @return FacebookRequest
326
+ *
327
+ * @throws FacebookSDKException
328
+ */
329
+ public function setParams(array $params = [])
330
+ {
331
+ if (isset($params['access_token'])) {
332
+ $this->setAccessTokenFromParams($params['access_token']);
333
+ }
334
+
335
+ // Don't let these buggers slip in.
336
+ unset($params['access_token'], $params['appsecret_proof']);
337
+
338
+ // @TODO Refactor code above with this
339
+ //$params = $this->sanitizeAuthenticationParams($params);
340
+ $params = $this->sanitizeFileParams($params);
341
+ $this->dangerouslySetParams($params);
342
+
343
+ return $this;
344
+ }
345
+
346
+ /**
347
+ * Set the params for this request without filtering them first.
348
+ *
349
+ * @param array $params
350
+ *
351
+ * @return FacebookRequest
352
+ */
353
+ public function dangerouslySetParams(array $params = [])
354
+ {
355
+ $this->params = array_merge($this->params, $params);
356
+
357
+ return $this;
358
+ }
359
+
360
+ /**
361
+ * Iterate over the params and pull out the file uploads.
362
+ *
363
+ * @param array $params
364
+ *
365
+ * @return array
366
+ */
367
+ public function sanitizeFileParams(array $params)
368
+ {
369
+ foreach ($params as $key => $value) {
370
+ if ($value instanceof FacebookFile) {
371
+ $this->addFile($key, $value);
372
+ unset($params[$key]);
373
+ }
374
+ }
375
+
376
+ return $params;
377
+ }
378
+
379
+ /**
380
+ * Add a file to be uploaded.
381
+ *
382
+ * @param string $key
383
+ * @param FacebookFile $file
384
+ */
385
+ public function addFile($key, FacebookFile $file)
386
+ {
387
+ $this->files[$key] = $file;
388
+ }
389
+
390
+ /**
391
+ * Removes all the files from the upload queue.
392
+ */
393
+ public function resetFiles()
394
+ {
395
+ $this->files = [];
396
+ }
397
+
398
+ /**
399
+ * Get the list of files to be uploaded.
400
+ *
401
+ * @return array
402
+ */
403
+ public function getFiles()
404
+ {
405
+ return $this->files;
406
+ }
407
+
408
+ /**
409
+ * Let's us know if there is a file upload with this request.
410
+ *
411
+ * @return boolean
412
+ */
413
+ public function containsFileUploads()
414
+ {
415
+ return !empty($this->files);
416
+ }
417
+
418
+ /**
419
+ * Let's us know if there is a video upload with this request.
420
+ *
421
+ * @return boolean
422
+ */
423
+ public function containsVideoUploads()
424
+ {
425
+ foreach ($this->files as $file) {
426
+ if ($file instanceof FacebookVideo) {
427
+ return true;
428
+ }
429
+ }
430
+
431
+ return false;
432
+ }
433
+
434
+ /**
435
+ * Returns the body of the request as multipart/form-data.
436
+ *
437
+ * @return RequestBodyMultipart
438
+ */
439
+ public function getMultipartBody()
440
+ {
441
+ $params = $this->getPostParams();
442
+
443
+ return new RequestBodyMultipart($params, $this->files);
444
+ }
445
+
446
+ /**
447
+ * Returns the body of the request as URL-encoded.
448
+ *
449
+ * @return RequestBodyUrlEncoded
450
+ */
451
+ public function getUrlEncodedBody()
452
+ {
453
+ $params = $this->getPostParams();
454
+
455
+ return new RequestBodyUrlEncoded($params);
456
+ }
457
+
458
+ /**
459
+ * Generate and return the params for this request.
460
+ *
461
+ * @return array
462
+ */
463
+ public function getParams()
464
+ {
465
+ $params = $this->params;
466
+
467
+ $accessToken = $this->getAccessToken();
468
+ if ($accessToken) {
469
+ $params['access_token'] = $accessToken;
470
+ $params['appsecret_proof'] = $this->getAppSecretProof();
471
+ }
472
+
473
+ return $params;
474
+ }
475
+
476
+ /**
477
+ * Only return params on POST requests.
478
+ *
479
+ * @return array
480
+ */
481
+ public function getPostParams()
482
+ {
483
+ if ($this->getMethod() === 'POST') {
484
+ return $this->getParams();
485
+ }
486
+
487
+ return [];
488
+ }
489
+
490
+ /**
491
+ * The graph version used for this request.
492
+ *
493
+ * @return string
494
+ */
495
+ public function getGraphVersion()
496
+ {
497
+ return $this->graphVersion;
498
+ }
499
+
500
+ /**
501
+ * Generate and return the URL for this request.
502
+ *
503
+ * @return string
504
+ */
505
+ public function getUrl()
506
+ {
507
+ $this->validateMethod();
508
+
509
+ $graphVersion = FacebookUrlManipulator::forceSlashPrefix($this->graphVersion);
510
+ $endpoint = FacebookUrlManipulator::forceSlashPrefix($this->getEndpoint());
511
+
512
+ $url = $graphVersion . $endpoint;
513
+
514
+ if ($this->getMethod() !== 'POST') {
515
+ $params = $this->getParams();
516
+ $url = FacebookUrlManipulator::appendParamsToUrl($url, $params);
517
+ }
518
+
519
+ return $url;
520
+ }
521
+
522
+ /**
523
+ * Return the default headers that every request should use.
524
+ *
525
+ * @return array
526
+ */
527
+ public static function getDefaultHeaders()
528
+ {
529
+ return [
530
+ 'User-Agent' => 'fb-php-' . Facebook::VERSION,
531
+ 'Accept-Encoding' => '*',
532
+ ];
533
+ }
534
+ }
facebook/facebook/FacebookResponse.php ADDED
@@ -0,0 +1,410 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook;
25
+
26
+ use Facebook\GraphNodes\GraphNodeFactory;
27
+ use Facebook\Exceptions\FacebookResponseException;
28
+ use Facebook\Exceptions\FacebookSDKException;
29
+
30
+ /**
31
+ * Class FacebookResponse
32
+ *
33
+ * @package Facebook
34
+ */
35
+ class FacebookResponse
36
+ {
37
+ /**
38
+ * @var int The HTTP status code response from Graph.
39
+ */
40
+ protected $httpStatusCode;
41
+
42
+ /**
43
+ * @var array The headers returned from Graph.
44
+ */
45
+ protected $headers;
46
+
47
+ /**
48
+ * @var string The raw body of the response from Graph.
49
+ */
50
+ protected $body;
51
+
52
+ /**
53
+ * @var array The decoded body of the Graph response.
54
+ */
55
+ protected $decodedBody = [];
56
+
57
+ /**
58
+ * @var FacebookRequest The original request that returned this response.
59
+ */
60
+ protected $request;
61
+
62
+ /**
63
+ * @var FacebookSDKException The exception thrown by this request.
64
+ */
65
+ protected $thrownException;
66
+
67
+ /**
68
+ * Creates a new Response entity.
69
+ *
70
+ * @param FacebookRequest $request
71
+ * @param string|null $body
72
+ * @param int|null $httpStatusCode
73
+ * @param array|null $headers
74
+ */
75
+ public function __construct(FacebookRequest $request, $body = null, $httpStatusCode = null, array $headers = [])
76
+ {
77
+ $this->request = $request;
78
+ $this->body = $body;
79
+ $this->httpStatusCode = $httpStatusCode;
80
+ $this->headers = $headers;
81
+
82
+ $this->decodeBody();
83
+ }
84
+
85
+ /**
86
+ * Return the original request that returned this response.
87
+ *
88
+ * @return FacebookRequest
89
+ */
90
+ public function getRequest()
91
+ {
92
+ return $this->request;
93
+ }
94
+
95
+ /**
96
+ * Return the FacebookApp entity used for this response.
97
+ *
98
+ * @return FacebookApp
99
+ */
100
+ public function getApp()
101
+ {
102
+ return $this->request->getApp();
103
+ }
104
+
105
+ /**
106
+ * Return the access token that was used for this response.
107
+ *
108
+ * @return string|null
109
+ */
110
+ public function getAccessToken()
111
+ {
112
+ return $this->request->getAccessToken();
113
+ }
114
+
115
+ /**
116
+ * Return the HTTP status code for this response.
117
+ *
118
+ * @return int
119
+ */
120
+ public function getHttpStatusCode()
121
+ {
122
+ return $this->httpStatusCode;
123
+ }
124
+
125
+ /**
126
+ * Return the HTTP headers for this response.
127
+ *
128
+ * @return array
129
+ */
130
+ public function getHeaders()
131
+ {
132
+ return $this->headers;
133
+ }
134
+
135
+ /**
136
+ * Return the raw body response.
137
+ *
138
+ * @return string
139
+ */
140
+ public function getBody()
141
+ {
142
+ return $this->body;
143
+ }
144
+
145
+ /**
146
+ * Return the decoded body response.
147
+ *
148
+ * @return array
149
+ */
150
+ public function getDecodedBody()
151
+ {
152
+ return $this->decodedBody;
153
+ }
154
+
155
+ /**
156
+ * Get the app secret proof that was used for this response.
157
+ *
158
+ * @return string|null
159
+ */
160
+ public function getAppSecretProof()
161
+ {
162
+ return $this->request->getAppSecretProof();
163
+ }
164
+
165
+ /**
166
+ * Get the ETag associated with the response.
167
+ *
168
+ * @return string|null
169
+ */
170
+ public function getETag()
171
+ {
172
+ return isset($this->headers['ETag']) ? $this->headers['ETag'] : null;
173
+ }
174
+
175
+ /**
176
+ * Get the version of Graph that returned this response.
177
+ *
178
+ * @return string|null
179
+ */
180
+ public function getGraphVersion()
181
+ {
182
+ return isset($this->headers['Facebook-API-Version']) ? $this->headers['Facebook-API-Version'] : null;
183
+ }
184
+
185
+ /**
186
+ * Returns true if Graph returned an error message.
187
+ *
188
+ * @return boolean
189
+ */
190
+ public function isError()
191
+ {
192
+ return isset($this->decodedBody['error']);
193
+ }
194
+
195
+ /**
196
+ * Throws the exception.
197
+ *
198
+ * @throws FacebookSDKException
199
+ */
200
+ public function throwException()
201
+ {
202
+ throw $this->thrownException;
203
+ }
204
+
205
+ /**
206
+ * Instantiates an exception to be thrown later.
207
+ */
208
+ public function makeException()
209
+ {
210
+ $this->thrownException = FacebookResponseException::create($this);
211
+ }
212
+
213
+ /**
214
+ * Returns the exception that was thrown for this request.
215
+ *
216
+ * @return FacebookResponseException|null
217
+ */
218
+ public function getThrownException()
219
+ {
220
+ return $this->thrownException;
221
+ }
222
+
223
+ /**
224
+ * Convert the raw response into an array if possible.
225
+ *
226
+ * Graph will return 2 types of responses:
227
+ * - JSON(P)
228
+ * Most responses from Graph are JSON(P)
229
+ * - application/x-www-form-urlencoded key/value pairs
230
+ * Happens on the `/oauth/access_token` endpoint when exchanging
231
+ * a short-lived access token for a long-lived access token
232
+ * - And sometimes nothing :/ but that'd be a bug.
233
+ */
234
+ public function decodeBody()
235
+ {
236
+ $this->decodedBody = json_decode($this->body, true);
237
+
238
+ if ($this->decodedBody === null) {
239
+ $this->decodedBody = [];
240
+ parse_str($this->body, $this->decodedBody);
241
+ } elseif (is_bool($this->decodedBody)) {
242
+ // Backwards compatibility for Graph < 2.1.
243
+ // Mimics 2.1 responses.
244
+ // @TODO Remove this after Graph 2.0 is no longer supported
245
+ $this->decodedBody = ['success' => $this->decodedBody];
246
+ } elseif (is_numeric($this->decodedBody)) {
247
+ $this->decodedBody = ['id' => $this->decodedBody];
248
+ }
249
+
250
+ if (!is_array($this->decodedBody)) {
251
+ $this->decodedBody = [];
252
+ }
253
+
254
+ if ($this->isError()) {
255
+ $this->makeException();
256
+ }
257
+ }
258
+
259
+ /**
260
+ * Instantiate a new GraphObject from response.
261
+ *
262
+ * @param string|null $subclassName The GraphNode subclass to cast to.
263
+ *
264
+ * @return \Facebook\GraphNodes\GraphObject
265
+ *
266
+ * @throws FacebookSDKException
267
+ *
268
+ * @deprecated 5.0.0 getGraphObject() has been renamed to getGraphNode()
269
+ * @todo v6: Remove this method
270
+ */
271
+ public function getGraphObject($subclassName = null)
272
+ {
273
+ return $this->getGraphNode($subclassName);
274
+ }
275
+
276
+ /**
277
+ * Instantiate a new GraphNode from response.
278
+ *
279
+ * @param string|null $subclassName The GraphNode subclass to cast to.
280
+ *
281
+ * @return \Facebook\GraphNodes\GraphNode
282
+ *
283
+ * @throws FacebookSDKException
284
+ */
285
+ public function getGraphNode($subclassName = null)
286
+ {
287
+ $factory = new GraphNodeFactory($this);
288
+
289
+ return $factory->makeGraphNode($subclassName);
290
+ }
291
+
292
+ /**
293
+ * Convenience method for creating a GraphAlbum collection.
294
+ *
295
+ * @return \Facebook\GraphNodes\GraphAlbum
296
+ *
297
+ * @throws FacebookSDKException
298
+ */
299
+ public function getGraphAlbum()
300
+ {
301
+ $factory = new GraphNodeFactory($this);
302
+
303
+ return $factory->makeGraphAlbum();
304
+ }
305
+
306
+ /**
307
+ * Convenience method for creating a GraphPage collection.
308
+ *
309
+ * @return \Facebook\GraphNodes\GraphPage
310
+ *
311
+ * @throws FacebookSDKException
312
+ */
313
+ public function getGraphPage()
314
+ {
315
+ $factory = new GraphNodeFactory($this);
316
+
317
+ return $factory->makeGraphPage();
318
+ }
319
+
320
+ /**
321
+ * Convenience method for creating a GraphSessionInfo collection.
322
+ *
323
+ * @return \Facebook\GraphNodes\GraphSessionInfo
324
+ *
325
+ * @throws FacebookSDKException
326
+ */
327
+ public function getGraphSessionInfo()
328
+ {
329
+ $factory = new GraphNodeFactory($this);
330
+
331
+ return $factory->makeGraphSessionInfo();
332
+ }
333
+
334
+ /**
335
+ * Convenience method for creating a GraphUser collection.
336
+ *
337
+ * @return \Facebook\GraphNodes\GraphUser
338
+ *
339
+ * @throws FacebookSDKException
340
+ */
341
+ public function getGraphUser()
342
+ {
343
+ $factory = new GraphNodeFactory($this);
344
+
345
+ return $factory->makeGraphUser();
346
+ }
347
+
348
+ /**
349
+ * Convenience method for creating a GraphEvent collection.
350
+ *
351
+ * @return \Facebook\GraphNodes\GraphEvent
352
+ *
353
+ * @throws FacebookSDKException
354
+ */
355
+ public function getGraphEvent()
356
+ {
357
+ $factory = new GraphNodeFactory($this);
358
+
359
+ return $factory->makeGraphEvent();
360
+ }
361
+
362
+ /**
363
+ * Convenience method for creating a GraphGroup collection.
364
+ *
365
+ * @return \Facebook\GraphNodes\GraphGroup
366
+ *
367
+ * @throws FacebookSDKException
368
+ */
369
+ public function getGraphGroup()
370
+ {
371
+ $factory = new GraphNodeFactory($this);
372
+
373
+ return $factory->makeGraphGroup();
374
+ }
375
+
376
+ /**
377
+ * Instantiate a new GraphList from response.
378
+ *
379
+ * @param string|null $subclassName The GraphNode subclass to cast list items to.
380
+ * @param boolean $auto_prefix Toggle to auto-prefix the subclass name.
381
+ *
382
+ * @return \Facebook\GraphNodes\GraphList
383
+ *
384
+ * @throws FacebookSDKException
385
+ *
386
+ * @deprecated 5.0.0 getGraphList() has been renamed to getGraphEdge()
387
+ * @todo v6: Remove this method
388
+ */
389
+ public function getGraphList($subclassName = null, $auto_prefix = true)
390
+ {
391
+ return $this->getGraphEdge($subclassName, $auto_prefix);
392
+ }
393
+
394
+ /**
395
+ * Instantiate a new GraphEdge from response.
396
+ *
397
+ * @param string|null $subclassName The GraphNode subclass to cast list items to.
398
+ * @param boolean $auto_prefix Toggle to auto-prefix the subclass name.
399
+ *
400
+ * @return \Facebook\GraphNodes\GraphEdge
401
+ *
402
+ * @throws FacebookSDKException
403
+ */
404
+ public function getGraphEdge($subclassName = null, $auto_prefix = true)
405
+ {
406
+ $factory = new GraphNodeFactory($this);
407
+
408
+ return $factory->makeGraphEdge($subclassName, $auto_prefix);
409
+ }
410
+ }
facebook/facebook/FileUpload/FacebookFile.php ADDED
@@ -0,0 +1,169 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook\FileUpload;
25
+
26
+ use Facebook\Exceptions\FacebookSDKException;
27
+
28
+ /**
29
+ * Class FacebookFile
30
+ *
31
+ * @package Facebook
32
+ */
33
+ class FacebookFile
34
+ {
35
+ /**
36
+ * @var string The path to the file on the system.
37
+ */
38
+ protected $path;
39
+
40
+ /**
41
+ * @var int The maximum bytes to read. Defaults to -1 (read all the remaining buffer).
42
+ */
43
+ private $maxLength;
44
+
45
+ /**
46
+ * @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.
47
+ */
48
+ private $offset;
49
+
50
+ /**
51
+ * @var resource The stream pointing to the file.
52
+ */
53
+ protected $stream;
54
+
55
+ /**
56
+ * Creates a new FacebookFile entity.
57
+ *
58
+ * @param string $filePath
59
+ * @param int $maxLength
60
+ * @param int $offset
61
+ *
62
+ * @throws FacebookSDKException
63
+ */
64
+ public function __construct($filePath, $maxLength = -1, $offset = -1)
65
+ {
66
+ $this->path = $filePath;
67
+ $this->maxLength = $maxLength;
68
+ $this->offset = $offset;
69
+ $this->open();
70
+ }
71
+
72
+ /**
73
+ * Closes the stream when destructed.
74
+ */
75
+ public function __destruct()
76
+ {
77
+ $this->close();
78
+ }
79
+
80
+ /**
81
+ * Opens a stream for the file.
82
+ *
83
+ * @throws FacebookSDKException
84
+ */
85
+ public function open()
86
+ {
87
+ if (!$this->isRemoteFile($this->path) && !is_readable($this->path)) {
88
+ throw new FacebookSDKException('Failed to create FacebookFile entity. Unable to read resource: ' . $this->path . '.');
89
+ }
90
+
91
+ $this->stream = fopen($this->path, 'r');
92
+
93
+ if (!$this->stream) {
94
+ throw new FacebookSDKException('Failed to create FacebookFile entity. Unable to open resource: ' . $this->path . '.');
95
+ }
96
+ }
97
+
98
+ /**
99
+ * Stops the file stream.
100
+ */
101
+ public function close()
102
+ {
103
+ if (is_resource($this->stream)) {
104
+ fclose($this->stream);
105
+ }
106
+ }
107
+
108
+ /**
109
+ * Return the contents of the file.
110
+ *
111
+ * @return string
112
+ */
113
+ public function getContents()
114
+ {
115
+ return stream_get_contents($this->stream, $this->maxLength, $this->offset);
116
+ }
117
+
118
+ /**
119
+ * Return the name of the file.
120
+ *
121
+ * @return string
122
+ */
123
+ public function getFileName()
124
+ {
125
+ return basename($this->path);
126
+ }
127
+
128
+ /**
129
+ * Return the path of the file.
130
+ *
131
+ * @return string
132
+ */
133
+ public function getFilePath()
134
+ {
135
+ return $this->path;
136
+ }
137
+
138
+ /**
139
+ * Return the size of the file.
140
+ *
141
+ * @return int
142
+ */
143
+ public function getSize()
144
+ {
145
+ return filesize($this->path);
146
+ }
147
+
148
+ /**
149
+ * Return the mimetype of the file.
150
+ *
151
+ * @return string
152
+ */
153
+ public function getMimetype()
154
+ {
155
+ return Mimetypes::getInstance()->fromFilename($this->path) ?: 'text/plain';
156
+ }
157
+
158
+ /**
159
+ * Returns true if the path to the file is remote.
160
+ *
161
+ * @param string $pathToFile
162
+ *
163
+ * @return boolean
164
+ */
165
+ protected function isRemoteFile($pathToFile)
166
+ {
167
+ return preg_match('/^(https?|ftp):\/\/.*/', $pathToFile) === 1;
168
+ }
169
+ }
facebook/facebook/FileUpload/FacebookResumableUploader.php ADDED
@@ -0,0 +1,167 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook\FileUpload;
25
+
26
+ use Facebook\Authentication\AccessToken;
27
+ use Facebook\Exceptions\FacebookResponseException;
28
+ use Facebook\Exceptions\FacebookResumableUploadException;
29
+ use Facebook\Exceptions\FacebookSDKException;
30
+ use Facebook\FacebookApp;
31
+ use Facebook\FacebookClient;
32
+ use Facebook\FacebookRequest;
33
+
34
+ /**
35
+ * Class FacebookResumableUploader
36
+ *
37
+ * @package Facebook
38
+ */
39
+ class FacebookResumableUploader
40
+ {
41
+ /**
42
+ * @var FacebookApp
43
+ */
44
+ protected $app;
45
+
46
+ /**
47
+ * @var string
48
+ */
49
+ protected $accessToken;
50
+
51
+ /**
52
+ * @var FacebookClient The Facebook client service.
53
+ */
54
+ protected $client;
55
+
56
+ /**
57
+ * @var string Graph version to use for this request.
58
+ */
59
+ protected $graphVersion;
60
+
61
+ /**
62
+ * @param FacebookApp $app
63
+ * @param FacebookClient $client
64
+ * @param AccessToken|string|null $accessToken
65
+ * @param string $graphVersion
66
+ */
67
+ public function __construct(FacebookApp $app, FacebookClient $client, $accessToken, $graphVersion)
68
+ {
69
+ $this->app = $app;
70
+ $this->client = $client;
71
+ $this->accessToken = $accessToken;
72
+ $this->graphVersion = $graphVersion;
73
+ }
74
+
75
+ /**
76
+ * Upload by chunks - start phase
77
+ *
78
+ * @param string $endpoint
79
+ * @param FacebookFile $file
80
+ *
81
+ * @return FacebookTransferChunk
82
+ *
83
+ * @throws FacebookSDKException
84
+ */
85
+ public function start($endpoint, FacebookFile $file)
86
+ {
87
+ $params = [
88
+ 'upload_phase' => 'start',
89
+ 'file_size' => $file->getSize(),
90
+ ];
91
+ $response = $this->sendUploadRequest($endpoint, $params);
92
+
93
+ return new FacebookTransferChunk($file, $response['upload_session_id'], $response['video_id'], $response['start_offset'], $response['end_offset']);
94
+ }
95
+
96
+ /**
97
+ * Upload by chunks - transfer phase
98
+ *
99
+ * @param string $endpoint
100
+ * @param FacebookTransferChunk $chunk
101
+ * @param boolean $allowToThrow
102
+ *
103
+ * @return FacebookTransferChunk
104
+ *
105
+ * @throws FacebookResponseException
106
+ */
107
+ public function transfer($endpoint, FacebookTransferChunk $chunk, $allowToThrow = false)
108
+ {
109
+ $params = [
110
+ 'upload_phase' => 'transfer',
111
+ 'upload_session_id' => $chunk->getUploadSessionId(),
112
+ 'start_offset' => $chunk->getStartOffset(),
113
+ 'video_file_chunk' => $chunk->getPartialFile(),
114
+ ];
115
+
116
+ try {
117
+ $response = $this->sendUploadRequest($endpoint, $params);
118
+ } catch (FacebookResponseException $e) {
119
+ $preException = $e->getPrevious();
120
+ if ($allowToThrow || !$preException instanceof FacebookResumableUploadException) {
121
+ throw $e;
122
+ }
123
+
124
+ // Return the same chunk entity so it can be retried.
125
+ return $chunk;
126
+ }
127
+
128
+ return new FacebookTransferChunk($chunk->getFile(), $chunk->getUploadSessionId(), $chunk->getVideoId(), $response['start_offset'], $response['end_offset']);
129
+ }
130
+
131
+ /**
132
+ * Upload by chunks - finish phase
133
+ *
134
+ * @param string $endpoint
135
+ * @param string $uploadSessionId
136
+ * @param array $metadata The metadata associated with the file.
137
+ *
138
+ * @return boolean
139
+ *
140
+ * @throws FacebookSDKException
141
+ */
142
+ public function finish($endpoint, $uploadSessionId, $metadata = [])
143
+ {
144
+ $params = array_merge($metadata, [
145
+ 'upload_phase' => 'finish',
146
+ 'upload_session_id' => $uploadSessionId,
147
+ ]);
148
+ $response = $this->sendUploadRequest($endpoint, $params);
149
+
150
+ return $response['success'];
151
+ }
152
+
153
+ /**
154
+ * Helper to make a FacebookRequest and send it.
155
+ *
156
+ * @param string $endpoint The endpoint to POST to.
157
+ * @param array $params The params to send with the request.
158
+ *
159
+ * @return array
160
+ */
161
+ private function sendUploadRequest($endpoint, $params = [])
162
+ {
163
+ $request = new FacebookRequest($this->app, $this->accessToken, 'POST', $endpoint, $params, null, $this->graphVersion);
164
+
165
+ return $this->client->sendRequest($request)->getDecodedBody();
166
+ }
167
+ }
facebook/facebook/FileUpload/FacebookTransferChunk.php ADDED
@@ -0,0 +1,133 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook\FileUpload;
25
+
26
+ /**
27
+ * Class FacebookTransferChunk
28
+ *
29
+ * @package Facebook
30
+ */
31
+ class FacebookTransferChunk
32
+ {
33
+ /**
34
+ * @var FacebookFile The file to chunk during upload.
35
+ */
36
+ private $file;
37
+
38
+ /**
39
+ * @var int The ID of the upload session.
40
+ */
41
+ private $uploadSessionId;
42
+
43
+ /**
44
+ * @var int Start byte position of the next file chunk.
45
+ */
46
+ private $startOffset;
47
+
48
+ /**
49
+ * @var int End byte position of the next file chunk.
50
+ */
51
+ private $endOffset;
52
+
53
+ /**
54
+ * @var int The ID of the video.
55
+ */
56
+ private $videoId;
57
+
58
+ /**
59
+ * @param FacebookFile $file
60
+ * @param int $uploadSessionId
61
+ * @param int $videoId
62
+ * @param int $startOffset
63
+ * @param int $endOffset
64
+ */
65
+ public function __construct(FacebookFile $file, $uploadSessionId, $videoId, $startOffset, $endOffset)
66
+ {
67
+ $this->file = $file;
68
+ $this->uploadSessionId = $uploadSessionId;
69
+ $this->videoId = $videoId;
70
+ $this->startOffset = $startOffset;
71
+ $this->endOffset = $endOffset;
72
+ }
73
+
74
+ /**
75
+ * Return the file entity.
76
+ *
77
+ * @return FacebookFile
78
+ */
79
+ public function getFile()
80
+ {
81
+ return $this->file;
82
+ }
83
+
84
+ /**
85
+ * Return a FacebookFile entity with partial content.
86
+ *
87
+ * @return FacebookFile
88
+ */
89
+ public function getPartialFile()
90
+ {
91
+ $maxLength = $this->endOffset - $this->startOffset;
92
+
93
+ return new FacebookFile($this->file->getFilePath(), $maxLength, $this->startOffset);
94
+ }
95
+
96
+ /**
97
+ * Return upload session Id
98
+ *
99
+ * @return int
100
+ */
101
+ public function getUploadSessionId()
102
+ {
103
+ return $this->uploadSessionId;
104
+ }
105
+
106
+ /**
107
+ * Check whether is the last chunk
108
+ *
109
+ * @return bool
110
+ */
111
+ public function isLastChunk()
112
+ {
113
+ return $this->startOffset === $this->endOffset;
114
+ }
115
+
116
+ /**
117
+ * @return int
118
+ */
119
+ public function getStartOffset()
120
+ {
121
+ return $this->startOffset;
122
+ }
123
+
124
+ /**
125
+ * Get uploaded video Id
126
+ *
127
+ * @return int
128
+ */
129
+ public function getVideoId()
130
+ {
131
+ return $this->videoId;
132
+ }
133
+ }
facebook/facebook/FileUpload/FacebookVideo.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook\FileUpload;
25
+
26
+ /**
27
+ * Class FacebookVideo
28
+ *
29
+ * @package Facebook
30
+ */
31
+ class FacebookVideo extends FacebookFile
32
+ {
33
+ }
facebook/facebook/FileUpload/Mimetypes.php ADDED
@@ -0,0 +1,988 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook\FileUpload;
25
+
26
+ /**
27
+ * Provides mappings of file extensions to mimetypes
28
+ *
29
+ * Taken from Guzzle
30
+ *
31
+ * @see https://github.com/guzzle/guzzle/blob/master/src/Mimetypes.php
32
+ *
33
+ * @link http://svn.apache.org/repos/asf/httpd/httpd/branches/1.3.x/conf/mime.types
34
+ */
35
+ class Mimetypes
36
+ {
37
+ /** @var self */
38
+ protected static $instance;
39
+
40
+ /** @var array Mapping of extension to mimetype */
41
+ protected $mimetypes = [
42
+ '3dml' => 'text/vnd.in3d.3dml',
43
+ '3g2' => 'video/3gpp2',
44
+ '3gp' => 'video/3gpp',
45
+ '7z' => 'application/x-7z-compressed',
46
+ 'aab' => 'application/x-authorware-bin',
47
+ 'aac' => 'audio/x-aac',
48
+ 'aam' => 'application/x-authorware-map',
49
+ 'aas' => 'application/x-authorware-seg',
50
+ 'abw' => 'application/x-abiword',
51
+ 'ac' => 'application/pkix-attr-cert',
52
+ 'acc' => 'application/vnd.americandynamics.acc',
53
+ 'ace' => 'application/x-ace-compressed',
54
+ 'acu' => 'application/vnd.acucobol',
55
+ 'acutc' => 'application/vnd.acucorp',
56
+ 'adp' => 'audio/adpcm',
57
+ 'aep' => 'application/vnd.audiograph',
58
+ 'afm' => 'application/x-font-type1',
59
+ 'afp' => 'application/vnd.ibm.modcap',
60
+ 'ahead' => 'application/vnd.ahead.space',
61
+ 'ai' => 'application/postscript',
62
+ 'aif' => 'audio/x-aiff',
63
+ 'aifc' => 'audio/x-aiff',
64
+ 'aiff' => 'audio/x-aiff',
65
+ 'air' => 'application/vnd.adobe.air-application-installer-package+zip',
66
+ 'ait' => 'application/vnd.dvb.ait',
67
+ 'ami' => 'application/vnd.amiga.ami',
68
+ 'apk' => 'application/vnd.android.package-archive',
69
+ 'application' => 'application/x-ms-application',
70
+ 'apr' => 'application/vnd.lotus-approach',
71
+ 'asa' => 'text/plain',
72
+ 'asax' => 'application/octet-stream',
73
+ 'asc' => 'application/pgp-signature',
74
+ 'ascx' => 'text/plain',
75
+ 'asf' => 'video/x-ms-asf',
76
+ 'ashx' => 'text/plain',
77
+ 'asm' => 'text/x-asm',
78
+ 'asmx' => 'text/plain',
79
+ 'aso' => 'application/vnd.accpac.simply.aso',
80
+ 'asp' => 'text/plain',
81
+ 'aspx' => 'text/plain',
82
+ 'asx' => 'video/x-ms-asf',
83
+ 'atc' => 'application/vnd.acucorp',
84
+ 'atom' => 'application/atom+xml',
85
+ 'atomcat' => 'application/atomcat+xml',
86
+ 'atomsvc' => 'application/atomsvc+xml',
87
+ 'atx' => 'application/vnd.antix.game-component',
88
+ 'au' => 'audio/basic',
89
+ 'avi' => 'video/x-msvideo',
90
+ 'aw' => 'application/applixware',
91
+ 'axd' => 'text/plain',
92
+ 'azf' => 'application/vnd.airzip.filesecure.azf',
93
+ 'azs' => 'application/vnd.airzip.filesecure.azs',
94
+ 'azw' => 'application/vnd.amazon.ebook',
95
+ 'bat' => 'application/x-msdownload',
96
+ 'bcpio' => 'application/x-bcpio',
97
+ 'bdf' => 'application/x-font-bdf',
98
+ 'bdm' => 'application/vnd.syncml.dm+wbxml',
99
+ 'bed' => 'application/vnd.realvnc.bed',
100
+ 'bh2' => 'application/vnd.fujitsu.oasysprs',
101
+ 'bin' => 'application/octet-stream',
102
+ 'bmi' => 'application/vnd.bmi',
103
+ 'bmp' => 'image/bmp',
104
+ 'book' => 'application/vnd.framemaker',
105
+ 'box' => 'application/vnd.previewsystems.box',
106
+ 'boz' => 'application/x-bzip2',
107
+ 'bpk' => 'application/octet-stream',
108
+ 'btif' => 'image/prs.btif',
109
+ 'bz' => 'application/x-bzip',
110
+ 'bz2' => 'application/x-bzip2',
111
+ 'c' => 'text/x-c',
112
+ 'c11amc' => 'application/vnd.cluetrust.cartomobile-config',
113
+ 'c11amz' => 'application/vnd.cluetrust.cartomobile-config-pkg',
114
+ 'c4d' => 'application/vnd.clonk.c4group',
115
+ 'c4f' => 'application/vnd.clonk.c4group',
116
+ 'c4g' => 'application/vnd.clonk.c4group',
117
+ 'c4p' => 'application/vnd.clonk.c4group',
118
+ 'c4u' => 'application/vnd.clonk.c4group',
119
+ 'cab' => 'application/vnd.ms-cab-compressed',
120
+ 'car' => 'application/vnd.curl.car',
121
+ 'cat' => 'application/vnd.ms-pki.seccat',
122
+ 'cc' => 'text/x-c',
123
+ 'cct' => 'application/x-director',
124
+ 'ccxml' => 'application/ccxml+xml',
125
+ 'cdbcmsg' => 'application/vnd.contact.cmsg',
126
+ 'cdf' => 'application/x-netcdf',
127
+ 'cdkey' => 'application/vnd.mediastation.cdkey',
128
+ 'cdmia' => 'application/cdmi-capability',
129
+ 'cdmic' => 'application/cdmi-container',
130
+ 'cdmid' => 'application/cdmi-domain',
131
+ 'cdmio' => 'application/cdmi-object',
132
+ 'cdmiq' => 'application/cdmi-queue',
133
+ 'cdx' => 'chemical/x-cdx',
134
+ 'cdxml' => 'application/vnd.chemdraw+xml',
135
+ 'cdy' => 'application/vnd.cinderella',
136
+ 'cer' => 'application/pkix-cert',
137
+ 'cfc' => 'application/x-coldfusion',
138
+ 'cfm' => 'application/x-coldfusion',
139
+ 'cgm' => 'image/cgm',
140
+ 'chat' => 'application/x-chat',
141
+ 'chm' => 'application/vnd.ms-htmlhelp',
142
+ 'chrt' => 'application/vnd.kde.kchart',
143
+ 'cif' => 'chemical/x-cif',
144
+ 'cii' => 'application/vnd.anser-web-certificate-issue-initiation',
145
+ 'cil' => 'application/vnd.ms-artgalry',
146
+ 'cla' => 'application/vnd.claymore',
147
+ 'class' => 'application/java-vm',
148
+ 'clkk' => 'application/vnd.crick.clicker.keyboard',
149
+ 'clkp' => 'application/vnd.crick.clicker.palette',
150
+ 'clkt' => 'application/vnd.crick.clicker.template',
151
+ 'clkw' => 'application/vnd.crick.clicker.wordbank',
152
+ 'clkx' => 'application/vnd.crick.clicker',
153
+ 'clp' => 'application/x-msclip',
154
+ 'cmc' => 'application/vnd.cosmocaller',
155
+ 'cmdf' => 'chemical/x-cmdf',
156
+ 'cml' => 'chemical/x-cml',
157
+ 'cmp' => 'application/vnd.yellowriver-custom-menu',
158
+ 'cmx' => 'image/x-cmx',
159
+ 'cod' => 'application/vnd.rim.cod',
160
+ 'com' => 'application/x-msdownload',
161
+ 'conf' => 'text/plain',
162
+ 'cpio' => 'application/x-cpio',
163
+ 'cpp' => 'text/x-c',
164
+ 'cpt' => 'application/mac-compactpro',
165
+ 'crd' => 'application/x-mscardfile',
166
+ 'crl' => 'application/pkix-crl',
167
+ 'crt' => 'application/x-x509-ca-cert',
168
+ 'cryptonote' => 'application/vnd.rig.cryptonote',
169
+ 'cs' => 'text/plain',
170
+ 'csh' => 'application/x-csh',
171
+ 'csml' => 'chemical/x-csml',
172
+ 'csp' => 'application/vnd.commonspace',
173
+ 'css' => 'text/css',
174
+ 'cst' => 'application/x-director',
175
+ 'csv' => 'text/csv',
176
+ 'cu' => 'application/cu-seeme',
177
+ 'curl' => 'text/vnd.curl',
178
+ 'cww' => 'application/prs.cww',
179
+ 'cxt' => 'application/x-director',
180
+ 'cxx' => 'text/x-c',
181
+ 'dae' => 'model/vnd.collada+xml',
182
+ 'daf' => 'application/vnd.mobius.daf',
183
+ 'dataless' => 'application/vnd.fdsn.seed',
184
+ 'davmount' => 'application/davmount+xml',
185
+ 'dcr' => 'application/x-director',
186
+ 'dcurl' => 'text/vnd.curl.dcurl',
187
+ 'dd2' => 'application/vnd.oma.dd2+xml',
188
+ 'ddd' => 'application/vnd.fujixerox.ddd',
189
+ 'deb' => 'application/x-debian-package',
190
+ 'def' => 'text/plain',
191
+ 'deploy' => 'application/octet-stream',
192
+ 'der' => 'application/x-x509-ca-cert',
193
+ 'dfac' => 'application/vnd.dreamfactory',
194
+ 'dic' => 'text/x-c',
195
+ 'dir' => 'application/x-director',
196
+ 'dis' => 'application/vnd.mobius.dis',
197
+ 'dist' => 'application/octet-stream',
198
+ 'distz' => 'application/octet-stream',
199
+ 'djv' => 'image/vnd.djvu',
200
+ 'djvu' => 'image/vnd.djvu',
201
+ 'dll' => 'application/x-msdownload',
202
+ 'dmg' => 'application/octet-stream',
203
+ 'dms' => 'application/octet-stream',
204
+ 'dna' => 'application/vnd.dna',
205
+ 'doc' => 'application/msword',
206
+ 'docm' => 'application/vnd.ms-word.document.macroenabled.12',
207
+ 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
208
+ 'dot' => 'application/msword',
209
+ 'dotm' => 'application/vnd.ms-word.template.macroenabled.12',
210
+ 'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template',
211
+ 'dp' => 'application/vnd.osgi.dp',
212
+ 'dpg' => 'application/vnd.dpgraph',
213
+ 'dra' => 'audio/vnd.dra',
214
+ 'dsc' => 'text/prs.lines.tag',
215
+ 'dssc' => 'application/dssc+der',
216
+ 'dtb' => 'application/x-dtbook+xml',
217
+ 'dtd' => 'application/xml-dtd',
218
+ 'dts' => 'audio/vnd.dts',
219
+ 'dtshd' => 'audio/vnd.dts.hd',
220
+ 'dump' => 'application/octet-stream',
221
+ 'dvi' => 'application/x-dvi',
222
+ 'dwf' => 'model/vnd.dwf',
223
+ 'dwg' => 'image/vnd.dwg',
224
+ 'dxf' => 'image/vnd.dxf',
225
+ 'dxp' => 'application/vnd.spotfire.dxp',
226
+ 'dxr' => 'application/x-director',
227
+ 'ecelp4800' => 'audio/vnd.nuera.ecelp4800',
228
+ 'ecelp7470' => 'audio/vnd.nuera.ecelp7470',
229
+ 'ecelp9600' => 'audio/vnd.nuera.ecelp9600',
230
+ 'ecma' => 'application/ecmascript',
231
+ 'edm' => 'application/vnd.novadigm.edm',
232
+ 'edx' => 'application/vnd.novadigm.edx',
233
+ 'efif' => 'application/vnd.picsel',
234
+ 'ei6' => 'application/vnd.pg.osasli',
235
+ 'elc' => 'application/octet-stream',
236
+ 'eml' => 'message/rfc822',
237
+ 'emma' => 'application/emma+xml',
238
+ 'eol' => 'audio/vnd.digital-winds',
239
+ 'eot' => 'application/vnd.ms-fontobject',
240
+ 'eps' => 'application/postscript',
241
+ 'epub' => 'application/epub+zip',
242
+ 'es3' => 'application/vnd.eszigno3+xml',
243
+ 'esf' => 'application/vnd.epson.esf',
244
+ 'et3' => 'application/vnd.eszigno3+xml',
245
+ 'etx' => 'text/x-setext',
246
+ 'exe' => 'application/x-msdownload',
247
+ 'exi' => 'application/exi',
248
+ 'ext' => 'application/vnd.novadigm.ext',
249
+ 'ez' => 'application/andrew-inset',
250
+ 'ez2' => 'application/vnd.ezpix-album',
251
+ 'ez3' => 'application/vnd.ezpix-package',
252
+ 'f' => 'text/x-fortran',
253
+ 'f4v' => 'video/x-f4v',
254
+ 'f77' => 'text/x-fortran',
255
+ 'f90' => 'text/x-fortran',
256
+ 'fbs' => 'image/vnd.fastbidsheet',
257
+ 'fcs' => 'application/vnd.isac.fcs',
258
+ 'fdf' => 'application/vnd.fdf',
259
+ 'fe_launch' => 'application/vnd.denovo.fcselayout-link',
260
+ 'fg5' => 'application/vnd.fujitsu.oasysgp',
261
+ 'fgd' => 'application/x-director',
262
+ 'fh' => 'image/x-freehand',
263
+ 'fh4' => 'image/x-freehand',
264
+ 'fh5' => 'image/x-freehand',
265
+ 'fh7' => 'image/x-freehand',
266
+ 'fhc' => 'image/x-freehand',
267
+ 'fig' => 'application/x-xfig',
268
+ 'fli' => 'video/x-fli',
269
+ 'flo' => 'application/vnd.micrografx.flo',
270
+ 'flv' => 'video/x-flv',
271
+ 'flw' => 'application/vnd.kde.kivio',
272
+ 'flx' => 'text/vnd.fmi.flexstor',
273
+ 'fly' => 'text/vnd.fly',
274
+ 'fm' => 'application/vnd.framemaker',
275
+ 'fnc' => 'application/vnd.frogans.fnc',
276
+ 'for' => 'text/x-fortran',
277
+ 'fpx' => 'image/vnd.fpx',
278
+ 'frame' => 'application/vnd.framemaker',
279
+ 'fsc' => 'application/vnd.fsc.weblaunch',
280
+ 'fst' => 'image/vnd.fst',
281
+ 'ftc' => 'application/vnd.fluxtime.clip',
282
+ 'fti' => 'application/vnd.anser-web-funds-transfer-initiation',
283
+ 'fvt' => 'video/vnd.fvt',
284
+ 'fxp' => 'application/vnd.adobe.fxp',
285
+ 'fxpl' => 'application/vnd.adobe.fxp',
286
+ 'fzs' => 'application/vnd.fuzzysheet',
287
+ 'g2w' => 'application/vnd.geoplan',
288
+ 'g3' => 'image/g3fax',
289
+ 'g3w' => 'application/vnd.geospace',
290
+ 'gac' => 'application/vnd.groove-account',
291
+ 'gdl' => 'model/vnd.gdl',
292
+ 'geo' => 'application/vnd.dynageo',
293
+ 'gex' => 'application/vnd.geometry-explorer',
294
+ 'ggb' => 'application/vnd.geogebra.file',
295
+ 'ggt' => 'application/vnd.geogebra.tool',
296
+ 'ghf' => 'application/vnd.groove-help',
297
+ 'gif' => 'image/gif',
298
+ 'gim' => 'application/vnd.groove-identity-message',
299
+ 'gmx' => 'application/vnd.gmx',
300
+ 'gnumeric' => 'application/x-gnumeric',
301
+ 'gph' => 'application/vnd.flographit',
302
+ 'gqf' => 'application/vnd.grafeq',
303
+ 'gqs' => 'application/vnd.grafeq',
304
+ 'gram' => 'application/srgs',
305
+ 'gre' => 'application/vnd.geometry-explorer',
306
+ 'grv' => 'application/vnd.groove-injector',
307
+ 'grxml' => 'application/srgs+xml',
308
+ 'gsf' => 'application/x-font-ghostscript',
309
+ 'gtar' => 'application/x-gtar',
310
+ 'gtm' => 'application/vnd.groove-tool-message',
311
+ 'gtw' => 'model/vnd.gtw',
312
+ 'gv' => 'text/vnd.graphviz',
313
+ 'gxt' => 'application/vnd.geonext',
314
+ 'h' => 'text/x-c',
315
+ 'h261' => 'video/h261',
316
+ 'h263' => 'video/h263',
317
+ 'h264' => 'video/h264',
318
+ 'hal' => 'application/vnd.hal+xml',
319
+ 'hbci' => 'application/vnd.hbci',
320
+ 'hdf' => 'application/x-hdf',
321
+ 'hh' => 'text/x-c',
322
+ 'hlp' => 'application/winhlp',
323
+ 'hpgl' => 'application/vnd.hp-hpgl',
324
+ 'hpid' => 'application/vnd.hp-hpid',
325
+ 'hps' => 'application/vnd.hp-hps',
326
+ 'hqx' => 'application/mac-binhex40',
327
+ 'hta' => 'application/octet-stream',
328
+ 'htc' => 'text/html',
329
+ 'htke' => 'application/vnd.kenameaapp',
330
+ 'htm' => 'text/html',
331
+ 'html' => 'text/html',
332
+ 'hvd' => 'application/vnd.yamaha.hv-dic',
333
+ 'hvp' => 'application/vnd.yamaha.hv-voice',
334
+ 'hvs' => 'application/vnd.yamaha.hv-script',
335
+ 'i2g' => 'application/vnd.intergeo',
336
+ 'icc' => 'application/vnd.iccprofile',
337
+ 'ice' => 'x-conference/x-cooltalk',
338
+ 'icm' => 'application/vnd.iccprofile',
339
+ 'ico' => 'image/x-icon',
340
+ 'ics' => 'text/calendar',
341
+ 'ief' => 'image/ief',
342
+ 'ifb' => 'text/calendar',
343
+ 'ifm' => 'application/vnd.shana.informed.formdata',
344
+ 'iges' => 'model/iges',
345
+ 'igl' => 'application/vnd.igloader',
346
+ 'igm' => 'application/vnd.insors.igm',
347
+ 'igs' => 'model/iges',
348
+ 'igx' => 'application/vnd.micrografx.igx',
349
+ 'iif' => 'application/vnd.shana.informed.interchange',
350
+ 'imp' => 'application/vnd.accpac.simply.imp',
351
+ 'ims' => 'application/vnd.ms-ims',
352
+ 'in' => 'text/plain',
353
+ 'ini' => 'text/plain',
354
+ 'ipfix' => 'application/ipfix',
355
+ 'ipk' => 'application/vnd.shana.informed.package',
356
+ 'irm' => 'application/vnd.ibm.rights-management',
357
+ 'irp' => 'application/vnd.irepository.package+xml',
358
+ 'iso' => 'application/octet-stream',
359
+ 'itp' => 'application/vnd.shana.informed.formtemplate',
360
+ 'ivp' => 'application/vnd.immervision-ivp',
361
+ 'ivu' => 'application/vnd.immervision-ivu',
362
+ 'jad' => 'text/vnd.sun.j2me.app-descriptor',
363
+ 'jam' => 'application/vnd.jam',
364
+ 'jar' => 'application/java-archive',
365
+ 'java' => 'text/x-java-source',
366
+ 'jisp' => 'application/vnd.jisp',
367
+ 'jlt' => 'application/vnd.hp-jlyt',
368
+ 'jnlp' => 'application/x-java-jnlp-file',
369
+ 'joda' => 'application/vnd.joost.joda-archive',
370
+ 'jpe' => 'image/jpeg',
371
+ 'jpeg' => 'image/jpeg',
372
+ 'jpg' => 'image/jpeg',
373
+ 'jpgm' => 'video/jpm',
374
+ 'jpgv' => 'video/jpeg',
375
+ 'jpm' => 'video/jpm',
376
+ 'js' => 'text/javascript',
377
+ 'json' => 'application/json',
378
+ 'kar' => 'audio/midi',
379
+ 'karbon' => 'application/vnd.kde.karbon',
380
+ 'kfo' => 'application/vnd.kde.kformula',
381
+ 'kia' => 'application/vnd.kidspiration',
382
+ 'kml' => 'application/vnd.google-earth.kml+xml',
383
+ 'kmz' => 'application/vnd.google-earth.kmz',
384
+ 'kne' => 'application/vnd.kinar',
385
+ 'knp' => 'application/vnd.kinar',
386
+ 'kon' => 'application/vnd.kde.kontour',
387
+ 'kpr' => 'application/vnd.kde.kpresenter',
388
+ 'kpt' => 'application/vnd.kde.kpresenter',
389
+ 'ksp' => 'application/vnd.kde.kspread',
390
+ 'ktr' => 'application/vnd.kahootz',
391
+ 'ktx' => 'image/ktx',
392
+ 'ktz' => 'application/vnd.kahootz',
393
+ 'kwd' => 'application/vnd.kde.kword',
394
+ 'kwt' => 'application/vnd.kde.kword',
395
+ 'lasxml' => 'application/vnd.las.las+xml',
396
+ 'latex' => 'application/x-latex',
397
+ 'lbd' => 'application/vnd.llamagraphics.life-balance.desktop',
398
+ 'lbe' => 'application/vnd.llamagraphics.life-balance.exchange+xml',
399
+ 'les' => 'application/vnd.hhe.lesson-player',
400
+ 'lha' => 'application/octet-stream',
401
+ 'link66' => 'application/vnd.route66.link66+xml',
402
+ 'list' => 'text/plain',
403
+ 'list3820' => 'application/vnd.ibm.modcap',
404
+ 'listafp' => 'application/vnd.ibm.modcap',
405
+ 'log' => 'text/plain',
406
+ 'lostxml' => 'application/lost+xml',
407
+ 'lrf' => 'application/octet-stream',
408
+ 'lrm' => 'application/vnd.ms-lrm',
409
+ 'ltf' => 'application/vnd.frogans.ltf',
410
+ 'lvp' => 'audio/vnd.lucent.voice',
411
+ 'lwp' => 'application/vnd.lotus-wordpro',
412
+ 'lzh' => 'application/octet-stream',
413
+ 'm13' => 'application/x-msmediaview',
414
+ 'm14' => 'application/x-msmediaview',
415
+ 'm1v' => 'video/mpeg',
416
+ 'm21' => 'application/mp21',
417
+ 'm2a' => 'audio/mpeg',
418
+ 'm2v' => 'video/mpeg',
419
+ 'm3a' => 'audio/mpeg',
420
+ 'm3u' => 'audio/x-mpegurl',
421
+ 'm3u8' => 'application/vnd.apple.mpegurl',
422
+ 'm4a' => 'audio/mp4',
423
+ 'm4u' => 'video/vnd.mpegurl',
424
+ 'm4v' => 'video/mp4',
425
+ 'ma' => 'application/mathematica',
426
+ 'mads' => 'application/mads+xml',
427
+ 'mag' => 'application/vnd.ecowin.chart',
428
+ 'maker' => 'application/vnd.framemaker',
429
+ 'man' => 'text/troff',
430
+ 'mathml' => 'application/mathml+xml',
431
+ 'mb' => 'application/mathematica',
432
+ 'mbk' => 'application/vnd.mobius.mbk',
433
+ 'mbox' => 'application/mbox',
434
+ 'mc1' => 'application/vnd.medcalcdata',
435
+ 'mcd' => 'application/vnd.mcd',
436
+ 'mcurl' => 'text/vnd.curl.mcurl',
437
+ 'mdb' => 'application/x-msaccess',
438
+ 'mdi' => 'image/vnd.ms-modi',
439
+ 'me' => 'text/troff',
440
+ 'mesh' => 'model/mesh',
441
+ 'meta4' => 'application/metalink4+xml',
442
+ 'mets' => 'application/mets+xml',
443
+ 'mfm' => 'application/vnd.mfmp',
444
+ 'mgp' => 'application/vnd.osgeo.mapguide.package',
445
+ 'mgz' => 'application/vnd.proteus.magazine',
446
+ 'mid' => 'audio/midi',
447
+ 'midi' => 'audio/midi',
448
+ 'mif' => 'application/vnd.mif',
449
+ 'mime' => 'message/rfc822',
450
+ 'mj2' => 'video/mj2',
451
+ 'mjp2' => 'video/mj2',
452
+ 'mlp' => 'application/vnd.dolby.mlp',
453
+ 'mmd' => 'application/vnd.chipnuts.karaoke-mmd',
454
+ 'mmf' => 'application/vnd.smaf',
455
+ 'mmr' => 'image/vnd.fujixerox.edmics-mmr',
456
+ 'mny' => 'application/x-msmoney',
457
+ 'mobi' => 'application/x-mobipocket-ebook',
458
+ 'mods' => 'application/mods+xml',
459
+ 'mov' => 'video/quicktime',
460
+ 'movie' => 'video/x-sgi-movie',
461
+ 'mp2' => 'audio/mpeg',
462
+ 'mp21' => 'application/mp21',
463
+ 'mp2a' => 'audio/mpeg',
464
+ 'mp3' => 'audio/mpeg',
465
+ 'mp4' => 'video/mp4',
466
+ 'mp4a' => 'audio/mp4',
467
+ 'mp4s' => 'application/mp4',
468
+ 'mp4v' => 'video/mp4',
469
+ 'mpc' => 'application/vnd.mophun.certificate',
470
+ 'mpe' => 'video/mpeg',
471
+ 'mpeg' => 'video/mpeg',
472
+ 'mpg' => 'video/mpeg',
473
+ 'mpg4' => 'video/mp4',
474
+ 'mpga' => 'audio/mpeg',
475
+ 'mpkg' => 'application/vnd.apple.installer+xml',
476
+ 'mpm' => 'application/vnd.blueice.multipass',
477
+ 'mpn' => 'application/vnd.mophun.application',
478
+ 'mpp' => 'application/vnd.ms-project',
479
+ 'mpt' => 'application/vnd.ms-project',
480
+ 'mpy' => 'application/vnd.ibm.minipay',
481
+ 'mqy' => 'application/vnd.mobius.mqy',
482
+ 'mrc' => 'application/marc',
483
+ 'mrcx' => 'application/marcxml+xml',
484
+ 'ms' => 'text/troff',
485
+ 'mscml' => 'application/mediaservercontrol+xml',
486
+ 'mseed' => 'application/vnd.fdsn.mseed',
487
+ 'mseq' => 'application/vnd.mseq',
488
+ 'msf' => 'application/vnd.epson.msf',
489
+ 'msh' => 'model/mesh',
490
+ 'msi' => 'application/x-msdownload',
491
+ 'msl' => 'application/vnd.mobius.msl',
492
+ 'msty' => 'application/vnd.muvee.style',
493
+ 'mts' => 'model/vnd.mts',
494
+ 'mus' => 'application/vnd.musician',
495
+ 'musicxml' => 'application/vnd.recordare.musicxml+xml',
496
+ 'mvb' => 'application/x-msmediaview',
497
+ 'mwf' => 'application/vnd.mfer',
498
+ 'mxf' => 'application/mxf',
499
+ 'mxl' => 'application/vnd.recordare.musicxml',
500
+ 'mxml' => 'application/xv+xml',
501
+ 'mxs' => 'application/vnd.triscape.mxs',
502
+ 'mxu' => 'video/vnd.mpegurl',
503
+ 'n-gage' => 'application/vnd.nokia.n-gage.symbian.install',
504
+ 'n3' => 'text/n3',
505
+ 'nb' => 'application/mathematica',
506
+ 'nbp' => 'application/vnd.wolfram.player',
507
+ 'nc' => 'application/x-netcdf',
508
+ 'ncx' => 'application/x-dtbncx+xml',
509
+ 'ngdat' => 'application/vnd.nokia.n-gage.data',
510
+ 'nlu' => 'application/vnd.neurolanguage.nlu',
511
+ 'nml' => 'application/vnd.enliven',
512
+ 'nnd' => 'application/vnd.noblenet-directory',
513
+ 'nns' => 'application/vnd.noblenet-sealer',
514
+ 'nnw' => 'application/vnd.noblenet-web',
515
+ 'npx' => 'image/vnd.net-fpx',
516
+ 'nsf' => 'application/vnd.lotus-notes',
517
+ 'oa2' => 'application/vnd.fujitsu.oasys2',
518
+ 'oa3' => 'application/vnd.fujitsu.oasys3',
519
+ 'oas' => 'application/vnd.fujitsu.oasys',
520
+ 'obd' => 'application/x-msbinder',
521
+ 'oda' => 'application/oda',
522
+ 'odb' => 'application/vnd.oasis.opendocument.database',
523
+ 'odc' => 'application/vnd.oasis.opendocument.chart',
524
+ 'odf' => 'application/vnd.oasis.opendocument.formula',
525
+ 'odft' => 'application/vnd.oasis.opendocument.formula-template',
526
+ 'odg' => 'application/vnd.oasis.opendocument.graphics',
527
+ 'odi' => 'application/vnd.oasis.opendocument.image',
528
+ 'odm' => 'application/vnd.oasis.opendocument.text-master',
529
+ 'odp' => 'application/vnd.oasis.opendocument.presentation',
530
+ 'ods' => 'application/vnd.oasis.opendocument.spreadsheet',
531
+ 'odt' => 'application/vnd.oasis.opendocument.text',
532
+ 'oga' => 'audio/ogg',
533
+ 'ogg' => 'audio/ogg',
534
+ 'ogv' => 'video/ogg',
535
+ 'ogx' => 'application/ogg',
536
+ 'onepkg' => 'application/onenote',
537
+ 'onetmp' => 'application/onenote',
538
+ 'onetoc' => 'application/onenote',
539
+ 'onetoc2' => 'application/onenote',
540
+ 'opf' => 'application/oebps-package+xml',
541
+ 'oprc' => 'application/vnd.palm',
542
+ 'org' => 'application/vnd.lotus-organizer',
543
+ 'osf' => 'application/vnd.yamaha.openscoreformat',
544
+ 'osfpvg' => 'application/vnd.yamaha.openscoreformat.osfpvg+xml',
545
+ 'otc' => 'application/vnd.oasis.opendocument.chart-template',
546
+ 'otf' => 'application/x-font-otf',
547
+ 'otg' => 'application/vnd.oasis.opendocument.graphics-template',
548
+ 'oth' => 'application/vnd.oasis.opendocument.text-web',
549
+ 'oti' => 'application/vnd.oasis.opendocument.image-template',
550
+ 'otp' => 'application/vnd.oasis.opendocument.presentation-template',
551
+ 'ots' => 'application/vnd.oasis.opendocument.spreadsheet-template',
552
+ 'ott' => 'application/vnd.oasis.opendocument.text-template',
553
+ 'oxt' => 'application/vnd.openofficeorg.extension',
554
+ 'p' => 'text/x-pascal',
555
+ 'p10' => 'application/pkcs10',
556
+ 'p12' => 'application/x-pkcs12',
557
+ 'p7b' => 'application/x-pkcs7-certificates',
558
+ 'p7c' => 'application/pkcs7-mime',
559
+ 'p7m' => 'application/pkcs7-mime',
560
+ 'p7r' => 'application/x-pkcs7-certreqresp',
561
+ 'p7s' => 'application/pkcs7-signature',
562
+ 'p8' => 'application/pkcs8',
563
+ 'pas' => 'text/x-pascal',
564
+ 'paw' => 'application/vnd.pawaafile',
565
+ 'pbd' => 'application/vnd.powerbuilder6',
566
+ 'pbm' => 'image/x-portable-bitmap',
567
+ 'pcf' => 'application/x-font-pcf',
568
+ 'pcl' => 'application/vnd.hp-pcl',
569
+ 'pclxl' => 'application/vnd.hp-pclxl',
570
+ 'pct' => 'image/x-pict',
571
+ 'pcurl' => 'application/vnd.curl.pcurl',
572
+ 'pcx' => 'image/x-pcx',
573
+ 'pdb' => 'application/vnd.palm',
574
+ 'pdf' => 'application/pdf',
575
+ 'pfa' => 'application/x-font-type1',
576
+ 'pfb' => 'application/x-font-type1',
577
+ 'pfm' => 'application/x-font-type1',
578
+ 'pfr' => 'application/font-tdpfr',
579
+ 'pfx' => 'application/x-pkcs12',
580
+ 'pgm' => 'image/x-portable-graymap',
581
+ 'pgn' => 'application/x-chess-pgn',
582
+ 'pgp' => 'application/pgp-encrypted',
583
+ 'php' => 'text/x-php',
584
+ 'phps' => 'application/x-httpd-phps',
585
+ 'pic' => 'image/x-pict',
586
+ 'pkg' => 'application/octet-stream',
587
+ 'pki' => 'application/pkixcmp',
588
+ 'pkipath' => 'application/pkix-pkipath',
589
+ 'plb' => 'application/vnd.3gpp.pic-bw-large',
590
+ 'plc' => 'application/vnd.mobius.plc',
591
+ 'plf' => 'application/vnd.pocketlearn',
592
+ 'pls' => 'application/pls+xml',
593
+ 'pml' => 'application/vnd.ctc-posml',
594
+ 'png' => 'image/png',
595
+ 'pnm' => 'image/x-portable-anymap',
596
+ 'portpkg' => 'application/vnd.macports.portpkg',
597
+ 'pot' => 'application/vnd.ms-powerpoint',
598
+ 'potm' => 'application/vnd.ms-powerpoint.template.macroenabled.12',
599
+ 'potx' => 'application/vnd.openxmlformats-officedocument.presentationml.template',
600
+ 'ppam' => 'application/vnd.ms-powerpoint.addin.macroenabled.12',
601
+ 'ppd' => 'application/vnd.cups-ppd',
602
+ 'ppm' => 'image/x-portable-pixmap',
603
+ 'pps' => 'application/vnd.ms-powerpoint',
604
+ 'ppsm' => 'application/vnd.ms-powerpoint.slideshow.macroenabled.12',
605
+ 'ppsx' => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow',
606
+ 'ppt' => 'application/vnd.ms-powerpoint',
607
+ 'pptm' => 'application/vnd.ms-powerpoint.presentation.macroenabled.12',
608
+ 'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
609
+ 'pqa' => 'application/vnd.palm',
610
+ 'prc' => 'application/x-mobipocket-ebook',
611
+ 'pre' => 'application/vnd.lotus-freelance',
612
+ 'prf' => 'application/pics-rules',
613
+ 'ps' => 'application/postscript',
614
+ 'psb' => 'application/vnd.3gpp.pic-bw-small',
615
+ 'psd' => 'image/vnd.adobe.photoshop',
616
+ 'psf' => 'application/x-font-linux-psf',
617
+ 'pskcxml' => 'application/pskc+xml',
618
+ 'ptid' => 'application/vnd.pvi.ptid1',
619
+ 'pub' => 'application/x-mspublisher',
620
+ 'pvb' => 'application/vnd.3gpp.pic-bw-var',
621
+ 'pwn' => 'application/vnd.3m.post-it-notes',
622
+ 'pya' => 'audio/vnd.ms-playready.media.pya',
623
+ 'pyv' => 'video/vnd.ms-playready.media.pyv',
624
+ 'qam' => 'application/vnd.epson.quickanime',
625
+ 'qbo' => 'application/vnd.intu.qbo',
626
+ 'qfx' => 'application/vnd.intu.qfx',
627
+ 'qps' => 'application/vnd.publishare-delta-tree',
628
+ 'qt' => 'video/quicktime',
629
+ 'qwd' => 'application/vnd.quark.quarkxpress',
630
+ 'qwt' => 'application/vnd.quark.quarkxpress',
631
+ 'qxb' => 'application/vnd.quark.quarkxpress',
632
+ 'qxd' => 'application/vnd.quark.quarkxpress',
633
+ 'qxl' => 'application/vnd.quark.quarkxpress',
634
+ 'qxt' => 'application/vnd.quark.quarkxpress',
635
+ 'ra' => 'audio/x-pn-realaudio',
636
+ 'ram' => 'audio/x-pn-realaudio',
637
+ 'rar' => 'application/x-rar-compressed',
638
+ 'ras' => 'image/x-cmu-raster',
639
+ 'rb' => 'text/plain',
640
+ 'rcprofile' => 'application/vnd.ipunplugged.rcprofile',
641
+ 'rdf' => 'application/rdf+xml',
642
+ 'rdz' => 'application/vnd.data-vision.rdz',
643
+ 'rep' => 'application/vnd.businessobjects',
644
+ 'res' => 'application/x-dtbresource+xml',
645
+ 'resx' => 'text/xml',
646
+ 'rgb' => 'image/x-rgb',
647
+ 'rif' => 'application/reginfo+xml',
648
+ 'rip' => 'audio/vnd.rip',
649
+ 'rl' => 'application/resource-lists+xml',
650
+ 'rlc' => 'image/vnd.fujixerox.edmics-rlc',
651
+ 'rld' => 'application/resource-lists-diff+xml',
652
+ 'rm' => 'application/vnd.rn-realmedia',
653
+ 'rmi' => 'audio/midi',
654
+ 'rmp' => 'audio/x-pn-realaudio-plugin',
655
+ 'rms' => 'application/vnd.jcp.javame.midlet-rms',
656
+ 'rnc' => 'application/relax-ng-compact-syntax',
657
+ 'roff' => 'text/troff',
658
+ 'rp9' => 'application/vnd.cloanto.rp9',
659
+ 'rpss' => 'application/vnd.nokia.radio-presets',
660
+ 'rpst' => 'application/vnd.nokia.radio-preset',
661
+ 'rq' => 'application/sparql-query',
662
+ 'rs' => 'application/rls-services+xml',
663
+ 'rsd' => 'application/rsd+xml',
664
+ 'rss' => 'application/rss+xml',
665
+ 'rtf' => 'application/rtf',
666
+ 'rtx' => 'text/richtext',
667
+ 's' => 'text/x-asm',
668
+ 'saf' => 'application/vnd.yamaha.smaf-audio',
669
+ 'sbml' => 'application/sbml+xml',
670
+ 'sc' => 'application/vnd.ibm.secure-container',
671
+ 'scd' => 'application/x-msschedule',
672
+ 'scm' => 'application/vnd.lotus-screencam',
673
+ 'scq' => 'application/scvp-cv-request',
674
+ 'scs' => 'application/scvp-cv-response',
675
+ 'scurl' => 'text/vnd.curl.scurl',
676
+ 'sda' => 'application/vnd.stardivision.draw',
677
+ 'sdc' => 'application/vnd.stardivision.calc',
678
+ 'sdd' => 'application/vnd.stardivision.impress',
679
+ 'sdkd' => 'application/vnd.solent.sdkm+xml',
680
+ 'sdkm' => 'application/vnd.solent.sdkm+xml',
681
+ 'sdp' => 'application/sdp',
682
+ 'sdw' => 'application/vnd.stardivision.writer',
683
+ 'see' => 'application/vnd.seemail',
684
+ 'seed' => 'application/vnd.fdsn.seed',
685
+ 'sema' => 'application/vnd.sema',
686
+ 'semd' => 'application/vnd.semd',
687
+ 'semf' => 'application/vnd.semf',
688
+ 'ser' => 'application/java-serialized-object',
689
+ 'setpay' => 'application/set-payment-initiation',
690
+ 'setreg' => 'application/set-registration-initiation',
691
+ 'sfd-hdstx' => 'application/vnd.hydrostatix.sof-data',
692
+ 'sfs' => 'application/vnd.spotfire.sfs',
693
+ 'sgl' => 'application/vnd.stardivision.writer-global',
694
+ 'sgm' => 'text/sgml',
695
+ 'sgml' => 'text/sgml',
696
+ 'sh' => 'application/x-sh',
697
+ 'shar' => 'application/x-shar',
698
+ 'shf' => 'application/shf+xml',
699
+ 'sig' => 'application/pgp-signature',
700
+ 'silo' => 'model/mesh',
701
+ 'sis' => 'application/vnd.symbian.install',
702
+ 'sisx' => 'application/vnd.symbian.install',
703
+ 'sit' => 'application/x-stuffit',
704
+ 'sitx' => 'application/x-stuffitx',
705
+ 'skd' => 'application/vnd.koan',
706
+ 'skm' => 'application/vnd.koan',
707
+ 'skp' => 'application/vnd.koan',
708
+ 'skt' => 'application/vnd.koan',
709
+ 'sldm' => 'application/vnd.ms-powerpoint.slide.macroenabled.12',
710
+ 'sldx' => 'application/vnd.openxmlformats-officedocument.presentationml.slide',
711
+ 'slt' => 'application/vnd.epson.salt',
712
+ 'sm' => 'application/vnd.stepmania.stepchart',
713
+ 'smf' => 'application/vnd.stardivision.math',
714
+ 'smi' => 'application/smil+xml',
715
+ 'smil' => 'application/smil+xml',
716
+ 'snd' => 'audio/basic',
717
+ 'snf' => 'application/x-font-snf',
718
+ 'so' => 'application/octet-stream',
719
+ 'spc' => 'application/x-pkcs7-certificates',
720
+ 'spf' => 'application/vnd.yamaha.smaf-phrase',
721
+ 'spl' => 'application/x-futuresplash',
722
+ 'spot' => 'text/vnd.in3d.spot',
723
+ 'spp' => 'application/scvp-vp-response',
724
+ 'spq' => 'application/scvp-vp-request',
725
+ 'spx' => 'audio/ogg',
726
+ 'src' => 'application/x-wais-source',
727
+ 'srt' => 'application/octet-stream',
728
+ 'sru' => 'application/sru+xml',
729
+ 'srx' => 'application/sparql-results+xml',
730
+ 'sse' => 'application/vnd.kodak-descriptor',
731
+ 'ssf' => 'application/vnd.epson.ssf',
732
+ 'ssml' => 'application/ssml+xml',
733
+ 'st' => 'application/vnd.sailingtracker.track',
734
+ 'stc' => 'application/vnd.sun.xml.calc.template',
735
+ 'std' => 'application/vnd.sun.xml.draw.template',
736
+ 'stf' => 'application/vnd.wt.stf',
737
+ 'sti' => 'application/vnd.sun.xml.impress.template',
738
+ 'stk' => 'application/hyperstudio',
739
+ 'stl' => 'application/vnd.ms-pki.stl',
740
+ 'str' => 'application/vnd.pg.format',
741
+ 'stw' => 'application/vnd.sun.xml.writer.template',
742
+ 'sub' => 'image/vnd.dvb.subtitle',
743
+ 'sus' => 'application/vnd.sus-calendar',
744
+ 'susp' => 'application/vnd.sus-calendar',
745
+ 'sv4cpio' => 'application/x-sv4cpio',
746
+ 'sv4crc' => 'application/x-sv4crc',
747
+ 'svc' => 'application/vnd.dvb.service',
748
+ 'svd' => 'application/vnd.svd',
749
+ 'svg' => 'image/svg+xml',
750
+ 'svgz' => 'image/svg+xml',
751
+ 'swa' => 'application/x-director',
752
+ 'swf' => 'application/x-shockwave-flash',
753
+ 'swi' => 'application/vnd.aristanetworks.swi',
754
+ 'sxc' => 'application/vnd.sun.xml.calc',
755
+ 'sxd' => 'application/vnd.sun.xml.draw',
756
+ 'sxg' => 'application/vnd.sun.xml.writer.global',
757
+ 'sxi' => 'application/vnd.sun.xml.impress',
758
+ 'sxm' => 'application/vnd.sun.xml.math',
759
+ 'sxw' => 'application/vnd.sun.xml.writer',
760
+ 't' => 'text/troff',
761
+ 'tao' => 'application/vnd.tao.intent-module-archive',
762
+ 'tar' => 'application/x-tar',
763
+ 'tcap' => 'application/vnd.3gpp2.tcap',
764
+ 'tcl' => 'application/x-tcl',
765
+ 'teacher' => 'application/vnd.smart.teacher',
766
+ 'tei' => 'application/tei+xml',
767
+ 'teicorpus' => 'application/tei+xml',
768
+ 'tex' => 'application/x-tex',
769
+ 'texi' => 'application/x-texinfo',
770
+ 'texinfo' => 'application/x-texinfo',
771
+ 'text' => 'text/plain',
772
+ 'tfi' => 'application/thraud+xml',
773
+ 'tfm' => 'application/x-tex-tfm',
774
+ 'thmx' => 'application/vnd.ms-officetheme',
775
+ 'tif' => 'image/tiff',
776
+ 'tiff' => 'image/tiff',
777
+ 'tmo' => 'application/vnd.tmobile-livetv',
778
+ 'torrent' => 'application/x-bittorrent',
779
+ 'tpl' => 'application/vnd.groove-tool-template',
780
+ 'tpt' => 'application/vnd.trid.tpt',
781
+ 'tr' => 'text/troff',
782
+ 'tra' => 'application/vnd.trueapp',
783
+ 'trm' => 'application/x-msterminal',
784
+ 'tsd' => 'application/timestamped-data',
785
+ 'tsv' => 'text/tab-separated-values',
786
+ 'ttc' => 'application/x-font-ttf',
787
+ 'ttf' => 'application/x-font-ttf',
788
+ 'ttl' => 'text/turtle',
789
+ 'twd' => 'application/vnd.simtech-mindmapper',
790
+ 'twds' => 'application/vnd.simtech-mindmapper',
791
+ 'txd' => 'application/vnd.genomatix.tuxedo',
792
+ 'txf' => 'application/vnd.mobius.txf',
793
+ 'txt' => 'text/plain',
794
+ 'u32' => 'application/x-authorware-bin',
795
+ 'udeb' => 'application/x-debian-package',
796
+ 'ufd' => 'application/vnd.ufdl',
797
+ 'ufdl' => 'application/vnd.ufdl',
798
+ 'umj' => 'application/vnd.umajin',
799
+ 'unityweb' => 'application/vnd.unity',
800
+ 'uoml' => 'application/vnd.uoml+xml',
801
+ 'uri' => 'text/uri-list',
802
+ 'uris' => 'text/uri-list',
803
+ 'urls' => 'text/uri-list',
804
+ 'ustar' => 'application/x-ustar',
805
+ 'utz' => 'application/vnd.uiq.theme',
806
+ 'uu' => 'text/x-uuencode',
807
+ 'uva' => 'audio/vnd.dece.audio',
808
+ 'uvd' => 'application/vnd.dece.data',
809
+ 'uvf' => 'application/vnd.dece.data',
810
+ 'uvg' => 'image/vnd.dece.graphic',
811
+ 'uvh' => 'video/vnd.dece.hd',
812
+ 'uvi' => 'image/vnd.dece.graphic',
813
+ 'uvm' => 'video/vnd.dece.mobile',
814
+ 'uvp' => 'video/vnd.dece.pd',
815
+ 'uvs' => 'video/vnd.dece.sd',
816
+ 'uvt' => 'application/vnd.dece.ttml+xml',
817
+ 'uvu' => 'video/vnd.uvvu.mp4',
818
+ 'uvv' => 'video/vnd.dece.video',
819
+ 'uvva' => 'audio/vnd.dece.audio',
820
+ 'uvvd' => 'application/vnd.dece.data',
821
+ 'uvvf' => 'application/vnd.dece.data',
822
+ 'uvvg' => 'image/vnd.dece.graphic',
823
+ 'uvvh' => 'video/vnd.dece.hd',
824
+ 'uvvi' => 'image/vnd.dece.graphic',
825
+ 'uvvm' => 'video/vnd.dece.mobile',
826
+ 'uvvp' => 'video/vnd.dece.pd',
827
+ 'uvvs' => 'video/vnd.dece.sd',
828
+ 'uvvt' => 'application/vnd.dece.ttml+xml',
829
+ 'uvvu' => 'video/vnd.uvvu.mp4',
830
+ 'uvvv' => 'video/vnd.dece.video',
831
+ 'uvvx' => 'application/vnd.dece.unspecified',
832
+ 'uvx' => 'application/vnd.dece.unspecified',
833
+ 'vcd' => 'application/x-cdlink',
834
+ 'vcf' => 'text/x-vcard',
835
+ 'vcg' => 'application/vnd.groove-vcard',
836
+ 'vcs' => 'text/x-vcalendar',
837
+ 'vcx' => 'application/vnd.vcx',
838
+ 'vis' => 'application/vnd.visionary',
839
+ 'viv' => 'video/vnd.vivo',
840
+ 'vor' => 'application/vnd.stardivision.writer',
841
+ 'vox' => 'application/x-authorware-bin',
842
+ 'vrml' => 'model/vrml',
843
+ 'vsd' => 'application/vnd.visio',
844
+ 'vsf' => 'application/vnd.vsf',
845
+ 'vss' => 'application/vnd.visio',
846
+ 'vst' => 'application/vnd.visio',
847
+ 'vsw' => 'application/vnd.visio',
848
+ 'vtu' => 'model/vnd.vtu',
849
+ 'vxml' => 'application/voicexml+xml',
850
+ 'w3d' => 'application/x-director',
851
+ 'wad' => 'application/x-doom',
852
+ 'wav' => 'audio/x-wav',
853
+ 'wax' => 'audio/x-ms-wax',
854
+ 'wbmp' => 'image/vnd.wap.wbmp',
855
+ 'wbs' => 'application/vnd.criticaltools.wbs+xml',
856
+ 'wbxml' => 'application/vnd.wap.wbxml',
857
+ 'wcm' => 'application/vnd.ms-works',
858
+ 'wdb' => 'application/vnd.ms-works',
859
+ 'weba' => 'audio/webm',
860
+ 'webm' => 'video/webm',
861
+ 'webp' => 'image/webp',
862
+ 'wg' => 'application/vnd.pmi.widget',
863
+ 'wgt' => 'application/widget',
864
+ 'wks' => 'application/vnd.ms-works',
865
+ 'wm' => 'video/x-ms-wm',
866
+ 'wma' => 'audio/x-ms-wma',
867
+ 'wmd' => 'application/x-ms-wmd',
868
+ 'wmf' => 'application/x-msmetafile',
869
+ 'wml' => 'text/vnd.wap.wml',
870
+ 'wmlc' => 'application/vnd.wap.wmlc',
871
+ 'wmls' => 'text/vnd.wap.wmlscript',
872
+ 'wmlsc' => 'application/vnd.wap.wmlscriptc',
873
+ 'wmv' => 'video/x-ms-wmv',
874
+ 'wmx' => 'video/x-ms-wmx',
875
+ 'wmz' => 'application/x-ms-wmz',
876
+ 'woff' => 'application/x-font-woff',
877
+ 'wpd' => 'application/vnd.wordperfect',
878
+ 'wpl' => 'application/vnd.ms-wpl',
879
+ 'wps' => 'application/vnd.ms-works',
880
+ 'wqd' => 'application/vnd.wqd',
881
+ 'wri' => 'application/x-mswrite',
882
+ 'wrl' => 'model/vrml',
883
+ 'wsdl' => 'application/wsdl+xml',
884
+ 'wspolicy' => 'application/wspolicy+xml',
885
+ 'wtb' => 'application/vnd.webturbo',
886
+ 'wvx' => 'video/x-ms-wvx',
887
+ 'x32' => 'application/x-authorware-bin',
888
+ 'x3d' => 'application/vnd.hzn-3d-crossword',
889
+ 'xap' => 'application/x-silverlight-app',
890
+ 'xar' => 'application/vnd.xara',
891
+ 'xbap' => 'application/x-ms-xbap',
892
+ 'xbd' => 'application/vnd.fujixerox.docuworks.binder',
893
+ 'xbm' => 'image/x-xbitmap',
894
+ 'xdf' => 'application/xcap-diff+xml',
895
+ 'xdm' => 'application/vnd.syncml.dm+xml',
896
+ 'xdp' => 'application/vnd.adobe.xdp+xml',
897
+ 'xdssc' => 'application/dssc+xml',
898
+ 'xdw' => 'application/vnd.fujixerox.docuworks',
899
+ 'xenc' => 'application/xenc+xml',
900
+ 'xer' => 'application/patch-ops-error+xml',
901
+ 'xfdf' => 'application/vnd.adobe.xfdf',
902
+ 'xfdl' => 'application/vnd.xfdl',
903
+ 'xht' => 'application/xhtml+xml',
904
+ 'xhtml' => 'application/xhtml+xml',
905
+ 'xhvml' => 'application/xv+xml',
906
+ 'xif' => 'image/vnd.xiff',
907
+ 'xla' => 'application/vnd.ms-excel',
908
+ 'xlam' => 'application/vnd.ms-excel.addin.macroenabled.12',
909
+ 'xlc' => 'application/vnd.ms-excel',
910
+ 'xlm' => 'application/vnd.ms-excel',
911
+ 'xls' => 'application/vnd.ms-excel',
912
+ 'xlsb' => 'application/vnd.ms-excel.sheet.binary.macroenabled.12',
913
+ 'xlsm' => 'application/vnd.ms-excel.sheet.macroenabled.12',
914
+ 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
915
+ 'xlt' => 'application/vnd.ms-excel',
916
+ 'xltm' => 'application/vnd.ms-excel.template.macroenabled.12',
917
+ 'xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template',
918
+ 'xlw' => 'application/vnd.ms-excel',
919
+ 'xml' => 'application/xml',
920
+ 'xo' => 'application/vnd.olpc-sugar',
921
+ 'xop' => 'application/xop+xml',
922
+ 'xpi' => 'application/x-xpinstall',
923
+ 'xpm' => 'image/x-xpixmap',
924
+ 'xpr' => 'application/vnd.is-xpr',
925
+ 'xps' => 'application/vnd.ms-xpsdocument',
926
+ 'xpw' => 'application/vnd.intercon.formnet',
927
+ 'xpx' => 'application/vnd.intercon.formnet',
928
+ 'xsl' => 'application/xml',
929
+ 'xslt' => 'application/xslt+xml',
930
+ 'xsm' => 'application/vnd.syncml+xml',
931
+ 'xspf' => 'application/xspf+xml',
932
+ 'xul' => 'application/vnd.mozilla.xul+xml',
933
+ 'xvm' => 'application/xv+xml',
934
+ 'xvml' => 'application/xv+xml',
935
+ 'xwd' => 'image/x-xwindowdump',
936
+ 'xyz' => 'chemical/x-xyz',
937
+ 'yaml' => 'text/yaml',
938
+ 'yang' => 'application/yang',
939
+ 'yin' => 'application/yin+xml',
940
+ 'yml' => 'text/yaml',
941
+ 'zaz' => 'application/vnd.zzazz.deck+xml',
942
+ 'zip' => 'application/zip',
943
+ 'zir' => 'application/vnd.zul',
944
+ 'zirz' => 'application/vnd.zul',
945
+ 'zmm' => 'application/vnd.handheld-entertainment+xml'
946
+ ];
947
+
948
+ /**
949
+ * Get a singleton instance of the class
950
+ *
951
+ * @return self
952
+ * @codeCoverageIgnore
953
+ */
954
+ public static function getInstance()
955
+ {
956
+ if (!self::$instance) {
957
+ self::$instance = new self();
958
+ }
959
+
960
+ return self::$instance;
961
+ }
962
+
963
+ /**
964
+ * Get a mimetype value from a file extension
965
+ *
966
+ * @param string $extension File extension
967
+ *
968
+ * @return string|null
969
+ */
970
+ public function fromExtension($extension)
971
+ {
972
+ $extension = strtolower($extension);
973
+
974
+ return isset($this->mimetypes[$extension]) ? $this->mimetypes[$extension] : null;
975
+ }
976
+
977
+ /**
978
+ * Get a mimetype from a filename
979
+ *
980
+ * @param string $filename Filename to generate a mimetype from
981
+ *
982
+ * @return string|null
983
+ */
984
+ public function fromFilename($filename)
985
+ {
986
+ return $this->fromExtension(pathinfo($filename, PATHINFO_EXTENSION));
987
+ }
988
+ }
facebook/facebook/GraphNodes/Birthday.php ADDED
@@ -0,0 +1,85 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook\GraphNodes;
25
+
26
+ use DateTime;
27
+
28
+ /**
29
+ * Birthday object to handle various Graph return formats
30
+ *
31
+ * @package Facebook
32
+ */
33
+ class Birthday extends DateTime
34
+ {
35
+ /**
36
+ * @var bool
37
+ */
38
+ private $hasDate = false;
39
+
40
+ /**
41
+ * @var bool
42
+ */
43
+ private $hasYear = false;
44
+
45
+ /**
46
+ * Parses Graph birthday format to set indication flags, possible values:
47
+ *
48
+ * MM/DD/YYYY
49
+ * MM/DD
50
+ * YYYY
51
+ *
52
+ * @link https://developers.facebook.com/docs/graph-api/reference/user
53
+ *
54
+ * @param string $date
55
+ */
56
+ public function __construct($date)
57
+ {
58
+ $parts = explode('/', $date);
59
+
60
+ $this->hasYear = count($parts) === 3 || count($parts) === 1;
61
+ $this->hasDate = count($parts) === 3 || count($parts) === 2;
62
+
63
+ parent::__construct($date);
64
+ }
65
+
66
+ /**
67
+ * Returns whether date object contains birth day and month
68
+ *
69
+ * @return bool
70
+ */
71
+ public function hasDate()
72
+ {
73
+ return $this->hasDate;
74
+ }
75
+
76
+ /**
77
+ * Returns whether date object contains birth year
78
+ *
79
+ * @return bool
80
+ */
81
+ public function hasYear()
82
+ {
83
+ return $this->hasYear;
84
+ }
85
+ }
facebook/facebook/GraphNodes/Collection.php ADDED
@@ -0,0 +1,242 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook\GraphNodes;
25
+
26
+ /**
27
+ * Class Collection
28
+ *
29
+ * Modified version of Collection in "illuminate/support" by Taylor Otwell
30
+ *
31
+ * @package Facebook
32
+ */
33
+
34
+ use ArrayAccess;
35
+ use ArrayIterator;
36
+ use Countable;
37
+ use IteratorAggregate;
38
+
39
+ class Collection implements ArrayAccess, Countable, IteratorAggregate
40
+ {
41
+ /**
42
+ * The items contained in the collection.
43
+ *
44
+ * @var array
45
+ */
46
+ protected $items = [];
47
+
48
+ /**
49
+ * Create a new collection.
50
+ *
51
+ * @param array $items
52
+ */
53
+ public function __construct(array $items = [])
54
+ {
55
+ $this->items = $items;
56
+ }
57
+
58
+ /**
59
+ * Gets the value of a field from the Graph node.
60
+ *
61
+ * @param string $name The field to retrieve.
62
+ * @param mixed $default The default to return if the field doesn't exist.
63
+ *
64
+ * @return mixed
65
+ */
66
+ public function getField($name, $default = null)
67
+ {
68
+ if (isset($this->items[$name])) {
69
+ return $this->items[$name];
70
+ }
71
+
72
+ return $default;
73
+ }
74
+
75
+ /**
76
+ * Gets the value of the named property for this graph object.
77
+ *
78
+ * @param string $name The property to retrieve.
79
+ * @param mixed $default The default to return if the property doesn't exist.
80
+ *
81
+ * @return mixed
82
+ *
83
+ * @deprecated 5.0.0 getProperty() has been renamed to getField()
84
+ * @todo v6: Remove this method
85
+ */
86
+ public function getProperty($name, $default = null)
87
+ {
88
+ return $this->getField($name, $default);
89
+ }
90
+
91
+ /**
92
+ * Returns a list of all fields set on the object.
93
+ *
94
+ * @return array
95
+ */
96
+ public function getFieldNames()
97
+ {
98
+ return array_keys($this->items);
99
+ }
100
+
101
+ /**
102
+ * Returns a list of all properties set on the object.
103
+ *
104
+ * @return array
105
+ *
106
+ * @deprecated 5.0.0 getPropertyNames() has been renamed to getFieldNames()
107
+ * @todo v6: Remove this method
108
+ */
109
+ public function getPropertyNames()
110
+ {
111
+ return $this->getFieldNames();
112
+ }
113
+
114
+ /**
115
+ * Get all of the items in the collection.
116
+ *
117
+ * @return array
118
+ */
119
+ public function all()
120
+ {
121
+ return $this->items;
122
+ }
123
+
124
+ /**
125
+ * Get the collection of items as a plain array.
126
+ *
127
+ * @return array
128
+ */
129
+ public function asArray()
130
+ {
131
+ return array_map(function ($value) {
132
+ return $value instanceof Collection ? $value->asArray() : $value;
133
+ }, $this->items);
134
+ }
135
+
136
+ /**
137
+ * Run a map over each of the items.
138
+ *
139
+ * @param \Closure $callback
140
+ *
141
+ * @return static
142
+ */
143
+ public function map(\Closure $callback)
144
+ {
145
+ return new static(array_map($callback, $this->items, array_keys($this->items)));
146
+ }
147
+
148
+ /**
149
+ * Get the collection of items as JSON.
150
+ *
151
+ * @param int $options
152
+ *
153
+ * @return string
154
+ */
155
+ public function asJson($options = 0)
156
+ {
157
+ return json_encode($this->asArray(), $options);
158
+ }
159
+
160
+ /**
161
+ * Count the number of items in the collection.
162
+ *
163
+ * @return int
164
+ */
165
+ public function count()
166
+ {
167
+ return count($this->items);
168
+ }
169
+
170
+ /**
171
+ * Get an iterator for the items.
172
+ *
173
+ * @return ArrayIterator
174
+ */
175
+ public function getIterator()
176
+ {
177
+ return new ArrayIterator($this->items);
178
+ }
179
+
180
+ /**
181
+ * Determine if an item exists at an offset.
182
+ *
183
+ * @param mixed $key
184
+ *
185
+ * @return bool
186
+ */
187
+ public function offsetExists($key)
188
+ {
189
+ return array_key_exists($key, $this->items);
190
+ }
191
+
192
+ /**
193
+ * Get an item at a given offset.
194
+ *
195
+ * @param mixed $key
196
+ *
197
+ * @return mixed
198
+ */
199
+ public function offsetGet($key)
200
+ {
201
+ return $this->items[$key];
202
+ }
203
+
204
+ /**
205
+ * Set the item at a given offset.
206
+ *
207
+ * @param mixed $key
208
+ * @param mixed $value
209
+ *
210
+ * @return void
211
+ */
212
+ public function offsetSet($key, $value)
213
+ {
214
+ if (is_null($key)) {
215
+ $this->items[] = $value;
216
+ } else {
217
+ $this->items[$key] = $value;
218
+ }
219
+ }
220
+
221
+ /**
222
+ * Unset the item at a given offset.
223
+ *
224
+ * @param string $key
225
+ *
226
+ * @return void
227
+ */
228
+ public function offsetUnset($key)
229
+ {
230
+ unset($this->items[$key]);
231
+ }
232
+
233
+ /**
234
+ * Convert the collection to its string representation.
235
+ *
236
+ * @return string
237
+ */
238
+ public function __toString()
239
+ {
240
+ return $this->asJson();
241
+ }
242
+ }
facebook/facebook/GraphNodes/GraphAchievement.php ADDED
@@ -0,0 +1,112 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook\GraphNodes;
25
+
26
+ /**
27
+ * Class GraphAchievement
28
+ *
29
+ * @package Facebook
30
+ */
31
+ class GraphAchievement extends GraphNode
32
+ {
33
+ /**
34
+ * @var array Maps object key names to Graph object types.
35
+ */
36
+ protected static $graphObjectMap = [
37
+ 'from' => '\Facebook\GraphNodes\GraphUser',
38
+ 'application' => '\Facebook\GraphNodes\GraphApplication',
39
+ ];
40
+
41
+ /**
42
+ * Returns the ID for the achievement.
43
+ *
44
+ * @return string|null
45
+ */
46
+ public function getId()
47
+ {
48
+ return $this->getField('id');
49
+ }
50
+
51
+ /**
52
+ * Returns the user who achieved this.
53
+ *
54
+ * @return GraphUser|null
55
+ */
56
+ public function getFrom()
57
+ {
58
+ return $this->getField('from');
59
+ }
60
+
61
+ /**
62
+ * Returns the time at which this was achieved.
63
+ *
64
+ * @return \DateTime|null
65
+ */
66
+ public function getPublishTime()
67
+ {
68
+ return $this->getField('publish_time');
69
+ }
70
+
71
+ /**
72
+ * Returns the app in which the user achieved this.
73
+ *
74
+ * @return GraphApplication|null
75
+ */
76
+ public function getApplication()
77
+ {
78
+ return $this->getField('application');
79
+ }
80
+
81
+ /**
82
+ * Returns information about the achievement type this instance is connected with.
83
+ *
84
+ * @return array|null
85
+ */
86
+ public function getData()
87
+ {
88
+ return $this->getField('data');
89
+ }
90
+
91
+ /**
92
+ * Returns the type of achievement.
93
+ *
94
+ * @see https://developers.facebook.com/docs/graph-api/reference/achievement
95
+ *
96
+ * @return string
97
+ */
98
+ public function getType()
99
+ {
100
+ return 'game.achievement';
101
+ }
102
+
103
+ /**
104
+ * Indicates whether gaining the achievement published a feed story for the user.
105
+ *
106
+ * @return boolean|null
107
+ */
108
+ public function isNoFeedStory()
109
+ {
110
+ return $this->getField('no_feed_story');
111
+ }
112
+ }
facebook/facebook/GraphNodes/GraphAlbum.php ADDED
@@ -0,0 +1,183 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook\GraphNodes;
25
+
26
+ /**
27
+ * Class GraphAlbum
28
+ *
29
+ * @package Facebook
30
+ */
31
+
32
+ class GraphAlbum extends GraphNode
33
+ {
34
+ /**
35
+ * @var array Maps object key names to Graph object types.
36
+ */
37
+ protected static $graphObjectMap = [
38
+ 'from' => '\Facebook\GraphNodes\GraphUser',
39
+ 'place' => '\Facebook\GraphNodes\GraphPage',
40
+ ];
41
+
42
+ /**
43
+ * Returns the ID for the album.
44
+ *
45
+ * @return string|null
46
+ */
47
+ public function getId()
48
+ {
49
+ return $this->getField('id');
50
+ }
51
+
52
+ /**
53
+ * Returns whether the viewer can upload photos to this album.
54
+ *
55
+ * @return boolean|null
56
+ */
57
+ public function getCanUpload()
58
+ {
59
+ return $this->getField('can_upload');
60
+ }
61
+
62
+ /**
63
+ * Returns the number of photos in this album.
64
+ *
65
+ * @return int|null
66
+ */
67
+ public function getCount()
68
+ {
69
+ return $this->getField('count');
70
+ }
71
+
72
+ /**
73
+ * Returns the ID of the album's cover photo.
74
+ *
75
+ * @return string|null
76
+ */
77
+ public function getCoverPhoto()
78
+ {
79
+ return $this->getField('cover_photo');
80
+ }
81
+
82
+ /**
83
+ * Returns the time the album was initially created.
84
+ *
85
+ * @return \DateTime|null
86
+ */
87
+ public function getCreatedTime()
88
+ {
89
+ return $this->getField('created_time');
90
+ }
91
+
92
+ /**
93
+ * Returns the time the album was updated.
94
+ *
95
+ * @return \DateTime|null
96
+ */
97
+ public function getUpdatedTime()
98
+ {
99
+ return $this->getField('updated_time');
100
+ }
101
+
102
+ /**
103
+ * Returns the description of the album.
104
+ *
105
+ * @return string|null
106
+ */
107
+ public function getDescription()
108
+ {
109
+ return $this->getField('description');
110
+ }
111
+
112
+ /**
113
+ * Returns profile that created the album.
114
+ *
115
+ * @return GraphUser|null
116
+ */
117
+ public function getFrom()
118
+ {
119
+ return $this->getField('from');
120
+ }
121
+
122
+ /**
123
+ * Returns profile that created the album.
124
+ *
125
+ * @return GraphPage|null
126
+ */
127
+ public function getPlace()
128
+ {
129
+ return $this->getField('place');
130
+ }
131
+
132
+ /**
133
+ * Returns a link to this album on Facebook.
134
+ *
135
+ * @return string|null
136
+ */
137
+ public function getLink()
138
+ {
139
+ return $this->getField('link');
140
+ }
141
+
142
+ /**
143
+ * Returns the textual location of the album.
144
+ *
145
+ * @return string|null
146
+ */
147
+ public function getLocation()
148
+ {
149
+ return $this->getField('location');
150
+ }
151
+
152
+ /**
153
+ * Returns the title of the album.
154
+ *
155
+ * @return string|null
156
+ */
157
+ public function getName()
158
+ {
159
+ return $this->getField('name');
160
+ }
161
+
162
+ /**
163
+ * Returns the privacy settings for the album.
164
+ *
165
+ * @return string|null
166
+ */
167
+ public function getPrivacy()
168
+ {
169
+ return $this->getField('privacy');
170
+ }
171
+
172
+ /**
173
+ * Returns the type of the album.
174
+ *
175
+ * enum{ profile, mobile, wall, normal, album }
176
+ *
177
+ * @return string|null
178
+ */
179
+ public function getType()
180
+ {
181
+ return $this->getField('type');
182
+ }
183
+ }
facebook/facebook/GraphNodes/GraphApplication.php ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook\GraphNodes;
25
+
26
+ /**
27
+ * Class GraphApplication
28
+ *
29
+ * @package Facebook
30
+ */
31
+
32
+ class GraphApplication extends GraphNode
33
+ {
34
+ /**
35
+ * Returns the ID for the application.
36
+ *
37
+ * @return string|null
38
+ */
39
+ public function getId()
40
+ {
41
+ return $this->getField('id');
42
+ }
43
+ }
facebook/facebook/GraphNodes/GraphCoverPhoto.php ADDED
@@ -0,0 +1,72 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook\GraphNodes;
25
+
26
+ /**
27
+ * Class GraphCoverPhoto
28
+ *
29
+ * @package Facebook
30
+ */
31
+ class GraphCoverPhoto extends GraphNode
32
+ {
33
+ /**
34
+ * Returns the id of cover if it exists
35
+ *
36
+ * @return int|null
37
+ */
38
+ public function getId()
39
+ {
40
+ return $this->getField('id');
41
+ }
42
+
43
+ /**
44
+ * Returns the source of cover if it exists
45
+ *
46
+ * @return string|null
47
+ */
48
+ public function getSource()
49
+ {
50
+ return $this->getField('source');
51
+ }
52
+
53
+ /**
54
+ * Returns the offset_x of cover if it exists
55
+ *
56
+ * @return int|null
57
+ */
58
+ public function getOffsetX()
59
+ {
60
+ return $this->getField('offset_x');
61
+ }
62
+
63
+ /**
64
+ * Returns the offset_y of cover if it exists
65
+ *
66
+ * @return int|null
67
+ */
68
+ public function getOffsetY()
69
+ {
70
+ return $this->getField('offset_y');
71
+ }
72
+ }
facebook/facebook/GraphNodes/GraphEdge.php ADDED
@@ -0,0 +1,252 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook\GraphNodes;
25
+
26
+ use Facebook\FacebookRequest;
27
+ use Facebook\Url\FacebookUrlManipulator;
28
+ use Facebook\Exceptions\FacebookSDKException;
29
+
30
+ /**
31
+ * Class GraphEdge
32
+ *
33
+ * @package Facebook
34
+ */
35
+ class GraphEdge extends Collection
36
+ {
37
+ /**
38
+ * @var FacebookRequest The original request that generated this data.
39
+ */
40
+ protected $request;
41
+
42
+ /**
43
+ * @var array An array of Graph meta data like pagination, etc.
44
+ */
45
+ protected $metaData = [];
46
+
47
+ /**
48
+ * @var string|null The parent Graph edge endpoint that generated the list.
49
+ */
50
+ protected $parentEdgeEndpoint;
51
+
52
+ /**
53
+ * @var string|null The subclass of the child GraphNode's.
54
+ */
55
+ protected $subclassName;
56
+
57
+ /**
58
+ * Init this collection of GraphNode's.
59
+ *
60
+ * @param FacebookRequest $request The original request that generated this data.
61
+ * @param array $data An array of GraphNode's.
62
+ * @param array $metaData An array of Graph meta data like pagination, etc.
63
+ * @param string|null $parentEdgeEndpoint The parent Graph edge endpoint that generated the list.
64
+ * @param string|null $subclassName The subclass of the child GraphNode's.
65
+ */
66
+ public function __construct(FacebookRequest $request, array $data = [], array $metaData = [], $parentEdgeEndpoint = null, $subclassName = null)
67
+ {
68
+ $this->request = $request;
69
+ $this->metaData = $metaData;
70
+ $this->parentEdgeEndpoint = $parentEdgeEndpoint;
71
+ $this->subclassName = $subclassName;
72
+
73
+ parent::__construct($data);
74
+ }
75
+
76
+ /**
77
+ * Gets the parent Graph edge endpoint that generated the list.
78
+ *
79
+ * @return string|null
80
+ */
81
+ public function getParentGraphEdge()
82
+ {
83
+ return $this->parentEdgeEndpoint;
84
+ }
85
+
86
+ /**
87
+ * Gets the subclass name that the child GraphNode's are cast as.
88
+ *
89
+ * @return string|null
90
+ */
91
+ public function getSubClassName()
92
+ {
93
+ return $this->subclassName;
94
+ }
95
+
96
+ /**
97
+ * Returns the raw meta data associated with this GraphEdge.
98
+ *
99
+ * @return array
100
+ */
101
+ public function getMetaData()
102
+ {
103
+ return $this->metaData;
104
+ }
105
+
106
+ /**
107
+ * Returns the next cursor if it exists.
108
+ *
109
+ * @return string|null
110
+ */
111
+ public function getNextCursor()
112
+ {
113
+ return $this->getCursor('after');
114
+ }
115
+
116
+ /**
117
+ * Returns the previous cursor if it exists.
118
+ *
119
+ * @return string|null
120
+ */
121
+ public function getPreviousCursor()
122
+ {
123
+ return $this->getCursor('before');
124
+ }
125
+
126
+ /**
127
+ * Returns the cursor for a specific direction if it exists.
128
+ *
129
+ * @param string $direction The direction of the page: after|before
130
+ *
131
+ * @return string|null
132
+ */
133
+ public function getCursor($direction)
134
+ {
135
+ if (isset($this->metaData['paging']['cursors'][$direction])) {
136
+ return $this->metaData['paging']['cursors'][$direction];
137
+ }
138
+
139
+ return null;
140
+ }
141
+
142
+ /**
143
+ * Generates a pagination URL based on a cursor.
144
+ *
145
+ * @param string $direction The direction of the page: next|previous
146
+ *
147
+ * @return string|null
148
+ *
149
+ * @throws FacebookSDKException
150
+ */
151
+ public function getPaginationUrl($direction)
152
+ {
153
+ $this->validateForPagination();
154
+
155
+ // Do we have a paging URL?
156
+ if (!isset($this->metaData['paging'][$direction])) {
157
+ return null;
158
+ }
159
+
160
+ $pageUrl = $this->metaData['paging'][$direction];
161
+
162
+ return FacebookUrlManipulator::baseGraphUrlEndpoint($pageUrl);
163
+ }
164
+
165
+ /**
166
+ * Validates whether or not we can paginate on this request.
167
+ *
168
+ * @throws FacebookSDKException
169
+ */
170
+ public function validateForPagination()
171
+ {
172
+ if ($this->request->getMethod() !== 'GET') {
173
+ throw new FacebookSDKException('You can only paginate on a GET request.', 720);
174
+ }
175
+ }
176
+
177
+ /**
178
+ * Gets the request object needed to make a next|previous page request.
179
+ *
180
+ * @param string $direction The direction of the page: next|previous
181
+ *
182
+ * @return FacebookRequest|null
183
+ *
184
+ * @throws FacebookSDKException
185
+ */
186
+ public function getPaginationRequest($direction)
187
+ {
188
+ $pageUrl = $this->getPaginationUrl($direction);
189
+ if (!$pageUrl) {
190
+ return null;
191
+ }
192
+
193
+ $newRequest = clone $this->request;
194
+ $newRequest->setEndpoint($pageUrl);
195
+
196
+ return $newRequest;
197
+ }
198
+
199
+ /**
200
+ * Gets the request object needed to make a "next" page request.
201
+ *
202
+ * @return FacebookRequest|null
203
+ *
204
+ * @throws FacebookSDKException
205
+ */
206
+ public function getNextPageRequest()
207
+ {
208
+ return $this->getPaginationRequest('next');
209
+ }
210
+
211
+ /**
212
+ * Gets the request object needed to make a "previous" page request.
213
+ *
214
+ * @return FacebookRequest|null
215
+ *
216
+ * @throws FacebookSDKException
217
+ */
218
+ public function getPreviousPageRequest()
219
+ {
220
+ return $this->getPaginationRequest('previous');
221
+ }
222
+
223
+ /**
224
+ * The total number of results according to Graph if it exists.
225
+ *
226
+ * This will be returned if the summary=true modifier is present in the request.
227
+ *
228
+ * @return int|null
229
+ */
230
+ public function getTotalCount()
231
+ {
232
+ if (isset($this->metaData['summary']['total_count'])) {
233
+ return $this->metaData['summary']['total_count'];
234
+ }
235
+
236
+ return null;
237
+ }
238
+
239
+ /**
240
+ * @inheritDoc
241
+ */
242
+ public function map(\Closure $callback)
243
+ {
244
+ return new static(
245
+ $this->request,
246
+ array_map($callback, $this->items, array_keys($this->items)),
247
+ $this->metaData,
248
+ $this->parentEdgeEndpoint,
249
+ $this->subclassName
250
+ );
251
+ }
252
+ }
facebook/facebook/GraphNodes/GraphEvent.php ADDED
@@ -0,0 +1,242 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook\GraphNodes;
25
+
26
+ /**
27
+ * Class GraphEvent
28
+ *
29
+ * @package Facebook
30
+ */
31
+ class GraphEvent extends GraphNode
32
+ {
33
+ /**
34
+ * @var array Maps object key names to GraphNode types.
35
+ */
36
+ protected static $graphObjectMap = [
37
+ 'cover' => '\Facebook\GraphNodes\GraphCoverPhoto',
38
+ 'place' => '\Facebook\GraphNodes\GraphPage',
39
+ 'picture' => '\Facebook\GraphNodes\GraphPicture',
40
+ 'parent_group' => '\Facebook\GraphNodes\GraphGroup',
41
+ ];
42
+
43
+ /**
44
+ * Returns the `id` (The event ID) as string if present.
45
+ *
46
+ * @return string|null
47
+ */
48
+ public function getId()
49
+ {
50
+ return $this->getField('id');
51
+ }
52
+
53
+ /**
54
+ * Returns the `cover` (Cover picture) as GraphCoverPhoto if present.
55
+ *
56
+ * @return GraphCoverPhoto|null
57
+ */
58
+ public function getCover()
59
+ {
60
+ return $this->getField('cover');
61
+ }
62
+
63
+ /**
64
+ * Returns the `description` (Long-form description) as string if present.
65
+ *
66
+ * @return string|null
67
+ */
68
+ public function getDescription()
69
+ {
70
+ return $this->getField('description');
71
+ }
72
+
73
+ /**
74
+ * Returns the `end_time` (End time, if one has been set) as DateTime if present.
75
+ *
76
+ * @return \DateTime|null
77
+ */
78
+ public function getEndTime()
79
+ {
80
+ return $this->getField('end_time');
81
+ }
82
+
83
+ /**
84
+ * Returns the `is_date_only` (Whether the event only has a date specified, but no time) as bool if present.
85
+ *
86
+ * @return bool|null
87
+ */
88
+ public function getIsDateOnly()
89
+ {
90
+ return $this->getField('is_date_only');
91
+ }
92
+
93
+ /**
94
+ * Returns the `name` (Event name) as string if present.
95
+ *
96
+ * @return string|null
97
+ */
98
+ public function getName()
99
+ {
100
+ return $this->getField('name');
101
+ }
102
+
103
+ /**
104
+ * Returns the `owner` (The profile that created the event) as GraphNode if present.
105
+ *
106
+ * @return GraphNode|null
107
+ */
108
+ public function getOwner()
109
+ {
110
+ return $this->getField('owner');
111
+ }
112
+
113
+ /**
114
+ * Returns the `parent_group` (The group the event belongs to) as GraphGroup if present.
115
+ *
116
+ * @return GraphGroup|null
117
+ */
118
+ public function getParentGroup()
119
+ {
120
+ return $this->getField('parent_group');
121
+ }
122
+
123
+ /**
124
+ * Returns the `place` (Event Place information) as GraphPage if present.
125
+ *
126
+ * @return GraphPage|null
127
+ */
128
+ public function getPlace()
129
+ {
130
+ return $this->getField('place');
131
+ }
132
+
133
+ /**
134
+ * Returns the `privacy` (Who can see the event) as string if present.
135
+ *
136
+ * @return string|null
137
+ */
138
+ public function getPrivacy()
139
+ {
140
+ return $this->getField('privacy');
141
+ }
142
+
143
+ /**
144
+ * Returns the `start_time` (Start time) as DateTime if present.
145
+ *
146
+ * @return \DateTime|null
147
+ */
148
+ public function getStartTime()
149
+ {
150
+ return $this->getField('start_time');
151
+ }
152
+
153
+ /**
154
+ * Returns the `ticket_uri` (The link users can visit to buy a ticket to this event) as string if present.
155
+ *
156
+ * @return string|null
157
+ */
158
+ public function getTicketUri()
159
+ {
160
+ return $this->getField('ticket_uri');
161
+ }
162
+
163
+ /**
164
+ * Returns the `timezone` (Timezone) as string if present.
165
+ *
166
+ * @return string|null
167
+ */
168
+ public function getTimezone()
169
+ {
170
+ return $this->getField('timezone');
171
+ }
172
+
173
+ /**
174
+ * Returns the `updated_time` (Last update time) as DateTime if present.
175
+ *
176
+ * @return \DateTime|null
177
+ */
178
+ public function getUpdatedTime()
179
+ {
180
+ return $this->getField('updated_time');
181
+ }
182
+
183
+ /**
184
+ * Returns the `picture` (Event picture) as GraphPicture if present.
185
+ *
186
+ * @return GraphPicture|null
187
+ */
188
+ public function getPicture()
189
+ {
190
+ return $this->getField('picture');
191
+ }
192
+
193
+ /**
194
+ * Returns the `attending_count` (Number of people attending the event) as int if present.
195
+ *
196
+ * @return int|null
197
+ */
198
+ public function getAttendingCount()
199
+ {
200
+ return $this->getField('attending_count');
201
+ }
202
+
203
+ /**
204
+ * Returns the `declined_count` (Number of people who declined the event) as int if present.
205
+ *
206
+ * @return int|null
207
+ */
208
+ public function getDeclinedCount()
209
+ {
210
+ return $this->getField('declined_count');
211
+ }
212
+
213
+ /**
214
+ * Returns the `maybe_count` (Number of people who maybe going to the event) as int if present.
215
+ *
216
+ * @return int|null
217
+ */
218
+ public function getMaybeCount()
219
+ {
220
+ return $this->getField('maybe_count');
221
+ }
222
+
223
+ /**
224
+ * Returns the `noreply_count` (Number of people who did not reply to the event) as int if present.
225
+ *
226
+ * @return int|null
227
+ */
228
+ public function getNoreplyCount()
229
+ {
230
+ return $this->getField('noreply_count');
231
+ }
232
+
233
+ /**
234
+ * Returns the `invited_count` (Number of people invited to the event) as int if present.
235
+ *
236
+ * @return int|null
237
+ */
238
+ public function getInvitedCount()
239
+ {
240
+ return $this->getField('invited_count');
241
+ }
242
+ }
facebook/facebook/GraphNodes/GraphGroup.php ADDED
@@ -0,0 +1,170 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook\GraphNodes;
25
+
26
+ /**
27
+ * Class GraphGroup
28
+ *
29
+ * @package Facebook
30
+ */
31
+ class GraphGroup extends GraphNode
32
+ {
33
+ /**
34
+ * @var array Maps object key names to GraphNode types.
35
+ */
36
+ protected static $graphObjectMap = [
37
+ 'cover' => '\Facebook\GraphNodes\GraphCoverPhoto',
38
+ 'venue' => '\Facebook\GraphNodes\GraphLocation',
39
+ ];
40
+
41
+ /**
42
+ * Returns the `id` (The Group ID) as string if present.
43
+ *
44
+ * @return string|null
45
+ */
46
+ public function getId()
47
+ {
48
+ return $this->getField('id');
49
+ }
50
+
51
+ /**
52
+ * Returns the `cover` (The cover photo of the Group) as GraphCoverPhoto if present.
53
+ *
54
+ * @return GraphCoverPhoto|null
55
+ */
56
+ public function getCover()
57
+ {
58
+ return $this->getField('cover');
59
+ }
60
+
61
+ /**
62
+ * Returns the `description` (A brief description of the Group) as string if present.
63
+ *
64
+ * @return string|null
65
+ */
66
+ public function getDescription()
67
+ {
68
+ return $this->getField('description');
69
+ }
70
+
71
+ /**
72
+ * Returns the `email` (The email address to upload content to the Group. Only current members of the Group can use this) as string if present.
73
+ *
74
+ * @return string|null
75
+ */
76
+ public function getEmail()
77
+ {
78
+ return $this->getField('email');
79
+ }
80
+
81
+ /**
82
+ * Returns the `icon` (The URL for the Group's icon) as string if present.
83
+ *
84
+ * @return string|null
85
+ */
86
+ public function getIcon()
87
+ {
88
+ return $this->getField('icon');
89
+ }
90
+
91
+ /**
92
+ * Returns the `link` (The Group's website) as string if present.
93
+ *
94
+ * @return string|null
95
+ */
96
+ public function getLink()
97
+ {
98
+ return $this->getField('link');
99
+ }
100
+
101
+ /**
102
+ * Returns the `name` (The name of the Group) as string if present.
103
+ *
104
+ * @return string|null
105
+ */
106
+ public function getName()
107
+ {
108
+ return $this->getField('name');
109
+ }
110
+
111
+ /**
112
+ * Returns the `member_request_count` (Number of people asking to join the group.) as int if present.
113
+ *
114
+ * @return int|null
115
+ */
116
+ public function getMemberRequestCount()
117
+ {
118
+ return $this->getField('member_request_count');
119
+ }
120
+
121
+ /**
122
+ * Returns the `owner` (The profile that created this Group) as GraphNode if present.
123
+ *
124
+ * @return GraphNode|null
125
+ */
126
+ public function getOwner()
127
+ {
128
+ return $this->getField('owner');
129
+ }
130
+
131
+ /**
132
+ * Returns the `parent` (The parent Group of this Group, if it exists) as GraphNode if present.
133
+ *
134
+ * @return GraphNode|null
135
+ */
136
+ public function getParent()
137
+ {
138
+ return $this->getField('parent');
139
+ }
140
+
141
+ /**
142
+ * Returns the `privacy` (The privacy setting of the Group) as string if present.
143
+ *
144
+ * @return string|null
145
+ */
146
+ public function getPrivacy()
147
+ {
148
+ return $this->getField('privacy');
149
+ }
150
+
151
+ /**
152
+ * Returns the `updated_time` (The last time the Group was updated (this includes changes in the Group's properties and changes in posts and comments if user can see them)) as \DateTime if present.
153
+ *
154
+ * @return \DateTime|null
155
+ */
156
+ public function getUpdatedTime()
157
+ {
158
+ return $this->getField('updated_time');
159
+ }
160
+
161
+ /**
162
+ * Returns the `venue` (The location for the Group) as GraphLocation if present.
163
+ *
164
+ * @return GraphLocation|null
165
+ */
166
+ public function getVenue()
167
+ {
168
+ return $this->getField('venue');
169
+ }
170
+ }
facebook/facebook/GraphNodes/GraphList.php ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook\GraphNodes;
25
+
26
+ /**
27
+ * Class GraphList
28
+ *
29
+ * @package Facebook
30
+ *
31
+ * @deprecated 5.0.0 GraphList has been renamed to GraphEdge
32
+ * @todo v6: Remove this class
33
+ */
34
+ class GraphList extends GraphEdge
35
+ {
36
+ }
facebook/facebook/GraphNodes/GraphLocation.php ADDED
@@ -0,0 +1,102 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook\GraphNodes;
25
+
26
+ /**
27
+ * Class GraphLocation
28
+ *
29
+ * @package Facebook
30
+ */
31
+ class GraphLocation extends GraphNode
32
+ {
33
+ /**
34
+ * Returns the street component of the location
35
+ *
36
+ * @return string|null
37
+ */
38
+ public function getStreet()
39
+ {
40
+ return $this->getField('street');
41
+ }
42
+
43
+ /**
44
+ * Returns the city component of the location
45
+ *
46
+ * @return string|null
47
+ */
48
+ public function getCity()
49
+ {
50
+ return $this->getField('city');
51
+ }
52
+
53
+ /**
54
+ * Returns the state component of the location
55
+ *
56
+ * @return string|null
57
+ */
58
+ public function getState()
59
+ {
60
+ return $this->getField('state');
61
+ }
62
+
63
+ /**
64
+ * Returns the country component of the location
65
+ *
66
+ * @return string|null
67
+ */
68
+ public function getCountry()
69
+ {
70
+ return $this->getField('country');
71
+ }
72
+
73
+ /**
74
+ * Returns the zipcode component of the location
75
+ *
76
+ * @return string|null
77
+ */
78
+ public function getZip()
79
+ {
80
+ return $this->getField('zip');
81
+ }
82
+
83
+ /**
84
+ * Returns the latitude component of the location
85
+ *
86
+ * @return float|null
87
+ */
88
+ public function getLatitude()
89
+ {
90
+ return $this->getField('latitude');
91
+ }
92
+
93
+ /**
94
+ * Returns the street component of the location
95
+ *
96
+ * @return float|null
97
+ */
98
+ public function getLongitude()
99
+ {
100
+ return $this->getField('longitude');
101
+ }
102
+ }
facebook/facebook/GraphNodes/GraphNode.php ADDED
@@ -0,0 +1,197 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook\GraphNodes;
25
+
26
+ /**
27
+ * Class GraphNode
28
+ *
29
+ * @package Facebook
30
+ */
31
+ class GraphNode extends Collection
32
+ {
33
+ /**
34
+ * @var array Maps object key names to Graph object types.
35
+ */
36
+ protected static $graphObjectMap = [];
37
+
38
+ /**
39
+ * Init this Graph object.
40
+ *
41
+ * @param array $data
42
+ */
43
+ public function __construct(array $data = [])
44
+ {
45
+ parent::__construct($this->castItems($data));
46
+ }
47
+
48
+ /**
49
+ * Iterates over an array and detects the types each node
50
+ * should be cast to and returns all the items as an array.
51
+ *
52
+ * @TODO Add auto-casting to AccessToken entities.
53
+ *
54
+ * @param array $data The array to iterate over.
55
+ *
56
+ * @return array
57
+ */
58
+ public function castItems(array $data)
59
+ {
60
+ $items = [];
61
+
62
+ foreach ($data as $k => $v) {
63
+ if ($this->shouldCastAsDateTime($k)
64
+ && (is_numeric($v)
65
+ || $this->isIso8601DateString($v))
66
+ ) {
67
+ $items[$k] = $this->castToDateTime($v);
68
+ } elseif ($k === 'birthday') {
69
+ $items[$k] = $this->castToBirthday($v);
70
+ } else {
71
+ $items[$k] = $v;
72
+ }
73
+ }
74
+
75
+ return $items;
76
+ }
77
+
78
+ /**
79
+ * Uncasts any auto-casted datatypes.
80
+ * Basically the reverse of castItems().
81
+ *
82
+ * @return array
83
+ */
84
+ public function uncastItems()
85
+ {
86
+ $items = $this->asArray();
87
+
88
+ return array_map(function ($v) {
89
+ if ($v instanceof \DateTime) {
90
+ return $v->format(\DateTime::ISO8601);
91
+ }
92
+
93
+ return $v;
94
+ }, $items);
95
+ }
96
+
97
+ /**
98
+ * Get the collection of items as JSON.
99
+ *
100
+ * @param int $options
101
+ *
102
+ * @return string
103
+ */
104
+ public function asJson($options = 0)
105
+ {
106
+ return json_encode($this->uncastItems(), $options);
107
+ }
108
+
109
+ /**
110
+ * Detects an ISO 8601 formatted string.
111
+ *
112
+ * @param string $string
113
+ *
114
+ * @return boolean
115
+ *
116
+ * @see https://developers.facebook.com/docs/graph-api/using-graph-api/#readmodifiers
117
+ * @see http://www.cl.cam.ac.uk/~mgk25/iso-time.html
118
+ * @see http://en.wikipedia.org/wiki/ISO_8601
119
+ */
120
+ public function isIso8601DateString($string)
121
+ {
122
+ // This insane regex was yoinked from here:
123
+ // http://www.pelagodesign.com/blog/2009/05/20/iso-8601-date-validation-that-doesnt-suck/
124
+ // ...and I'm all like:
125
+ // http://thecodinglove.com/post/95378251969/when-code-works-and-i-dont-know-why
126
+ $crazyInsaneRegexThatSomehowDetectsIso8601 = '/^([\+-]?\d{4}(?!\d{2}\b))'
127
+ . '((-?)((0[1-9]|1[0-2])(\3([12]\d|0[1-9]|3[01]))?'
128
+ . '|W([0-4]\d|5[0-2])(-?[1-7])?|(00[1-9]|0[1-9]\d'
129
+ . '|[12]\d{2}|3([0-5]\d|6[1-6])))([T\s]((([01]\d|2[0-3])'
130
+ . '((:?)[0-5]\d)?|24\:?00)([\.,]\d+(?!:))?)?(\17[0-5]\d'
131
+ . '([\.,]\d+)?)?([zZ]|([\+-])([01]\d|2[0-3]):?([0-5]\d)?)?)?)?$/';
132
+
133
+ return preg_match($crazyInsaneRegexThatSomehowDetectsIso8601, $string) === 1;
134
+ }
135
+
136
+ /**
137
+ * Determines if a value from Graph should be cast to DateTime.
138
+ *
139
+ * @param string $key
140
+ *
141
+ * @return boolean
142
+ */
143
+ public function shouldCastAsDateTime($key)
144
+ {
145
+ return in_array($key, [
146
+ 'created_time',
147
+ 'updated_time',
148
+ 'start_time',
149
+ 'end_time',
150
+ 'backdated_time',
151
+ 'issued_at',
152
+ 'expires_at',
153
+ 'publish_time'
154
+ ], true);
155
+ }
156
+
157
+ /**
158
+ * Casts a date value from Graph to DateTime.
159
+ *
160
+ * @param int|string $value
161
+ *
162
+ * @return \DateTime
163
+ */
164
+ public function castToDateTime($value)
165
+ {
166
+ if (is_int($value)) {
167
+ $dt = new \DateTime();
168
+ $dt->setTimestamp($value);
169
+ } else {
170
+ $dt = new \DateTime($value);
171
+ }
172
+
173
+ return $dt;
174
+ }
175
+
176
+ /**
177
+ * Casts a birthday value from Graph to Birthday
178
+ *
179
+ * @param string $value
180
+ *
181
+ * @return Birthday
182
+ */
183
+ public function castToBirthday($value)
184
+ {
185
+ return new Birthday($value);
186
+ }
187
+
188
+ /**
189
+ * Getter for $graphObjectMap.
190
+ *
191
+ * @return array
192
+ */
193
+ public static function getObjectMap()
194
+ {
195
+ return static::$graphObjectMap;
196
+ }
197
+ }
facebook/facebook/GraphNodes/GraphNodeFactory.php ADDED
@@ -0,0 +1,392 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook\GraphNodes;
25
+
26
+ use Facebook\FacebookResponse;
27
+ use Facebook\Exceptions\FacebookSDKException;
28
+
29
+ /**
30
+ * Class GraphNodeFactory
31
+ *
32
+ * @package Facebook
33
+ *
34
+ * ## Assumptions ##
35
+ * GraphEdge - is ALWAYS a numeric array
36
+ * GraphEdge - is ALWAYS an array of GraphNode types
37
+ * GraphNode - is ALWAYS an associative array
38
+ * GraphNode - MAY contain GraphNode's "recurrable"
39
+ * GraphNode - MAY contain GraphEdge's "recurrable"
40
+ * GraphNode - MAY contain DateTime's "primitives"
41
+ * GraphNode - MAY contain string's "primitives"
42
+ */
43
+ class GraphNodeFactory
44
+ {
45
+ /**
46
+ * @const string The base graph object class.
47
+ */
48
+ const BASE_GRAPH_NODE_CLASS = '\Facebook\GraphNodes\GraphNode';
49
+
50
+ /**
51
+ * @const string The base graph edge class.
52
+ */
53
+ const BASE_GRAPH_EDGE_CLASS = '\Facebook\GraphNodes\GraphEdge';
54
+
55
+ /**
56
+ * @const string The graph object prefix.
57
+ */
58
+ const BASE_GRAPH_OBJECT_PREFIX = '\Facebook\GraphNodes\\';
59
+
60
+ /**
61
+ * @var FacebookResponse The response entity from Graph.
62
+ */
63
+ protected $response;
64
+
65
+ /**
66
+ * @var array The decoded body of the FacebookResponse entity from Graph.
67
+ */
68
+ protected $decodedBody;
69
+
70
+ /**
71
+ * Init this Graph object.
72
+ *
73
+ * @param FacebookResponse $response The response entity from Graph.
74
+ */
75
+ public function __construct(FacebookResponse $response)
76
+ {
77
+ $this->response = $response;
78
+ $this->decodedBody = $response->getDecodedBody();
79
+ }
80
+
81
+ /**
82
+ * Tries to convert a FacebookResponse entity into a GraphNode.
83
+ *
84
+ * @param string|null $subclassName The GraphNode sub class to cast to.
85
+ *
86
+ * @return GraphNode
87
+ *
88
+ * @throws FacebookSDKException
89
+ */
90
+ public function makeGraphNode($subclassName = null)
91
+ {
92
+ $this->validateResponseAsArray();
93
+ $this->validateResponseCastableAsGraphNode();
94
+
95
+ return $this->castAsGraphNodeOrGraphEdge($this->decodedBody, $subclassName);
96
+ }
97
+
98
+ /**
99
+ * Convenience method for creating a GraphAchievement collection.
100
+ *
101
+ * @return GraphAchievement
102
+ *
103
+ * @throws FacebookSDKException
104
+ */
105
+ public function makeGraphAchievement()
106
+ {
107
+ return $this->makeGraphNode(static::BASE_GRAPH_OBJECT_PREFIX . 'GraphAchievement');
108
+ }
109
+
110
+ /**
111
+ * Convenience method for creating a GraphAlbum collection.
112
+ *
113
+ * @return GraphAlbum
114
+ *
115
+ * @throws FacebookSDKException
116
+ */
117
+ public function makeGraphAlbum()
118
+ {
119
+ return $this->makeGraphNode(static::BASE_GRAPH_OBJECT_PREFIX . 'GraphAlbum');
120
+ }
121
+
122
+ /**
123
+ * Convenience method for creating a GraphPage collection.
124
+ *
125
+ * @return GraphPage
126
+ *
127
+ * @throws FacebookSDKException
128
+ */
129
+ public function makeGraphPage()
130
+ {
131
+ return $this->makeGraphNode(static::BASE_GRAPH_OBJECT_PREFIX . 'GraphPage');
132
+ }
133
+
134
+ /**
135
+ * Convenience method for creating a GraphSessionInfo collection.
136
+ *
137
+ * @return GraphSessionInfo
138
+ *
139
+ * @throws FacebookSDKException
140
+ */
141
+ public function makeGraphSessionInfo()
142
+ {
143
+ return $this->makeGraphNode(static::BASE_GRAPH_OBJECT_PREFIX . 'GraphSessionInfo');
144
+ }
145
+
146
+ /**
147
+ * Convenience method for creating a GraphUser collection.
148
+ *
149
+ * @return GraphUser
150
+ *
151
+ * @throws FacebookSDKException
152
+ */
153
+ public function makeGraphUser()
154
+ {
155
+ return $this->makeGraphNode(static::BASE_GRAPH_OBJECT_PREFIX . 'GraphUser');
156
+ }
157
+
158
+ /**
159
+ * Convenience method for creating a GraphEvent collection.
160
+ *
161
+ * @return GraphEvent
162
+ *
163
+ * @throws FacebookSDKException
164
+ */
165
+ public function makeGraphEvent()
166
+ {
167
+ return $this->makeGraphNode(static::BASE_GRAPH_OBJECT_PREFIX . 'GraphEvent');
168
+ }
169
+
170
+ /**
171
+ * Convenience method for creating a GraphGroup collection.
172
+ *
173
+ * @return GraphGroup
174
+ *
175
+ * @throws FacebookSDKException
176
+ */
177
+ public function makeGraphGroup()
178
+ {
179
+ return $this->makeGraphNode(static::BASE_GRAPH_OBJECT_PREFIX . 'GraphGroup');
180
+ }
181
+
182
+ /**
183
+ * Tries to convert a FacebookResponse entity into a GraphEdge.
184
+ *
185
+ * @param string|null $subclassName The GraphNode sub class to cast the list items to.
186
+ * @param boolean $auto_prefix Toggle to auto-prefix the subclass name.
187
+ *
188
+ * @return GraphEdge
189
+ *
190
+ * @throws FacebookSDKException
191
+ */
192
+ public function makeGraphEdge($subclassName = null, $auto_prefix = true)
193
+ {
194
+ $this->validateResponseAsArray();
195
+ $this->validateResponseCastableAsGraphEdge();
196
+
197
+ if ($subclassName && $auto_prefix) {
198
+ $subclassName = static::BASE_GRAPH_OBJECT_PREFIX . $subclassName;
199
+ }
200
+
201
+ return $this->castAsGraphNodeOrGraphEdge($this->decodedBody, $subclassName);
202
+ }
203
+
204
+ /**
205
+ * Validates the decoded body.
206
+ *
207
+ * @throws FacebookSDKException
208
+ */
209
+ public function validateResponseAsArray()
210
+ {
211
+ if (!is_array($this->decodedBody)) {
212
+ throw new FacebookSDKException('Unable to get response from Graph as array.', 620);
213
+ }
214
+ }
215
+
216
+ /**
217
+ * Validates that the return data can be cast as a GraphNode.
218
+ *
219
+ * @throws FacebookSDKException
220
+ */
221
+ public function validateResponseCastableAsGraphNode()
222
+ {
223
+ if (isset($this->decodedBody['data']) && static::isCastableAsGraphEdge($this->decodedBody['data'])) {
224
+ throw new FacebookSDKException(
225
+ 'Unable to convert response from Graph to a GraphNode because the response looks like a GraphEdge. Try using GraphNodeFactory::makeGraphEdge() instead.',
226
+ 620
227
+ );
228
+ }
229
+ }
230
+
231
+ /**
232
+ * Validates that the return data can be cast as a GraphEdge.
233
+ *
234
+ * @throws FacebookSDKException
235
+ */
236
+ public function validateResponseCastableAsGraphEdge()
237
+ {
238
+ if (!(isset($this->decodedBody['data']) && static::isCastableAsGraphEdge($this->decodedBody['data']))) {
239
+ throw new FacebookSDKException(
240
+ 'Unable to convert response from Graph to a GraphEdge because the response does not look like a GraphEdge. Try using GraphNodeFactory::makeGraphNode() instead.',
241
+ 620
242
+ );
243
+ }
244
+ }
245
+
246
+ /**
247
+ * Safely instantiates a GraphNode of $subclassName.
248
+ *
249
+ * @param array $data The array of data to iterate over.
250
+ * @param string|null $subclassName The subclass to cast this collection to.
251
+ *
252
+ * @return GraphNode
253
+ *
254
+ * @throws FacebookSDKException
255
+ */
256
+ public function safelyMakeGraphNode(array $data, $subclassName = null)
257
+ {
258
+ $subclassName = $subclassName ?: static::BASE_GRAPH_NODE_CLASS;
259
+ static::validateSubclass($subclassName);
260
+
261
+ // Remember the parent node ID
262
+ $parentNodeId = isset($data['id']) ? $data['id'] : null;
263
+
264
+ $items = [];
265
+
266
+ foreach ($data as $k => $v) {
267
+ // Array means could be recurable
268
+ if (is_array($v)) {
269
+ // Detect any smart-casting from the $graphObjectMap array.
270
+ // This is always empty on the GraphNode collection, but subclasses can define
271
+ // their own array of smart-casting types.
272
+ $graphObjectMap = $subclassName::getObjectMap();
273
+ $objectSubClass = isset($graphObjectMap[$k])
274
+ ? $graphObjectMap[$k]
275
+ : null;
276
+
277
+ // Could be a GraphEdge or GraphNode
278
+ $items[$k] = $this->castAsGraphNodeOrGraphEdge($v, $objectSubClass, $k, $parentNodeId);
279
+ } else {
280
+ $items[$k] = $v;
281
+ }
282
+ }
283
+
284
+ return new $subclassName($items);
285
+ }
286
+
287
+ /**
288
+ * Takes an array of values and determines how to cast each node.
289
+ *
290
+ * @param array $data The array of data to iterate over.
291
+ * @param string|null $subclassName The subclass to cast this collection to.
292
+ * @param string|null $parentKey The key of this data (Graph edge).
293
+ * @param string|null $parentNodeId The parent Graph node ID.
294
+ *
295
+ * @return GraphNode|GraphEdge
296
+ *
297
+ * @throws FacebookSDKException
298
+ */
299
+ public function castAsGraphNodeOrGraphEdge(array $data, $subclassName = null, $parentKey = null, $parentNodeId = null)
300
+ {
301
+ if (isset($data['data'])) {
302
+ // Create GraphEdge
303
+ if (static::isCastableAsGraphEdge($data['data'])) {
304
+ return $this->safelyMakeGraphEdge($data, $subclassName, $parentKey, $parentNodeId);
305
+ }
306
+ // Sometimes Graph is a weirdo and returns a GraphNode under the "data" key
307
+ $data = $data['data'];
308
+ }
309
+
310
+ // Create GraphNode
311
+ return $this->safelyMakeGraphNode($data, $subclassName);
312
+ }
313
+
314
+ /**
315
+ * Return an array of GraphNode's.
316
+ *
317
+ * @param array $data The array of data to iterate over.
318
+ * @param string|null $subclassName The GraphNode subclass to cast each item in the list to.
319
+ * @param string|null $parentKey The key of this data (Graph edge).
320
+ * @param string|null $parentNodeId The parent Graph node ID.
321
+ *
322
+ * @return GraphEdge
323
+ *
324
+ * @throws FacebookSDKException
325
+ */
326
+ public function safelyMakeGraphEdge(array $data, $subclassName = null, $parentKey = null, $parentNodeId = null)
327
+ {
328
+ if (!isset($data['data'])) {
329
+ throw new FacebookSDKException('Cannot cast data to GraphEdge. Expected a "data" key.', 620);
330
+ }
331
+
332
+ $dataList = [];
333
+ foreach ($data['data'] as $graphNode) {
334
+ $dataList[] = $this->safelyMakeGraphNode($graphNode, $subclassName);
335
+ }
336
+
337
+ $metaData = $this->getMetaData($data);
338
+
339
+ // We'll need to make an edge endpoint for this in case it's a GraphEdge (for cursor pagination)
340
+ $parentGraphEdgeEndpoint = $parentNodeId && $parentKey ? '/' . $parentNodeId . '/' . $parentKey : null;
341
+ $className = static::BASE_GRAPH_EDGE_CLASS;
342
+
343
+ return new $className($this->response->getRequest(), $dataList, $metaData, $parentGraphEdgeEndpoint, $subclassName);
344
+ }
345
+
346
+ /**
347
+ * Get the meta data from a list in a Graph response.
348
+ *
349
+ * @param array $data The Graph response.
350
+ *
351
+ * @return array
352
+ */
353
+ public function getMetaData(array $data)
354
+ {
355
+ unset($data['data']);
356
+
357
+ return $data;
358
+ }
359
+
360
+ /**
361
+ * Determines whether or not the data should be cast as a GraphEdge.
362
+ *
363
+ * @param array $data
364
+ *
365
+ * @return boolean
366
+ */
367
+ public static function isCastableAsGraphEdge(array $data)
368
+ {
369
+ if ($data === []) {
370
+ return true;
371
+ }
372
+
373
+ // Checks for a sequential numeric array which would be a GraphEdge
374
+ return array_keys($data) === range(0, count($data) - 1);
375
+ }
376
+
377
+ /**
378
+ * Ensures that the subclass in question is valid.
379
+ *
380
+ * @param string $subclassName The GraphNode subclass to validate.
381
+ *
382
+ * @throws FacebookSDKException
383
+ */
384
+ public static function validateSubclass($subclassName)
385
+ {
386
+ if ($subclassName == static::BASE_GRAPH_NODE_CLASS || is_subclass_of($subclassName, static::BASE_GRAPH_NODE_CLASS)) {
387
+ return;
388
+ }
389
+
390
+ throw new FacebookSDKException('The given subclass "' . $subclassName . '" is not valid. Cannot cast to an object that is not a GraphNode subclass.', 620);
391
+ }
392
+ }
facebook/facebook/GraphNodes/GraphObject.php ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook\GraphNodes;
25
+
26
+ /**
27
+ * Class GraphObject
28
+ *
29
+ * @package Facebook
30
+ *
31
+ * @deprecated 5.0.0 GraphObject has been renamed to GraphNode
32
+ * @todo v6: Remove this class
33
+ */
34
+ class GraphObject extends GraphNode
35
+ {
36
+ }
facebook/facebook/GraphNodes/GraphObjectFactory.php ADDED
@@ -0,0 +1,88 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook\GraphNodes;
25
+
26
+ use Facebook\Exceptions\FacebookSDKException;
27
+
28
+ /**
29
+ * Class GraphObjectFactory
30
+ *
31
+ * @package Facebook
32
+ *
33
+ * @deprecated 5.0.0 GraphObjectFactory has been renamed to GraphNodeFactory
34
+ * @todo v6: Remove this class
35
+ */
36
+ class GraphObjectFactory extends GraphNodeFactory
37
+ {
38
+ /**
39
+ * @const string The base graph object class.
40
+ */
41
+ const BASE_GRAPH_NODE_CLASS = '\Facebook\GraphNodes\GraphObject';
42
+
43
+ /**
44
+ * @const string The base graph edge class.
45
+ */
46
+ const BASE_GRAPH_EDGE_CLASS = '\Facebook\GraphNodes\GraphList';
47
+
48
+ /**
49
+ * Tries to convert a FacebookResponse entity into a GraphNode.
50
+ *
51
+ * @param string|null $subclassName The GraphNode sub class to cast to.
52
+ *
53
+ * @return GraphNode
54
+ *
55
+ * @deprecated 5.0.0 GraphObjectFactory has been renamed to GraphNodeFactory
56
+ */
57
+ public function makeGraphObject($subclassName = null)
58
+ {
59
+ return $this->makeGraphNode($subclassName);
60
+ }
61
+
62
+ /**
63
+ * Convenience method for creating a GraphEvent collection.
64
+ *
65
+ * @return GraphEvent
66
+ *
67
+ * @throws FacebookSDKException
68
+ */
69
+ public function makeGraphEvent()
70
+ {
71
+ return $this->makeGraphNode(static::BASE_GRAPH_OBJECT_PREFIX . 'GraphEvent');
72
+ }
73
+
74
+ /**
75
+ * Tries to convert a FacebookResponse entity into a GraphEdge.
76
+ *
77
+ * @param string|null $subclassName The GraphNode sub class to cast the list items to.
78
+ * @param boolean $auto_prefix Toggle to auto-prefix the subclass name.
79
+ *
80
+ * @return GraphEdge
81
+ *
82
+ * @deprecated 5.0.0 GraphObjectFactory has been renamed to GraphNodeFactory
83
+ */
84
+ public function makeGraphList($subclassName = null, $auto_prefix = true)
85
+ {
86
+ return $this->makeGraphEdge($subclassName, $auto_prefix);
87
+ }
88
+ }
facebook/facebook/GraphNodes/GraphPage.php ADDED
@@ -0,0 +1,147 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook\GraphNodes;
25
+
26
+ /**
27
+ * Class GraphPage
28
+ *
29
+ * @package Facebook
30
+ */
31
+ class GraphPage extends GraphNode
32
+ {
33
+ /**
34
+ * @var array Maps object key names to Graph object types.
35
+ */
36
+ protected static $graphObjectMap = [
37
+ 'best_page' => '\Facebook\GraphNodes\GraphPage',
38
+ 'global_brand_parent_page' => '\Facebook\GraphNodes\GraphPage',
39
+ 'location' => '\Facebook\GraphNodes\GraphLocation',
40
+ 'cover' => '\Facebook\GraphNodes\GraphCoverPhoto',
41
+ 'picture' => '\Facebook\GraphNodes\GraphPicture',
42
+ ];
43
+
44
+ /**
45
+ * Returns the ID for the user's page as a string if present.
46
+ *
47
+ * @return string|null
48
+ */
49
+ public function getId()
50
+ {
51
+ return $this->getField('id');
52
+ }
53
+
54
+ /**
55
+ * Returns the Category for the user's page as a string if present.
56
+ *
57
+ * @return string|null
58
+ */
59
+ public function getCategory()
60
+ {
61
+ return $this->getField('category');
62
+ }
63
+
64
+ /**
65
+ * Returns the Name of the user's page as a string if present.
66
+ *
67
+ * @return string|null
68
+ */
69
+ public function getName()
70
+ {
71
+ return $this->getField('name');
72
+ }
73
+
74
+ /**
75
+ * Returns the best available Page on Facebook.
76
+ *
77
+ * @return GraphPage|null
78
+ */
79
+ public function getBestPage()
80
+ {
81
+ return $this->getField('best_page');
82
+ }
83
+
84
+ /**
85
+ * Returns the brand's global (parent) Page.
86
+ *
87
+ * @return GraphPage|null
88
+ */
89
+ public function getGlobalBrandParentPage()
90
+ {
91
+ return $this->getField('global_brand_parent_page');
92
+ }
93
+
94
+ /**
95
+ * Returns the location of this place.
96
+ *
97
+ * @return GraphLocation|null
98
+ */
99
+ public function getLocation()
100
+ {
101
+ return $this->getField('location');
102
+ }
103
+
104
+ /**
105
+ * Returns CoverPhoto of the Page.
106
+ *
107
+ * @return GraphCoverPhoto|null
108
+ */
109
+ public function getCover()
110
+ {
111
+ return $this->getField('cover');
112
+ }
113
+
114
+ /**
115
+ * Returns Picture of the Page.
116
+ *
117
+ * @return GraphPicture|null
118
+ */
119
+ public function getPicture()
120
+ {
121
+ return $this->getField('picture');
122
+ }
123
+
124
+ /**
125
+ * Returns the page access token for the admin user.
126
+ *
127
+ * Only available in the `/me/accounts` context.
128
+ *
129
+ * @return string|null
130
+ */
131
+ public function getAccessToken()
132
+ {
133
+ return $this->getField('access_token');
134
+ }
135
+
136
+ /**
137
+ * Returns the roles of the page admin user.
138
+ *
139
+ * Only available in the `/me/accounts` context.
140
+ *
141
+ * @return array|null
142
+ */
143
+ public function getPerms()
144
+ {
145
+ return $this->getField('perms');
146
+ }
147
+ }
facebook/facebook/GraphNodes/GraphPicture.php ADDED
@@ -0,0 +1,72 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook\GraphNodes;
25
+
26
+ /**
27
+ * Class GraphPicture
28
+ *
29
+ * @package Facebook
30
+ */
31
+ class GraphPicture extends GraphNode
32
+ {
33
+ /**
34
+ * Returns true if user picture is silhouette.
35
+ *
36
+ * @return bool|null
37
+ */
38
+ public function isSilhouette()
39
+ {
40
+ return $this->getField('is_silhouette');
41
+ }
42
+
43
+ /**
44
+ * Returns the url of user picture if it exists
45
+ *
46
+ * @return string|null
47
+ */
48
+ public function getUrl()
49
+ {
50
+ return $this->getField('url');
51
+ }
52
+
53
+ /**
54
+ * Returns the width of user picture if it exists
55
+ *
56
+ * @return int|null
57
+ */
58
+ public function getWidth()
59
+ {
60
+ return $this->getField('width');
61
+ }
62
+
63
+ /**
64
+ * Returns the height of user picture if it exists
65
+ *
66
+ * @return int|null
67
+ */
68
+ public function getHeight()
69
+ {
70
+ return $this->getField('height');
71
+ }
72
+ }
facebook/facebook/GraphNodes/GraphSessionInfo.php ADDED
@@ -0,0 +1,102 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook\GraphNodes;
25
+
26
+ /**
27
+ * Class GraphSessionInfo
28
+ *
29
+ * @package Facebook
30
+ */
31
+ class GraphSessionInfo extends GraphNode
32
+ {
33
+ /**
34
+ * Returns the application id the token was issued for.
35
+ *
36
+ * @return string|null
37
+ */
38
+ public function getAppId()
39
+ {
40
+ return $this->getField('app_id');
41
+ }
42
+
43
+ /**
44
+ * Returns the application name the token was issued for.
45
+ *
46
+ * @return string|null
47
+ */
48
+ public function getApplication()
49
+ {
50
+ return $this->getField('application');
51
+ }
52
+
53
+ /**
54
+ * Returns the date & time that the token expires.
55
+ *
56
+ * @return \DateTime|null
57
+ */
58
+ public function getExpiresAt()
59
+ {
60
+ return $this->getField('expires_at');
61
+ }
62
+
63
+ /**
64
+ * Returns whether the token is valid.
65
+ *
66
+ * @return boolean
67
+ */
68
+ public function getIsValid()
69
+ {
70
+ return $this->getField('is_valid');
71
+ }
72
+
73
+ /**
74
+ * Returns the date & time the token was issued at.
75
+ *
76
+ * @return \DateTime|null
77
+ */
78
+ public function getIssuedAt()
79
+ {
80
+ return $this->getField('issued_at');
81
+ }
82
+
83
+ /**
84
+ * Returns the scope permissions associated with the token.
85
+ *
86
+ * @return array
87
+ */
88
+ public function getScopes()
89
+ {
90
+ return $this->getField('scopes');
91
+ }
92
+
93
+ /**
94
+ * Returns the login id of the user associated with the token.
95
+ *
96
+ * @return string|null
97
+ */
98
+ public function getUserId()
99
+ {
100
+ return $this->getField('user_id');
101
+ }
102
+ }
facebook/facebook/GraphNodes/GraphUser.php ADDED
@@ -0,0 +1,172 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook\GraphNodes;
25
+
26
+ /**
27
+ * Class GraphUser
28
+ *
29
+ * @package Facebook
30
+ */
31
+ class GraphUser extends GraphNode
32
+ {
33
+ /**
34
+ * @var array Maps object key names to Graph object types.
35
+ */
36
+ protected static $graphObjectMap = [
37
+ 'hometown' => '\Facebook\GraphNodes\GraphPage',
38
+ 'location' => '\Facebook\GraphNodes\GraphPage',
39
+ 'significant_other' => '\Facebook\GraphNodes\GraphUser',
40
+ 'picture' => '\Facebook\GraphNodes\GraphPicture',
41
+ ];
42
+
43
+ /**
44
+ * Returns the ID for the user as a string if present.
45
+ *
46
+ * @return string|null
47
+ */
48
+ public function getId()
49
+ {
50
+ return $this->getField('id');
51
+ }
52
+
53
+ /**
54
+ * Returns the name for the user as a string if present.
55
+ *
56
+ * @return string|null
57
+ */
58
+ public function getName()
59
+ {
60
+ return $this->getField('name');
61
+ }
62
+
63
+ /**
64
+ * Returns the first name for the user as a string if present.
65
+ *
66
+ * @return string|null
67
+ */
68
+ public function getFirstName()
69
+ {
70
+ return $this->getField('first_name');
71
+ }
72
+
73
+ /**
74
+ * Returns the middle name for the user as a string if present.
75
+ *
76
+ * @return string|null
77
+ */
78
+ public function getMiddleName()
79
+ {
80
+ return $this->getField('middle_name');
81
+ }
82
+
83
+ /**
84
+ * Returns the last name for the user as a string if present.
85
+ *
86
+ * @return string|null
87
+ */
88
+ public function getLastName()
89
+ {
90
+ return $this->getField('last_name');
91
+ }
92
+
93
+ /**
94
+ * Returns the email for the user as a string if present.
95
+ *
96
+ * @return string|null
97
+ */
98
+ public function getEmail()
99
+ {
100
+ return $this->getField('email');
101
+ }
102
+
103
+ /**
104
+ * Returns the gender for the user as a string if present.
105
+ *
106
+ * @return string|null
107
+ */
108
+ public function getGender()
109
+ {
110
+ return $this->getField('gender');
111
+ }
112
+
113
+ /**
114
+ * Returns the Facebook URL for the user as a string if available.
115
+ *
116
+ * @return string|null
117
+ */
118
+ public function getLink()
119
+ {
120
+ return $this->getField('link');
121
+ }
122
+
123
+ /**
124
+ * Returns the users birthday, if available.
125
+ *
126
+ * @return Birthday|null
127
+ */
128
+ public function getBirthday()
129
+ {
130
+ return $this->getField('birthday');
131
+ }
132
+
133
+ /**
134
+ * Returns the current location of the user as a GraphPage.
135
+ *
136
+ * @return GraphPage|null
137
+ */
138
+ public function getLocation()
139
+ {
140
+ return $this->getField('location');
141
+ }
142
+
143
+ /**
144
+ * Returns the current location of the user as a GraphPage.
145
+ *
146
+ * @return GraphPage|null
147
+ */
148
+ public function getHometown()
149
+ {
150
+ return $this->getField('hometown');
151
+ }
152
+
153
+ /**
154
+ * Returns the current location of the user as a GraphUser.
155
+ *
156
+ * @return GraphUser|null
157
+ */
158
+ public function getSignificantOther()
159
+ {
160
+ return $this->getField('significant_other');
161
+ }
162
+
163
+ /**
164
+ * Returns the picture of the user as a GraphPicture
165
+ *
166
+ * @return GraphPicture|null
167
+ */
168
+ public function getPicture()
169
+ {
170
+ return $this->getField('picture');
171
+ }
172
+ }
facebook/facebook/Helpers/FacebookCanvasHelper.php ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook\Helpers;
25
+
26
+ /**
27
+ * Class FacebookCanvasLoginHelper
28
+ *
29
+ * @package Facebook
30
+ */
31
+ class FacebookCanvasHelper extends FacebookSignedRequestFromInputHelper
32
+ {
33
+ /**
34
+ * Returns the app data value.
35
+ *
36
+ * @return mixed|null
37
+ */
38
+ public function getAppData()
39
+ {
40
+ return $this->signedRequest ? $this->signedRequest->get('app_data') : null;
41
+ }
42
+
43
+ /**
44
+ * Get raw signed request from POST.
45
+ *
46
+ * @return string|null
47
+ */
48
+ public function getRawSignedRequest()
49
+ {
50
+ return $this->getRawSignedRequestFromPost() ?: null;
51
+ }
52
+ }
facebook/facebook/Helpers/FacebookJavaScriptHelper.php ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook\Helpers;
25
+
26
+ /**
27
+ * Class FacebookJavaScriptLoginHelper
28
+ *
29
+ * @package Facebook
30
+ */
31
+ class FacebookJavaScriptHelper extends FacebookSignedRequestFromInputHelper
32
+ {
33
+ /**
34
+ * Get raw signed request from the cookie.
35
+ *
36
+ * @return string|null
37
+ */
38
+ public function getRawSignedRequest()
39
+ {
40
+ return $this->getRawSignedRequestFromCookie();
41
+ }
42
+ }
facebook/facebook/Helpers/FacebookPageTabHelper.php ADDED
@@ -0,0 +1,95 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook\Helpers;
25
+
26
+ use Facebook\FacebookApp;
27
+ use Facebook\FacebookClient;
28
+
29
+ /**
30
+ * Class FacebookPageTabHelper
31
+ *
32
+ * @package Facebook
33
+ */
34
+ class FacebookPageTabHelper extends FacebookCanvasHelper
35
+ {
36
+ /**
37
+ * @var array|null
38
+ */
39
+ protected $pageData;
40
+
41
+ /**
42
+ * Initialize the helper and process available signed request data.
43
+ *
44
+ * @param FacebookApp $app The FacebookApp entity.
45
+ * @param FacebookClient $client The client to make HTTP requests.
46
+ * @param string|null $graphVersion The version of Graph to use.
47
+ */
48
+ public function __construct(FacebookApp $app, FacebookClient $client, $graphVersion = null)
49
+ {
50
+ parent::__construct($app, $client, $graphVersion);
51
+
52
+ if (!$this->signedRequest) {
53
+ return;
54
+ }
55
+
56
+ $this->pageData = $this->signedRequest->get('page');
57
+ }
58
+
59
+ /**
60
+ * Returns a value from the page data.
61
+ *
62
+ * @param string $key
63
+ * @param mixed|null $default
64
+ *
65
+ * @return mixed|null
66
+ */
67
+ public function getPageData($key, $default = null)
68
+ {
69
+ if (isset($this->pageData[$key])) {
70
+ return $this->pageData[$key];
71
+ }
72
+
73
+ return $default;
74
+ }
75
+
76
+ /**
77
+ * Returns true if the user is an admin.
78
+ *
79
+ * @return boolean
80
+ */
81
+ public function isAdmin()
82
+ {
83
+ return $this->getPageData('admin') === true;
84
+ }
85
+
86
+ /**
87
+ * Returns the page id if available.
88
+ *
89
+ * @return string|null
90
+ */
91
+ public function getPageId()
92
+ {
93
+ return $this->getPageData('id');
94
+ }
95
+ }
facebook/facebook/Helpers/FacebookRedirectLoginHelper.php ADDED
@@ -0,0 +1,333 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook\Helpers;
25
+
26
+ use Facebook\Authentication\AccessToken;
27
+ use Facebook\Authentication\OAuth2Client;
28
+ use Facebook\Exceptions\FacebookSDKException;
29
+ use Facebook\PersistentData\FacebookSessionPersistentDataHandler;
30
+ use Facebook\PersistentData\PersistentDataInterface;
31
+ use Facebook\PseudoRandomString\PseudoRandomStringGeneratorFactory;
32
+ use Facebook\PseudoRandomString\PseudoRandomStringGeneratorInterface;
33
+ use Facebook\Url\FacebookUrlDetectionHandler;
34
+ use Facebook\Url\FacebookUrlManipulator;
35
+ use Facebook\Url\UrlDetectionInterface;
36
+
37
+ /**
38
+ * Class FacebookRedirectLoginHelper
39
+ *
40
+ * @package Facebook
41
+ */
42
+ class FacebookRedirectLoginHelper
43
+ {
44
+ /**
45
+ * @const int The length of CSRF string to validate the login link.
46
+ */
47
+ const CSRF_LENGTH = 32;
48
+
49
+ /**
50
+ * @var OAuth2Client The OAuth 2.0 client service.
51
+ */
52
+ protected $oAuth2Client;
53
+
54
+ /**
55
+ * @var UrlDetectionInterface The URL detection handler.
56
+ */
57
+ protected $urlDetectionHandler;
58
+
59
+ /**
60
+ * @var PersistentDataInterface The persistent data handler.
61
+ */
62
+ protected $persistentDataHandler;
63
+
64
+ /**
65
+ * @var PseudoRandomStringGeneratorInterface The cryptographically secure pseudo-random string generator.
66
+ */
67
+ protected $pseudoRandomStringGenerator;
68
+
69
+ /**
70
+ * @param OAuth2Client $oAuth2Client The OAuth 2.0 client service.
71
+ * @param PersistentDataInterface|null $persistentDataHandler The persistent data handler.
72
+ * @param UrlDetectionInterface|null $urlHandler The URL detection handler.
73
+ * @param PseudoRandomStringGeneratorInterface|null $prsg The cryptographically secure pseudo-random string generator.
74
+ */
75
+ public function __construct(OAuth2Client $oAuth2Client, PersistentDataInterface $persistentDataHandler = null, UrlDetectionInterface $urlHandler = null, PseudoRandomStringGeneratorInterface $prsg = null)
76
+ {
77
+ $this->oAuth2Client = $oAuth2Client;
78
+ $this->persistentDataHandler = $persistentDataHandler ?: new FacebookSessionPersistentDataHandler();
79
+ $this->urlDetectionHandler = $urlHandler ?: new FacebookUrlDetectionHandler();
80
+ $this->pseudoRandomStringGenerator = PseudoRandomStringGeneratorFactory::createPseudoRandomStringGenerator($prsg);
81
+ }
82
+
83
+ /**
84
+ * Returns the persistent data handler.
85
+ *
86
+ * @return PersistentDataInterface
87
+ */
88
+ public function getPersistentDataHandler()
89
+ {
90
+ return $this->persistentDataHandler;
91
+ }
92
+
93
+ /**
94
+ * Returns the URL detection handler.
95
+ *
96
+ * @return UrlDetectionInterface
97
+ */
98
+ public function getUrlDetectionHandler()
99
+ {
100
+ return $this->urlDetectionHandler;
101
+ }
102
+
103
+ /**
104
+ * Returns the cryptographically secure pseudo-random string generator.
105
+ *
106
+ * @return PseudoRandomStringGeneratorInterface
107
+ */
108
+ public function getPseudoRandomStringGenerator()
109
+ {
110
+ return $this->pseudoRandomStringGenerator;
111
+ }
112
+
113
+ /**
114
+ * Stores CSRF state and returns a URL to which the user should be sent to in order to continue the login process with Facebook.
115
+ *
116
+ * @param string $redirectUrl The URL Facebook should redirect users to after login.
117
+ * @param array $scope List of permissions to request during login.
118
+ * @param array $params An array of parameters to generate URL.
119
+ * @param string $separator The separator to use in http_build_query().
120
+ *
121
+ * @return string
122
+ */
123
+ private function makeUrl($redirectUrl, array $scope, array $params = [], $separator = '&')
124
+ {
125
+ $state = $this->persistentDataHandler->get('state') ?: $this->pseudoRandomStringGenerator->getPseudoRandomString(static::CSRF_LENGTH);
126
+ $this->persistentDataHandler->set('state', $state);
127
+
128
+ return $this->oAuth2Client->getAuthorizationUrl($redirectUrl, $state, $scope, $params, $separator);
129
+ }
130
+
131
+ /**
132
+ * Returns the URL to send the user in order to login to Facebook.
133
+ *
134
+ * @param string $redirectUrl The URL Facebook should redirect users to after login.
135
+ * @param array $scope List of permissions to request during login.
136
+ * @param string $separator The separator to use in http_build_query().
137
+ *
138
+ * @return string
139
+ */
140
+ public function getLoginUrl($redirectUrl, array $scope = [], $separator = '&')
141
+ {
142
+ return $this->makeUrl($redirectUrl, $scope, [], $separator);
143
+ }
144
+
145
+ /**
146
+ * Returns the URL to send the user in order to log out of Facebook.
147
+ *
148
+ * @param AccessToken|string $accessToken The access token that will be logged out.
149
+ * @param string $next The url Facebook should redirect the user to after a successful logout.
150
+ * @param string $separator The separator to use in http_build_query().
151
+ *
152
+ * @return string
153
+ *
154
+ * @throws FacebookSDKException
155
+ */
156
+ public function getLogoutUrl($accessToken, $next, $separator = '&')
157
+ {
158
+ if (!$accessToken instanceof AccessToken) {
159
+ $accessToken = new AccessToken($accessToken);
160
+ }
161
+
162
+ if ($accessToken->isAppAccessToken()) {
163
+ throw new FacebookSDKException('Cannot generate a logout URL with an app access token.', 722);
164
+ }
165
+
166
+ $params = [
167
+ 'next' => $next,
168
+ 'access_token' => $accessToken->getValue(),
169
+ ];
170
+
171
+ return 'https://www.facebook.com/logout.php?' . http_build_query($params, null, $separator);
172
+ }
173
+
174
+ /**
175
+ * Returns the URL to send the user in order to login to Facebook with permission(s) to be re-asked.
176
+ *
177
+ * @param string $redirectUrl The URL Facebook should redirect users to after login.
178
+ * @param array $scope List of permissions to request during login.
179
+ * @param string $separator The separator to use in http_build_query().
180
+ *
181
+ * @return string
182
+ */
183
+ public function getReRequestUrl($redirectUrl, array $scope = [], $separator = '&')
184
+ {
185
+ $params = ['auth_type' => 'rerequest'];
186
+
187
+ return $this->makeUrl($redirectUrl, $scope, $params, $separator);
188
+ }
189
+
190
+ /**
191
+ * Returns the URL to send the user in order to login to Facebook with user to be re-authenticated.
192
+ *
193
+ * @param string $redirectUrl The URL Facebook should redirect users to after login.
194
+ * @param array $scope List of permissions to request during login.
195
+ * @param string $separator The separator to use in http_build_query().
196
+ *
197
+ * @return string
198
+ */
199
+ public function getReAuthenticationUrl($redirectUrl, array $scope = [], $separator = '&')
200
+ {
201
+ $params = ['auth_type' => 'reauthenticate'];
202
+
203
+ return $this->makeUrl($redirectUrl, $scope, $params, $separator);
204
+ }
205
+
206
+ /**
207
+ * Takes a valid code from a login redirect, and returns an AccessToken entity.
208
+ *
209
+ * @param string|null $redirectUrl The redirect URL.
210
+ *
211
+ * @return AccessToken|null
212
+ *
213
+ * @throws FacebookSDKException
214
+ */
215
+ public function getAccessToken($redirectUrl = null)
216
+ {
217
+ if (!$code = $this->getCode()) {
218
+ return null;
219
+ }
220
+
221
+ $this->validateCsrf();
222
+ $this->resetCsrf();
223
+
224
+ $redirectUrl = $redirectUrl ?: $this->urlDetectionHandler->getCurrentUrl();
225
+ // At minimum we need to remove the state param
226
+ $redirectUrl = FacebookUrlManipulator::removeParamsFromUrl($redirectUrl, ['state']);
227
+
228
+ return $this->oAuth2Client->getAccessTokenFromCode($code, $redirectUrl);
229
+ }
230
+
231
+ /**
232
+ * Validate the request against a cross-site request forgery.
233
+ *
234
+ * @throws FacebookSDKException
235
+ */
236
+ protected function validateCsrf()
237
+ {
238
+ $state = $this->getState();
239
+ if (!$state) {
240
+ throw new FacebookSDKException('Cross-site request forgery validation failed. Required GET param "state" missing.');
241
+ }
242
+ $savedState = $this->persistentDataHandler->get('state');
243
+ if (!$savedState) {
244
+ throw new FacebookSDKException('Cross-site request forgery validation failed. Required param "state" missing from persistent data.');
245
+ }
246
+
247
+ if (\hash_equals($savedState, $state)) {
248
+ return;
249
+ }
250
+
251
+ throw new FacebookSDKException('Cross-site request forgery validation failed. The "state" param from the URL and session do not match.');
252
+ }
253
+
254
+ /**
255
+ * Resets the CSRF so that it doesn't get reused.
256
+ */
257
+ private function resetCsrf()
258
+ {
259
+ $this->persistentDataHandler->set('state', null);
260
+ }
261
+
262
+ /**
263
+ * Return the code.
264
+ *
265
+ * @return string|null
266
+ */
267
+ protected function getCode()
268
+ {
269
+ return $this->getInput('code');
270
+ }
271
+
272
+ /**
273
+ * Return the state.
274
+ *
275
+ * @return string|null
276
+ */
277
+ protected function getState()
278
+ {
279
+ return $this->getInput('state');
280
+ }
281
+
282
+ /**
283
+ * Return the error code.
284
+ *
285
+ * @return string|null
286
+ */
287
+ public function getErrorCode()
288
+ {
289
+ return $this->getInput('error_code');
290
+ }
291
+
292
+ /**
293
+ * Returns the error.
294
+ *
295
+ * @return string|null
296
+ */
297
+ public function getError()
298
+ {
299
+ return $this->getInput('error');
300
+ }
301
+
302
+ /**
303
+ * Returns the error reason.
304
+ *
305
+ * @return string|null
306
+ */
307
+ public function getErrorReason()
308
+ {
309
+ return $this->getInput('error_reason');
310
+ }
311
+
312
+ /**
313
+ * Returns the error description.
314
+ *
315
+ * @return string|null
316
+ */
317
+ public function getErrorDescription()
318
+ {
319
+ return $this->getInput('error_description');
320
+ }
321
+
322
+ /**
323
+ * Returns a value from a GET param.
324
+ *
325
+ * @param string $key
326
+ *
327
+ * @return string|null
328
+ */
329
+ private function getInput($key)
330
+ {
331
+ return isset($_GET[$key]) ? $_GET[$key] : null;
332
+ }
333
+ }
facebook/facebook/Helpers/FacebookSignedRequestFromInputHelper.php ADDED
@@ -0,0 +1,166 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook\Helpers;
25
+
26
+ use Facebook\Facebook;
27
+ use Facebook\FacebookApp;
28
+ use Facebook\FacebookClient;
29
+ use Facebook\SignedRequest;
30
+ use Facebook\Authentication\AccessToken;
31
+ use Facebook\Authentication\OAuth2Client;
32
+
33
+ /**
34
+ * Class FacebookSignedRequestFromInputHelper
35
+ *
36
+ * @package Facebook
37
+ */
38
+ abstract class FacebookSignedRequestFromInputHelper
39
+ {
40
+ /**
41
+ * @var SignedRequest|null The SignedRequest entity.
42
+ */
43
+ protected $signedRequest;
44
+
45
+ /**
46
+ * @var FacebookApp The FacebookApp entity.
47
+ */
48
+ protected $app;
49
+
50
+ /**
51
+ * @var OAuth2Client The OAuth 2.0 client service.
52
+ */
53
+ protected $oAuth2Client;
54
+
55
+ /**
56
+ * Initialize the helper and process available signed request data.
57
+ *
58
+ * @param FacebookApp $app The FacebookApp entity.
59
+ * @param FacebookClient $client The client to make HTTP requests.
60
+ * @param string|null $graphVersion The version of Graph to use.
61
+ */
62
+ public function __construct(FacebookApp $app, FacebookClient $client, $graphVersion = null)
63
+ {
64
+ $this->app = $app;
65
+ $graphVersion = $graphVersion ?: Facebook::DEFAULT_GRAPH_VERSION;
66
+ $this->oAuth2Client = new OAuth2Client($this->app, $client, $graphVersion);
67
+
68
+ $this->instantiateSignedRequest();
69
+ }
70
+
71
+ /**
72
+ * Instantiates a new SignedRequest entity.
73
+ *
74
+ * @param string|null
75
+ */
76
+ public function instantiateSignedRequest($rawSignedRequest = null)
77
+ {
78
+ $rawSignedRequest = $rawSignedRequest ?: $this->getRawSignedRequest();
79
+
80
+ if (!$rawSignedRequest) {
81
+ return;
82
+ }
83
+
84
+ $this->signedRequest = new SignedRequest($this->app, $rawSignedRequest);
85
+ }
86
+
87
+ /**
88
+ * Returns an AccessToken entity from the signed request.
89
+ *
90
+ * @return AccessToken|null
91
+ *
92
+ * @throws \Facebook\Exceptions\FacebookSDKException
93
+ */
94
+ public function getAccessToken()
95
+ {
96
+ if ($this->signedRequest && $this->signedRequest->hasOAuthData()) {
97
+ $code = $this->signedRequest->get('code');
98
+ $accessToken = $this->signedRequest->get('oauth_token');
99
+
100
+ if ($code && !$accessToken) {
101
+ return $this->oAuth2Client->getAccessTokenFromCode($code);
102
+ }
103
+
104
+ $expiresAt = $this->signedRequest->get('expires', 0);
105
+
106
+ return new AccessToken($accessToken, $expiresAt);
107
+ }
108
+
109
+ return null;
110
+ }
111
+
112
+ /**
113
+ * Returns the SignedRequest entity.
114
+ *
115
+ * @return SignedRequest|null
116
+ */
117
+ public function getSignedRequest()
118
+ {
119
+ return $this->signedRequest;
120
+ }
121
+
122
+ /**
123
+ * Returns the user_id if available.
124
+ *
125
+ * @return string|null
126
+ */
127
+ public function getUserId()
128
+ {
129
+ return $this->signedRequest ? $this->signedRequest->getUserId() : null;
130
+ }
131
+
132
+ /**
133
+ * Get raw signed request from input.
134
+ *
135
+ * @return string|null
136
+ */
137
+ abstract public function getRawSignedRequest();
138
+
139
+ /**
140
+ * Get raw signed request from POST input.
141
+ *
142
+ * @return string|null
143
+ */
144
+ public function getRawSignedRequestFromPost()
145
+ {
146
+ if (isset($_POST['signed_request'])) {
147
+ return $_POST['signed_request'];
148
+ }
149
+
150
+ return null;
151
+ }
152
+
153
+ /**
154
+ * Get raw signed request from cookie set from the Javascript SDK.
155
+ *
156
+ * @return string|null
157
+ */
158
+ public function getRawSignedRequestFromCookie()
159
+ {
160
+ if (isset($_COOKIE['fbsr_' . $this->app->getId()])) {
161
+ return $_COOKIE['fbsr_' . $this->app->getId()];
162
+ }
163
+
164
+ return null;
165
+ }
166
+ }
facebook/facebook/Http/GraphRawResponse.php ADDED
@@ -0,0 +1,137 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook\Http;
25
+
26
+ /**
27
+ * Class GraphRawResponse
28
+ *
29
+ * @package Facebook
30
+ */
31
+ class GraphRawResponse
32
+ {
33
+ /**
34
+ * @var array The response headers in the form of an associative array.
35
+ */
36
+ protected $headers;
37
+
38
+ /**
39
+ * @var string The raw response body.
40
+ */
41
+ protected $body;
42
+
43
+ /**
44
+ * @var int The HTTP status response code.
45
+ */
46
+ protected $httpResponseCode;
47
+
48
+ /**
49
+ * Creates a new GraphRawResponse entity.
50
+ *
51
+ * @param string|array $headers The headers as a raw string or array.
52
+ * @param string $body The raw response body.
53
+ * @param int $httpStatusCode The HTTP response code (if sending headers as parsed array).
54
+ */
55
+ public function __construct($headers, $body, $httpStatusCode = null)
56
+ {
57
+ if (is_numeric($httpStatusCode)) {
58
+ $this->httpResponseCode = (int)$httpStatusCode;
59
+ }
60
+
61
+ if (is_array($headers)) {
62
+ $this->headers = $headers;
63
+ } else {
64
+ $this->setHeadersFromString($headers);
65
+ }
66
+
67
+ $this->body = $body;
68
+ }
69
+
70
+ /**
71
+ * Return the response headers.
72
+ *
73
+ * @return array
74
+ */
75
+ public function getHeaders()
76
+ {
77
+ return $this->headers;
78
+ }
79
+
80
+ /**
81
+ * Return the body of the response.
82
+ *
83
+ * @return string
84
+ */
85
+ public function getBody()
86
+ {
87
+ return $this->body;
88
+ }
89
+
90
+ /**
91
+ * Return the HTTP response code.
92
+ *
93
+ * @return int
94
+ */
95
+ public function getHttpResponseCode()
96
+ {
97
+ return $this->httpResponseCode;
98
+ }
99
+
100
+ /**
101
+ * Sets the HTTP response code from a raw header.
102
+ *
103
+ * @param string $rawResponseHeader
104
+ */
105
+ public function setHttpResponseCodeFromHeader($rawResponseHeader)
106
+ {
107
+ preg_match('|HTTP/\d\.\d\s+(\d+)\s+.*|', $rawResponseHeader, $match);
108
+ $this->httpResponseCode = (int)$match[1];
109
+ }
110
+
111
+ /**
112
+ * Parse the raw headers and set as an array.
113
+ *
114
+ * @param string $rawHeaders The raw headers from the response.
115
+ */
116
+ protected function setHeadersFromString($rawHeaders)
117
+ {
118
+ // Normalize line breaks
119
+ $rawHeaders = str_replace("\r\n", "\n", $rawHeaders);
120
+
121
+ // There will be multiple headers if a 301 was followed
122
+ // or a proxy was followed, etc
123
+ $headerCollection = explode("\n\n", trim($rawHeaders));
124
+ // We just want the last response (at the end)
125
+ $rawHeader = array_pop($headerCollection);
126
+
127
+ $headerComponents = explode("\n", $rawHeader);
128
+ foreach ($headerComponents as $line) {
129
+ if (strpos($line, ': ') === false) {
130
+ $this->setHttpResponseCodeFromHeader($line);
131
+ } else {
132
+ list($key, $value) = explode(': ', $line, 2);
133
+ $this->headers[$key] = $value;
134
+ }
135
+ }
136
+ }
137
+ }
facebook/facebook/Http/RequestBodyInterface.php ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook\Http;
25
+
26
+ /**
27
+ * Interface
28
+ *
29
+ * @package Facebook
30
+ */
31
+ interface RequestBodyInterface
32
+ {
33
+ /**
34
+ * Get the body of the request to send to Graph.
35
+ *
36
+ * @return string
37
+ */
38
+ public function getBody();
39
+ }
facebook/facebook/Http/RequestBodyMultipart.php ADDED
@@ -0,0 +1,170 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook\Http;
25
+
26
+ use Facebook\FileUpload\FacebookFile;
27
+
28
+ /**
29
+ * Class RequestBodyMultipartt
30
+ *
31
+ * Some things copied from Guzzle
32
+ *
33
+ * @package Facebook
34
+ *
35
+ * @see https://github.com/guzzle/guzzle/blob/master/src/Post/MultipartBody.php
36
+ */
37
+ class RequestBodyMultipart implements RequestBodyInterface
38
+ {
39
+ /**
40
+ * @var string The boundary.
41
+ */
42
+ private $boundary;
43
+
44
+ /**
45
+ * @var array The parameters to send with this request.
46
+ */
47
+ private $params;
48
+
49
+ /**
50
+ * @var array The files to send with this request.
51
+ */
52
+ private $files = [];
53
+
54
+ /**
55
+ * @param array $params The parameters to send with this request.
56
+ * @param array $files The files to send with this request.
57
+ * @param string $boundary Provide a specific boundary.
58
+ */
59
+ public function __construct(array $params = [], array $files = [], $boundary = null)
60
+ {
61
+ $this->params = $params;
62
+ $this->files = $files;
63
+ $this->boundary = $boundary ?: uniqid();
64
+ }
65
+
66
+ /**
67
+ * @inheritdoc
68
+ */
69
+ public function getBody()
70
+ {
71
+ $body = '';
72
+
73
+ // Compile normal params
74
+ $params = $this->getNestedParams($this->params);
75
+ foreach ($params as $k => $v) {
76
+ $body .= $this->getParamString($k, $v);
77
+ }
78
+
79
+ // Compile files
80
+ foreach ($this->files as $k => $v) {
81
+ $body .= $this->getFileString($k, $v);
82
+ }
83
+
84
+ // Peace out
85
+ $body .= "--{$this->boundary}--\r\n";
86
+
87
+ return $body;
88
+ }
89
+
90
+ /**
91
+ * Get the boundary
92
+ *
93
+ * @return string
94
+ */
95
+ public function getBoundary()
96
+ {
97
+ return $this->boundary;
98
+ }
99
+
100
+ /**
101
+ * Get the string needed to transfer a file.
102
+ *
103
+ * @param string $name
104
+ * @param FacebookFile $file
105
+ *
106
+ * @return string
107
+ */
108
+ private function getFileString($name, FacebookFile $file)
109
+ {
110
+ return sprintf(
111
+ "--%s\r\nContent-Disposition: form-data; name=\"%s\"; filename=\"%s\"%s\r\n\r\n%s\r\n",
112
+ $this->boundary,
113
+ $name,
114
+ $file->getFileName(),
115
+ $this->getFileHeaders($file),
116
+ $file->getContents()
117
+ );
118
+ }
119
+
120
+ /**
121
+ * Get the string needed to transfer a POST field.
122
+ *
123
+ * @param string $name
124
+ * @param string $value
125
+ *
126
+ * @return string
127
+ */
128
+ private function getParamString($name, $value)
129
+ {
130
+ return sprintf(
131
+ "--%s\r\nContent-Disposition: form-data; name=\"%s\"\r\n\r\n%s\r\n",
132
+ $this->boundary,
133
+ $name,
134
+ $value
135
+ );
136
+ }
137
+
138
+ /**
139
+ * Returns the params as an array of nested params.
140
+ *
141
+ * @param array $params
142
+ *
143
+ * @return array
144
+ */
145
+ private function getNestedParams(array $params)
146
+ {
147
+ $query = http_build_query($params, null, '&');
148
+ $params = explode('&', $query);
149
+ $result = [];
150
+
151
+ foreach ($params as $param) {
152
+ list($key, $value) = explode('=', $param, 2);
153
+ $result[urldecode($key)] = urldecode($value);
154
+ }
155
+
156
+ return $result;
157
+ }
158
+
159
+ /**
160
+ * Get the headers needed before transferring the content of a POST file.
161
+ *
162
+ * @param FacebookFile $file
163
+ *
164
+ * @return string
165
+ */
166
+ protected function getFileHeaders(FacebookFile $file)
167
+ {
168
+ return "\r\nContent-Type: {$file->getMimetype()}";
169
+ }
170
+ }
facebook/facebook/Http/RequestBodyUrlEncoded.php ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook\Http;
25
+
26
+ /**
27
+ * Class RequestBodyUrlEncoded
28
+ *
29
+ * @package Facebook
30
+ */
31
+ class RequestBodyUrlEncoded implements RequestBodyInterface
32
+ {
33
+ /**
34
+ * @var array The parameters to send with this request.
35
+ */
36
+ protected $params = [];
37
+
38
+ /**
39
+ * Creates a new GraphUrlEncodedBody entity.
40
+ *
41
+ * @param array $params
42
+ */
43
+ public function __construct(array $params)
44
+ {
45
+ $this->params = $params;
46
+ }
47
+
48
+ /**
49
+ * @inheritdoc
50
+ */
51
+ public function getBody()
52
+ {
53
+ return http_build_query($this->params, null, '&');
54
+ }
55
+ }
facebook/facebook/HttpClients/FacebookCurl.php ADDED
@@ -0,0 +1,129 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook\HttpClients;
25
+
26
+ /**
27
+ * Class FacebookCurl
28
+ *
29
+ * Abstraction for the procedural curl elements so that curl can be mocked and the implementation can be tested.
30
+ *
31
+ * @package Facebook
32
+ */
33
+ class FacebookCurl
34
+ {
35
+
36
+ /**
37
+ * @var resource Curl resource instance
38
+ */
39
+ protected $curl;
40
+
41
+ /**
42
+ * Make a new curl reference instance
43
+ */
44
+ public function init()
45
+ {
46
+ $this->curl = curl_init();
47
+ }
48
+
49
+ /**
50
+ * Set a curl option
51
+ *
52
+ * @param $key
53
+ * @param $value
54
+ */
55
+ public function setopt($key, $value)
56
+ {
57
+ curl_setopt($this->curl, $key, $value);
58
+ }
59
+
60
+ /**
61
+ * Set an array of options to a curl resource
62
+ *
63
+ * @param array $options
64
+ */
65
+ public function setoptArray(array $options)
66
+ {
67
+ curl_setopt_array($this->curl, $options);
68
+ }
69
+
70
+ /**
71
+ * Send a curl request
72
+ *
73
+ * @return mixed
74
+ */
75
+ public function exec()
76
+ {
77
+ return curl_exec($this->curl);
78
+ }
79
+
80
+ /**
81
+ * Return the curl error number
82
+ *
83
+ * @return int
84
+ */
85
+ public function errno()
86
+ {
87
+ return curl_errno($this->curl);
88
+ }
89
+
90
+ /**
91
+ * Return the curl error message
92
+ *
93
+ * @return string
94
+ */
95
+ public function error()
96
+ {
97
+ return curl_error($this->curl);
98
+ }
99
+
100
+ /**
101
+ * Get info from a curl reference
102
+ *
103
+ * @param $type
104
+ *
105
+ * @return mixed
106
+ */
107
+ public function getinfo($type)
108
+ {
109
+ return curl_getinfo($this->curl, $type);
110
+ }
111
+
112
+ /**
113
+ * Get the currently installed curl version
114
+ *
115
+ * @return array
116
+ */
117
+ public function version()
118
+ {
119
+ return curl_version();
120
+ }
121
+
122
+ /**
123
+ * Close the resource connection to curl
124
+ */
125
+ public function close()
126
+ {
127
+ curl_close($this->curl);
128
+ }
129
+ }
facebook/facebook/HttpClients/FacebookCurlHttpClient.php ADDED
@@ -0,0 +1,163 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook\HttpClients;
25
+
26
+ use Facebook\Http\GraphRawResponse;
27
+ use Facebook\Exceptions\FacebookSDKException;
28
+
29
+ /**
30
+ * Class FacebookCurlHttpClient
31
+ *
32
+ * @package Facebook
33
+ */
34
+ class FacebookCurlHttpClient implements FacebookHttpClientInterface
35
+ {
36
+ /**
37
+ * @var string The client error message
38
+ */
39
+ protected $curlErrorMessage = '';
40
+
41
+ /**
42
+ * @var int The curl client error code
43
+ */
44
+ protected $curlErrorCode = 0;
45
+
46
+ /**
47
+ * @var string|boolean The raw response from the server
48
+ */
49
+ protected $rawResponse;
50
+
51
+ /**
52
+ * @var FacebookCurl Procedural curl as object
53
+ */
54
+ protected $facebookCurl;
55
+
56
+ /**
57
+ * @param FacebookCurl|null Procedural curl as object
58
+ */
59
+ public function __construct(FacebookCurl $facebookCurl = null)
60
+ {
61
+ $this->facebookCurl = $facebookCurl ?: new FacebookCurl();
62
+ }
63
+
64
+ /**
65
+ * @inheritdoc
66
+ */
67
+ public function send($url, $method, $body, array $headers, $timeOut)
68
+ {
69
+ $this->openConnection($url, $method, $body, $headers, $timeOut);
70
+ $this->sendRequest();
71
+
72
+ if ($curlErrorCode = $this->facebookCurl->errno()) {
73
+ throw new FacebookSDKException($this->facebookCurl->error(), $curlErrorCode);
74
+ }
75
+
76
+ // Separate the raw headers from the raw body
77
+ list($rawHeaders, $rawBody) = $this->extractResponseHeadersAndBody();
78
+
79
+ $this->closeConnection();
80
+
81
+ return new GraphRawResponse($rawHeaders, $rawBody);
82
+ }
83
+
84
+ /**
85
+ * Opens a new curl connection.
86
+ *
87
+ * @param string $url The endpoint to send the request to.
88
+ * @param string $method The request method.
89
+ * @param string $body The body of the request.
90
+ * @param array $headers The request headers.
91
+ * @param int $timeOut The timeout in seconds for the request.
92
+ */
93
+ public function openConnection($url, $method, $body, array $headers, $timeOut)
94
+ {
95
+ $options = [
96
+ CURLOPT_CUSTOMREQUEST => $method,
97
+ CURLOPT_HTTPHEADER => $this->compileRequestHeaders($headers),
98
+ CURLOPT_URL => $url,
99
+ CURLOPT_CONNECTTIMEOUT => 10,
100
+ CURLOPT_TIMEOUT => $timeOut,
101
+ CURLOPT_RETURNTRANSFER => true, // Return response as string
102
+ CURLOPT_HEADER => true, // Enable header processing
103
+ CURLOPT_SSL_VERIFYHOST => 2,
104
+ CURLOPT_SSL_VERIFYPEER => true,
105
+ CURLOPT_CAINFO => __DIR__ . '/certs/DigiCertHighAssuranceEVRootCA.pem',
106
+ ];
107
+
108
+ if ($method !== "GET") {
109
+ $options[CURLOPT_POSTFIELDS] = $body;
110
+ }
111
+
112
+ $this->facebookCurl->init();
113
+ $this->facebookCurl->setoptArray($options);
114
+ }
115
+
116
+ /**
117
+ * Closes an existing curl connection
118
+ */
119
+ public function closeConnection()
120
+ {
121
+ $this->facebookCurl->close();
122
+ }
123
+
124
+ /**
125
+ * Send the request and get the raw response from curl
126
+ */
127
+ public function sendRequest()
128
+ {
129
+ $this->rawResponse = $this->facebookCurl->exec();
130
+ }
131
+
132
+ /**
133
+ * Compiles the request headers into a curl-friendly format.
134
+ *
135
+ * @param array $headers The request headers.
136
+ *
137
+ * @return array
138
+ */
139
+ public function compileRequestHeaders(array $headers)
140
+ {
141
+ $return = [];
142
+
143
+ foreach ($headers as $key => $value) {
144
+ $return[] = $key . ': ' . $value;
145
+ }
146
+
147
+ return $return;
148
+ }
149
+
150
+ /**
151
+ * Extracts the headers and the body into a two-part array
152
+ *
153
+ * @return array
154
+ */
155
+ public function extractResponseHeadersAndBody()
156
+ {
157
+ $parts = explode("\r\n\r\n", $this->rawResponse);
158
+ $rawBody = array_pop($parts);
159
+ $rawHeaders = implode("\r\n\r\n", $parts);
160
+
161
+ return [trim($rawHeaders), trim($rawBody)];
162
+ }
163
+ }
facebook/facebook/HttpClients/FacebookGuzzleHttpClient.php ADDED
@@ -0,0 +1,97 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook\HttpClients;
25
+
26
+ use Facebook\Http\GraphRawResponse;
27
+ use Facebook\Exceptions\FacebookSDKException;
28
+
29
+ use GuzzleHttp\Client;
30
+ use GuzzleHttp\Message\ResponseInterface;
31
+ use GuzzleHttp\Ring\Exception\RingException;
32
+ use GuzzleHttp\Exception\RequestException;
33
+
34
+ class FacebookGuzzleHttpClient implements FacebookHttpClientInterface
35
+ {
36
+ /**
37
+ * @var \GuzzleHttp\Client The Guzzle client.
38
+ */
39
+ protected $guzzleClient;
40
+
41
+ /**
42
+ * @param \GuzzleHttp\Client|null The Guzzle client.
43
+ */
44
+ public function __construct(Client $guzzleClient = null)
45
+ {
46
+ $this->guzzleClient = $guzzleClient ?: new Client();
47
+ }
48
+
49
+ /**
50
+ * @inheritdoc
51
+ */
52
+ public function send($url, $method, $body, array $headers, $timeOut)
53
+ {
54
+ $options = [
55
+ 'headers' => $headers,
56
+ 'body' => $body,
57
+ 'timeout' => $timeOut,
58
+ 'connect_timeout' => 10,
59
+ 'verify' => __DIR__ . '/certs/DigiCertHighAssuranceEVRootCA.pem',
60
+ ];
61
+ $request = $this->guzzleClient->createRequest($method, $url, $options);
62
+
63
+ try {
64
+ $rawResponse = $this->guzzleClient->send($request);
65
+ } catch (RequestException $e) {
66
+ $rawResponse = $e->getResponse();
67
+
68
+ if ($e->getPrevious() instanceof RingException || !$rawResponse instanceof ResponseInterface) {
69
+ throw new FacebookSDKException($e->getMessage(), $e->getCode());
70
+ }
71
+ }
72
+
73
+ $rawHeaders = $this->getHeadersAsString($rawResponse);
74
+ $rawBody = $rawResponse->getBody();
75
+ $httpStatusCode = $rawResponse->getStatusCode();
76
+
77
+ return new GraphRawResponse($rawHeaders, $rawBody, $httpStatusCode);
78
+ }
79
+
80
+ /**
81
+ * Returns the Guzzle array of headers as a string.
82
+ *
83
+ * @param ResponseInterface $response The Guzzle response.
84
+ *
85
+ * @return string
86
+ */
87
+ public function getHeadersAsString(ResponseInterface $response)
88
+ {
89
+ $headers = $response->getHeaders();
90
+ $rawHeaders = [];
91
+ foreach ($headers as $name => $values) {
92
+ $rawHeaders[] = $name . ": " . implode(", ", $values);
93
+ }
94
+
95
+ return implode("\r\n", $rawHeaders);
96
+ }
97
+ }
facebook/facebook/HttpClients/FacebookHttpClientInterface.php ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook\HttpClients;
25
+
26
+ /**
27
+ * Interface FacebookHttpClientInterface
28
+ *
29
+ * @package Facebook
30
+ */
31
+ interface FacebookHttpClientInterface
32
+ {
33
+ /**
34
+ * Sends a request to the server and returns the raw response.
35
+ *
36
+ * @param string $url The endpoint to send the request to.
37
+ * @param string $method The request method.
38
+ * @param string $body The body of the request.
39
+ * @param array $headers The request headers.
40
+ * @param int $timeOut The timeout in seconds for the request.
41
+ *
42
+ * @return \Facebook\Http\GraphRawResponse Raw response from the server.
43
+ *
44
+ * @throws \Facebook\Exceptions\FacebookSDKException
45
+ */
46
+ public function send($url, $method, $body, array $headers, $timeOut);
47
+ }
facebook/facebook/HttpClients/FacebookStream.php ADDED
@@ -0,0 +1,80 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook\HttpClients;
25
+
26
+ /**
27
+ * Class FacebookStream
28
+ *
29
+ * Abstraction for the procedural stream elements so that the functions can be
30
+ * mocked and the implementation can be tested.
31
+ *
32
+ * @package Facebook
33
+ */
34
+ class FacebookStream
35
+ {
36
+ /**
37
+ * @var resource Context stream resource instance
38
+ */
39
+ protected $stream;
40
+
41
+ /**
42
+ * @var array Response headers from the stream wrapper
43
+ */
44
+ protected $responseHeaders = [];
45
+
46
+ /**
47
+ * Make a new context stream reference instance
48
+ *
49
+ * @param array $options
50
+ */
51
+ public function streamContextCreate(array $options)
52
+ {
53
+ $this->stream = stream_context_create($options);
54
+ }
55
+
56
+ /**
57
+ * The response headers from the stream wrapper
58
+ *
59
+ * @return array
60
+ */
61
+ public function getResponseHeaders()
62
+ {
63
+ return $this->responseHeaders;
64
+ }
65
+
66
+ /**
67
+ * Send a stream wrapped request
68
+ *
69
+ * @param string $url
70
+ *
71
+ * @return mixed
72
+ */
73
+ public function fileGetContents($url)
74
+ {
75
+ $rawResponse = file_get_contents($url, false, $this->stream);
76
+ $this->responseHeaders = $http_response_header ?: [];
77
+
78
+ return $rawResponse;
79
+ }
80
+ }
facebook/facebook/HttpClients/FacebookStreamHttpClient.php ADDED
@@ -0,0 +1,94 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook\HttpClients;
25
+
26
+ use Facebook\Http\GraphRawResponse;
27
+ use Facebook\Exceptions\FacebookSDKException;
28
+
29
+ class FacebookStreamHttpClient implements FacebookHttpClientInterface
30
+ {
31
+ /**
32
+ * @var FacebookStream Procedural stream wrapper as object.
33
+ */
34
+ protected $facebookStream;
35
+
36
+ /**
37
+ * @param FacebookStream|null Procedural stream wrapper as object.
38
+ */
39
+ public function __construct(FacebookStream $facebookStream = null)
40
+ {
41
+ $this->facebookStream = $facebookStream ?: new FacebookStream();
42
+ }
43
+
44
+ /**
45
+ * @inheritdoc
46
+ */
47
+ public function send($url, $method, $body, array $headers, $timeOut)
48
+ {
49
+ $options = [
50
+ 'http' => [
51
+ 'method' => $method,
52
+ 'header' => $this->compileHeader($headers),
53
+ 'content' => $body,
54
+ 'timeout' => $timeOut,
55
+ 'ignore_errors' => true
56
+ ],
57
+ 'ssl' => [
58
+ 'verify_peer' => true,
59
+ 'verify_peer_name' => true,
60
+ 'allow_self_signed' => true, // All root certificates are self-signed
61
+ 'cafile' => __DIR__ . '/certs/DigiCertHighAssuranceEVRootCA.pem',
62
+ ],
63
+ ];
64
+
65
+ $this->facebookStream->streamContextCreate($options);
66
+ $rawBody = $this->facebookStream->fileGetContents($url);
67
+ $rawHeaders = $this->facebookStream->getResponseHeaders();
68
+
69
+ if ($rawBody === false || empty($rawHeaders)) {
70
+ throw new FacebookSDKException('Stream returned an empty response', 660);
71
+ }
72
+
73
+ $rawHeaders = implode("\r\n", $rawHeaders);
74
+
75
+ return new GraphRawResponse($rawHeaders, $rawBody);
76
+ }
77
+
78
+ /**
79
+ * Formats the headers for use in the stream wrapper.
80
+ *
81
+ * @param array $headers The request headers.
82
+ *
83
+ * @return string
84
+ */
85
+ public function compileHeader(array $headers)
86
+ {
87
+ $header = [];
88
+ foreach ($headers as $k => $v) {
89
+ $header[] = $k . ': ' . $v;
90
+ }
91
+
92
+ return implode("\r\n", $header);
93
+ }
94
+ }
facebook/facebook/HttpClients/HttpClientsFactory.php ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook\HttpClients;
25
+
26
+ use GuzzleHttp\Client;
27
+ use InvalidArgumentException;
28
+ use Exception;
29
+
30
+ class HttpClientsFactory
31
+ {
32
+ private function __construct()
33
+ {
34
+ // a factory constructor should never be invoked
35
+ }
36
+
37
+ /**
38
+ * HTTP client generation.
39
+ *
40
+ * @param FacebookHttpClientInterface|Client|string|null $handler
41
+ *
42
+ * @throws Exception If the cURL extension or the Guzzle client aren't available (if required).
43
+ * @throws InvalidArgumentException If the http client handler isn't "curl", "stream", "guzzle", or an instance of Facebook\HttpClients\FacebookHttpClientInterface.
44
+ *
45
+ * @return FacebookHttpClientInterface
46
+ */
47
+ public static function createHttpClient($handler)
48
+ {
49
+ if (!$handler) {
50
+ return self::detectDefaultClient();
51
+ }
52
+
53
+ if ($handler instanceof FacebookHttpClientInterface) {
54
+ return $handler;
55
+ }
56
+
57
+ if ('stream' === $handler) {
58
+ return new FacebookStreamHttpClient();
59
+ }
60
+ if ('curl' === $handler) {
61
+ if (!extension_loaded('curl')) {
62
+ throw new Exception('The cURL extension must be loaded in order to use the "curl" handler.');
63
+ }
64
+
65
+ return new FacebookCurlHttpClient();
66
+ }
67
+
68
+ if ('guzzle' === $handler && !class_exists('GuzzleHttp\Client')) {
69
+ throw new Exception('The Guzzle HTTP client must be included in order to use the "guzzle" handler.');
70
+ }
71
+
72
+ if ($handler instanceof Client) {
73
+ return new FacebookGuzzleHttpClient($handler);
74
+ }
75
+ if ('guzzle' === $handler) {
76
+ return new FacebookGuzzleHttpClient();
77
+ }
78
+
79
+ 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');
80
+ }
81
+
82
+ /**
83
+ * Detect default HTTP client.
84
+ *
85
+ * @return FacebookHttpClientInterface
86
+ */
87
+ private static function detectDefaultClient()
88
+ {
89
+ if (extension_loaded('curl')) {
90
+ return new FacebookCurlHttpClient();
91
+ }
92
+
93
+ if (class_exists('GuzzleHttp\Client')) {
94
+ return new FacebookGuzzleHttpClient();
95
+ }
96
+
97
+ return new FacebookStreamHttpClient();
98
+ }
99
+ }
facebook/facebook/HttpClients/certs/DigiCertHighAssuranceEVRootCA.pem ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs
3
+ MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
4
+ d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j
5
+ ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL
6
+ MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3
7
+ LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug
8
+ RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm
9
+ +9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW
10
+ PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM
11
+ xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB
12
+ Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3
13
+ hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg
14
+ EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF
15
+ MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA
16
+ FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec
17
+ nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z
18
+ eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF
19
+ hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2
20
+ Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe
21
+ vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep
22
+ +OkuE6N36B9K
23
+ -----END CERTIFICATE-----
facebook/facebook/PersistentData/FacebookMemoryPersistentDataHandler.php ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook\PersistentData;
25
+
26
+ /**
27
+ * Class FacebookMemoryPersistentDataHandler
28
+ *
29
+ * @package Facebook
30
+ */
31
+ class FacebookMemoryPersistentDataHandler implements PersistentDataInterface
32
+ {
33
+ /**
34
+ * @var array The session data to keep in memory.
35
+ */
36
+ protected $sessionData = [];
37
+
38
+ /**
39
+ * @inheritdoc
40
+ */
41
+ public function get($key)
42
+ {
43
+ return isset($this->sessionData[$key]) ? $this->sessionData[$key] : null;
44
+ }
45
+
46
+ /**
47
+ * @inheritdoc
48
+ */
49
+ public function set($key, $value)
50
+ {
51
+ $this->sessionData[$key] = $value;
52
+ }
53
+ }
facebook/facebook/PersistentData/FacebookSessionPersistentDataHandler.php ADDED
@@ -0,0 +1,76 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook\PersistentData;
25
+
26
+ use Facebook\Exceptions\FacebookSDKException;
27
+
28
+ /**
29
+ * Class FacebookSessionPersistentDataHandler
30
+ *
31
+ * @package Facebook
32
+ */
33
+ class FacebookSessionPersistentDataHandler implements PersistentDataInterface
34
+ {
35
+ /**
36
+ * @var string Prefix to use for session variables.
37
+ */
38
+ protected $sessionPrefix = 'FBRLH_';
39
+
40
+ /**
41
+ * Init the session handler.
42
+ *
43
+ * @param boolean $enableSessionCheck
44
+ *
45
+ * @throws FacebookSDKException
46
+ */
47
+ public function __construct($enableSessionCheck = true)
48
+ {
49
+ if ($enableSessionCheck && session_status() !== PHP_SESSION_ACTIVE) {
50
+ throw new FacebookSDKException(
51
+ 'Sessions are not active. Please make sure session_start() is at the top of your script.',
52
+ 720
53
+ );
54
+ }
55
+ }
56
+
57
+ /**
58
+ * @inheritdoc
59
+ */
60
+ public function get($key)
61
+ {
62
+ if (isset($_SESSION[$this->sessionPrefix . $key])) {
63
+ return $_SESSION[$this->sessionPrefix . $key];
64
+ }
65
+
66
+ return null;
67
+ }
68
+
69
+ /**
70
+ * @inheritdoc
71
+ */
72
+ public function set($key, $value)
73
+ {
74
+ $_SESSION[$this->sessionPrefix . $key] = $value;
75
+ }
76
+ }
facebook/facebook/PersistentData/PersistentDataFactory.php ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook\PersistentData;
25
+
26
+ use InvalidArgumentException;
27
+
28
+ class PersistentDataFactory
29
+ {
30
+ private function __construct()
31
+ {
32
+ // a factory constructor should never be invoked
33
+ }
34
+
35
+ /**
36
+ * PersistentData generation.
37
+ *
38
+ * @param PersistentDataInterface|string|null $handler
39
+ *
40
+ * @throws InvalidArgumentException If the persistent data handler isn't "session", "memory", or an instance of Facebook\PersistentData\PersistentDataInterface.
41
+ *
42
+ * @return PersistentDataInterface
43
+ */
44
+ public static function createPersistentDataHandler($handler)
45
+ {
46
+ if (!$handler) {
47
+ return session_status() === PHP_SESSION_ACTIVE
48
+ ? new FacebookSessionPersistentDataHandler()
49
+ : new FacebookMemoryPersistentDataHandler();
50
+ }
51
+
52
+ if ($handler instanceof PersistentDataInterface) {
53
+ return $handler;
54
+ }
55
+
56
+ if ('session' === $handler) {
57
+ return new FacebookSessionPersistentDataHandler();
58
+ }
59
+ if ('memory' === $handler) {
60
+ return new FacebookMemoryPersistentDataHandler();
61
+ }
62
+
63
+ throw new InvalidArgumentException('The persistent data handler must be set to "session", "memory", or be an instance of Facebook\PersistentData\PersistentDataInterface');
64
+ }
65
+ }
facebook/facebook/PersistentData/PersistentDataInterface.php ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook\PersistentData;
25
+
26
+ /**
27
+ * Interface PersistentDataInterface
28
+ *
29
+ * @package Facebook
30
+ */
31
+ interface PersistentDataInterface
32
+ {
33
+ /**
34
+ * Get a value from a persistent data store.
35
+ *
36
+ * @param string $key
37
+ *
38
+ * @return mixed
39
+ */
40
+ public function get($key);
41
+
42
+ /**
43
+ * Set a value in the persistent data store.
44
+ *
45
+ * @param string $key
46
+ * @param mixed $value
47
+ */
48
+ public function set($key, $value);
49
+ }
facebook/facebook/PseudoRandomString/McryptPseudoRandomStringGenerator.php ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook\PseudoRandomString;
25
+
26
+ use Facebook\Exceptions\FacebookSDKException;
27
+
28
+ class McryptPseudoRandomStringGenerator implements PseudoRandomStringGeneratorInterface
29
+ {
30
+ use PseudoRandomStringGeneratorTrait;
31
+
32
+ /**
33
+ * @const string The error message when generating the string fails.
34
+ */
35
+ const ERROR_MESSAGE = 'Unable to generate a cryptographically secure pseudo-random string from mcrypt_create_iv(). ';
36
+
37
+ /**
38
+ * @throws FacebookSDKException
39
+ */
40
+ public function __construct()
41
+ {
42
+ if (!function_exists('mcrypt_create_iv')) {
43
+ throw new FacebookSDKException(
44
+ static::ERROR_MESSAGE .
45
+ 'The function mcrypt_create_iv() does not exist.'
46
+ );
47
+ }
48
+ }
49
+
50
+ /**
51
+ * @inheritdoc
52
+ */
53
+ public function getPseudoRandomString($length)
54
+ {
55
+ $this->validateLength($length);
56
+
57
+ $binaryString = mcrypt_create_iv($length, MCRYPT_DEV_URANDOM);
58
+
59
+ if ($binaryString === false) {
60
+ throw new FacebookSDKException(
61
+ static::ERROR_MESSAGE .
62
+ 'mcrypt_create_iv() returned an error.'
63
+ );
64
+ }
65
+
66
+ return $this->binToHex($binaryString, $length);
67
+ }
68
+ }
facebook/facebook/PseudoRandomString/OpenSslPseudoRandomStringGenerator.php ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook\PseudoRandomString;
25
+
26
+ use Facebook\Exceptions\FacebookSDKException;
27
+
28
+ class OpenSslPseudoRandomStringGenerator implements PseudoRandomStringGeneratorInterface
29
+ {
30
+ use PseudoRandomStringGeneratorTrait;
31
+
32
+ /**
33
+ * @const string The error message when generating the string fails.
34
+ */
35
+ const ERROR_MESSAGE = 'Unable to generate a cryptographically secure pseudo-random string from openssl_random_pseudo_bytes().';
36
+
37
+ /**
38
+ * @throws FacebookSDKException
39
+ */
40
+ public function __construct()
41
+ {
42
+ if (!function_exists('openssl_random_pseudo_bytes')) {
43
+ throw new FacebookSDKException(static::ERROR_MESSAGE . 'The function openssl_random_pseudo_bytes() does not exist.');
44
+ }
45
+ }
46
+
47
+ /**
48
+ * @inheritdoc
49
+ */
50
+ public function getPseudoRandomString($length)
51
+ {
52
+ $this->validateLength($length);
53
+
54
+ $wasCryptographicallyStrong = false;
55
+ $binaryString = openssl_random_pseudo_bytes($length, $wasCryptographicallyStrong);
56
+
57
+ if ($binaryString === false) {
58
+ throw new FacebookSDKException(static::ERROR_MESSAGE . 'openssl_random_pseudo_bytes() returned an unknown error.');
59
+ }
60
+
61
+ if ($wasCryptographicallyStrong !== true) {
62
+ throw new FacebookSDKException(static::ERROR_MESSAGE . 'openssl_random_pseudo_bytes() returned a pseudo-random string but it was not cryptographically secure and cannot be used.');
63
+ }
64
+
65
+ return $this->binToHex($binaryString, $length);
66
+ }
67
+ }
facebook/facebook/PseudoRandomString/PseudoRandomStringGeneratorFactory.php ADDED
@@ -0,0 +1,101 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook\PseudoRandomString;
25
+
26
+ use Facebook\Exceptions\FacebookSDKException;
27
+ use InvalidArgumentException;
28
+
29
+ class PseudoRandomStringGeneratorFactory
30
+ {
31
+ private function __construct()
32
+ {
33
+ // a factory constructor should never be invoked
34
+ }
35
+
36
+ /**
37
+ * Pseudo random string generator creation.
38
+ *
39
+ * @param PseudoRandomStringGeneratorInterface|string|null $generator
40
+ *
41
+ * @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.
42
+ *
43
+ * @return PseudoRandomStringGeneratorInterface
44
+ */
45
+ public static function createPseudoRandomStringGenerator($generator)
46
+ {
47
+ if (!$generator) {
48
+ return self::detectDefaultPseudoRandomStringGenerator();
49
+ }
50
+
51
+ if ($generator instanceof PseudoRandomStringGeneratorInterface) {
52
+ return $generator;
53
+ }
54
+
55
+ if ('random_bytes' === $generator) {
56
+ return new RandomBytesPseudoRandomStringGenerator();
57
+ }
58
+ if ('mcrypt' === $generator) {
59
+ return new McryptPseudoRandomStringGenerator();
60
+ }
61
+ if ('openssl' === $generator) {
62
+ return new OpenSslPseudoRandomStringGenerator();
63
+ }
64
+ if ('urandom' === $generator) {
65
+ return new UrandomPseudoRandomStringGenerator();
66
+ }
67
+
68
+ 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');
69
+ }
70
+
71
+ /**
72
+ * Detects which pseudo-random string generator to use.
73
+ *
74
+ * @throws FacebookSDKException If unable to detect a cryptographically secure pseudo-random string generator.
75
+ *
76
+ * @return PseudoRandomStringGeneratorInterface
77
+ */
78
+ private static function detectDefaultPseudoRandomStringGenerator()
79
+ {
80
+ // Check for PHP 7's CSPRNG first to keep mcrypt deprecation messages from appearing in PHP 7.1.
81
+ if (function_exists('random_bytes')) {
82
+ return new RandomBytesPseudoRandomStringGenerator();
83
+ }
84
+
85
+ // Since openssl_random_pseudo_bytes() can sometimes return non-cryptographically
86
+ // secure pseudo-random strings (in rare cases), we check for mcrypt_create_iv() next.
87
+ if (function_exists('mcrypt_create_iv')) {
88
+ return new McryptPseudoRandomStringGenerator();
89
+ }
90
+
91
+ if (function_exists('openssl_random_pseudo_bytes')) {
92
+ return new OpenSslPseudoRandomStringGenerator();
93
+ }
94
+
95
+ if (!ini_get('open_basedir') && is_readable('/dev/urandom')) {
96
+ return new UrandomPseudoRandomStringGenerator();
97
+ }
98
+
99
+ throw new FacebookSDKException('Unable to detect a cryptographically secure pseudo-random string generator.');
100
+ }
101
+ }
facebook/facebook/PseudoRandomString/PseudoRandomStringGeneratorInterface.php ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook\PseudoRandomString;
25
+
26
+ /**
27
+ * Interface
28
+ *
29
+ * @package Facebook
30
+ */
31
+ interface PseudoRandomStringGeneratorInterface
32
+ {
33
+ /**
34
+ * Get a cryptographically secure pseudo-random string of arbitrary length.
35
+ *
36
+ * @see http://sockpuppet.org/blog/2014/02/25/safely-generate-random-numbers/
37
+ *
38
+ * @param int $length The length of the string to return.
39
+ *
40
+ * @return string
41
+ *
42
+ * @throws \Facebook\Exceptions\FacebookSDKException|\InvalidArgumentException
43
+ */
44
+ public function getPseudoRandomString($length);
45
+ }
facebook/facebook/PseudoRandomString/PseudoRandomStringGeneratorTrait.php ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook\PseudoRandomString;
25
+
26
+ trait PseudoRandomStringGeneratorTrait
27
+ {
28
+ /**
29
+ * Validates the length argument of a random string.
30
+ *
31
+ * @param int $length The length to validate.
32
+ *
33
+ * @throws \InvalidArgumentException
34
+ */
35
+ public function validateLength($length)
36
+ {
37
+ if (!is_int($length)) {
38
+ throw new \InvalidArgumentException('getPseudoRandomString() expects an integer for the string length');
39
+ }
40
+
41
+ if ($length < 1) {
42
+ throw new \InvalidArgumentException('getPseudoRandomString() expects a length greater than 1');
43
+ }
44
+ }
45
+
46
+ /**
47
+ * Converts binary data to hexadecimal of arbitrary length.
48
+ *
49
+ * @param string $binaryData The binary data to convert to hex.
50
+ * @param int $length The length of the string to return.
51
+ *
52
+ * @return string
53
+ */
54
+ public function binToHex($binaryData, $length)
55
+ {
56
+ return \substr(\bin2hex($binaryData), 0, $length);
57
+ }
58
+ }
facebook/facebook/PseudoRandomString/RandomBytesPseudoRandomStringGenerator.php ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook\PseudoRandomString;
25
+
26
+ use Facebook\Exceptions\FacebookSDKException;
27
+
28
+ class RandomBytesPseudoRandomStringGenerator implements PseudoRandomStringGeneratorInterface
29
+ {
30
+ use PseudoRandomStringGeneratorTrait;
31
+
32
+ /**
33
+ * @const string The error message when generating the string fails.
34
+ */
35
+ const ERROR_MESSAGE = 'Unable to generate a cryptographically secure pseudo-random string from random_bytes(). ';
36
+
37
+ /**
38
+ * @throws FacebookSDKException
39
+ */
40
+ public function __construct()
41
+ {
42
+ if (!function_exists('random_bytes')) {
43
+ throw new FacebookSDKException(
44
+ static::ERROR_MESSAGE .
45
+ 'The function random_bytes() does not exist.'
46
+ );
47
+ }
48
+ }
49
+
50
+ /**
51
+ * @inheritdoc
52
+ */
53
+ public function getPseudoRandomString($length)
54
+ {
55
+ $this->validateLength($length);
56
+
57
+ return $this->binToHex(random_bytes($length), $length);
58
+ }
59
+ }
facebook/facebook/PseudoRandomString/UrandomPseudoRandomStringGenerator.php ADDED
@@ -0,0 +1,89 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook\PseudoRandomString;
25
+
26
+ use Facebook\Exceptions\FacebookSDKException;
27
+
28
+ class UrandomPseudoRandomStringGenerator implements PseudoRandomStringGeneratorInterface
29
+ {
30
+
31
+ use PseudoRandomStringGeneratorTrait;
32
+
33
+ /**
34
+ * @const string The error message when generating the string fails.
35
+ */
36
+ const ERROR_MESSAGE = 'Unable to generate a cryptographically secure pseudo-random string from /dev/urandom. ';
37
+
38
+ /**
39
+ * @throws FacebookSDKException
40
+ */
41
+ public function __construct()
42
+ {
43
+ if (ini_get('open_basedir')) {
44
+ throw new FacebookSDKException(
45
+ static::ERROR_MESSAGE .
46
+ 'There is an open_basedir constraint that prevents access to /dev/urandom.'
47
+ );
48
+ }
49
+
50
+ if (!is_readable('/dev/urandom')) {
51
+ throw new FacebookSDKException(
52
+ static::ERROR_MESSAGE .
53
+ 'Unable to read from /dev/urandom.'
54
+ );
55
+ }
56
+ }
57
+
58
+ /**
59
+ * @inheritdoc
60
+ */
61
+ public function getPseudoRandomString($length)
62
+ {
63
+ $this->validateLength($length);
64
+
65
+ $stream = fopen('/dev/urandom', 'rb');
66
+ if (!is_resource($stream)) {
67
+ throw new FacebookSDKException(
68
+ static::ERROR_MESSAGE .
69
+ 'Unable to open stream to /dev/urandom.'
70
+ );
71
+ }
72
+
73
+ if (!defined('HHVM_VERSION')) {
74
+ stream_set_read_buffer($stream, 0);
75
+ }
76
+
77
+ $binaryString = fread($stream, $length);
78
+ fclose($stream);
79
+
80
+ if (!$binaryString) {
81
+ throw new FacebookSDKException(
82
+ static::ERROR_MESSAGE .
83
+ 'Stream to /dev/urandom returned no data.'
84
+ );
85
+ }
86
+
87
+ return $this->binToHex($binaryString, $length);
88
+ }
89
+ }
facebook/facebook/SignedRequest.php ADDED
@@ -0,0 +1,326 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook;
25
+
26
+ use Facebook\Exceptions\FacebookSDKException;
27
+
28
+ /**
29
+ * Class SignedRequest
30
+ *
31
+ * @package Facebook
32
+ */
33
+ class SignedRequest
34
+ {
35
+ /**
36
+ * @var FacebookApp The FacebookApp entity.
37
+ */
38
+ protected $app;
39
+
40
+ /**
41
+ * @var string The raw encrypted signed request.
42
+ */
43
+ protected $rawSignedRequest;
44
+
45
+ /**
46
+ * @var array The payload from the decrypted signed request.
47
+ */
48
+ protected $payload;
49
+
50
+ /**
51
+ * Instantiate a new SignedRequest entity.
52
+ *
53
+ * @param FacebookApp $facebookApp The FacebookApp entity.
54
+ * @param string|null $rawSignedRequest The raw signed request.
55
+ */
56
+ public function __construct(FacebookApp $facebookApp, $rawSignedRequest = null)
57
+ {
58
+ $this->app = $facebookApp;
59
+
60
+ if (!$rawSignedRequest) {
61
+ return;
62
+ }
63
+
64
+ $this->rawSignedRequest = $rawSignedRequest;
65
+
66
+ $this->parse();
67
+ }
68
+
69
+ /**
70
+ * Returns the raw signed request data.
71
+ *
72
+ * @return string|null
73
+ */
74
+ public function getRawSignedRequest()
75
+ {
76
+ return $this->rawSignedRequest;
77
+ }
78
+
79
+ /**
80
+ * Returns the parsed signed request data.
81
+ *
82
+ * @return array|null
83
+ */
84
+ public function getPayload()
85
+ {
86
+ return $this->payload;
87
+ }
88
+
89
+ /**
90
+ * Returns a property from the signed request data if available.
91
+ *
92
+ * @param string $key
93
+ * @param mixed|null $default
94
+ *
95
+ * @return mixed|null
96
+ */
97
+ public function get($key, $default = null)
98
+ {
99
+ if (isset($this->payload[$key])) {
100
+ return $this->payload[$key];
101
+ }
102
+
103
+ return $default;
104
+ }
105
+
106
+ /**
107
+ * Returns user_id from signed request data if available.
108
+ *
109
+ * @return string|null
110
+ */
111
+ public function getUserId()
112
+ {
113
+ return $this->get('user_id');
114
+ }
115
+
116
+ /**
117
+ * Checks for OAuth data in the payload.
118
+ *
119
+ * @return boolean
120
+ */
121
+ public function hasOAuthData()
122
+ {
123
+ return $this->get('oauth_token') || $this->get('code');
124
+ }
125
+
126
+ /**
127
+ * Creates a signed request from an array of data.
128
+ *
129
+ * @param array $payload
130
+ *
131
+ * @return string
132
+ */
133
+ public function make(array $payload)
134
+ {
135
+ $payload['algorithm'] = isset($payload['algorithm']) ? $payload['algorithm'] : 'HMAC-SHA256';
136
+ $payload['issued_at'] = isset($payload['issued_at']) ? $payload['issued_at'] : time();
137
+ $encodedPayload = $this->base64UrlEncode(json_encode($payload));
138
+
139
+ $hashedSig = $this->hashSignature($encodedPayload);
140
+ $encodedSig = $this->base64UrlEncode($hashedSig);
141
+
142
+ return $encodedSig . '.' . $encodedPayload;
143
+ }
144
+
145
+ /**
146
+ * Validates and decodes a signed request and saves
147
+ * the payload to an array.
148
+ */
149
+ protected function parse()
150
+ {
151
+ list($encodedSig, $encodedPayload) = $this->split();
152
+
153
+ // Signature validation
154
+ $sig = $this->decodeSignature($encodedSig);
155
+ $hashedSig = $this->hashSignature($encodedPayload);
156
+ $this->validateSignature($hashedSig, $sig);
157
+
158
+ $this->payload = $this->decodePayload($encodedPayload);
159
+
160
+ // Payload validation
161
+ $this->validateAlgorithm();
162
+ }
163
+
164
+ /**
165
+ * Splits a raw signed request into signature and payload.
166
+ *
167
+ * @return array
168
+ *
169
+ * @throws FacebookSDKException
170
+ */
171
+ protected function split()
172
+ {
173
+ if (strpos($this->rawSignedRequest, '.') === false) {
174
+ throw new FacebookSDKException('Malformed signed request.', 606);
175
+ }
176
+
177
+ return explode('.', $this->rawSignedRequest, 2);
178
+ }
179
+
180
+ /**
181
+ * Decodes the raw signature from a signed request.
182
+ *
183
+ * @param string $encodedSig
184
+ *
185
+ * @return string
186
+ *
187
+ * @throws FacebookSDKException
188
+ */
189
+ protected function decodeSignature($encodedSig)
190
+ {
191
+ $sig = $this->base64UrlDecode($encodedSig);
192
+
193
+ if (!$sig) {
194
+ throw new FacebookSDKException('Signed request has malformed encoded signature data.', 607);
195
+ }
196
+
197
+ return $sig;
198
+ }
199
+
200
+ /**
201
+ * Decodes the raw payload from a signed request.
202
+ *
203
+ * @param string $encodedPayload
204
+ *
205
+ * @return array
206
+ *
207
+ * @throws FacebookSDKException
208
+ */
209
+ protected function decodePayload($encodedPayload)
210
+ {
211
+ $payload = $this->base64UrlDecode($encodedPayload);
212
+
213
+ if ($payload) {
214
+ $payload = json_decode($payload, true);
215
+ }
216
+
217
+ if (!is_array($payload)) {
218
+ throw new FacebookSDKException('Signed request has malformed encoded payload data.', 607);
219
+ }
220
+
221
+ return $payload;
222
+ }
223
+
224
+ /**
225
+ * Validates the algorithm used in a signed request.
226
+ *
227
+ * @throws FacebookSDKException
228
+ */
229
+ protected function validateAlgorithm()
230
+ {
231
+ if ($this->get('algorithm') !== 'HMAC-SHA256') {
232
+ throw new FacebookSDKException('Signed request is using the wrong algorithm.', 605);
233
+ }
234
+ }
235
+
236
+ /**
237
+ * Hashes the signature used in a signed request.
238
+ *
239
+ * @param string $encodedData
240
+ *
241
+ * @return string
242
+ *
243
+ * @throws FacebookSDKException
244
+ */
245
+ protected function hashSignature($encodedData)
246
+ {
247
+ $hashedSig = hash_hmac(
248
+ 'sha256',
249
+ $encodedData,
250
+ $this->app->getSecret(),
251
+ $raw_output = true
252
+ );
253
+
254
+ if (!$hashedSig) {
255
+ throw new FacebookSDKException('Unable to hash signature from encoded payload data.', 602);
256
+ }
257
+
258
+ return $hashedSig;
259
+ }
260
+
261
+ /**
262
+ * Validates the signature used in a signed request.
263
+ *
264
+ * @param string $hashedSig
265
+ * @param string $sig
266
+ *
267
+ * @throws FacebookSDKException
268
+ */
269
+ protected function validateSignature($hashedSig, $sig)
270
+ {
271
+ if (\hash_equals($hashedSig, $sig)) {
272
+ return;
273
+ }
274
+
275
+ throw new FacebookSDKException('Signed request has an invalid signature.', 602);
276
+ }
277
+
278
+ /**
279
+ * Base64 decoding which replaces characters:
280
+ * + instead of -
281
+ * / instead of _
282
+ *
283
+ * @link http://en.wikipedia.org/wiki/Base64#URL_applications
284
+ *
285
+ * @param string $input base64 url encoded input
286
+ *
287
+ * @return string decoded string
288
+ */
289
+ public function base64UrlDecode($input)
290
+ {
291
+ $urlDecodedBase64 = strtr($input, '-_', '+/');
292
+ $this->validateBase64($urlDecodedBase64);
293
+
294
+ return base64_decode($urlDecodedBase64);
295
+ }
296
+
297
+ /**
298
+ * Base64 encoding which replaces characters:
299
+ * + instead of -
300
+ * / instead of _
301
+ *
302
+ * @link http://en.wikipedia.org/wiki/Base64#URL_applications
303
+ *
304
+ * @param string $input string to encode
305
+ *
306
+ * @return string base64 url encoded input
307
+ */
308
+ public function base64UrlEncode($input)
309
+ {
310
+ return strtr(base64_encode($input), '+/', '-_');
311
+ }
312
+
313
+ /**
314
+ * Validates a base64 string.
315
+ *
316
+ * @param string $input base64 value to validate
317
+ *
318
+ * @throws FacebookSDKException
319
+ */
320
+ protected function validateBase64($input)
321
+ {
322
+ if (!preg_match('/^[a-zA-Z0-9\/\r\n+]*={0,2}$/', $input)) {
323
+ throw new FacebookSDKException('Signed request contains malformed base64 encoding.', 608);
324
+ }
325
+ }
326
+ }
facebook/facebook/Url/FacebookUrlDetectionHandler.php ADDED
@@ -0,0 +1,182 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook\Url;
25
+
26
+ /**
27
+ * Class FacebookUrlDetectionHandler
28
+ *
29
+ * @package Facebook
30
+ */
31
+ class FacebookUrlDetectionHandler implements UrlDetectionInterface
32
+ {
33
+ /**
34
+ * @inheritdoc
35
+ */
36
+ public function getCurrentUrl()
37
+ {
38
+ return $this->getHttpScheme() . '://' . $this->getHostName() . $this->getServerVar('REQUEST_URI');
39
+ }
40
+
41
+ /**
42
+ * Get the currently active URL scheme.
43
+ *
44
+ * @return string
45
+ */
46
+ protected function getHttpScheme()
47
+ {
48
+ return $this->isBehindSsl() ? 'https' : 'http';
49
+ }
50
+
51
+ /**
52
+ * Tries to detect if the server is running behind an SSL.
53
+ *
54
+ * @return boolean
55
+ */
56
+ protected function isBehindSsl()
57
+ {
58
+ // Check for proxy first
59
+ $protocol = $this->getHeader('X_FORWARDED_PROTO');
60
+ if ($protocol) {
61
+ return $this->protocolWithActiveSsl($protocol);
62
+ }
63
+
64
+ $protocol = $this->getServerVar('HTTPS');
65
+ if ($protocol) {
66
+ return $this->protocolWithActiveSsl($protocol);
67
+ }
68
+
69
+ return (string)$this->getServerVar('SERVER_PORT') === '443';
70
+ }
71
+
72
+ /**
73
+ * Detects an active SSL protocol value.
74
+ *
75
+ * @param string $protocol
76
+ *
77
+ * @return boolean
78
+ */
79
+ protected function protocolWithActiveSsl($protocol)
80
+ {
81
+ $protocol = strtolower((string)$protocol);
82
+
83
+ return in_array($protocol, ['on', '1', 'https', 'ssl'], true);
84
+ }
85
+
86
+ /**
87
+ * Tries to detect the host name of the server.
88
+ *
89
+ * Some elements adapted from
90
+ *
91
+ * @see https://github.com/symfony/HttpFoundation/blob/master/Request.php
92
+ *
93
+ * @return string
94
+ */
95
+ protected function getHostName()
96
+ {
97
+ // Check for proxy first
98
+ $header = $this->getHeader('X_FORWARDED_HOST');
99
+ if ($header && $this->isValidForwardedHost($header)) {
100
+ $elements = explode(',', $header);
101
+ $host = $elements[count($elements) - 1];
102
+ } elseif (!$host = $this->getHeader('HOST')) {
103
+ if (!$host = $this->getServerVar('SERVER_NAME')) {
104
+ $host = $this->getServerVar('SERVER_ADDR');
105
+ }
106
+ }
107
+
108
+ // trim and remove port number from host
109
+ // host is lowercase as per RFC 952/2181
110
+ $host = strtolower(preg_replace('/:\d+$/', '', trim($host)));
111
+
112
+ // Port number
113
+ $scheme = $this->getHttpScheme();
114
+ $port = $this->getCurrentPort();
115
+ $appendPort = ':' . $port;
116
+
117
+ // Don't append port number if a normal port.
118
+ if (($scheme == 'http' && $port == '80') || ($scheme == 'https' && $port == '443')) {
119
+ $appendPort = '';
120
+ }
121
+
122
+ return $host . $appendPort;
123
+ }
124
+
125
+ protected function getCurrentPort()
126
+ {
127
+ // Check for proxy first
128
+ $port = $this->getHeader('X_FORWARDED_PORT');
129
+ if ($port) {
130
+ return (string)$port;
131
+ }
132
+
133
+ $protocol = (string)$this->getHeader('X_FORWARDED_PROTO');
134
+ if ($protocol === 'https') {
135
+ return '443';
136
+ }
137
+
138
+ return (string)$this->getServerVar('SERVER_PORT');
139
+ }
140
+
141
+ /**
142
+ * Returns the a value from the $_SERVER super global.
143
+ *
144
+ * @param string $key
145
+ *
146
+ * @return string
147
+ */
148
+ protected function getServerVar($key)
149
+ {
150
+ return isset($_SERVER[$key]) ? $_SERVER[$key] : '';
151
+ }
152
+
153
+ /**
154
+ * Gets a value from the HTTP request headers.
155
+ *
156
+ * @param string $key
157
+ *
158
+ * @return string
159
+ */
160
+ protected function getHeader($key)
161
+ {
162
+ return $this->getServerVar('HTTP_' . $key);
163
+ }
164
+
165
+ /**
166
+ * Checks if the value in X_FORWARDED_HOST is a valid hostname
167
+ * Could prevent unintended redirections
168
+ *
169
+ * @param string $header
170
+ *
171
+ * @return boolean
172
+ */
173
+ protected function isValidForwardedHost($header)
174
+ {
175
+ $elements = explode(',', $header);
176
+ $host = $elements[count($elements) - 1];
177
+
178
+ return preg_match("/^([a-z\d](-*[a-z\d])*)(\.([a-z\d](-*[a-z\d])*))*$/i", $host) //valid chars check
179
+ && 0 < strlen($host) && strlen($host) < 254 //overall length check
180
+ && preg_match("/^[^\.]{1,63}(\.[^\.]{1,63})*$/", $host); //length of each label
181
+ }
182
+ }
facebook/facebook/Url/FacebookUrlManipulator.php ADDED
@@ -0,0 +1,167 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook\Url;
25
+
26
+ /**
27
+ * Class FacebookUrlManipulator
28
+ *
29
+ * @package Facebook
30
+ */
31
+ class FacebookUrlManipulator
32
+ {
33
+ /**
34
+ * Remove params from a URL.
35
+ *
36
+ * @param string $url The URL to filter.
37
+ * @param array $paramsToFilter The params to filter from the URL.
38
+ *
39
+ * @return string The URL with the params removed.
40
+ */
41
+ public static function removeParamsFromUrl($url, array $paramsToFilter)
42
+ {
43
+ $parts = parse_url($url);
44
+
45
+ $query = '';
46
+ if (isset($parts['query'])) {
47
+ $params = [];
48
+ parse_str($parts['query'], $params);
49
+
50
+ // Remove query params
51
+ foreach ($paramsToFilter as $paramName) {
52
+ unset($params[$paramName]);
53
+ }
54
+
55
+ if (count($params) > 0) {
56
+ $query = '?' . http_build_query($params, null, '&');
57
+ }
58
+ }
59
+
60
+ $scheme = isset($parts['scheme']) ? $parts['scheme'] . '://' : '';
61
+ $host = isset($parts['host']) ? $parts['host'] : '';
62
+ $port = isset($parts['port']) ? ':' . $parts['port'] : '';
63
+ $path = isset($parts['path']) ? $parts['path'] : '';
64
+ $fragment = isset($parts['fragment']) ? '#' . $parts['fragment'] : '';
65
+
66
+ return $scheme . $host . $port . $path . $query . $fragment;
67
+ }
68
+
69
+ /**
70
+ * Gracefully appends params to the URL.
71
+ *
72
+ * @param string $url The URL that will receive the params.
73
+ * @param array $newParams The params to append to the URL.
74
+ *
75
+ * @return string
76
+ */
77
+ public static function appendParamsToUrl($url, array $newParams = [])
78
+ {
79
+ if (empty($newParams)) {
80
+ return $url;
81
+ }
82
+
83
+ if (strpos($url, '?') === false) {
84
+ return $url . '?' . http_build_query($newParams, null, '&');
85
+ }
86
+
87
+ list($path, $query) = explode('?', $url, 2);
88
+ $existingParams = [];
89
+ parse_str($query, $existingParams);
90
+
91
+ // Favor params from the original URL over $newParams
92
+ $newParams = array_merge($newParams, $existingParams);
93
+
94
+ // Sort for a predicable order
95
+ ksort($newParams);
96
+
97
+ return $path . '?' . http_build_query($newParams, null, '&');
98
+ }
99
+
100
+ /**
101
+ * Returns the params from a URL in the form of an array.
102
+ *
103
+ * @param string $url The URL to parse the params from.
104
+ *
105
+ * @return array
106
+ */
107
+ public static function getParamsAsArray($url)
108
+ {
109
+ $query = parse_url($url, PHP_URL_QUERY);
110
+ if (!$query) {
111
+ return [];
112
+ }
113
+ $params = [];
114
+ parse_str($query, $params);
115
+
116
+ return $params;
117
+ }
118
+
119
+ /**
120
+ * Adds the params of the first URL to the second URL.
121
+ *
122
+ * Any params that already exist in the second URL will go untouched.
123
+ *
124
+ * @param string $urlToStealFrom The URL harvest the params from.
125
+ * @param string $urlToAddTo The URL that will receive the new params.
126
+ *
127
+ * @return string The $urlToAddTo with any new params from $urlToStealFrom.
128
+ */
129
+ public static function mergeUrlParams($urlToStealFrom, $urlToAddTo)
130
+ {
131
+ $newParams = static::getParamsAsArray($urlToStealFrom);
132
+ // Nothing new to add, return as-is
133
+ if (!$newParams) {
134
+ return $urlToAddTo;
135
+ }
136
+
137
+ return static::appendParamsToUrl($urlToAddTo, $newParams);
138
+ }
139
+
140
+ /**
141
+ * Check for a "/" prefix and prepend it if not exists.
142
+ *
143
+ * @param string|null $string
144
+ *
145
+ * @return string|null
146
+ */
147
+ public static function forceSlashPrefix($string)
148
+ {
149
+ if (!$string) {
150
+ return $string;
151
+ }
152
+
153
+ return strpos($string, '/') === 0 ? $string : '/' . $string;
154
+ }
155
+
156
+ /**
157
+ * Trims off the hostname and Graph version from a URL.
158
+ *
159
+ * @param string $urlToTrim The URL the needs the surgery.
160
+ *
161
+ * @return string The $urlToTrim with the hostname and Graph version removed.
162
+ */
163
+ public static function baseGraphUrlEndpoint($urlToTrim)
164
+ {
165
+ return '/' . preg_replace('/^https:\/\/.+\.facebook\.com(\/v.+?)?\//', '', $urlToTrim);
166
+ }
167
+ }
facebook/facebook/Url/UrlDetectionInterface.php ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+ namespace Facebook\Url;
25
+
26
+ /**
27
+ * Interface UrlDetectionInterface
28
+ *
29
+ * @package Facebook
30
+ */
31
+ interface UrlDetectionInterface
32
+ {
33
+ /**
34
+ * Get the currently active URL.
35
+ *
36
+ * @return string
37
+ */
38
+ public function getCurrentUrl();
39
+ }
facebook/facebook/autoload.php ADDED
@@ -0,0 +1,81 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+
25
+ /**
26
+ * You only need this file if you are not using composer.
27
+ * Why are you not using composer?
28
+ * https://getcomposer.org/
29
+ */
30
+
31
+ if (version_compare(PHP_VERSION, '5.4.0', '<')) {
32
+ throw new Exception('The Facebook SDK requires PHP version 5.4 or higher.');
33
+ }
34
+
35
+ require_once __DIR__ . '/polyfills.php';
36
+
37
+ /**
38
+ * Register the autoloader for the Facebook SDK classes.
39
+ *
40
+ * Based off the official PSR-4 autoloader example found here:
41
+ * https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-4-autoloader-examples.md
42
+ *
43
+ * @param string $class The fully-qualified class name.
44
+ *
45
+ * @return void
46
+ */
47
+ spl_autoload_register(function ($class) {
48
+ // project-specific namespace prefix
49
+ $prefix = 'Facebook\\';
50
+
51
+ // For backwards compatibility
52
+ $customBaseDir = '';
53
+ // @todo v6: Remove support for 'FACEBOOK_SDK_V4_SRC_DIR'
54
+ if (defined('FACEBOOK_SDK_V4_SRC_DIR')) {
55
+ $customBaseDir = FACEBOOK_SDK_V4_SRC_DIR;
56
+ } elseif (defined('FACEBOOK_SDK_SRC_DIR')) {
57
+ $customBaseDir = FACEBOOK_SDK_SRC_DIR;
58
+ }
59
+ // base directory for the namespace prefix
60
+ $baseDir = $customBaseDir ?: __DIR__ . '/';
61
+
62
+ // does the class use the namespace prefix?
63
+ $len = strlen($prefix);
64
+ if (strncmp($prefix, $class, $len) !== 0) {
65
+ // no, move to the next registered autoloader
66
+ return;
67
+ }
68
+
69
+ // get the relative class name
70
+ $relativeClass = substr($class, $len);
71
+
72
+ // replace the namespace prefix with the base directory, replace namespace
73
+ // separators with directory separators in the relative class name, append
74
+ // with .php
75
+ $file = rtrim($baseDir, '/') . '/' . str_replace('\\', '/', $relativeClass) . '.php';
76
+
77
+ // if the file exists, require it
78
+ if (file_exists($file)) {
79
+ require $file;
80
+ }
81
+ });
facebook/facebook/polyfills.php ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+
25
+ /**
26
+ * @see https://github.com/sarciszewski/php-future/blob/master/src/Security.php#L37-L51
27
+ */
28
+ if (!function_exists('hash_equals')) {
29
+ function hash_equals($knownString, $userString)
30
+ {
31
+ if (function_exists('mb_strlen')) {
32
+ $kLen = mb_strlen($knownString, '8bit');
33
+ $uLen = mb_strlen($userString, '8bit');
34
+ } else {
35
+ $kLen = strlen($knownString);
36
+ $uLen = strlen($userString);
37
+ }
38
+ if ($kLen !== $uLen) {
39
+ return false;
40
+ }
41
+ $result = 0;
42
+ for ($i = 0; $i < $kLen; $i++) {
43
+ $result |= (ord($knownString[$i]) ^ ord($userString[$i]));
44
+ }
45
+
46
+ // They are only identical strings if $result is exactly 0...
47
+ return 0 === $result;
48
+ }
49
+ }
facebook/polyfills.php ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2017 Facebook, Inc.
4
+ *
5
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
+ * use, copy, modify, and distribute this software in source code or binary
7
+ * form for use in connection with the web services and APIs provided by
8
+ * Facebook.
9
+ *
10
+ * As with any software that integrates with the Facebook platform, your use
11
+ * of this software is subject to the Facebook Developer Principles and
12
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
+ * shall be included in all copies or substantial portions of the software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ * DEALINGS IN THE SOFTWARE.
22
+ *
23
+ */
24
+
25
+ /**
26
+ * @see https://github.com/sarciszewski/php-future/blob/master/src/Security.php#L37-L51
27
+ */
28
+ if (!function_exists('hash_equals')) {
29
+ function hash_equals($knownString, $userString)
30
+ {
31
+ if (function_exists('mb_strlen')) {
32
+ $kLen = mb_strlen($knownString, '8bit');
33
+ $uLen = mb_strlen($userString, '8bit');
34
+ } else {
35
+ $kLen = strlen($knownString);
36
+ $uLen = strlen($userString);
37
+ }
38
+ if ($kLen !== $uLen) {
39
+ return false;
40
+ }
41
+ $result = 0;
42
+ for ($i = 0; $i < $kLen; $i++) {
43
+ $result |= (ord($knownString[$i]) ^ ord($userString[$i]));
44
+ }
45
+
46
+ // They are only identical strings if $result is exactly 0...
47
+ return 0 === $result;
48
+ }
49
+ }
inc/frontend/login_check.php CHANGED
@@ -1,102 +1,99 @@
1
  <?php
 
2
 
3
- defined('ABSPATH') or die("No script kiddies please!");
4
-
5
- if (!class_exists('APSL_Lite_Login_Check_Class')) {
6
 
7
  class APSL_Lite_Login_Check_Class {
8
-
9
  //constructor
10
  function __construct() {
11
 
12
- if (isset($_GET['apsl_login_id'])) {
13
- if (isset($_REQUEST['state'])) {
14
- parse_str(base64_decode($_REQUEST['state']), $state_vars);
15
 
16
- if (isset($state_vars['redirect_to'])) {
17
  $_GET['redirect_to'] = $_REQUEST['redirect_to'] = $state_vars['redirect_to'];
18
  }
19
  }
20
 
21
- $exploder = explode('_', $_GET['apsl_login_id']);
22
- switch ($exploder[0]) {
23
  case 'facebook':
24
- if (version_compare(PHP_VERSION, '5.4.0', '<')) {
25
- echo _e('The Facebook SDK requires PHP version 5.4 or higher. Please notify about this error to site admin.', 'accesspress-social-login-lite');
26
  die();
27
  }
28
  $this->onFacebookLogin();
29
- break;
30
  case 'twitter':
31
- if (!class_exists('TwitterOAuth')) {
32
  include( APSL_PLUGIN_DIR . 'twitter/OAuth.php' );
33
  include( APSL_PLUGIN_DIR . 'twitter/twitteroauth.php' );
34
  }
35
  $this->onTwitterLogin();
36
- break;
37
  case 'google':
38
- if (!class_exists('Google_Client')) {
39
- include( APSL_PLUGIN_DIR . 'google/Client.php' );
40
- }
41
- if (!class_exists('Google_Service_Plus')) {
42
- include( APSL_PLUGIN_DIR . 'google/Service/Plus.php' );
43
- }
44
  $this->onGoogleLogin();
45
- break;
46
  }
47
  }
48
  }
49
-
50
  //for facebook login
51
  function onFacebookLogin() {
52
  $response = new stdClass();
53
- $result = $this->facebookLogin($response);
54
- if (isset($result->status) && $result->status == 'SUCCESS') {
55
  global $wpdb;
56
- $unique_verifier = sha1($result->deutype . $result->deuid);
57
  $sql = "SELECT * FROM `{$wpdb->prefix}apsl_users_social_profile_details` WHERE `provider_name` LIKE '$result->deutype' AND `identifier` LIKE '$result->deuid' AND `unique_verifier` LIKE '$unique_verifier'";
58
  $row = $wpdb->get_row($sql);
59
- if (!$row) {
60
  //check if there is already a user with the email address provided from social login already
61
  $user_details_by_email = $this->getUserByMail($result->email);
62
- if ($user_details_by_email != false) {
63
  //user already there so log him in
64
  $id = $user_details_by_email->ID;
65
  $sql = "SELECT * FROM `{$wpdb->prefix}apsl_users_social_profile_details` WHERE `user_id` LIKE '$id'; ";
66
  $row = $wpdb->get_row($sql);
67
- if (!$row) {
68
- self:: link_user($id, $result);
69
  }
70
- self:: loginUser($id);
71
  die();
72
  }
73
- $_SESSION['user_details'] = $result;
74
-
75
  // use FB id as username if sanitized username is empty
76
- $sanitized_user_name = sanitize_user($result->username, true);
77
- if (empty($sanitized_user_name)) {
78
- $sanitized_user_name = $result->deuid;
79
  }
80
- $user_Id = self::creatUser($sanitized_user_name, $result->email);
81
- $user_row = self:: getUserByMail($result->email);
82
  $id = $user_row->ID;
83
  $result = $result;
84
  $role = 'subscriber';
85
- self:: UpdateUserMeta($id, $result, $role);
86
- self:: loginUser($id);
87
  exit();
88
- } else {
89
- if (($row->provider_name == $result->deutype) && ($row->identifier == $result->deuid)) {
90
  //echo "user found in our database";
91
- self:: loginUser($row->user_id);
92
  exit();
93
- } else {
94
  // user not found in our database
95
  // need to handle an exception
96
  }
97
  }
98
- } else {
99
- if (isset($_REQUEST['error'])) {
100
  $_SESSION['apsl_login_error_flag'] = 1;
101
  $redirect_url = isset($_REQUEST['redirect_to']) ? $_REQUEST['redirect_to'] : site_url();
102
  $this->redirect($redirect_url);
@@ -104,322 +101,337 @@ if (!class_exists('APSL_Lite_Login_Check_Class')) {
104
  die();
105
  }
106
  }
107
-
108
  function facebookLogin() {
109
  $request = $_REQUEST;
110
  $site = $this->siteUrl();
111
  $callBackUrl = $this->callBackUrl();
112
  $response = new stdClass();
113
  $return_user_details = new stdClass();
114
- $exploder = explode('_', $_GET['apsl_login_id']);
115
  $action = $exploder[1];
116
- $options = get_option(APSL_SETTINGS);
117
- if (isset($options['apsl_facebook_settings']['apsl_profile_image_width'])) {
118
- $width = $options['apsl_facebook_settings']['apsl_profile_image_width'];
119
- } else {
120
- $width = 150;
121
  }
122
 
123
- if (isset($options['apsl_facebook_settings']['apsl_profile_image_height'])) {
124
  $height = $options['apsl_facebook_settings']['apsl_profile_image_height'];
125
- } else {
126
  $height = 150;
127
  }
128
 
129
- $config = array('app_id' => $options['apsl_facebook_settings']['apsl_facebook_app_id'], 'app_secret' => $options['apsl_facebook_settings']['apsl_facebook_app_secret'], 'default_graph_version' => 'v2.4', 'persistent_data_handler' => 'session');
130
  include( APSL_PLUGIN_DIR . 'facebook/autoload.php' );
131
- $fb = new Facebook\Facebook($config);
132
 
133
  $callback = $callBackUrl . 'apsl_login_id' . '=facebook_check';
134
 
135
- if ($action == 'login') {
136
  // Well looks like we are a fresh dude, login to Facebook!
137
  $helper = $fb->getRedirectLoginHelper();
138
  $permissions = array('email', 'public_profile'); // optional
139
- $loginUrl = $helper->getLoginUrl($callback, $permissions);
140
 
141
- $encoded_url = isset($_GET['redirect_to']) ? $_GET['redirect_to'] : '';
142
- if (isset($encoded_url) && $encoded_url != '') {
143
- setcookie("apsl_login_redirect_url", $encoded_url, time() + 3600);
144
  // $callback = $callBackUrl . 'apsl_login_id' . '=facebook_check&redirect_to=' . $encoded_url;
145
  }
146
- $this->redirect($loginUrl);
147
- } else {
148
- if (isset($_REQUEST['error'])) {
 
149
  $response->status = 'ERROR';
150
  $response->error_code = 2;
151
  $response->error_message = 'INVALID AUTHORIZATION';
152
  return $response;
153
  die();
154
  }
155
- if (isset($_REQUEST['code'])) {
156
  $helper = $fb->getRedirectLoginHelper();
157
  // Trick below will avoid "Cross-site request forgery validation failed. Required param "state" missing." from Facebook
158
  $_SESSION['FBRLH_state'] = $_REQUEST['state'];
159
  try {
160
  $accessToken = $helper->getAccessToken($callback);
161
- } catch (Facebook\Exceptions\FacebookResponseException $e) {
 
162
  // When Graph returns an error
163
  echo 'Graph returned an error: ' . $e->getMessage();
164
  exit;
165
- } catch (Facebook\Exceptions\FacebookSDKException $e) {
 
166
  // When validation fails or other local issues
167
  echo 'Facebook SDK returned an error: ' . $e->getMessage();
168
  exit;
169
  }
170
-
171
- if (isset($accessToken)) {
172
  // Logged in!
173
- $_SESSION['facebook_access_token'] = (string) $accessToken;
174
- $fb->setDefaultAccessToken($accessToken);
175
 
176
  try {
177
- $response = $fb->get('/me?fields=email,name, first_name, last_name, gender, link, about, birthday, education, hometown, is_verified, languages, location, website');
178
  $userNode = $response->getGraphUser();
179
- } catch (Facebook\Exceptions\FacebookResponseException $e) {
 
180
  // When Graph returns an error
181
  echo 'Graph returned an error: ' . $e->getMessage();
182
  exit;
183
- } catch (Facebook\Exceptions\FacebookSDKException $e) {
 
184
  // When validation fails or other local issues
185
  echo 'Facebook SDK returned an error: ' . $e->getMessage();
186
  exit;
187
  }
188
  // get the user profile details
189
- $user_profile = $this->accessProtected($userNode, 'items');
190
- if ($user_profile != null) {
191
  $return_user_details->status = 'SUCCESS';
192
  $return_user_details->deuid = $user_profile['id'];
193
  $return_user_details->deutype = 'facebook';
194
  $return_user_details->first_name = $user_profile['first_name'];
195
  $return_user_details->last_name = $user_profile['last_name'];
196
- if (isset($user_profile['email']) || $user_profile['email'] != '') {
197
  $user_email = $user_profile['email'];
198
- } else {
199
- $user_email = $user_profile['id'] . '@facebook.com';
200
  }
201
  $return_user_details->email = $user_email;
202
- $return_user_details->username = ($user_profile['first_name'] != '') ? strtolower($user_profile['first_name']) : $user_email;
203
  $return_user_details->gender = isset($user_profile['gender']) ? $user_profile['gender'] : 'N/A';
204
  $return_user_details->url = $user_profile['link'];
205
  $return_user_details->about = ''; //facebook doesn't return user about details.
206
- $headers = get_headers('https://graph.facebook.com/' . $user_profile['id'] . '/picture?width=' . $width . '&height=' . $height, 1);
207
  // just a precaution, check whether the header isset...
208
- if (isset($headers['Location'])) {
209
  $return_user_details->deuimage = $headers['Location']; // string
210
- } else {
 
 
211
  $return_user_details->deuimage = false; // nothing there? .. weird, but okay!
 
212
  }
213
  $return_user_details->error_message = '';
214
- } else {
 
215
  $return_user_details->status = 'ERROR';
216
  $return_user_details->error_code = 2;
217
  $return_user_details->error_message = 'INVALID AUTHORIZATION';
218
  }
219
  }
220
- } else {
 
221
  // Well looks like we are a fresh dude, login to Facebook!
222
  $helper = $fb->getRedirectLoginHelper();
223
  $permissions = array('email', 'public_profile'); // optional
224
- $loginUrl = $helper->getLoginUrl($callback, $permissions);
225
- $this->redirect($loginUrl);
226
  }
227
  }
228
  return $return_user_details;
229
  }
230
-
231
  //for twitter login
232
  function onTwitterLogin() {
233
  $result = $this->twitterLogin();
234
- if (isset($result->status) && $result->status == 'SUCCESS') {
235
  global $wpdb;
236
- $unique_verifier = sha1($result->deutype . $result->deuid);
237
  $sql = "SELECT * FROM `{$wpdb->prefix}apsl_users_social_profile_details` WHERE `provider_name` LIKE '$result->deutype' AND `identifier` LIKE '$result->deuid' AND `unique_verifier` LIKE '$unique_verifier'";
238
  $row = $wpdb->get_row($sql);
239
- if (!$row) {
240
  //check if there is already a user with the email address provided from social login already
241
  $user_details_by_email = $this->getUserByMail($result->email);
242
- if ($user_details_by_email != false) {
243
  //user already there so log him in
244
  $id = $user_details_by_email->ID;
245
  $sql = "SELECT * FROM `{$wpdb->prefix}apsl_users_social_profile_details` WHERE `user_id` LIKE '$id'; ";
246
  $row = $wpdb->get_row($sql);
247
  // var_dump($row);
248
- if (!$row) {
249
- self:: link_user($id, $result);
250
  }
251
- self:: loginUser($id);
252
  die();
253
  }
254
- $_SESSION['user_details'] = $result;
255
- self::creatUser($result->username, $result->email);
256
- $user_row = self:: getUserByMail($result->email);
257
  $id = $user_row->ID;
258
  $result = $result;
259
  $role = 'subscriber';
260
- self:: UpdateUserMeta($id, $result, $role);
261
- self:: loginUser($id);
262
  exit();
263
- } else {
264
- if (($row->provider_name == $result->deutype) && ($row->identifier == $result->deuid)) {
265
  //echo "user found in our database";
266
- self:: loginUser($row->user_id);
267
  exit();
268
- } else {
269
  // user not found in our database
270
  // need to handle an exception
271
  }
272
  }
273
- $_SESSION['apsl_login_error_flag'] = 1;
274
- } else {
275
- if (isset($_REQUEST['denied'])) {
276
  $redirect_url = isset($_REQUEST['redirect_to']) ? $_REQUEST['redirect_to'] : site_url();
277
  $this->redirect($redirect_url);
278
  }
279
  die();
280
  }
281
  }
282
-
283
  function twitterLogin() {
284
  $request = $_REQUEST;
285
  $site = $this->siteUrl();
286
  $callBackUrl = $this->callBackUrl();
287
  $response = new stdClass();
288
- $exploder = explode('_', $_GET['apsl_login_id']);
289
  $action = $exploder[1];
290
  @session_start();
291
- $options = get_option(APSL_SETTINGS);
292
- if ($action == 'login') {
293
  // Get identity from user and redirect browser to OpenID Server
294
- if (!isset($request['oauth_token']) || $request['oauth_token'] == '') {
295
- $twitterObj = new TwitterOAuth($options['apsl_twitter_settings']['apsl_twitter_api_key'], $options['apsl_twitter_settings']['apsl_twitter_api_secret']);
296
- $encoded_url = isset($_GET['redirect_to']) ? $_GET['redirect_to'] : '';
297
- if (isset($encoded_url) && $encoded_url != '') {
298
  $callback = $callBackUrl . 'apsl_login_id' . '=twitter_check&redirect_to=' . $encoded_url;
299
- } else {
 
300
  $callback = $callBackUrl . 'apsl_login_id' . '=twitter_check';
301
  }
302
-
303
- $request_token = $twitterObj->getRequestToken($callback);
304
  $_SESSION['oauth_twitter'] = array();
305
  /* Save temporary credentials to session. */
306
  $_SESSION['oauth_twitter']['oauth_token'] = $token = $request_token['oauth_token'];
307
  $_SESSION['oauth_twitter']['oauth_token_secret'] = $request_token['oauth_token_secret'];
308
  /* If last connection failed don't display authorization link. */
309
- switch ($twitterObj->http_code) {
310
  case 200:
311
  try {
312
- $url = $twitterObj->getAuthorizeUrl($token);
313
- $this->redirect($url);
314
- } catch (Exception $e) {
 
315
  $response->status = 'ERROR';
316
  $response->error_code = 2;
317
  $response->error_message = 'Could not get AuthorizeUrl.';
318
  }
319
- break;
320
  default:
321
  $response->status = 'ERROR';
322
  $response->error_code = 2;
323
  $response->error_message = 'Could not connect to Twitter. Refresh the page or try again later.';
324
- break;
325
  }
326
- } else {
 
327
  $response->status = 'ERROR';
328
  $response->error_code = 2;
329
  $response->error_message = 'INVALID AUTHORIZATION';
330
  }
331
- } else if (isset($request['oauth_token']) && isset($request['oauth_verifier'])) {
 
332
  /* Create TwitteroAuth object with app key/secret and token key/secret from default phase */
333
- $twitterObj = new TwitterOAuth($options['apsl_twitter_settings']['apsl_twitter_api_key'], $options['apsl_twitter_settings']['apsl_twitter_api_secret'], $_SESSION['oauth_twitter']['oauth_token'], $_SESSION['oauth_twitter']['oauth_token_secret']);
334
  /* Remove no longer needed request tokens */
335
- unset($_SESSION['oauth_twitter']);
336
  try {
337
- $access_token = $twitterObj->getAccessToken($request['oauth_verifier']);
338
  /* If HTTP response is 200 continue otherwise send to connect page to retry */
339
- if (200 == $twitterObj->http_code) {
340
- $user_profile = $twitterObj->get('account/verify_credentials', array(
341
- 'screen_name' => $access_token['screen_name'],
342
- 'skip_status' => 'true',
343
- 'include_entities' => 'true',
344
- 'include_email' => 'true'
345
- )
346
- );
347
  /* Request access twitterObj from twitter */
348
  $response->status = 'SUCCESS';
349
  $response->deuid = $user_profile->id;
350
  $response->deutype = 'twitter';
351
- $response->name = explode(' ', $user_profile->name, 2);
352
  $response->first_name = $response->name[0];
353
- $response->last_name = ( isset($response->name[1]) ) ? $response->name[1] : '';
354
  $response->deuimage = $user_profile->profile_image_url_https;
355
  $response->email = isset($user_profile->email) ? $user_profile->email : $user_profile->screen_name . '@twitter.com';
356
- $response->username = ($user_profile->screen_name != '') ? strtolower($user_profile->screen_name) : $user_email;
357
  $response->url = $user_profile->url;
358
  $response->about = isset($user_profile->description) ? $user_profile->description : '';
359
  $response->gender = isset($user_profile->gender) ? $user_profile->gender : 'N/A';
360
  $response->location = $user_profile->location;
361
  $response->error_message = '';
362
- } else {
 
363
  $response->status = 'ERROR';
364
  $response->error_code = 2;
365
  $response->error_message = 'Could not connect to Twitter. Refresh the page or try again later.';
366
  }
367
- } catch (Exception $e) {
 
368
  $response->status = 'ERROR';
369
  $response->error_code = 2;
370
  $response->error_message = 'Could not get AccessToken.';
371
  }
372
- } else { // User Canceled your Request
 
373
  $response->status = 'ERROR';
374
  $response->error_code = 1;
375
  $response->error_message = "USER CANCELED REQUEST";
376
  }
377
  return $response;
378
  }
379
-
380
  //for google login
381
  function onGoogleLogin() {
382
  $result = $this->GoogleLogin();
383
- if (isset($result->status) && $result->status == 'SUCCESS') {
384
  global $wpdb;
385
- $unique_verifier = sha1($result->deutype . $result->deuid);
386
  $sql = "SELECT * FROM `{$wpdb->prefix}apsl_users_social_profile_details` WHERE `provider_name` LIKE '$result->deutype' AND `identifier` LIKE '$result->deuid' AND `unique_verifier` LIKE '$unique_verifier'";
387
  $row = $wpdb->get_row($sql);
388
- if (!$row) {
389
  //check if there is already a user with the email address provided from social login already
390
  $user_details_by_email = $this->getUserByMail($result->email);
391
- if ($user_details_by_email != false) {
392
  //user already there so log him in
393
  $id = $user_details_by_email->ID;
394
  $sql = "SELECT * FROM `{$wpdb->prefix}apsl_users_social_profile_details` WHERE `user_id` LIKE '$id'; ";
395
  $row = $wpdb->get_row($sql);
396
- if (!$row) {
397
- self:: link_user($id, $result);
398
  }
399
- self:: loginUser($id);
400
  die();
401
  }
402
- $_SESSION['user_details'] = $result;
403
- self::creatUser($result->username, $result->email);
404
- $user_row = self:: getUserByMail($result->email);
405
  $id = $user_row->ID;
406
  $result = $result;
407
  $role = 'subscriber';
408
- self:: UpdateUserMeta($id, $result, $role);
409
- self:: loginUser($id);
410
  exit();
411
- } else {
412
- if (($row->provider_name == $result->deutype) && ($row->identifier == $result->deuid)) {
413
  //echo "user found in our database";
414
- self:: loginUser($row->user_id);
415
  exit();
416
- } else {
417
  // user not found in our database
418
  // need to handle an exception
419
  }
420
  }
421
- } else {
422
- if (isset($_REQUEST['error'])) {
423
  $_SESSION['apsl_login_error_flag'] = 1;
424
  $redirect_url = isset($_REQUEST['redirect_to']) ? $_REQUEST['redirect_to'] : site_url();
425
  $this->redirect($redirect_url);
@@ -427,67 +439,71 @@ if (!class_exists('APSL_Lite_Login_Check_Class')) {
427
  die();
428
  }
429
  }
430
-
431
  function GoogleLogin() {
432
  $post = $_POST;
433
  $get = $_GET;
434
  $request = $_REQUEST;
435
  $site = $this->siteUrl();
436
  $callBackUrl = $this->callBackUrl();
437
- $options = get_option(APSL_SETTINGS);
438
  $response = new stdClass();
439
- $a = explode('_', $_GET['apsl_login_id']);
440
  $action = $a[1];
441
  $client_id = $options['apsl_google_settings']['apsl_google_client_id'];
442
  $client_secret = $options['apsl_google_settings']['apsl_google_client_secret'];
443
-
444
  $site_url = site_url() . '/wp-admin';
445
- $encoded_url = isset($_GET['redirect_to']) ? $_GET['redirect_to'] : $site_url;
446
  $callback = $callBackUrl . 'apsl_login_id' . '=google_check';
447
-
448
  $redirect_uri = $callback;
449
  $client = new Google_Client;
450
-
451
- $client->setClientId($client_id);
452
- $client->setClientSecret($client_secret);
453
- $client->setRedirectUri($redirect_uri);
454
- $client->addScope("https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/plus.profile.emails.read");
455
- if (isset($encoded_url) && $encoded_url != '') {
456
- $client->setState(base64_encode("redirect_to=$encoded_url"));
457
  }
458
-
459
- $service = new Google_Service_Plus($client);
460
-
461
- if ($action == 'login') { // Get identity from user and redirect browser to OpenID Server
462
- unset($_SESSION['access_token']);
463
- if (!( isset($_SESSION['access_token']) && $_SESSION['access_token'] )) {
464
  $authUrl = $client->createAuthUrl();
465
- $this->redirect($authUrl);
466
  die();
467
- } else {
468
- $this->redirect($redirect_uri . "&redirect_to=$encoded_url");
 
469
  die();
470
  }
471
- } elseif (isset($_GET['code'])) { // Perform HTTP Request to OpenID server to validate key
472
- $client->authenticate($_GET['code']);
 
473
  $_SESSION['access_token'] = $client->getAccessToken();
474
- $this->redirect($redirect_uri . "&redirect_to=$encoded_url");
475
  die();
476
- } elseif (isset($_SESSION['access_token']) && $_SESSION['access_token']) {
477
- $client->setAccessToken($_SESSION['access_token']);
478
-
 
479
  try {
480
- $user = $service->people->get("me", array());
481
- } catch (Exception $fault) {
482
- unset($_SESSION['access_token']);
483
- $ref_object = $this->accessProtected($fault, 'errors');
 
484
  echo $ref_object[0]['message'] . " Please notify about this error to the Site Admin.";
485
  die();
486
  }
487
-
488
- if (!empty($user)) {
489
- if (!empty($user->emails)) {
490
-
491
  $response->email = $user->emails[0]->value;
492
  $response->username = ($user->name->givenName) ? strtolower($user->name->givenName) : $user_email;
493
  $response->first_name = $user->name->givenName;
@@ -501,24 +517,26 @@ if (!class_exists('APSL_Lite_Login_Check_Class')) {
501
  $response->deutype = 'google';
502
  $response->status = 'SUCCESS';
503
  $response->error_message = '';
504
- } else {
 
505
  $response->status = 'ERROR';
506
  $response->error_code = 2;
507
  $response->error_message = "INVALID AUTHORIZATION";
508
  }
509
- } else { // Signature Verification Failed
 
510
  $response->status = 'ERROR';
511
  $response->error_code = 2;
512
  $response->error_message = "INVALID AUTHORIZATION";
513
  }
514
- } else { // User failed to login
 
515
  $response->status = 'ERROR';
516
  $response->error_code = 3;
517
  $response->error_message = "USER LOGIN FAIL";
518
  }
519
  return $response;
520
  }
521
-
522
  //other remaining methods
523
  function siteUrl() {
524
  return site_url();
@@ -527,279 +545,277 @@ if (!class_exists('APSL_Lite_Login_Check_Class')) {
527
  function callBackUrl() {
528
  // $connection = !empty( $_SERVER['HTTPS'] ) ? 'https://' : 'http://';
529
  $url = wp_login_url();
530
- if (strpos($url, '?') === false) {
531
- $url .= '?';
532
- } else {
533
- $url .= '&';
 
534
  }
535
  return $url;
536
  }
537
-
538
  //function to return json values from social media urls
539
- function get_json_values($url) {
540
- $response = wp_remote_get($url);
541
- $json_response = wp_remote_retrieve_body($response);
542
  return $json_response;
543
  }
544
 
545
- function redirect($redirect) {
546
- if (headers_sent()) { // Use JavaScript to redirect if content has been previously sent (not recommended, but safe)
547
  echo '<script language="JavaScript" type="text/javascript">window.location=\'';
548
  echo $redirect;
549
  echo '\';</script>';
550
- } else { // Default Header Redirect
551
- header('Location: ' . $redirect);
 
552
  }
553
  exit;
554
  }
555
 
556
- static function get_username($user_name) {
557
  $username = $user_name;
558
  $i = 1;
559
- while (username_exists($username)) {
560
- $username = $user_name . '_' . $i;
561
  $i++;
562
  }
563
  return $username;
564
  }
565
 
566
- function updateUser($username, $email) {
567
- $row = $this->getUserByUsername($username);
568
- if ($row && $email != '' && $row->user_email != $email) {
569
- $row = (array) $row;
570
  $row['user_email'] = $email;
571
- wp_update_user($row);
572
  }
573
  }
574
 
575
- function getUserByMail($email) {
576
  global $wpdb;
577
- $row = $wpdb->get_row("SELECT * FROM $wpdb->users WHERE user_email = '$email'");
578
- if ($row) {
579
  return $row;
580
  }
581
  return false;
582
  }
583
 
584
- function getUserByUsername($username) {
585
  global $wpdb;
586
- $row = $wpdb->get_row("SELECT * FROM $wpdb->users WHERE user_login = '$username'");
587
- if ($row) {
588
  return $row;
589
  }
590
  return false;
591
  }
592
 
593
- function creatUser($user_name, $user_email) {
594
- $username = self:: get_username($user_name);
595
- $random_password = wp_generate_password(12, false);
596
- $user_id = wp_create_user($username, $random_password, $user_email);
597
- do_action('APSL_createUser', $user_id); //hookable function to perform additional work after creation of user.
598
- $options = get_option(APSL_SETTINGS);
599
- if ($options['apsl_send_email_notification_options'] == 'yes') {
600
- if (version_compare(get_bloginfo('version'), '4.3.1', '>=')) {
601
- wp_new_user_notification($user_id, $deprecated = null, $notify = 'both');
602
- } else {
603
- wp_new_user_notification($user_id, $random_password);
604
  }
605
  }
606
  return $user_id;
607
  }
608
 
609
- function set_cookies($user_id = 0, $remember = true) {
610
- if (!function_exists('wp_set_auth_cookie')) {
611
  return false;
612
  }
613
- if (!$user_id) {
614
  return false;
615
  }
616
  wp_clear_auth_cookie();
617
- wp_set_auth_cookie($user_id, $remember);
618
- wp_set_current_user($user_id);
619
  return true;
620
  }
621
 
622
- function loginUser($user_id) {
623
  $current_url_an = get_permalink();
624
- $reauth = empty($_REQUEST['reauth']) ? false : true;
625
- if ($reauth)
626
- wp_clear_auth_cookie();
627
-
628
- if (isset($_REQUEST['redirect_to'])) {
629
  $redirect_to = $_REQUEST['redirect_to'];
630
  // Redirect to https if user wants ssl
631
- if (isset($secure_cookie) && false !== strpos($redirect_to, 'wp-admin'))
632
- $redirect_to = preg_replace('|^http://|', 'https://', $redirect_to);
633
  }
634
  else {
635
  $redirect_to = admin_url();
636
  }
637
- if (!isset($secure_cookie) && is_ssl() && !force_ssl_admin() && ( 0 !== strpos($redirect_to, 'https') ) && ( 0 === strpos($redirect_to, 'http') ))
638
- $secure_cookie = false;
639
  // If cookies are disabled we can't log in even with a valid user+pass
640
- if (isset($_POST['testcookie']) && empty($_COOKIE[TEST_COOKIE]))
641
- $user = new WP_Error('test_cookie', __("<strong>ERROR</strong>: Cookies are blocked or not supported by your browser. You must <a href='http://www.google.com/cookies.html'>enable cookies</a> to use WordPress."));
642
- else
643
- $user = wp_signon('', isset($secure_cookie));
644
 
645
- if (!$this->set_cookies($user_id)) {
646
  return false;
647
  }
648
- $requested_redirect_to = isset($_REQUEST['redirect_to']) ? $_REQUEST['redirect_to'] : site_url();
649
- $user_login_url = apply_filters('login_redirect', $redirect_to, $requested_redirect_to, $user);
650
 
651
- $options = get_option(APSL_SETTINGS);
652
- if (isset($options['apsl_custom_login_redirect_options']) && $options['apsl_custom_login_redirect_options'] != '') {
653
- if ($options['apsl_custom_login_redirect_options'] == 'home') {
654
  $user_login_url = home_url();
655
- } else if ($options['apsl_custom_login_redirect_options'] == 'current_page') {
656
- if (isset($_REQUEST['redirect_to'])) {
 
657
  $redirect_to = $_REQUEST['redirect_to'];
658
  // Redirect to https if user wants ssl
659
- if (isset($secure_cookie) && false !== strpos($redirect_to, 'wp-admin'))
660
- $user_login_url = preg_replace('|^http://|', 'https://', $redirect_to);
661
  }
662
  else {
663
  $user_login_url = home_url();
664
  }
665
- } else if ($options['apsl_custom_login_redirect_options'] == 'custom_page') {
666
- if ($options['apsl_custom_login_redirect_link'] != '') {
 
667
  $login_page = $options['apsl_custom_login_redirect_link'];
668
  $user_login_url = $login_page;
669
- } else {
 
670
  $user_login_url = home_url();
671
  }
672
  }
673
- } else {
 
674
  $user_login_url = home_url();
675
  }
676
  $redirect_to = $user_login_url;
677
- $redirect_to = apply_filters('login_redirect', $redirect_to);
678
  $redirect_to = isset($_COOKIE["apsl_login_redirect_url"]) ? urldecode($_COOKIE["apsl_login_redirect_url"]) : $redirect_to;
679
  // echo "<script> window.close(); window.opener.location.href='$redirect_to'; </script>";
680
- wp_safe_redirect($redirect_to);
681
  exit();
682
  }
683
-
684
  //returns the current page url
685
  public static function curPageURL() {
686
  $pageURL = 'http';
687
- if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') {
688
- $pageURL .= "s";
689
  }
690
- $pageURL .= "://";
691
- if ($_SERVER["SERVER_PORT"] != "80") {
692
- $pageURL .= $_SERVER["SERVER_NAME"] . ":" . $_SERVER["SERVER_PORT"] . $_SERVER["REQUEST_URI"];
693
- } else {
694
- $pageURL .= $_SERVER["SERVER_NAME"] . $_SERVER["REQUEST_URI"];
 
695
  }
696
  return $pageURL;
697
  }
698
-
699
  //function to access the protected object properties
700
- function accessProtected($obj, $prop) {
701
- $reflection = new ReflectionClass($obj);
702
- $property = $reflection->getProperty($prop);
703
- $property->setAccessible(true);
704
- return $property->getValue($obj);
705
  }
706
 
 
707
  //insert the user data into plugin's custom database
708
- static function link_user($id, $result) {
709
  global $wpdb;
710
- $unique_verifier = sha1($result->deutype . $result->deuid);
711
  $apsl_userdetails = "{$wpdb->prefix}apsl_users_social_profile_details";
712
 
713
  $first_name = sanitize_text_field($result->first_name);
714
  $last_name = sanitize_text_field($result->last_name);
715
  $profile_url = sanitize_text_field($result->url);
716
- $photo_url = sanitize_text_field($result->deuimage);
717
- $display_name = sanitize_text_field($result->first_name . ' ' . $result->last_name);
718
  $description = sanitize_text_field($result->about);
719
 
720
- $table_name = $apsl_userdetails;
721
- $submit_array = array(
722
- "user_id" => $id,
723
- "provider_name" => $result->deutype,
724
- "identifier" => $result->deuid,
725
- "unique_verifier" => $unique_verifier,
726
- "email" => $result->email,
727
- "first_name" => $first_name,
728
- "last_name" => $last_name,
729
- "profile_url" => $profile_url,
730
- "photo_url" => $photo_url,
731
- "display_name" => $display_name,
732
- "description" => $description,
733
- "gender" => $result->gender
734
- );
735
  $user_profile_details = $result;
736
- $wpdb->insert($table_name, $submit_array);
737
- if (!$result) {
738
  echo "Data insertion failed";
739
  // die(mysql_error());
740
  }
741
  }
742
 
743
  //update the user meta data
744
- static function UpdateUserMeta($id, $result, $role) {
745
- update_user_meta($id, 'email', $result->email);
746
- update_user_meta($id, 'first_name', $result->first_name);
747
- update_user_meta($id, 'last_name', $result->last_name);
748
- update_user_meta($id, 'billing_first_name', $result->first_name);
749
- update_user_meta($id, 'billing_last_name', $result->last_name);
750
- update_user_meta($id, 'deuid', $result->deuid);
751
- update_user_meta($id, 'deutype', $result->deutype);
752
- update_user_meta($id, 'deuimage', $result->deuimage);
753
- update_user_meta($id, 'description', $result->about);
754
- update_user_meta($id, 'sex', $result->gender);
755
- wp_update_user(array(
756
  'ID' => $id,
757
  'display_name' => $result->first_name . ' ' . $result->last_name,
758
  // 'role' => $role,
759
  'user_url' => $result->url
760
- ));
761
 
762
  global $wpdb;
763
- $unique_verifier = sha1($result->deutype . $result->deuid);
764
  $apsl_userdetails = "{$wpdb->prefix}apsl_users_social_profile_details";
765
 
766
  $first_name = sanitize_text_field($result->first_name);
767
  $last_name = sanitize_text_field($result->last_name);
768
  $profile_url = sanitize_text_field($result->url);
769
- $photo_url = sanitize_text_field($result->deuimage);
770
- $display_name = sanitize_text_field($result->first_name . ' ' . $result->last_name);
771
  $description = sanitize_text_field($result->about);
772
 
773
- $table_name = $apsl_userdetails;
774
- $submit_array = array(
775
- "user_id" => $id,
776
- "provider_name" => $result->deutype,
777
- "identifier" => $result->deuid,
778
- "unique_verifier" => $unique_verifier,
779
- "email" => $result->email,
780
- "first_name" => $first_name,
781
- "last_name" => $last_name,
782
- "profile_url" => $profile_url,
783
- "photo_url" => $photo_url,
784
- "display_name" => $display_name,
785
- "description" => $description,
786
- "gender" => $result->gender
787
- );
788
  $user_profile_details = $result;
789
- $wpdb->insert($table_name, $submit_array);
790
 
791
  // if(function_exists('bp_has_profile')){
792
  // self:: apsl_buddypress_xprofile_mapping($id, $user_profile_details->deutype, $user_profile_details);
793
  // }
794
- if (!$result) {
795
  echo "Data insertion failed";
796
  // die(mysql_error());
797
  }
798
  }
799
 
800
- }
801
 
802
- //termination of a class
803
  } //end of if statement
804
 
805
  $apsl_login_check = new APSL_Lite_Login_Check_Class();
1
  <?php
2
+ defined( 'ABSPATH' ) or die( "No script kiddies please!" );
3
 
4
+ if( !class_exists( 'APSL_Lite_Login_Check_Class' ) ) {
 
 
5
 
6
  class APSL_Lite_Login_Check_Class {
 
7
  //constructor
8
  function __construct() {
9
 
10
+ if( isset( $_GET['apsl_login_id'] ) ) {
11
+ if( isset( $_REQUEST['state'] ) ) {
12
+ parse_str( base64_decode( $_REQUEST['state'] ), $state_vars );
13
 
14
+ if( isset( $state_vars['redirect_to'] ) ) {
15
  $_GET['redirect_to'] = $_REQUEST['redirect_to'] = $state_vars['redirect_to'];
16
  }
17
  }
18
 
19
+ $exploder = explode( '_', $_GET['apsl_login_id'] );
20
+ switch( $exploder[0] ) {
21
  case 'facebook':
22
+ if( version_compare( PHP_VERSION, '5.4.0', '<' ) ) {
23
+ echo _e( 'The Facebook SDK requires PHP version 5.4 or higher. Please notify about this error to site admin.', 'accesspress-social-login-lite' );
24
  die();
25
  }
26
  $this->onFacebookLogin();
27
+ break;
28
  case 'twitter':
29
+ if( !class_exists( 'TwitterOAuth' ) ) {
30
  include( APSL_PLUGIN_DIR . 'twitter/OAuth.php' );
31
  include( APSL_PLUGIN_DIR . 'twitter/twitteroauth.php' );
32
  }
33
  $this->onTwitterLogin();
34
+ break;
35
  case 'google':
36
+ if( !class_exists( 'Google_Client' ) ) {
37
+ include( APSL_PLUGIN_DIR . 'google/Client.php' );
38
+ }
39
+ if(!class_exists('Google_Service_Plus')){
40
+ include( APSL_PLUGIN_DIR . 'google/Service/Plus.php' );
41
+ }
42
  $this->onGoogleLogin();
43
+ break;
44
  }
45
  }
46
  }
 
47
  //for facebook login
48
  function onFacebookLogin() {
49
  $response = new stdClass();
50
+ $result = $this->facebookLogin( $response );
51
+ if( isset( $result->status ) && $result->status == 'SUCCESS' ) {
52
  global $wpdb;
53
+ $unique_verifier = sha1($result->deutype.$result->deuid);
54
  $sql = "SELECT * FROM `{$wpdb->prefix}apsl_users_social_profile_details` WHERE `provider_name` LIKE '$result->deutype' AND `identifier` LIKE '$result->deuid' AND `unique_verifier` LIKE '$unique_verifier'";
55
  $row = $wpdb->get_row($sql);
56
+ if( !$row ) {
57
  //check if there is already a user with the email address provided from social login already
58
  $user_details_by_email = $this->getUserByMail($result->email);
59
+ if( $user_details_by_email != false ){
60
  //user already there so log him in
61
  $id = $user_details_by_email->ID;
62
  $sql = "SELECT * FROM `{$wpdb->prefix}apsl_users_social_profile_details` WHERE `user_id` LIKE '$id'; ";
63
  $row = $wpdb->get_row($sql);
64
+ if(!$row){
65
+ self:: link_user($id, $result);
66
  }
67
+ self:: loginUser( $id );
68
  die();
69
  }
70
+ $_SESSION['user_details']= $result;
71
+
72
  // use FB id as username if sanitized username is empty
73
+ $sanitized_user_name = sanitize_user( $result->username, true );
74
+ if ( empty( $sanitized_user_name ) ) {
75
+ $sanitized_user_name = $result->deuid;
76
  }
77
+ $user_Id = self::creatUser( $sanitized_user_name, $result->email );
78
+ $user_row = self:: getUserByMail( $result->email );
79
  $id = $user_row->ID;
80
  $result = $result;
81
  $role = 'subscriber';
82
+ self:: UpdateUserMeta( $id, $result, $role );
83
+ self:: loginUser( $id );
84
  exit();
85
+ }else{
86
+ if( ($row->provider_name == $result->deutype) && ($row->identifier == $result->deuid) ){
87
  //echo "user found in our database";
88
+ self:: loginUser( $row->user_id );
89
  exit();
90
+ }else{
91
  // user not found in our database
92
  // need to handle an exception
93
  }
94
  }
95
+ }else{
96
+ if(isset($_REQUEST['error'])){
97
  $_SESSION['apsl_login_error_flag'] = 1;
98
  $redirect_url = isset($_REQUEST['redirect_to']) ? $_REQUEST['redirect_to'] : site_url();
99
  $this->redirect($redirect_url);
101
  die();
102
  }
103
  }
104
+
105
  function facebookLogin() {
106
  $request = $_REQUEST;
107
  $site = $this->siteUrl();
108
  $callBackUrl = $this->callBackUrl();
109
  $response = new stdClass();
110
  $return_user_details = new stdClass();
111
+ $exploder = explode( '_', $_GET['apsl_login_id'] );
112
  $action = $exploder[1];
113
+ $options = get_option( APSL_SETTINGS );
114
+ if(isset($options['apsl_facebook_settings']['apsl_profile_image_width'])){
115
+ $width = $options['apsl_facebook_settings']['apsl_profile_image_width'];
116
+ }else{
117
+ $width = 150;
118
  }
119
 
120
+ if(isset($options['apsl_facebook_settings']['apsl_profile_image_height'])){
121
  $height = $options['apsl_facebook_settings']['apsl_profile_image_height'];
122
+ }else{
123
  $height = 150;
124
  }
125
 
126
+ $config = array('app_id' => $options['apsl_facebook_settings']['apsl_facebook_app_id'], 'app_secret' => $options['apsl_facebook_settings']['apsl_facebook_app_secret'], 'default_graph_version' => 'v2.4', 'persistent_data_handler' => 'session' );
127
  include( APSL_PLUGIN_DIR . 'facebook/autoload.php' );
128
+ $fb = new Facebook\Facebook( $config );
129
 
130
  $callback = $callBackUrl . 'apsl_login_id' . '=facebook_check';
131
 
132
+ if( $action == 'login' ) {
133
  // Well looks like we are a fresh dude, login to Facebook!
134
  $helper = $fb->getRedirectLoginHelper();
135
  $permissions = array('email', 'public_profile'); // optional
136
+ $loginUrl = $helper->getLoginUrl( $callback, $permissions );
137
 
138
+ $encoded_url = isset( $_GET['redirect_to'] ) ? $_GET['redirect_to'] : '';
139
+ if( isset( $encoded_url ) && $encoded_url != '' ) {
140
+ setcookie("apsl_login_redirect_url", $encoded_url, time()+3600);
141
  // $callback = $callBackUrl . 'apsl_login_id' . '=facebook_check&redirect_to=' . $encoded_url;
142
  }
143
+ $this->redirect( $loginUrl );
144
+ }
145
+ else {
146
+ if( isset( $_REQUEST['error'] ) ) {
147
  $response->status = 'ERROR';
148
  $response->error_code = 2;
149
  $response->error_message = 'INVALID AUTHORIZATION';
150
  return $response;
151
  die();
152
  }
153
+ if( isset( $_REQUEST['code'] ) ) {
154
  $helper = $fb->getRedirectLoginHelper();
155
  // Trick below will avoid "Cross-site request forgery validation failed. Required param "state" missing." from Facebook
156
  $_SESSION['FBRLH_state'] = $_REQUEST['state'];
157
  try {
158
  $accessToken = $helper->getAccessToken($callback);
159
+ }
160
+ catch( Facebook\Exceptions\FacebookResponseException $e ) {
161
  // When Graph returns an error
162
  echo 'Graph returned an error: ' . $e->getMessage();
163
  exit;
164
+ }
165
+ catch( Facebook\Exceptions\FacebookSDKException $e ) {
166
  // When validation fails or other local issues
167
  echo 'Facebook SDK returned an error: ' . $e->getMessage();
168
  exit;
169
  }
170
+
171
+ if( isset( $accessToken ) ) {
172
  // Logged in!
173
+ $_SESSION['facebook_access_token'] = (string)$accessToken;
174
+ $fb->setDefaultAccessToken( $accessToken );
175
 
176
  try {
177
+ $response = $fb->get( '/me?fields=email,name, first_name, last_name, gender, link, about, birthday, education, hometown, is_verified, languages, location, website' );
178
  $userNode = $response->getGraphUser();
179
+ }
180
+ catch( Facebook\Exceptions\FacebookResponseException $e ) {
181
  // When Graph returns an error
182
  echo 'Graph returned an error: ' . $e->getMessage();
183
  exit;
184
+ }
185
+ catch( Facebook\Exceptions\FacebookSDKException $e ) {
186
  // When validation fails or other local issues
187
  echo 'Facebook SDK returned an error: ' . $e->getMessage();
188
  exit;
189
  }
190
  // get the user profile details
191
+ $user_profile = $this->accessProtected( $userNode, 'items' );
192
+ if( $user_profile != null ) {
193
  $return_user_details->status = 'SUCCESS';
194
  $return_user_details->deuid = $user_profile['id'];
195
  $return_user_details->deutype = 'facebook';
196
  $return_user_details->first_name = $user_profile['first_name'];
197
  $return_user_details->last_name = $user_profile['last_name'];
198
+ if(isset($user_profile['email']) || $user_profile['email'] != ''){
199
  $user_email = $user_profile['email'];
200
+ }else{
201
+ $user_email = $user_profile['id'].'@facebook.com';
202
  }
203
  $return_user_details->email = $user_email;
204
+ $return_user_details->username = ($user_profile['first_name'] !='') ? strtolower( $user_profile['first_name'] ) : $user_email;
205
  $return_user_details->gender = isset($user_profile['gender']) ? $user_profile['gender'] : 'N/A';
206
  $return_user_details->url = $user_profile['link'];
207
  $return_user_details->about = ''; //facebook doesn't return user about details.
208
+ $headers = get_headers( 'https://graph.facebook.com/' . $user_profile['id'] . '/picture?width='.$width.'&height='.$height, 1 );
209
  // just a precaution, check whether the header isset...
210
+ if( isset( $headers['Location'] ) ) {
211
  $return_user_details->deuimage = $headers['Location']; // string
212
+
213
+ }
214
+ else {
215
  $return_user_details->deuimage = false; // nothing there? .. weird, but okay!
216
+
217
  }
218
  $return_user_details->error_message = '';
219
+ }
220
+ else {
221
  $return_user_details->status = 'ERROR';
222
  $return_user_details->error_code = 2;
223
  $return_user_details->error_message = 'INVALID AUTHORIZATION';
224
  }
225
  }
226
+ }
227
+ else {
228
  // Well looks like we are a fresh dude, login to Facebook!
229
  $helper = $fb->getRedirectLoginHelper();
230
  $permissions = array('email', 'public_profile'); // optional
231
+ $loginUrl = $helper->getLoginUrl( $callback, $permissions );
232
+ $this->redirect( $loginUrl );
233
  }
234
  }
235
  return $return_user_details;
236
  }
 
237
  //for twitter login
238
  function onTwitterLogin() {
239
  $result = $this->twitterLogin();
240
+ if( isset( $result->status ) && $result->status == 'SUCCESS' ) {
241
  global $wpdb;
242
+ $unique_verifier = sha1($result->deutype.$result->deuid);
243
  $sql = "SELECT * FROM `{$wpdb->prefix}apsl_users_social_profile_details` WHERE `provider_name` LIKE '$result->deutype' AND `identifier` LIKE '$result->deuid' AND `unique_verifier` LIKE '$unique_verifier'";
244
  $row = $wpdb->get_row($sql);
245
+ if( !$row ) {
246
  //check if there is already a user with the email address provided from social login already
247
  $user_details_by_email = $this->getUserByMail($result->email);
248
+ if( $user_details_by_email != false ){
249
  //user already there so log him in
250
  $id = $user_details_by_email->ID;
251
  $sql = "SELECT * FROM `{$wpdb->prefix}apsl_users_social_profile_details` WHERE `user_id` LIKE '$id'; ";
252
  $row = $wpdb->get_row($sql);
253
  // var_dump($row);
254
+ if(!$row){
255
+ self:: link_user($id, $result);
256
  }
257
+ self:: loginUser( $id );
258
  die();
259
  }
260
+ $_SESSION['user_details']= $result;
261
+ self::creatUser( $result->username, $result->email );
262
+ $user_row = self:: getUserByMail( $result->email );
263
  $id = $user_row->ID;
264
  $result = $result;
265
  $role = 'subscriber';
266
+ self:: UpdateUserMeta( $id, $result, $role );
267
+ self:: loginUser( $id );
268
  exit();
269
+ }else{
270
+ if( ($row->provider_name == $result->deutype) && ($row->identifier == $result->deuid) ){
271
  //echo "user found in our database";
272
+ self:: loginUser( $row->user_id );
273
  exit();
274
+ }else{
275
  // user not found in our database
276
  // need to handle an exception
277
  }
278
  }
279
+ $_SESSION['apsl_login_error_flag'] = 1;
280
+ }else{
281
+ if(isset($_REQUEST['denied'])){
282
  $redirect_url = isset($_REQUEST['redirect_to']) ? $_REQUEST['redirect_to'] : site_url();
283
  $this->redirect($redirect_url);
284
  }
285
  die();
286
  }
287
  }
288
+
289
  function twitterLogin() {
290
  $request = $_REQUEST;
291
  $site = $this->siteUrl();
292
  $callBackUrl = $this->callBackUrl();
293
  $response = new stdClass();
294
+ $exploder = explode( '_', $_GET['apsl_login_id'] );
295
  $action = $exploder[1];
296
  @session_start();
297
+ $options = get_option( APSL_SETTINGS );
298
+ if( $action == 'login' ) {
299
  // Get identity from user and redirect browser to OpenID Server
300
+ if( !isset( $request['oauth_token'] ) || $request['oauth_token'] == '' ) {
301
+ $twitterObj = new TwitterOAuth( $options['apsl_twitter_settings']['apsl_twitter_api_key'], $options['apsl_twitter_settings']['apsl_twitter_api_secret'] );
302
+ $encoded_url = isset( $_GET['redirect_to'] ) ? $_GET['redirect_to'] : '';
303
+ if( isset( $encoded_url ) && $encoded_url != '' ) {
304
  $callback = $callBackUrl . 'apsl_login_id' . '=twitter_check&redirect_to=' . $encoded_url;
305
+ }
306
+ else {
307
  $callback = $callBackUrl . 'apsl_login_id' . '=twitter_check';
308
  }
309
+
310
+ $request_token = $twitterObj->getRequestToken( $callback );
311
  $_SESSION['oauth_twitter'] = array();
312
  /* Save temporary credentials to session. */
313
  $_SESSION['oauth_twitter']['oauth_token'] = $token = $request_token['oauth_token'];
314
  $_SESSION['oauth_twitter']['oauth_token_secret'] = $request_token['oauth_token_secret'];
315
  /* If last connection failed don't display authorization link. */
316
+ switch( $twitterObj->http_code ) {
317
  case 200:
318
  try {
319
+ $url = $twitterObj->getAuthorizeUrl( $token );
320
+ $this->redirect( $url );
321
+ }
322
+ catch( Exception $e ) {
323
  $response->status = 'ERROR';
324
  $response->error_code = 2;
325
  $response->error_message = 'Could not get AuthorizeUrl.';
326
  }
327
+ break;
328
  default:
329
  $response->status = 'ERROR';
330
  $response->error_code = 2;
331
  $response->error_message = 'Could not connect to Twitter. Refresh the page or try again later.';
332
+ break;
333
  }
334
+ }
335
+ else {
336
  $response->status = 'ERROR';
337
  $response->error_code = 2;
338
  $response->error_message = 'INVALID AUTHORIZATION';
339
  }
340
+ }
341
+ else if( isset( $request['oauth_token'] ) && isset( $request['oauth_verifier'] ) ) {
342
  /* Create TwitteroAuth object with app key/secret and token key/secret from default phase */
343
+ $twitterObj = new TwitterOAuth( $options['apsl_twitter_settings']['apsl_twitter_api_key'], $options['apsl_twitter_settings']['apsl_twitter_api_secret'], $_SESSION['oauth_twitter']['oauth_token'], $_SESSION['oauth_twitter']['oauth_token_secret'] );
344
  /* Remove no longer needed request tokens */
345
+ unset( $_SESSION['oauth_twitter'] );
346
  try {
347
+ $access_token = $twitterObj->getAccessToken( $request['oauth_verifier'] );
348
  /* If HTTP response is 200 continue otherwise send to connect page to retry */
349
+ if( 200 == $twitterObj->http_code ) {
350
+ $user_profile = $twitterObj->get( 'account/verify_credentials', array(
351
+ 'screen_name' => $access_token['screen_name'],
352
+ 'skip_status' => 'true',
353
+ 'include_entities' => 'true',
354
+ 'include_email' => 'true'
355
+ )
356
+ );
357
  /* Request access twitterObj from twitter */
358
  $response->status = 'SUCCESS';
359
  $response->deuid = $user_profile->id;
360
  $response->deutype = 'twitter';
361
+ $response->name = explode( ' ', $user_profile->name, 2 );
362
  $response->first_name = $response->name[0];
363
+ $response->last_name =( isset( $response->name[1] ) ) ? $response->name[1] : '';
364
  $response->deuimage = $user_profile->profile_image_url_https;
365
  $response->email = isset($user_profile->email) ? $user_profile->email : $user_profile->screen_name . '@twitter.com';
366
+ $response->username = ($user_profile->screen_name !='') ? strtolower($user_profile->screen_name) : $user_email;
367
  $response->url = $user_profile->url;
368
  $response->about = isset($user_profile->description) ? $user_profile->description : '';
369
  $response->gender = isset($user_profile->gender) ? $user_profile->gender : 'N/A';
370
  $response->location = $user_profile->location;
371
  $response->error_message = '';
372
+ }
373
+ else {
374
  $response->status = 'ERROR';
375
  $response->error_code = 2;
376
  $response->error_message = 'Could not connect to Twitter. Refresh the page or try again later.';
377
  }
378
+ }
379
+ catch( Exception $e ) {
380
  $response->status = 'ERROR';
381
  $response->error_code = 2;
382
  $response->error_message = 'Could not get AccessToken.';
383
  }
384
+ }
385
+ else { // User Canceled your Request
386
  $response->status = 'ERROR';
387
  $response->error_code = 1;
388
  $response->error_message = "USER CANCELED REQUEST";
389
  }
390
  return $response;
391
  }
 
392
  //for google login
393
  function onGoogleLogin() {
394
  $result = $this->GoogleLogin();
395
+ if( isset( $result->status ) && $result->status == 'SUCCESS' ) {
396
  global $wpdb;
397
+ $unique_verifier = sha1($result->deutype.$result->deuid);
398
  $sql = "SELECT * FROM `{$wpdb->prefix}apsl_users_social_profile_details` WHERE `provider_name` LIKE '$result->deutype' AND `identifier` LIKE '$result->deuid' AND `unique_verifier` LIKE '$unique_verifier'";
399
  $row = $wpdb->get_row($sql);
400
+ if( !$row ) {
401
  //check if there is already a user with the email address provided from social login already
402
  $user_details_by_email = $this->getUserByMail($result->email);
403
+ if( $user_details_by_email != false ){
404
  //user already there so log him in
405
  $id = $user_details_by_email->ID;
406
  $sql = "SELECT * FROM `{$wpdb->prefix}apsl_users_social_profile_details` WHERE `user_id` LIKE '$id'; ";
407
  $row = $wpdb->get_row($sql);
408
+ if(!$row){
409
+ self:: link_user($id, $result);
410
  }
411
+ self:: loginUser( $id );
412
  die();
413
  }
414
+ $_SESSION['user_details']= $result;
415
+ self::creatUser( $result->username, $result->email );
416
+ $user_row = self:: getUserByMail( $result->email );
417
  $id = $user_row->ID;
418
  $result = $result;
419
  $role = 'subscriber';
420
+ self:: UpdateUserMeta( $id, $result, $role );
421
+ self:: loginUser( $id );
422
  exit();
423
+ }else{
424
+ if( ($row->provider_name == $result->deutype) && ($row->identifier == $result->deuid) ){
425
  //echo "user found in our database";
426
+ self:: loginUser( $row->user_id );
427
  exit();
428
+ }else{
429
  // user not found in our database
430
  // need to handle an exception
431
  }
432
  }
433
+ }else{
434
+ if(isset($_REQUEST['error'])){
435
  $_SESSION['apsl_login_error_flag'] = 1;
436
  $redirect_url = isset($_REQUEST['redirect_to']) ? $_REQUEST['redirect_to'] : site_url();
437
  $this->redirect($redirect_url);
439
  die();
440
  }
441
  }
442
+
443
  function GoogleLogin() {
444
  $post = $_POST;
445
  $get = $_GET;
446
  $request = $_REQUEST;
447
  $site = $this->siteUrl();
448
  $callBackUrl = $this->callBackUrl();
449
+ $options = get_option( APSL_SETTINGS );
450
  $response = new stdClass();
451
+ $a = explode( '_', $_GET['apsl_login_id'] );
452
  $action = $a[1];
453
  $client_id = $options['apsl_google_settings']['apsl_google_client_id'];
454
  $client_secret = $options['apsl_google_settings']['apsl_google_client_secret'];
455
+
456
  $site_url = site_url() . '/wp-admin';
457
+ $encoded_url = isset( $_GET['redirect_to'] ) ? $_GET['redirect_to'] : $site_url;
458
  $callback = $callBackUrl . 'apsl_login_id' . '=google_check';
459
+
460
  $redirect_uri = $callback;
461
  $client = new Google_Client;
462
+
463
+ $client->setClientId( $client_id );
464
+ $client->setClientSecret( $client_secret );
465
+ $client->setRedirectUri( $redirect_uri );
466
+ $client->addScope( "https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/plus.profile.emails.read" );
467
+ if( isset( $encoded_url ) && $encoded_url != '' ) {
468
+ $client->setState( base64_encode( "redirect_to=$encoded_url" ) );
469
  }
470
+
471
+ $service = new Google_Service_Plus( $client );
472
+
473
+ if( $action == 'login' ) { // Get identity from user and redirect browser to OpenID Server
474
+ unset($_SESSION['access_token']);
475
+ if( !( isset( $_SESSION['access_token'] ) && $_SESSION['access_token'] ) ) {
476
  $authUrl = $client->createAuthUrl();
477
+ $this->redirect( $authUrl );
478
  die();
479
+ }
480
+ else {
481
+ $this->redirect( $redirect_uri . "&redirect_to=$encoded_url" );
482
  die();
483
  }
484
+ }
485
+ elseif( isset( $_GET['code'] ) ) { // Perform HTTP Request to OpenID server to validate key
486
+ $client->authenticate( $_GET['code'] );
487
  $_SESSION['access_token'] = $client->getAccessToken();
488
+ $this->redirect( $redirect_uri . "&redirect_to=$encoded_url" );
489
  die();
490
+ }
491
+ elseif( isset( $_SESSION['access_token'] ) && $_SESSION['access_token'] ) {
492
+ $client->setAccessToken( $_SESSION['access_token'] );
493
+
494
  try {
495
+ $user = $service->people->get( "me", array() );
496
+ }
497
+ catch( Exception $fault ) {
498
+ unset( $_SESSION['access_token'] );
499
+ $ref_object = $this->accessProtected( $fault, 'errors' );
500
  echo $ref_object[0]['message'] . " Please notify about this error to the Site Admin.";
501
  die();
502
  }
503
+
504
+ if( !empty( $user ) ) {
505
+ if( !empty( $user->emails ) ) {
506
+
507
  $response->email = $user->emails[0]->value;
508
  $response->username = ($user->name->givenName) ? strtolower($user->name->givenName) : $user_email;
509
  $response->first_name = $user->name->givenName;
517
  $response->deutype = 'google';
518
  $response->status = 'SUCCESS';
519
  $response->error_message = '';
520
+ }
521
+ else {
522
  $response->status = 'ERROR';
523
  $response->error_code = 2;
524
  $response->error_message = "INVALID AUTHORIZATION";
525
  }
526
+ }
527
+ else { // Signature Verification Failed
528
  $response->status = 'ERROR';
529
  $response->error_code = 2;
530
  $response->error_message = "INVALID AUTHORIZATION";
531
  }
532
+ }
533
+ else { // User failed to login
534
  $response->status = 'ERROR';
535
  $response->error_code = 3;
536
  $response->error_message = "USER LOGIN FAIL";
537
  }
538
  return $response;
539
  }
 
540
  //other remaining methods
541
  function siteUrl() {
542
  return site_url();
545
  function callBackUrl() {
546
  // $connection = !empty( $_SERVER['HTTPS'] ) ? 'https://' : 'http://';
547
  $url = wp_login_url();
548
+ if( strpos( $url, '?' ) === false ) {
549
+ $url.= '?';
550
+ }
551
+ else {
552
+ $url.= '&';
553
  }
554
  return $url;
555
  }
 
556
  //function to return json values from social media urls
557
+ function get_json_values( $url ) {
558
+ $response = wp_remote_get( $url );
559
+ $json_response = wp_remote_retrieve_body( $response );
560
  return $json_response;
561
  }
562
 
563
+ function redirect( $redirect ) {
564
+ if( headers_sent() ) { // Use JavaScript to redirect if content has been previously sent (not recommended, but safe)
565
  echo '<script language="JavaScript" type="text/javascript">window.location=\'';
566
  echo $redirect;
567
  echo '\';</script>';
568
+ }
569
+ else { // Default Header Redirect
570
+ header( 'Location: ' . $redirect );
571
  }
572
  exit;
573
  }
574
 
575
+ static function get_username($user_name){
576
  $username = $user_name;
577
  $i = 1;
578
+ while(username_exists( $username )){
579
+ $username = $user_name.'_'.$i;
580
  $i++;
581
  }
582
  return $username;
583
  }
584
 
585
+ function updateUser( $username, $email ) {
586
+ $row = $this->getUserByUsername( $username );
587
+ if( $row && $email != '' && $row->user_email != $email ) {
588
+ $row = (array)$row;
589
  $row['user_email'] = $email;
590
+ wp_update_user( $row );
591
  }
592
  }
593
 
594
+ function getUserByMail( $email ) {
595
  global $wpdb;
596
+ $row = $wpdb->get_row( "SELECT * FROM $wpdb->users WHERE user_email = '$email'" );
597
+ if( $row ) {
598
  return $row;
599
  }
600
  return false;
601
  }
602
 
603
+ function getUserByUsername( $username ) {
604
  global $wpdb;
605
+ $row = $wpdb->get_row( "SELECT * FROM $wpdb->users WHERE user_login = '$username'" );
606
+ if( $row ) {
607
  return $row;
608
  }
609
  return false;
610
  }
611
 
612
+ function creatUser( $user_name, $user_email ) {
613
+ $username = self:: get_username($user_name);
614
+ $random_password = wp_generate_password( 12, false );
615
+ $user_id = wp_create_user( $username, $random_password, $user_email );
616
+ do_action( 'APSL_createUser', $user_id ); //hookable function to perform additional work after creation of user.
617
+ $options = get_option( APSL_SETTINGS );
618
+ if( $options['apsl_send_email_notification_options'] == 'yes' ) {
619
+ if (version_compare(get_bloginfo('version'), '4.3.1', '>=')){
620
+ wp_new_user_notification( $user_id, $deprecated = null, $notify = 'both' );
621
+ }else{
622
+ wp_new_user_notification( $user_id, $random_password );
623
  }
624
  }
625
  return $user_id;
626
  }
627
 
628
+ function set_cookies( $user_id = 0, $remember = true ) {
629
+ if( !function_exists( 'wp_set_auth_cookie' ) ) {
630
  return false;
631
  }
632
+ if( !$user_id ) {
633
  return false;
634
  }
635
  wp_clear_auth_cookie();
636
+ wp_set_auth_cookie( $user_id, $remember );
637
+ wp_set_current_user( $user_id );
638
  return true;
639
  }
640
 
641
+ function loginUser( $user_id ) {
642
  $current_url_an = get_permalink();
643
+ $reauth = empty( $_REQUEST['reauth'] ) ? false : true;
644
+ if( $reauth )wp_clear_auth_cookie();
645
+
646
+ if( isset( $_REQUEST['redirect_to'] ) ) {
 
647
  $redirect_to = $_REQUEST['redirect_to'];
648
  // Redirect to https if user wants ssl
649
+ if( isset( $secure_cookie ) && false !== strpos( $redirect_to, 'wp-admin' ) )$redirect_to = preg_replace( '|^http://|', 'https://', $redirect_to );
 
650
  }
651
  else {
652
  $redirect_to = admin_url();
653
  }
654
+ if( !isset( $secure_cookie ) && is_ssl() && !force_ssl_admin() &&( 0 !== strpos( $redirect_to, 'https' ) ) &&( 0 === strpos( $redirect_to, 'http' ) ) )$secure_cookie = false;
 
655
  // If cookies are disabled we can't log in even with a valid user+pass
656
+ if( isset( $_POST['testcookie'] ) && empty( $_COOKIE[TEST_COOKIE] ) )$user = new WP_Error( 'test_cookie', __( "<strong>ERROR</strong>: Cookies are blocked or not supported by your browser. You must <a href='http://www.google.com/cookies.html'>enable cookies</a> to use WordPress." ) );
657
+ else $user = wp_signon( '', isset( $secure_cookie ) );
 
 
658
 
659
+ if( !$this->set_cookies( $user_id ) ) {
660
  return false;
661
  }
662
+ $requested_redirect_to = isset( $_REQUEST['redirect_to'] ) ? $_REQUEST['redirect_to'] : site_url();
663
+ $user_login_url = apply_filters( 'login_redirect', $redirect_to, $requested_redirect_to, $user );
664
 
665
+ $options = get_option( APSL_SETTINGS );
666
+ if( isset( $options['apsl_custom_login_redirect_options'] ) && $options['apsl_custom_login_redirect_options'] != '' ) {
667
+ if( $options['apsl_custom_login_redirect_options'] == 'home' ) {
668
  $user_login_url = home_url();
669
+ }
670
+ else if( $options['apsl_custom_login_redirect_options'] == 'current_page' ) {
671
+ if( isset( $_REQUEST['redirect_to'] ) ) {
672
  $redirect_to = $_REQUEST['redirect_to'];
673
  // Redirect to https if user wants ssl
674
+ if( isset( $secure_cookie ) && false !== strpos( $redirect_to, 'wp-admin' ) )$user_login_url = preg_replace( '|^http://|', 'https://', $redirect_to );
 
675
  }
676
  else {
677
  $user_login_url = home_url();
678
  }
679
+ }
680
+ else if( $options['apsl_custom_login_redirect_options'] == 'custom_page' ) {
681
+ if( $options['apsl_custom_login_redirect_link'] != '' ) {
682
  $login_page = $options['apsl_custom_login_redirect_link'];
683
  $user_login_url = $login_page;
684
+ }
685
+ else {
686
  $user_login_url = home_url();
687
  }
688
  }
689
+ }
690
+ else {
691
  $user_login_url = home_url();
692
  }
693
  $redirect_to = $user_login_url;
694
+ $redirect_to = apply_filters( 'login_redirect', $redirect_to );
695
  $redirect_to = isset($_COOKIE["apsl_login_redirect_url"]) ? urldecode($_COOKIE["apsl_login_redirect_url"]) : $redirect_to;
696
  // echo "<script> window.close(); window.opener.location.href='$redirect_to'; </script>";
697
+ wp_safe_redirect( $redirect_to );
698
  exit();
699
  }
 
700
  //returns the current page url
701
  public static function curPageURL() {
702
  $pageURL = 'http';
703
+ if( isset( $_SERVER['HTTPS'] ) && $_SERVER['HTTPS'] == 'on' ) {
704
+ $pageURL.= "s";
705
  }
706
+ $pageURL.= "://";
707
+ if( $_SERVER["SERVER_PORT"] != "80" ) {
708
+ $pageURL.= $_SERVER["SERVER_NAME"] . ":" . $_SERVER["SERVER_PORT"] . $_SERVER["REQUEST_URI"];
709
+ }
710
+ else {
711
+ $pageURL.= $_SERVER["SERVER_NAME"] . $_SERVER["REQUEST_URI"];
712
  }
713
  return $pageURL;
714
  }
 
715
  //function to access the protected object properties
716
+ function accessProtected( $obj, $prop ) {
717
+ $reflection = new ReflectionClass( $obj );
718
+ $property = $reflection->getProperty( $prop );
719
+ $property->setAccessible( true );
720
+ return $property->getValue( $obj );
721
  }
722
 
723
+
724
  //insert the user data into plugin's custom database
725
+ static function link_user($id, $result){
726
  global $wpdb;
727
+ $unique_verifier = sha1($result->deutype.$result->deuid);
728
  $apsl_userdetails = "{$wpdb->prefix}apsl_users_social_profile_details";
729
 
730
  $first_name = sanitize_text_field($result->first_name);
731
  $last_name = sanitize_text_field($result->last_name);
732
  $profile_url = sanitize_text_field($result->url);
733
+ $photo_url = sanitize_text_field( $result->deuimage);
734
+ $display_name = sanitize_text_field( $result->first_name . ' ' . $result->last_name);
735
  $description = sanitize_text_field($result->about);
736
 
737
+ $table_name = $apsl_userdetails;
738
+ $submit_array = array(
739
+ "user_id" => $id,
740
+ "provider_name" => $result->deutype,
741
+ "identifier" => $result->deuid,
742
+ "unique_verifier" => $unique_verifier,
743
+ "email" => $result->email,
744
+ "first_name" => $first_name,
745
+ "last_name" => $last_name,
746
+ "profile_url" =>$profile_url,
747
+ "photo_url" =>$photo_url,
748
+ "display_name" =>$display_name,
749
+ "description" =>$description,
750
+ "gender" =>$result->gender
751
+ );
752
  $user_profile_details = $result;
753
+ $wpdb->insert($table_name, $submit_array );
754
+ if(!$result){
755
  echo "Data insertion failed";
756
  // die(mysql_error());
757
  }
758
  }
759
 
760
  //update the user meta data
761
+ static function UpdateUserMeta( $id, $result, $role ) {
762
+ update_user_meta( $id, 'email', $result->email );
763
+ update_user_meta( $id, 'first_name', $result->first_name );
764
+ update_user_meta( $id, 'last_name', $result->last_name );
765
+ update_user_meta( $id, 'billing_first_name', $result->first_name );
766
+ update_user_meta( $id, 'billing_last_name', $result->last_name );
767
+ update_user_meta( $id, 'deuid', $result->deuid );
768
+ update_user_meta( $id, 'deutype', $result->deutype );
769
+ update_user_meta( $id, 'deuimage', $result->deuimage );
770
+ update_user_meta( $id, 'description', $result->about );
771
+ update_user_meta( $id, 'sex', $result->gender );
772
+ wp_update_user( array(
773
  'ID' => $id,
774
  'display_name' => $result->first_name . ' ' . $result->last_name,
775
  // 'role' => $role,
776
  'user_url' => $result->url
777
+ ) );
778
 
779
  global $wpdb;
780
+ $unique_verifier = sha1($result->deutype.$result->deuid);
781
  $apsl_userdetails = "{$wpdb->prefix}apsl_users_social_profile_details";
782
 
783
  $first_name = sanitize_text_field($result->first_name);
784
  $last_name = sanitize_text_field($result->last_name);
785
  $profile_url = sanitize_text_field($result->url);
786
+ $photo_url = sanitize_text_field( $result->deuimage);
787
+ $display_name = sanitize_text_field( $result->first_name . ' ' . $result->last_name);
788
  $description = sanitize_text_field($result->about);
789
 
790
+ $table_name = $apsl_userdetails;
791
+ $submit_array = array(
792
+ "user_id" => $id,
793
+ "provider_name" => $result->deutype,
794
+ "identifier" => $result->deuid,
795
+ "unique_verifier" => $unique_verifier,
796
+ "email" => $result->email,
797
+ "first_name" => $first_name,
798
+ "last_name" => $last_name,
799
+ "profile_url" =>$profile_url,
800
+ "photo_url" =>$photo_url,
801
+ "display_name" =>$display_name,
802
+ "description" =>$description,
803
+ "gender" =>$result->gender
804
+ );
805
  $user_profile_details = $result;
806
+ $wpdb->insert($table_name, $submit_array );
807
 
808
  // if(function_exists('bp_has_profile')){
809
  // self:: apsl_buddypress_xprofile_mapping($id, $user_profile_details->deutype, $user_profile_details);
810
  // }
811
+ if(!$result){
812
  echo "Data insertion failed";
813
  // die(mysql_error());
814
  }
815
  }
816
 
817
+ } //termination of a class
818
 
 
819
  } //end of if statement
820
 
821
  $apsl_login_check = new APSL_Lite_Login_Check_Class();
readme.txt CHANGED
@@ -4,7 +4,7 @@ Tags: social, login, social login, facebook, twitter, google, social connect, s
4
  Donate link: http://accesspressthemes.com/donation/
5
  Requires at least: 3.8
6
  Tested up to: 4.9
7
- Stable tag: 3.3.4
8
  Requires PHP: 5.4
9
  License: GPLv2 or later
10
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
@@ -138,6 +138,10 @@ Yes. You can use the AccessPress social login lite anywhere by using the shortco
138
  4. Backend Other settings Section.
139
 
140
  == Changelog ==
 
 
 
 
141
  = 3.3.4 =
142
  * Done some code cleanup and small issue with force_ssl_login resolved
143
 
4
  Donate link: http://accesspressthemes.com/donation/
5
  Requires at least: 3.8
6
  Tested up to: 4.9
7
+ Stable tag: 3.3.5
8
  Requires PHP: 5.4
9
  License: GPLv2 or later
10
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
138
  4. Backend Other settings Section.
139
 
140
  == Changelog ==
141
+
142
+ = 3.3.5 =
143
+ * Issue with social login with facebok since our last update resolved
144
+
145
  = 3.3.4 =
146
  * Done some code cleanup and small issue with force_ssl_login resolved
147