├── README
├── config.php
├── friends.php
├── index.php
├── library
├── facebook.php
└── fb_ca_chain_bundle.crt
├── photos.php
├── photos_add.php
├── rest_user_isappuser.php
├── status.php
├── status_add.php
└── user.php
/README:
--------------------------------------------------------------------------------
1 | Here are a few examples on using the Facebook Graph API with the PHP SDK. Download the files, edit the config.php file to enter your app id and secrete, then run the index.php page. For more information visit my blog post at:
2 |
3 | http://www.joeyrivera.com/2010/facebook-graph-api-app-easy-w-php-sdk/
--------------------------------------------------------------------------------
/config.php:
--------------------------------------------------------------------------------
1 | $app_id,
9 | 'secret' => $app_secret,
10 | 'cookie' => true
11 | ));
12 |
13 | if(is_null($facebook->getUser()))
14 | {
15 | header("Location:{$facebook->getLoginUrl(array('req_perms' => 'user_status,publish_stream,user_photos'))}");
16 | exit;
17 | }
--------------------------------------------------------------------------------
/friends.php:
--------------------------------------------------------------------------------
1 | api('/me/friends');
6 | var_dump($friends);
--------------------------------------------------------------------------------
/index.php:
--------------------------------------------------------------------------------
1 |
4 |
Status
5 | View Status
6 | Add Status
7 |
8 | Photos
9 | View Photos
10 | Add Photo
11 |
12 | Friends
13 | View List
14 |
15 | Rest
16 | User: Is App User
--------------------------------------------------------------------------------
/library/facebook.php:
--------------------------------------------------------------------------------
1 |
14 | */
15 | class FacebookApiException extends Exception
16 | {
17 | /**
18 | * The result from the API server that represents the exception information.
19 | */
20 | protected $result;
21 |
22 | /**
23 | * Make a new API Exception with the given result.
24 | *
25 | * @param Array $result the result from the API server
26 | */
27 | public function __construct($result) {
28 | $this->result = $result;
29 |
30 | $code = isset($result['error_code']) ? $result['error_code'] : 0;
31 |
32 | if (isset($result['error_description'])) {
33 | // OAuth 2.0 Draft 10 style
34 | $msg = $result['error_description'];
35 | } else if (isset($result['error']) && is_array($result['error'])) {
36 | // OAuth 2.0 Draft 00 style
37 | $msg = $result['error']['message'];
38 | } else if (isset($result['error_msg'])) {
39 | // Rest server style
40 | $msg = $result['error_msg'];
41 | } else {
42 | $msg = 'Unknown Error. Check getResult()';
43 | }
44 |
45 | parent::__construct($msg, $code);
46 | }
47 |
48 | /**
49 | * Return the associated result object returned by the API server.
50 | *
51 | * @returns Array the result from the API server
52 | */
53 | public function getResult() {
54 | return $this->result;
55 | }
56 |
57 | /**
58 | * Returns the associated type for the error. This will default to
59 | * 'Exception' when a type is not available.
60 | *
61 | * @return String
62 | */
63 | public function getType() {
64 | if (isset($this->result['error'])) {
65 | $error = $this->result['error'];
66 | if (is_string($error)) {
67 | // OAuth 2.0 Draft 10 style
68 | return $error;
69 | } else if (is_array($error)) {
70 | // OAuth 2.0 Draft 00 style
71 | if (isset($error['type'])) {
72 | return $error['type'];
73 | }
74 | }
75 | }
76 | return 'Exception';
77 | }
78 |
79 | /**
80 | * To make debugging easier.
81 | *
82 | * @returns String the string representation of the error
83 | */
84 | public function __toString() {
85 | $str = $this->getType() . ': ';
86 | if ($this->code != 0) {
87 | $str .= $this->code . ': ';
88 | }
89 | return $str . $this->message;
90 | }
91 | }
92 |
93 | /**
94 | * Provides access to the Facebook Platform.
95 | *
96 | * @author Naitik Shah
97 | */
98 | class Facebook
99 | {
100 | /**
101 | * Version.
102 | */
103 | const VERSION = '2.1.2';
104 |
105 | /**
106 | * Default options for curl.
107 | */
108 | public static $CURL_OPTS = array(
109 | CURLOPT_CONNECTTIMEOUT => 10,
110 | CURLOPT_RETURNTRANSFER => true,
111 | CURLOPT_TIMEOUT => 60,
112 | CURLOPT_USERAGENT => 'facebook-php-2.0',
113 | );
114 |
115 | /**
116 | * List of query parameters that get automatically dropped when rebuilding
117 | * the current URL.
118 | */
119 | protected static $DROP_QUERY_PARAMS = array(
120 | 'session',
121 | 'signed_request',
122 | );
123 |
124 | /**
125 | * Maps aliases to Facebook domains.
126 | */
127 | public static $DOMAIN_MAP = array(
128 | 'api' => 'https://api.facebook.com/',
129 | 'api_read' => 'https://api-read.facebook.com/',
130 | 'graph' => 'https://graph.facebook.com/',
131 | 'www' => 'https://www.facebook.com/',
132 | );
133 |
134 | /**
135 | * The Application ID.
136 | */
137 | protected $appId;
138 |
139 | /**
140 | * The Application API Secret.
141 | */
142 | protected $apiSecret;
143 |
144 | /**
145 | * The active user session, if one is available.
146 | */
147 | protected $session;
148 |
149 | /**
150 | * The data from the signed_request token.
151 | */
152 | protected $signedRequest;
153 |
154 | /**
155 | * Indicates that we already loaded the session as best as we could.
156 | */
157 | protected $sessionLoaded = false;
158 |
159 | /**
160 | * Indicates if Cookie support should be enabled.
161 | */
162 | protected $cookieSupport = false;
163 |
164 | /**
165 | * Base domain for the Cookie.
166 | */
167 | protected $baseDomain = '';
168 |
169 | /**
170 | * Indicates if the CURL based @ syntax for file uploads is enabled.
171 | */
172 | protected $fileUploadSupport = false;
173 |
174 | /**
175 | * Initialize a Facebook Application.
176 | *
177 | * The configuration:
178 | * - appId: the application ID
179 | * - secret: the application secret
180 | * - cookie: (optional) boolean true to enable cookie support
181 | * - domain: (optional) domain for the cookie
182 | * - fileUpload: (optional) boolean indicating if file uploads are enabled
183 | *
184 | * @param Array $config the application configuration
185 | */
186 | public function __construct($config) {
187 | $this->setAppId($config['appId']);
188 | $this->setApiSecret($config['secret']);
189 | if (isset($config['cookie'])) {
190 | $this->setCookieSupport($config['cookie']);
191 | }
192 | if (isset($config['domain'])) {
193 | $this->setBaseDomain($config['domain']);
194 | }
195 | if (isset($config['fileUpload'])) {
196 | $this->setFileUploadSupport($config['fileUpload']);
197 | }
198 | }
199 |
200 | /**
201 | * Set the Application ID.
202 | *
203 | * @param String $appId the Application ID
204 | */
205 | public function setAppId($appId) {
206 | $this->appId = $appId;
207 | return $this;
208 | }
209 |
210 | /**
211 | * Get the Application ID.
212 | *
213 | * @return String the Application ID
214 | */
215 | public function getAppId() {
216 | return $this->appId;
217 | }
218 |
219 | /**
220 | * Set the API Secret.
221 | *
222 | * @param String $appId the API Secret
223 | */
224 | public function setApiSecret($apiSecret) {
225 | $this->apiSecret = $apiSecret;
226 | return $this;
227 | }
228 |
229 | /**
230 | * Get the API Secret.
231 | *
232 | * @return String the API Secret
233 | */
234 | public function getApiSecret() {
235 | return $this->apiSecret;
236 | }
237 |
238 | /**
239 | * Set the Cookie Support status.
240 | *
241 | * @param Boolean $cookieSupport the Cookie Support status
242 | */
243 | public function setCookieSupport($cookieSupport) {
244 | $this->cookieSupport = $cookieSupport;
245 | return $this;
246 | }
247 |
248 | /**
249 | * Get the Cookie Support status.
250 | *
251 | * @return Boolean the Cookie Support status
252 | */
253 | public function useCookieSupport() {
254 | return $this->cookieSupport;
255 | }
256 |
257 | /**
258 | * Set the base domain for the Cookie.
259 | *
260 | * @param String $domain the base domain
261 | */
262 | public function setBaseDomain($domain) {
263 | $this->baseDomain = $domain;
264 | return $this;
265 | }
266 |
267 | /**
268 | * Get the base domain for the Cookie.
269 | *
270 | * @return String the base domain
271 | */
272 | public function getBaseDomain() {
273 | return $this->baseDomain;
274 | }
275 |
276 | /**
277 | * Set the file upload support status.
278 | *
279 | * @param String $domain the base domain
280 | */
281 | public function setFileUploadSupport($fileUploadSupport) {
282 | $this->fileUploadSupport = $fileUploadSupport;
283 | return $this;
284 | }
285 |
286 | /**
287 | * Get the file upload support status.
288 | *
289 | * @return String the base domain
290 | */
291 | public function useFileUploadSupport() {
292 | return $this->fileUploadSupport;
293 | }
294 |
295 | /**
296 | * Get the data from a signed_request token
297 | *
298 | * @return String the base domain
299 | */
300 | public function getSignedRequest() {
301 | if (!$this->signedRequest) {
302 | if (isset($_REQUEST['signed_request'])) {
303 | $this->signedRequest = $this->parseSignedRequest(
304 | $_REQUEST['signed_request']);
305 | }
306 | }
307 | return $this->signedRequest;
308 | }
309 |
310 | /**
311 | * Set the Session.
312 | *
313 | * @param Array $session the session
314 | * @param Boolean $write_cookie indicate if a cookie should be written. this
315 | * value is ignored if cookie support has been disabled.
316 | */
317 | public function setSession($session=null, $write_cookie=true) {
318 | $session = $this->validateSessionObject($session);
319 | $this->sessionLoaded = true;
320 | $this->session = $session;
321 | if ($write_cookie) {
322 | $this->setCookieFromSession($session);
323 | }
324 | return $this;
325 | }
326 |
327 | /**
328 | * Get the session object. This will automatically look for a signed session
329 | * sent via the signed_request, Cookie or Query Parameters if needed.
330 | *
331 | * @return Array the session
332 | */
333 | public function getSession() {
334 | if (!$this->sessionLoaded) {
335 | $session = null;
336 | $write_cookie = true;
337 |
338 | // try loading session from signed_request in $_REQUEST
339 | $signedRequest = $this->getSignedRequest();
340 | if ($signedRequest) {
341 | // sig is good, use the signedRequest
342 | $session = $this->createSessionFromSignedRequest($signedRequest);
343 | }
344 |
345 | // try loading session from $_REQUEST
346 | if (!$session && isset($_REQUEST['session'])) {
347 | $session = json_decode(
348 | get_magic_quotes_gpc()
349 | ? stripslashes($_REQUEST['session'])
350 | : $_REQUEST['session'],
351 | true
352 | );
353 | $session = $this->validateSessionObject($session);
354 | }
355 |
356 | // try loading session from cookie if necessary
357 | if (!$session && $this->useCookieSupport()) {
358 | $cookieName = $this->getSessionCookieName();
359 | if (isset($_COOKIE[$cookieName])) {
360 | $session = array();
361 | parse_str(trim(
362 | get_magic_quotes_gpc()
363 | ? stripslashes($_COOKIE[$cookieName])
364 | : $_COOKIE[$cookieName],
365 | '"'
366 | ), $session);
367 | $session = $this->validateSessionObject($session);
368 | // write only if we need to delete a invalid session cookie
369 | $write_cookie = empty($session);
370 | }
371 | }
372 |
373 | $this->setSession($session, $write_cookie);
374 | }
375 |
376 | return $this->session;
377 | }
378 |
379 | /**
380 | * Get the UID from the session.
381 | *
382 | * @return String the UID if available
383 | */
384 | public function getUser() {
385 | $session = $this->getSession();
386 | return $session ? $session['uid'] : null;
387 | }
388 |
389 | /**
390 | * Gets a OAuth access token.
391 | *
392 | * @return String the access token
393 | */
394 | public function getAccessToken() {
395 | $session = $this->getSession();
396 | // either user session signed, or app signed
397 | if ($session) {
398 | return $session['access_token'];
399 | } else {
400 | return $this->getAppId() .'|'. $this->getApiSecret();
401 | }
402 | }
403 |
404 | /**
405 | * Get a Login URL for use with redirects. By default, full page redirect is
406 | * assumed. If you are using the generated URL with a window.open() call in
407 | * JavaScript, you can pass in display=popup as part of the $params.
408 | *
409 | * The parameters:
410 | * - next: the url to go to after a successful login
411 | * - cancel_url: the url to go to after the user cancels
412 | * - req_perms: comma separated list of requested extended perms
413 | * - display: can be "page" (default, full page) or "popup"
414 | *
415 | * @param Array $params provide custom parameters
416 | * @return String the URL for the login flow
417 | */
418 | public function getLoginUrl($params=array()) {
419 | $currentUrl = $this->getCurrentUrl();
420 | return $this->getUrl(
421 | 'www',
422 | 'login.php',
423 | array_merge(array(
424 | 'api_key' => $this->getAppId(),
425 | 'cancel_url' => $currentUrl,
426 | 'display' => 'page',
427 | 'fbconnect' => 1,
428 | 'next' => $currentUrl,
429 | 'return_session' => 1,
430 | 'session_version' => 3,
431 | 'v' => '1.0',
432 | ), $params)
433 | );
434 | }
435 |
436 | /**
437 | * Get a Logout URL suitable for use with redirects.
438 | *
439 | * The parameters:
440 | * - next: the url to go to after a successful logout
441 | *
442 | * @param Array $params provide custom parameters
443 | * @return String the URL for the logout flow
444 | */
445 | public function getLogoutUrl($params=array()) {
446 | return $this->getUrl(
447 | 'www',
448 | 'logout.php',
449 | array_merge(array(
450 | 'next' => $this->getCurrentUrl(),
451 | 'access_token' => $this->getAccessToken(),
452 | ), $params)
453 | );
454 | }
455 |
456 | /**
457 | * Get a login status URL to fetch the status from facebook.
458 | *
459 | * The parameters:
460 | * - ok_session: the URL to go to if a session is found
461 | * - no_session: the URL to go to if the user is not connected
462 | * - no_user: the URL to go to if the user is not signed into facebook
463 | *
464 | * @param Array $params provide custom parameters
465 | * @return String the URL for the logout flow
466 | */
467 | public function getLoginStatusUrl($params=array()) {
468 | return $this->getUrl(
469 | 'www',
470 | 'extern/login_status.php',
471 | array_merge(array(
472 | 'api_key' => $this->getAppId(),
473 | 'no_session' => $this->getCurrentUrl(),
474 | 'no_user' => $this->getCurrentUrl(),
475 | 'ok_session' => $this->getCurrentUrl(),
476 | 'session_version' => 3,
477 | ), $params)
478 | );
479 | }
480 |
481 | /**
482 | * Make an API call.
483 | *
484 | * @param Array $params the API call parameters
485 | * @return the decoded response
486 | */
487 | public function api(/* polymorphic */) {
488 | $args = func_get_args();
489 | if (is_array($args[0])) {
490 | return $this->_restserver($args[0]);
491 | } else {
492 | return call_user_func_array(array($this, '_graph'), $args);
493 | }
494 | }
495 |
496 | /**
497 | * Invoke the old restserver.php endpoint.
498 | *
499 | * @param Array $params method call object
500 | * @return the decoded response object
501 | * @throws FacebookApiException
502 | */
503 | protected function _restserver($params) {
504 | // generic application level parameters
505 | $params['api_key'] = $this->getAppId();
506 | $params['format'] = 'json-strings';
507 |
508 | $result = json_decode($this->_oauthRequest(
509 | $this->getApiUrl($params['method']),
510 | $params
511 | ), true);
512 |
513 | // results are returned, errors are thrown
514 | if (is_array($result) && isset($result['error_code'])) {
515 | throw new FacebookApiException($result);
516 | }
517 | return $result;
518 | }
519 |
520 | /**
521 | * Invoke the Graph API.
522 | *
523 | * @param String $path the path (required)
524 | * @param String $method the http method (default 'GET')
525 | * @param Array $params the query/post data
526 | * @return the decoded response object
527 | * @throws FacebookApiException
528 | */
529 | protected function _graph($path, $method='GET', $params=array()) {
530 | if (is_array($method) && empty($params)) {
531 | $params = $method;
532 | $method = 'GET';
533 | }
534 | $params['method'] = $method; // method override as we always do a POST
535 |
536 | $result = json_decode($this->_oauthRequest(
537 | $this->getUrl('graph', $path),
538 | $params
539 | ), true);
540 |
541 | // results are returned, errors are thrown
542 | if (is_array($result) && isset($result['error'])) {
543 | $e = new FacebookApiException($result);
544 | switch ($e->getType()) {
545 | // OAuth 2.0 Draft 00 style
546 | case 'OAuthException':
547 | // OAuth 2.0 Draft 10 style
548 | case 'invalid_token':
549 | $this->setSession(null);
550 | }
551 | throw $e;
552 | }
553 | return $result;
554 | }
555 |
556 | /**
557 | * Make a OAuth Request
558 | *
559 | * @param String $path the path (required)
560 | * @param Array $params the query/post data
561 | * @return the decoded response object
562 | * @throws FacebookApiException
563 | */
564 | protected function _oauthRequest($url, $params) {
565 | if (!isset($params['access_token'])) {
566 | $params['access_token'] = $this->getAccessToken();
567 | }
568 |
569 | // json_encode all params values that are not strings
570 | foreach ($params as $key => $value) {
571 | if (!is_string($value)) {
572 | $params[$key] = json_encode($value);
573 | }
574 | }
575 | return $this->makeRequest($url, $params);
576 | }
577 |
578 | /**
579 | * Makes an HTTP request. This method can be overriden by subclasses if
580 | * developers want to do fancier things or use something other than curl to
581 | * make the request.
582 | *
583 | * @param String $url the URL to make the request to
584 | * @param Array $params the parameters to use for the POST body
585 | * @param CurlHandler $ch optional initialized curl handle
586 | * @return String the response text
587 | */
588 | protected function makeRequest($url, $params, $ch=null) {
589 | if (!$ch) {
590 | $ch = curl_init();
591 | }
592 |
593 | $opts = self::$CURL_OPTS;
594 | if ($this->useFileUploadSupport()) {
595 | $opts[CURLOPT_POSTFIELDS] = $params;
596 | } else {
597 | $opts[CURLOPT_POSTFIELDS] = http_build_query($params, null, '&');
598 | }
599 | $opts[CURLOPT_URL] = $url;
600 |
601 | // disable the 'Expect: 100-continue' behaviour. This causes CURL to wait
602 | // for 2 seconds if the server does not support this header.
603 | if (isset($opts[CURLOPT_HTTPHEADER])) {
604 | $existing_headers = $opts[CURLOPT_HTTPHEADER];
605 | $existing_headers[] = 'Expect:';
606 | $opts[CURLOPT_HTTPHEADER] = $existing_headers;
607 | } else {
608 | $opts[CURLOPT_HTTPHEADER] = array('Expect:');
609 | }
610 |
611 | curl_setopt_array($ch, $opts);
612 | $result = curl_exec($ch);
613 |
614 | if (curl_errno($ch) == 60) { // CURLE_SSL_CACERT
615 | self::errorLog('Invalid or no certificate authority found, using bundled information');
616 | curl_setopt($ch, CURLOPT_CAINFO,
617 | dirname(__FILE__) . '/fb_ca_chain_bundle.crt');
618 | $result = curl_exec($ch);
619 | }
620 |
621 | if ($result === false) {
622 | $e = new FacebookApiException(array(
623 | 'error_code' => curl_errno($ch),
624 | 'error' => array(
625 | 'message' => curl_error($ch),
626 | 'type' => 'CurlException',
627 | ),
628 | ));
629 | curl_close($ch);
630 | throw $e;
631 | }
632 | curl_close($ch);
633 | return $result;
634 | }
635 |
636 | /**
637 | * The name of the Cookie that contains the session.
638 | *
639 | * @return String the cookie name
640 | */
641 | protected function getSessionCookieName() {
642 | return 'fbs_' . $this->getAppId();
643 | }
644 |
645 | /**
646 | * Set a JS Cookie based on the _passed in_ session. It does not use the
647 | * currently stored session -- you need to explicitly pass it in.
648 | *
649 | * @param Array $session the session to use for setting the cookie
650 | */
651 | protected function setCookieFromSession($session=null) {
652 | if (!$this->useCookieSupport()) {
653 | return;
654 | }
655 |
656 | $cookieName = $this->getSessionCookieName();
657 | $value = 'deleted';
658 | $expires = time() - 3600;
659 | $domain = $this->getBaseDomain();
660 | if ($session) {
661 | $value = '"' . http_build_query($session, null, '&') . '"';
662 | if (isset($session['base_domain'])) {
663 | $domain = $session['base_domain'];
664 | }
665 | $expires = $session['expires'];
666 | }
667 |
668 | // prepend dot if a domain is found
669 | if ($domain) {
670 | $domain = '.' . $domain;
671 | }
672 |
673 | // if an existing cookie is not set, we dont need to delete it
674 | if ($value == 'deleted' && empty($_COOKIE[$cookieName])) {
675 | return;
676 | }
677 |
678 | if (headers_sent()) {
679 | self::errorLog('Could not set cookie. Headers already sent.');
680 |
681 | // ignore for code coverage as we will never be able to setcookie in a CLI
682 | // environment
683 | // @codeCoverageIgnoreStart
684 | } else {
685 | setcookie($cookieName, $value, $expires, '/', $domain);
686 | }
687 | // @codeCoverageIgnoreEnd
688 | }
689 |
690 | /**
691 | * Validates a session_version=3 style session object.
692 | *
693 | * @param Array $session the session object
694 | * @return Array the session object if it validates, null otherwise
695 | */
696 | protected function validateSessionObject($session) {
697 | // make sure some essential fields exist
698 | if (is_array($session) &&
699 | isset($session['uid']) &&
700 | isset($session['access_token']) &&
701 | isset($session['sig'])) {
702 | // validate the signature
703 | $session_without_sig = $session;
704 | unset($session_without_sig['sig']);
705 | $expected_sig = self::generateSignature(
706 | $session_without_sig,
707 | $this->getApiSecret()
708 | );
709 | if ($session['sig'] != $expected_sig) {
710 | self::errorLog('Got invalid session signature in cookie.');
711 | $session = null;
712 | }
713 | // check expiry time
714 | } else {
715 | $session = null;
716 | }
717 | return $session;
718 | }
719 |
720 | /**
721 | * Returns something that looks like our JS session object from the
722 | * signed token's data
723 | *
724 | * TODO: Nuke this once the login flow uses OAuth2
725 | *
726 | * @param Array the output of getSignedRequest
727 | * @return Array Something that will work as a session
728 | */
729 | protected function createSessionFromSignedRequest($data) {
730 | if (!isset($data['oauth_token'])) {
731 | return null;
732 | }
733 |
734 | $session = array(
735 | 'uid' => $data['user_id'],
736 | 'access_token' => $data['oauth_token'],
737 | 'expires' => $data['expires'],
738 | );
739 |
740 | // put a real sig, so that validateSignature works
741 | $session['sig'] = self::generateSignature(
742 | $session,
743 | $this->getApiSecret()
744 | );
745 |
746 | return $session;
747 | }
748 |
749 | /**
750 | * Parses a signed_request and validates the signature.
751 | * Then saves it in $this->signed_data
752 | *
753 | * @param String A signed token
754 | * @param Boolean Should we remove the parts of the payload that
755 | * are used by the algorithm?
756 | * @return Array the payload inside it or null if the sig is wrong
757 | */
758 | protected function parseSignedRequest($signed_request) {
759 | list($encoded_sig, $payload) = explode('.', $signed_request, 2);
760 |
761 | // decode the data
762 | $sig = self::base64UrlDecode($encoded_sig);
763 | $data = json_decode(self::base64UrlDecode($payload), true);
764 |
765 | if (strtoupper($data['algorithm']) !== 'HMAC-SHA256') {
766 | self::errorLog('Unknown algorithm. Expected HMAC-SHA256');
767 | return null;
768 | }
769 |
770 | // check sig
771 | $expected_sig = hash_hmac('sha256', $payload,
772 | $this->getApiSecret(), $raw = true);
773 | if ($sig !== $expected_sig) {
774 | self::errorLog('Bad Signed JSON signature!');
775 | return null;
776 | }
777 |
778 | return $data;
779 | }
780 |
781 | /**
782 | * Build the URL for api given parameters.
783 | *
784 | * @param $method String the method name.
785 | * @return String the URL for the given parameters
786 | */
787 | protected function getApiUrl($method) {
788 | static $READ_ONLY_CALLS =
789 | array('admin.getallocation' => 1,
790 | 'admin.getappproperties' => 1,
791 | 'admin.getbannedusers' => 1,
792 | 'admin.getlivestreamvialink' => 1,
793 | 'admin.getmetrics' => 1,
794 | 'admin.getrestrictioninfo' => 1,
795 | 'application.getpublicinfo' => 1,
796 | 'auth.getapppublickey' => 1,
797 | 'auth.getsession' => 1,
798 | 'auth.getsignedpublicsessiondata' => 1,
799 | 'comments.get' => 1,
800 | 'connect.getunconnectedfriendscount' => 1,
801 | 'dashboard.getactivity' => 1,
802 | 'dashboard.getcount' => 1,
803 | 'dashboard.getglobalnews' => 1,
804 | 'dashboard.getnews' => 1,
805 | 'dashboard.multigetcount' => 1,
806 | 'dashboard.multigetnews' => 1,
807 | 'data.getcookies' => 1,
808 | 'events.get' => 1,
809 | 'events.getmembers' => 1,
810 | 'fbml.getcustomtags' => 1,
811 | 'feed.getappfriendstories' => 1,
812 | 'feed.getregisteredtemplatebundlebyid' => 1,
813 | 'feed.getregisteredtemplatebundles' => 1,
814 | 'fql.multiquery' => 1,
815 | 'fql.query' => 1,
816 | 'friends.arefriends' => 1,
817 | 'friends.get' => 1,
818 | 'friends.getappusers' => 1,
819 | 'friends.getlists' => 1,
820 | 'friends.getmutualfriends' => 1,
821 | 'gifts.get' => 1,
822 | 'groups.get' => 1,
823 | 'groups.getmembers' => 1,
824 | 'intl.gettranslations' => 1,
825 | 'links.get' => 1,
826 | 'notes.get' => 1,
827 | 'notifications.get' => 1,
828 | 'pages.getinfo' => 1,
829 | 'pages.isadmin' => 1,
830 | 'pages.isappadded' => 1,
831 | 'pages.isfan' => 1,
832 | 'permissions.checkavailableapiaccess' => 1,
833 | 'permissions.checkgrantedapiaccess' => 1,
834 | 'photos.get' => 1,
835 | 'photos.getalbums' => 1,
836 | 'photos.gettags' => 1,
837 | 'profile.getinfo' => 1,
838 | 'profile.getinfooptions' => 1,
839 | 'stream.get' => 1,
840 | 'stream.getcomments' => 1,
841 | 'stream.getfilters' => 1,
842 | 'users.getinfo' => 1,
843 | 'users.getloggedinuser' => 1,
844 | 'users.getstandardinfo' => 1,
845 | 'users.hasapppermission' => 1,
846 | 'users.isappuser' => 1,
847 | 'users.isverified' => 1,
848 | 'video.getuploadlimits' => 1);
849 | $name = 'api';
850 | if (isset($READ_ONLY_CALLS[strtolower($method)])) {
851 | $name = 'api_read';
852 | }
853 | return self::getUrl($name, 'restserver.php');
854 | }
855 |
856 | /**
857 | * Build the URL for given domain alias, path and parameters.
858 | *
859 | * @param $name String the name of the domain
860 | * @param $path String optional path (without a leading slash)
861 | * @param $params Array optional query parameters
862 | * @return String the URL for the given parameters
863 | */
864 | protected function getUrl($name, $path='', $params=array()) {
865 | $url = self::$DOMAIN_MAP[$name];
866 | if ($path) {
867 | if ($path[0] === '/') {
868 | $path = substr($path, 1);
869 | }
870 | $url .= $path;
871 | }
872 | if ($params) {
873 | $url .= '?' . http_build_query($params, null, '&');
874 | }
875 | return $url;
876 | }
877 |
878 | /**
879 | * Returns the Current URL, stripping it of known FB parameters that should
880 | * not persist.
881 | *
882 | * @return String the current URL
883 | */
884 | protected function getCurrentUrl() {
885 | $protocol = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on'
886 | ? 'https://'
887 | : 'http://';
888 | $currentUrl = $protocol . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
889 | $parts = parse_url($currentUrl);
890 |
891 | // drop known fb params
892 | $query = '';
893 | if (!empty($parts['query'])) {
894 | $params = array();
895 | parse_str($parts['query'], $params);
896 | foreach(self::$DROP_QUERY_PARAMS as $key) {
897 | unset($params[$key]);
898 | }
899 | if (!empty($params)) {
900 | $query = '?' . http_build_query($params, null, '&');
901 | }
902 | }
903 |
904 | // use port if non default
905 | $port =
906 | isset($parts['port']) &&
907 | (($protocol === 'http://' && $parts['port'] !== 80) ||
908 | ($protocol === 'https://' && $parts['port'] !== 443))
909 | ? ':' . $parts['port'] : '';
910 |
911 | // rebuild
912 | return $protocol . $parts['host'] . $port . $parts['path'] . $query;
913 | }
914 |
915 | /**
916 | * Generate a signature for the given params and secret.
917 | *
918 | * @param Array $params the parameters to sign
919 | * @param String $secret the secret to sign with
920 | * @return String the generated signature
921 | */
922 | protected static function generateSignature($params, $secret) {
923 | // work with sorted data
924 | ksort($params);
925 |
926 | // generate the base string
927 | $base_string = '';
928 | foreach($params as $key => $value) {
929 | $base_string .= $key . '=' . $value;
930 | }
931 | $base_string .= $secret;
932 |
933 | return md5($base_string);
934 | }
935 |
936 | /**
937 | * Prints to the error log if you aren't in command line mode.
938 | *
939 | * @param String log message
940 | */
941 | protected static function errorLog($msg) {
942 | // disable error log if we are running in a CLI environment
943 | // @codeCoverageIgnoreStart
944 | if (php_sapi_name() != 'cli') {
945 | error_log($msg);
946 | }
947 | // uncomment this if you want to see the errors on the page
948 | // print 'error_log: '.$msg."\n";
949 | // @codeCoverageIgnoreEnd
950 | }
951 |
952 | /**
953 | * Base64 encoding that doesn't need to be urlencode()ed.
954 | * Exactly the same as base64_encode except it uses
955 | * - instead of +
956 | * _ instead of /
957 | *
958 | * @param String base64UrlEncodeded string
959 | */
960 | protected static function base64UrlDecode($input) {
961 | return base64_decode(strtr($input, '-_', '+/'));
962 | }
963 | }
964 |
--------------------------------------------------------------------------------
/library/fb_ca_chain_bundle.crt:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIFgjCCBGqgAwIBAgIQDKKbZcnESGaLDuEaVk6fQjANBgkqhkiG9w0BAQUFADBm
3 | MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
4 | d3cuZGlnaWNlcnQuY29tMSUwIwYDVQQDExxEaWdpQ2VydCBIaWdoIEFzc3VyYW5j
5 | ZSBDQS0zMB4XDTEwMDExMzAwMDAwMFoXDTEzMDQxMTIzNTk1OVowaDELMAkGA1UE
6 | BhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExEjAQBgNVBAcTCVBhbG8gQWx0bzEX
7 | MBUGA1UEChMORmFjZWJvb2ssIEluYy4xFzAVBgNVBAMUDiouZmFjZWJvb2suY29t
8 | MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC9rzj7QIuLM3sdHu1HcI1VcR3g
9 | b5FExKNV646agxSle1aQ/sJev1mh/u91ynwqd2BQmM0brZ1Hc3QrfYyAaiGGgEkp
10 | xbhezyfeYhAyO0TKAYxPnm2cTjB5HICzk6xEIwFbA7SBJ2fSyW1CFhYZyo3tIBjj
11 | 19VjKyBfpRaPkzLmRwIDAQABo4ICrDCCAqgwHwYDVR0jBBgwFoAUUOpzidsp+xCP
12 | nuUBINTeeZlIg/cwHQYDVR0OBBYEFPp+tsFBozkjrHlEnZ9J4cFj2eM0MA4GA1Ud
13 | DwEB/wQEAwIFoDAMBgNVHRMBAf8EAjAAMF8GA1UdHwRYMFYwKaAnoCWGI2h0dHA6
14 | Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9jYTMtZmIuY3JsMCmgJ6AlhiNodHRwOi8vY3Js
15 | NC5kaWdpY2VydC5jb20vY2EzLWZiLmNybDCCAcYGA1UdIASCAb0wggG5MIIBtQYL
16 | YIZIAYb9bAEDAAEwggGkMDoGCCsGAQUFBwIBFi5odHRwOi8vd3d3LmRpZ2ljZXJ0
17 | LmNvbS9zc2wtY3BzLXJlcG9zaXRvcnkuaHRtMIIBZAYIKwYBBQUHAgIwggFWHoIB
18 | UgBBAG4AeQAgAHUAcwBlACAAbwBmACAAdABoAGkAcwAgAEMAZQByAHQAaQBmAGkA
19 | YwBhAHQAZQAgAGMAbwBuAHMAdABpAHQAdQB0AGUAcwAgAGEAYwBjAGUAcAB0AGEA
20 | bgBjAGUAIABvAGYAIAB0AGgAZQAgAEQAaQBnAGkAQwBlAHIAdAAgAEMAUAAvAEMA
21 | UABTACAAYQBuAGQAIAB0AGgAZQAgAFIAZQBsAHkAaQBuAGcAIABQAGEAcgB0AHkA
22 | IABBAGcAcgBlAGUAbQBlAG4AdAAgAHcAaABpAGMAaAAgAGwAaQBtAGkAdAAgAGwA
23 | aQBhAGIAaQBsAGkAdAB5ACAAYQBuAGQAIABhAHIAZQAgAGkAbgBjAG8AcgBwAG8A
24 | cgBhAHQAZQBkACAAaABlAHIAZQBpAG4AIABiAHkAIAByAGUAZgBlAHIAZQBuAGMA
25 | ZQAuMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjANBgkqhkiG9w0BAQUF
26 | AAOCAQEACOkTIdxMy11+CKrbGNLBSg5xHaTvu/v1wbyn3dO/mf68pPfJnX6ShPYy
27 | 4XM4Vk0x4uaFaU4wAGke+nCKGi5dyg0Esg7nemLNKEJaFAJZ9enxZm334lSCeARy
28 | wlDtxULGOFRyGIZZPmbV2eNq5xdU/g3IuBEhL722mTpAye9FU/J8Wsnw54/gANyO
29 | Gzkewigua8ip8Lbs9Cht399yAfbfhUP1DrAm/xEcnHrzPr3cdCtOyJaM6SRPpRqH
30 | ITK5Nc06tat9lXVosSinT3KqydzxBYua9gCFFiR3x3DgZfvXkC6KDdUlDrNcJUub
31 | a1BHnLLP4mxTHL6faAXYd05IxNn/IA==
32 | -----END CERTIFICATE-----
33 | -----BEGIN CERTIFICATE-----
34 | MIIGVTCCBT2gAwIBAgIQCFH5WYFBRcq94CTiEsnCDjANBgkqhkiG9w0BAQUFADBs
35 | MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
36 | d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j
37 | ZSBFViBSb290IENBMB4XDTA3MDQwMzAwMDAwMFoXDTIyMDQwMzAwMDAwMFowZjEL
38 | MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3
39 | LmRpZ2ljZXJ0LmNvbTElMCMGA1UEAxMcRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug
40 | Q0EtMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL9hCikQH17+NDdR
41 | CPge+yLtYb4LDXBMUGMmdRW5QYiXtvCgFbsIYOBC6AUpEIc2iihlqO8xB3RtNpcv
42 | KEZmBMcqeSZ6mdWOw21PoF6tvD2Rwll7XjZswFPPAAgyPhBkWBATaccM7pxCUQD5
43 | BUTuJM56H+2MEb0SqPMV9Bx6MWkBG6fmXcCabH4JnudSREoQOiPkm7YDr6ictFuf
44 | 1EutkozOtREqqjcYjbTCuNhcBoz4/yO9NV7UfD5+gw6RlgWYw7If48hl66l7XaAs
45 | zPw82W3tzPpLQ4zJ1LilYRyyQLYoEt+5+F/+07LJ7z20Hkt8HEyZNp496+ynaF4d
46 | 32duXvsCAwEAAaOCAvcwggLzMA4GA1UdDwEB/wQEAwIBhjCCAcYGA1UdIASCAb0w
47 | ggG5MIIBtQYLYIZIAYb9bAEDAAIwggGkMDoGCCsGAQUFBwIBFi5odHRwOi8vd3d3
48 | LmRpZ2ljZXJ0LmNvbS9zc2wtY3BzLXJlcG9zaXRvcnkuaHRtMIIBZAYIKwYBBQUH
49 | AgIwggFWHoIBUgBBAG4AeQAgAHUAcwBlACAAbwBmACAAdABoAGkAcwAgAEMAZQBy
50 | AHQAaQBmAGkAYwBhAHQAZQAgAGMAbwBuAHMAdABpAHQAdQB0AGUAcwAgAGEAYwBj
51 | AGUAcAB0AGEAbgBjAGUAIABvAGYAIAB0AGgAZQAgAEQAaQBnAGkAQwBlAHIAdAAg
52 | AEMAUAAvAEMAUABTACAAYQBuAGQAIAB0AGgAZQAgAFIAZQBsAHkAaQBuAGcAIABQ
53 | AGEAcgB0AHkAIABBAGcAcgBlAGUAbQBlAG4AdAAgAHcAaABpAGMAaAAgAGwAaQBt
54 | AGkAdAAgAGwAaQBhAGIAaQBsAGkAdAB5ACAAYQBuAGQAIABhAHIAZQAgAGkAbgBj
55 | AG8AcgBwAG8AcgBhAHQAZQBkACAAaABlAHIAZQBpAG4AIABiAHkAIAByAGUAZgBl
56 | AHIAZQBuAGMAZQAuMA8GA1UdEwEB/wQFMAMBAf8wNAYIKwYBBQUHAQEEKDAmMCQG
57 | CCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wgY8GA1UdHwSBhzCB
58 | hDBAoD6gPIY6aHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0SGlnaEFz
59 | c3VyYW5jZUVWUm9vdENBLmNybDBAoD6gPIY6aHR0cDovL2NybDQuZGlnaWNlcnQu
60 | Y29tL0RpZ2lDZXJ0SGlnaEFzc3VyYW5jZUVWUm9vdENBLmNybDAfBgNVHSMEGDAW
61 | gBSxPsNpA/i/RwHUmCYaCALvY2QrwzAdBgNVHQ4EFgQUUOpzidsp+xCPnuUBINTe
62 | eZlIg/cwDQYJKoZIhvcNAQEFBQADggEBAF1PhPGoiNOjsrycbeUpSXfh59bcqdg1
63 | rslx3OXb3J0kIZCmz7cBHJvUV5eR13UWpRLXuT0uiT05aYrWNTf58SHEW0CtWakv
64 | XzoAKUMncQPkvTAyVab+hA4LmzgZLEN8rEO/dTHlIxxFVbdpCJG1z9fVsV7un5Tk
65 | 1nq5GMO41lJjHBC6iy9tXcwFOPRWBW3vnuzoYTYMFEuFFFoMg08iXFnLjIpx2vrF
66 | EIRYzwfu45DC9fkpx1ojcflZtGQriLCnNseaIGHr+k61rmsb5OPs4tk8QUmoIKRU
67 | 9ZKNu8BVIASm2LAXFszj0Mi0PeXZhMbT9m5teMl5Q+h6N/9cNUm/ocU=
68 | -----END CERTIFICATE-----
69 | -----BEGIN CERTIFICATE-----
70 | MIIEQjCCA6ugAwIBAgIEQoclDjANBgkqhkiG9w0BAQUFADCBwzELMAkGA1UEBhMC
71 | VVMxFDASBgNVBAoTC0VudHJ1c3QubmV0MTswOQYDVQQLEzJ3d3cuZW50cnVzdC5u
72 | ZXQvQ1BTIGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMc
73 | KGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDE6MDgGA1UEAxMxRW50cnVzdC5u
74 | ZXQgU2VjdXJlIFNlcnZlciBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEy
75 | MjIxNTI3MjdaFw0xNDA3MjIxNTU3MjdaMGwxCzAJBgNVBAYTAlVTMRUwEwYDVQQK
76 | EwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xKzApBgNV
77 | BAMTIkRpZ2lDZXJ0IEhpZ2ggQXNzdXJhbmNlIEVWIFJvb3QgQ0EwggEiMA0GCSqG
78 | SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDGzOVz5vvUu+UtLTKm3+WBP8nNJUm2cSrD
79 | 1ZQ0Z6IKHLBfaaZAscS3so/QmKSpQVk609yU1jzbdDikSsxNJYL3SqVTEjju80lt
80 | cZF+Y7arpl/DpIT4T2JRvvjF7Ns4kuMG5QiRDMQoQVX7y1qJFX5x6DW/TXIJPb46
81 | OFBbdzEbjbPHJEWap6xtABRaBLe6E+tRCphBQSJOZWGHgUFQpnlcid4ZSlfVLuZd
82 | HFMsfpjNGgYWpGhz0DQEE1yhcdNafFXbXmThN4cwVgTlEbQpgBLxeTmIogIRfCdm
83 | t4i3ePLKCqg4qwpkwr9mXZWEwaElHoddGlALIBLMQbtuC1E4uEvLAgMBAAGjggET
84 | MIIBDzASBgNVHRMBAf8ECDAGAQH/AgEBMCcGA1UdJQQgMB4GCCsGAQUFBwMBBggr
85 | BgEFBQcDAgYIKwYBBQUHAwQwMwYIKwYBBQUHAQEEJzAlMCMGCCsGAQUFBzABhhdo
86 | dHRwOi8vb2NzcC5lbnRydXN0Lm5ldDAzBgNVHR8ELDAqMCigJqAkhiJodHRwOi8v
87 | Y3JsLmVudHJ1c3QubmV0L3NlcnZlcjEuY3JsMB0GA1UdDgQWBBSxPsNpA/i/RwHU
88 | mCYaCALvY2QrwzALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAU8BdiE1U9s/8KAGv7
89 | UISX8+1i0BowGQYJKoZIhvZ9B0EABAwwChsEVjcuMQMCAIEwDQYJKoZIhvcNAQEF
90 | BQADgYEAUuVY7HCc/9EvhaYzC1rAIo348LtGIiMduEl5Xa24G8tmJnDioD2GU06r
91 | 1kjLX/ktCdpdBgXadbjtdrZXTP59uN0AXlsdaTiFufsqVLPvkp5yMnqnuI3E2o6p
92 | NpAkoQSbB6kUCNnXcW26valgOjDLZFOnr241QiwdBAJAAE/rRa8=
93 | -----END CERTIFICATE-----
94 | -----BEGIN CERTIFICATE-----
95 | MIIE2DCCBEGgAwIBAgIEN0rSQzANBgkqhkiG9w0BAQUFADCBwzELMAkGA1UEBhMC
96 | VVMxFDASBgNVBAoTC0VudHJ1c3QubmV0MTswOQYDVQQLEzJ3d3cuZW50cnVzdC5u
97 | ZXQvQ1BTIGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMc
98 | KGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDE6MDgGA1UEAxMxRW50cnVzdC5u
99 | ZXQgU2VjdXJlIFNlcnZlciBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw05OTA1
100 | MjUxNjA5NDBaFw0xOTA1MjUxNjM5NDBaMIHDMQswCQYDVQQGEwJVUzEUMBIGA1UE
101 | ChMLRW50cnVzdC5uZXQxOzA5BgNVBAsTMnd3dy5lbnRydXN0Lm5ldC9DUFMgaW5j
102 | b3JwLiBieSByZWYuIChsaW1pdHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBF
103 | bnRydXN0Lm5ldCBMaW1pdGVkMTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUg
104 | U2VydmVyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGdMA0GCSqGSIb3DQEBAQUA
105 | A4GLADCBhwKBgQDNKIM0VBuJ8w+vN5Ex/68xYMmo6LIQaO2f55M28Qpku0f1BBc/
106 | I0dNxScZgSYMVHINiC3ZH5oSn7yzcdOAGT9HZnuMNSjSuQrfJNqc1lB5gXpa0zf3
107 | wkrYKZImZNHkmGw6AIr1NJtl+O3jEP/9uElY3KDegjlrgbEWGWG5VLbmQwIBA6OC
108 | AdcwggHTMBEGCWCGSAGG+EIBAQQEAwIABzCCARkGA1UdHwSCARAwggEMMIHeoIHb
109 | oIHYpIHVMIHSMQswCQYDVQQGEwJVUzEUMBIGA1UEChMLRW50cnVzdC5uZXQxOzA5
110 | BgNVBAsTMnd3dy5lbnRydXN0Lm5ldC9DUFMgaW5jb3JwLiBieSByZWYuIChsaW1p
111 | dHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBFbnRydXN0Lm5ldCBMaW1pdGVk
112 | MTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUgU2VydmVyIENlcnRpZmljYXRp
113 | b24gQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMCmgJ6AlhiNodHRwOi8vd3d3LmVu
114 | dHJ1c3QubmV0L0NSTC9uZXQxLmNybDArBgNVHRAEJDAigA8xOTk5MDUyNTE2MDk0
115 | MFqBDzIwMTkwNTI1MTYwOTQwWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAU8Bdi
116 | E1U9s/8KAGv7UISX8+1i0BowHQYDVR0OBBYEFPAXYhNVPbP/CgBr+1CEl/PtYtAa
117 | MAwGA1UdEwQFMAMBAf8wGQYJKoZIhvZ9B0EABAwwChsEVjQuMAMCBJAwDQYJKoZI
118 | hvcNAQEFBQADgYEAkNwwAvpkdMKnCqV8IY00F6j7Rw7/JXyNEwr75Ji174z4xRAN
119 | 95K+8cPV1ZVqBLssziY2ZcgxxufuP+NXdYR6Ee9GTxj005i7qIcyunL2POI9n9cd
120 | 2cNgQ4xYDiKWL2KjLB+6rQXvqzJ4h6BUcxm1XAX5Uj5tLUUL9wqT6u0G+bI=
121 | -----END CERTIFICATE-----
122 |
--------------------------------------------------------------------------------
/photos.php:
--------------------------------------------------------------------------------
1 | api('/me/albums');
6 |
7 | foreach($albums['data'] as $album)
8 | {
9 | // get all photos for album
10 | $photos = $facebook->api("/{$album['id']}/photos");
11 |
12 | foreach($photos['data'] as $photo)
13 | {
14 | echo "
", "
";
15 | }
16 | }
--------------------------------------------------------------------------------
/photos_add.php:
--------------------------------------------------------------------------------
1 | setFileUploadSupport("http://" . $_SERVER['SERVER_NAME']);
8 |
9 | // add a status message
10 | $photo = $facebook->api('/me/photos', 'POST',
11 | array(
12 | 'source' => '@' . $img,
13 | 'message' => 'This photo came from my app.'
14 | )
15 | );
16 |
17 | var_dump($photo);
--------------------------------------------------------------------------------
/rest_user_isappuser.php:
--------------------------------------------------------------------------------
1 | api(array('method' => 'users.isappuser'));
5 | echo (string)$return;
--------------------------------------------------------------------------------
/status.php:
--------------------------------------------------------------------------------
1 | api('/me/statuses');
6 | foreach($statuses['data'] as $status)
7 | {
8 | echo $status["message"], "
";
9 | }
--------------------------------------------------------------------------------
/status_add.php:
--------------------------------------------------------------------------------
1 | api('/me/feed', 'POST', array('message' => 'This post came from my app.'));
6 |
7 | var_dump($status);
--------------------------------------------------------------------------------
/user.php:
--------------------------------------------------------------------------------
1 | api('/me');
5 | var_dump($me);
--------------------------------------------------------------------------------