commit
44ffa35ce2
174 changed files with 4773 additions and 0 deletions
@ -0,0 +1,15 @@ |
|||
Copyright (C) 2008 Neil Edelman |
|||
|
|||
Sex is free software: you can redistribute it and/or modify |
|||
it under the terms of the GNU General Public License as published by |
|||
the Free Software Foundation, either version 3 of the License, or |
|||
(at your option) any later version. |
|||
|
|||
This program is distributed in the hope that it will be useful, |
|||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
GNU General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU General Public License |
|||
along with Sex (see gnu.txt.) If not, see |
|||
<http://www.gnu.org/licenses/>. |
@ -0,0 +1,465 @@ |
|||
<?php |
|||
// Copyright 2004-2008 Facebook. All Rights Reserved. |
|||
// |
|||
// +---------------------------------------------------------------------------+ |
|||
// | Facebook Platform PHP5 client | |
|||
// +---------------------------------------------------------------------------+ |
|||
// | Copyright (c) 2007 Facebook, Inc. | |
|||
// | All rights reserved. | |
|||
// | | |
|||
// | Redistribution and use in source and binary forms, with or without | |
|||
// | modification, are permitted provided that the following conditions | |
|||
// | are met: | |
|||
// | | |
|||
// | 1. Redistributions of source code must retain the above copyright | |
|||
// | notice, this list of conditions and the following disclaimer. | |
|||
// | 2. Redistributions in binary form must reproduce the above copyright | |
|||
// | notice, this list of conditions and the following disclaimer in the | |
|||
// | documentation and/or other materials provided with the distribution. | |
|||
// | | |
|||
// | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | |
|||
// | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
|||
// | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |
|||
// | IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | |
|||
// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
|||
// | NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
|||
// | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
|||
// | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
|||
// | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |
|||
// | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
|||
// +---------------------------------------------------------------------------+ |
|||
// | For help with this library, contact developers-help@facebook.com | |
|||
// +---------------------------------------------------------------------------+ |
|||
// |
|||
include_once 'facebookapi_php5_restlib.php'; |
|||
|
|||
define('FACEBOOK_API_VALIDATION_ERROR', 1); |
|||
class Facebook { |
|||
public $api_client; |
|||
|
|||
public $api_key; |
|||
public $secret; |
|||
public $generate_session_secret; |
|||
public $session_expires; |
|||
|
|||
public $fb_params; |
|||
public $user; |
|||
public $profile_user; |
|||
public $canvas_user; |
|||
|
|||
/* |
|||
* Create a Facebook client like this: |
|||
* |
|||
* $fb = new Facebook(API_KEY, SECRET); |
|||
* |
|||
* This will automatically pull in any parameters, validate them against the |
|||
* session signature, and chuck them in the public $fb_params member variable. |
|||
* |
|||
* @param api_key your Developer API key |
|||
* @param secret your Developer API secret |
|||
* @param generate_session_secret whether to automatically generate a session |
|||
* if the user doesn't have one, but |
|||
* there is an auth token present in the url, |
|||
*/ |
|||
public function __construct($api_key, $secret, $generate_session_secret=false) { |
|||
$this->api_key = $api_key; |
|||
$this->secret = $secret; |
|||
$this->generate_session_secret = $generate_session_secret; |
|||
$this->api_client = new FacebookRestClient($api_key, $secret); |
|||
|
|||
$this->validate_fb_params(); |
|||
if (isset($this->fb_params['friends'])) { |
|||
$this->api_client->friends_list = explode(',', $this->fb_params['friends']); |
|||
} |
|||
if (isset($this->fb_params['added'])) { |
|||
$this->api_client->added = $this->fb_params['added']; |
|||
} |
|||
if (isset($this->fb_params['canvas_user'])) { |
|||
$this->api_client->canvas_user = $this->fb_params['canvas_user']; |
|||
} |
|||
} |
|||
|
|||
/* |
|||
* Validates that the parameters passed in were sent from Facebook. It does so |
|||
* by validating that the signature matches one that could only be generated |
|||
* by using your application's secret key. |
|||
* |
|||
* Facebook-provided parameters will come from $_POST, $_GET, or $_COOKIE, |
|||
* in that order. $_POST and $_GET are always more up-to-date than cookies, |
|||
* so we prefer those if they are available. |
|||
* |
|||
* For nitty-gritty details of when each of these is used, check out |
|||
* http://wiki.developers.facebook.com/index.php/Verifying_The_Signature |
|||
* |
|||
* @param bool resolve_auth_token convert an auth token into a session |
|||
*/ |
|||
public function validate_fb_params($resolve_auth_token=true) { |
|||
$this->fb_params = $this->get_valid_fb_params($_POST, 48*3600, 'fb_sig'); |
|||
|
|||
// note that with preload FQL, it's possible to receive POST params in |
|||
// addition to GET, so use a different prefix to differentiate them |
|||
if (!$this->fb_params) { |
|||
$fb_params = $this->get_valid_fb_params($_GET, 48*3600, 'fb_sig'); |
|||
$fb_post_params = $this->get_valid_fb_params($_POST, 48*3600, 'fb_post_sig'); |
|||
$this->fb_params = array_merge($fb_params, $fb_post_params); |
|||
} |
|||
|
|||
// Okay, something came in via POST or GET |
|||
if ($this->fb_params) { |
|||
$user = isset($this->fb_params['user']) ? |
|||
$this->fb_params['user'] : null; |
|||
$this->profile_user = isset($this->fb_params['profile_user']) ? |
|||
$this->fb_params['profile_user'] : null; |
|||
$this->canvas_user = isset($this->fb_params['canvas_user']) ? |
|||
$this->fb_params['canvas_user'] : null; |
|||
|
|||
if (isset($this->fb_params['session_key'])) { |
|||
$session_key = $this->fb_params['session_key']; |
|||
} else if (isset($this->fb_params['profile_session_key'])) { |
|||
$session_key = $this->fb_params['profile_session_key']; |
|||
} else { |
|||
$session_key = null; |
|||
} |
|||
$expires = isset($this->fb_params['expires']) ? |
|||
$this->fb_params['expires'] : null; |
|||
$this->set_user($user, |
|||
$session_key, |
|||
$expires); |
|||
} |
|||
// if no Facebook parameters were found in the GET or POST variables, |
|||
// then fall back to cookies, which may have cached user information |
|||
// Cookies are also used to receive session data via the Javascript API |
|||
else if ($cookies = |
|||
$this->get_valid_fb_params($_COOKIE, null, $this->api_key)) { |
|||
// use $api_key . '_' as a prefix for the cookies in case there are |
|||
// multiple facebook clients on the same domain. |
|||
$expires = isset($cookies['expires']) ? $cookies['expires'] : null; |
|||
$this->set_user($cookies['user'], |
|||
$cookies['session_key'], |
|||
$expires); |
|||
} |
|||
// finally, if we received no parameters, but the 'auth_token' GET var |
|||
// is present, then we are in the middle of auth handshake, |
|||
// so go ahead and create the session |
|||
else if ($resolve_auth_token && isset($_GET['auth_token']) && |
|||
$session = $this->do_get_session($_GET['auth_token'])) { |
|||
if ($this->generate_session_secret && |
|||
!empty($session['secret'])) { |
|||
$session_secret = $session['secret']; |
|||
} |
|||
$this->set_user($session['uid'], |
|||
$session['session_key'], |
|||
$session['expires'], |
|||
$session_secret ? $session_secret : null); |
|||
} |
|||
|
|||
return !empty($this->fb_params); |
|||
} |
|||
|
|||
// Store a temporary session secret for the current session |
|||
// for use with the JS client library |
|||
public function promote_session() { |
|||
try { |
|||
$session_secret = $this->api_client->auth_promoteSession(); |
|||
if (!$this->in_fb_canvas()) { |
|||
$this->set_cookies($this->user, $this->api_client->session_key, $this->session_expires, $session_secret); |
|||
} |
|||
return $session_secret; |
|||
} catch (FacebookRestClientException $e) { |
|||
// API_EC_PARAM means we don't have a logged in user, otherwise who |
|||
// knows what it means, so just throw it. |
|||
if ($e->getCode() != FacebookAPIErrorCodes::API_EC_PARAM) { |
|||
throw $e; |
|||
} |
|||
} |
|||
} |
|||
|
|||
public function do_get_session($auth_token) { |
|||
try { |
|||
return $this->api_client->auth_getSession($auth_token, $this->generate_session_secret); |
|||
} catch (FacebookRestClientException $e) { |
|||
// API_EC_PARAM means we don't have a logged in user, otherwise who |
|||
// knows what it means, so just throw it. |
|||
if ($e->getCode() != FacebookAPIErrorCodes::API_EC_PARAM) { |
|||
throw $e; |
|||
} |
|||
} |
|||
} |
|||
|
|||
// Invalidate the session currently being used, and clear any state associated with it |
|||
public function expire_session() { |
|||
if ($this->api_client->auth_expireSession()) { |
|||
if (!$this->in_fb_canvas() && isset($_COOKIE[$this->api_key . '_user'])) { |
|||
$cookies = array('user', 'session_key', 'expires', 'ss'); |
|||
foreach ($cookies as $name) { |
|||
setcookie($this->api_key . '_' . $name, false, time() - 3600); |
|||
unset($_COOKIE[$this->api_key . '_' . $name]); |
|||
} |
|||
setcookie($this->api_key, false, time() - 3600); |
|||
unset($_COOKIE[$this->api_key]); |
|||
} |
|||
|
|||
// now, clear the rest of the stored state |
|||
$this->user = 0; |
|||
$this->api_client->session_key = 0; |
|||
return true; |
|||
} else { |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
public function redirect($url) { |
|||
if ($this->in_fb_canvas()) { |
|||
echo '<fb:redirect url="' . $url . '"/>'; |
|||
} else if (preg_match('/^https?:\/\/([^\/]*\.)?facebook\.com(:\d+)?/i', $url)) { |
|||
// make sure facebook.com url's load in the full frame so that we don't |
|||
// get a frame within a frame. |
|||
echo "<script type=\"text/javascript\">\ntop.location.href = \"$url\";\n</script>"; |
|||
} else { |
|||
header('Location: ' . $url); |
|||
} |
|||
exit; |
|||
} |
|||
|
|||
public function in_frame() { |
|||
return isset($this->fb_params['in_canvas']) || isset($this->fb_params['in_iframe']); |
|||
} |
|||
public function in_fb_canvas() { |
|||
return isset($this->fb_params['in_canvas']); |
|||
} |
|||
|
|||
public function get_loggedin_user() { |
|||
return $this->user; |
|||
} |
|||
|
|||
public function get_canvas_user() { |
|||
return $this->canvas_user; |
|||
} |
|||
|
|||
public function get_profile_user() { |
|||
return $this->profile_user; |
|||
} |
|||
|
|||
public static function current_url() { |
|||
return 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']; |
|||
} |
|||
|
|||
// require_add and require_install have been removed. |
|||
// see http://developer.facebook.com/news.php?blog=1&story=116 for more details |
|||
public function require_login() { |
|||
if ($user = $this->get_loggedin_user()) { |
|||
return $user; |
|||
} |
|||
$this->redirect($this->get_login_url(self::current_url(), $this->in_frame())); |
|||
} |
|||
|
|||
public function require_frame() { |
|||
if (!$this->in_frame()) { |
|||
$this->redirect($this->get_login_url(self::current_url(), true)); |
|||
} |
|||
} |
|||
|
|||
public static function get_facebook_url($subdomain='www') { |
|||
return 'http://' . $subdomain . '.new.facebook.com'; |
|||
} |
|||
|
|||
public function get_install_url($next=null) { |
|||
// this was renamed, keeping for compatibility's sake |
|||
return $this->get_add_url($next); |
|||
} |
|||
|
|||
public function get_add_url($next=null) { |
|||
return self::get_facebook_url().'/add.php?api_key='.$this->api_key . |
|||
($next ? '&next=' . urlencode($next) : ''); |
|||
} |
|||
|
|||
public function get_login_url($next, $canvas) { |
|||
return self::get_facebook_url().'/login.php?v=1.0&api_key=' . $this->api_key . |
|||
($next ? '&next=' . urlencode($next) : '') . |
|||
($canvas ? '&canvas' : ''); |
|||
} |
|||
|
|||
public function set_user($user, $session_key, $expires=null, $session_secret=null) { |
|||
if (!$this->in_fb_canvas() && (!isset($_COOKIE[$this->api_key . '_user']) |
|||
|| $_COOKIE[$this->api_key . '_user'] != $user)) { |
|||
$this->set_cookies($user, $session_key, $expires, $session_secret); |
|||
} |
|||
$this->user = $user; |
|||
$this->api_client->session_key = $session_key; |
|||
$this->session_expires = $expires; |
|||
} |
|||
|
|||
public function set_cookies($user, $session_key, $expires=null, $session_secret=null) { |
|||
$cookies = array(); |
|||
$cookies['user'] = $user; |
|||
$cookies['session_key'] = $session_key; |
|||
if ($expires != null) { |
|||
$cookies['expires'] = $expires; |
|||
} |
|||
if ($session_secret != null) { |
|||
$cookies['ss'] = $session_secret; |
|||
} |
|||
foreach ($cookies as $name => $val) { |
|||
setcookie($this->api_key . '_' . $name, $val, (int)$expires); |
|||
$_COOKIE[$this->api_key . '_' . $name] = $val; |
|||
} |
|||
$sig = self::generate_sig($cookies, $this->secret); |
|||
setcookie($this->api_key, $sig, (int)$expires); |
|||
$_COOKIE[$this->api_key] = $sig; |
|||
} |
|||
|
|||
/** |
|||
* Tries to undo the badness of magic quotes as best we can |
|||
* @param string $val Should come directly from $_GET, $_POST, etc. |
|||
* @return string val without added slashes |
|||
*/ |
|||
public static function no_magic_quotes($val) { |
|||
if (get_magic_quotes_gpc()) { |
|||
return stripslashes($val); |
|||
} else { |
|||
return $val; |
|||
} |
|||
} |
|||
|
|||
/* |
|||
* Get the signed parameters that were sent from Facebook. Validates the set |
|||
* of parameters against the included signature. |
|||
* |
|||
* Since Facebook sends data to your callback URL via unsecured means, the |
|||
* signature is the only way to make sure that the data actually came from |
|||
* Facebook. So if an app receives a request at the callback URL, it should |
|||
* always verify the signature that comes with against your own secret key. |
|||
* Otherwise, it's possible for someone to spoof a request by |
|||
* pretending to be someone else, i.e.: |
|||
* www.your-callback-url.com/?fb_user=10101 |
|||
* |
|||
* This is done automatically by verify_fb_params. |
|||
* |
|||
* @param assoc $params a full array of external parameters. |
|||
* presumed $_GET, $_POST, or $_COOKIE |
|||
* @param int $timeout number of seconds that the args are good for. |
|||
* Specifically good for forcing cookies to expire. |
|||
* @param string $namespace prefix string for the set of parameters we want |
|||
* to verify. i.e., fb_sig or fb_post_sig |
|||
* |
|||
* @return assoc the subset of parameters containing the given prefix, |
|||
* and also matching the signature associated with them. |
|||
* OR an empty array if the params do not validate |
|||
*/ |
|||
public function get_valid_fb_params($params, $timeout=null, $namespace='fb_sig') { |
|||
$prefix = $namespace . '_'; |
|||
$prefix_len = strlen($prefix); |
|||
$fb_params = array(); |
|||
if (empty($params)) { |
|||
return array(); |
|||
} |
|||
|
|||
foreach ($params as $name => $val) { |
|||
// pull out only those parameters that match the prefix |
|||
// note that the signature itself ($params[$namespace]) is not in the list |
|||
if (strpos($name, $prefix) === 0) { |
|||
$fb_params[substr($name, $prefix_len)] = self::no_magic_quotes($val); |
|||
} |
|||
} |
|||
|
|||
// validate that the request hasn't expired. this is most likely |
|||
// for params that come from $_COOKIE |
|||
if ($timeout && (!isset($fb_params['time']) || time() - $fb_params['time'] > $timeout)) { |
|||
return array(); |
|||
} |
|||
|
|||
// validate that the params match the signature |
|||
$signature = isset($params[$namespace]) ? $params[$namespace] : null; |
|||
if (!$signature || (!$this->verify_signature($fb_params, $signature))) { |
|||
return array(); |
|||
} |
|||
return $fb_params; |
|||
} |
|||
|
|||
/* |
|||
* Validates that a given set of parameters match their signature. |
|||
* Parameters all match a given input prefix, such as "fb_sig". |
|||
* |
|||
* @param $fb_params an array of all Facebook-sent parameters, |
|||
* not including the signature itself |
|||
* @param $expected_sig the expected result to check against |
|||
*/ |
|||
public function verify_signature($fb_params, $expected_sig) { |
|||
return self::generate_sig($fb_params, $this->secret) == $expected_sig; |
|||
} |
|||
|
|||
/* |
|||
* Generate a signature using the application secret key. |
|||
* |
|||
* The only two entities that know your secret key are you and Facebook, |
|||
* according to the Terms of Service. Since nobody else can generate |
|||
* the signature, you can rely on it to verify that the information |
|||
* came from Facebook. |
|||
* |
|||
* @param $params_array an array of all Facebook-sent parameters, |
|||
* NOT INCLUDING the signature itself |
|||
* @param $secret your app's secret key |
|||
* |
|||
* @return a hash to be checked against the signature provided by Facebook |
|||
*/ |
|||
public static function generate_sig($params_array, $secret) { |
|||
$str = ''; |
|||
|
|||
ksort($params_array); |
|||
// Note: make sure that the signature parameter is not already included in |
|||
// $params_array. |
|||
foreach ($params_array as $k=>$v) { |
|||
$str .= "$k=$v"; |
|||
} |
|||
$str .= $secret; |
|||
|
|||
return md5($str); |
|||
} |
|||
|
|||
public function encode_validationError($summary, $message) { |
|||
return json_encode( |
|||
array('errorCode' => FACEBOOK_API_VALIDATION_ERROR, |
|||
'errorTitle' => $summary, |
|||
'errorMessage' => $message)); |
|||
} |
|||
|
|||
public function encode_multiFeedStory($feed, $next) { |
|||
return json_encode( |
|||
array('method' => 'multiFeedStory', |
|||
'content' => |
|||
array('next' => $next, |
|||
'feed' => $feed))); |
|||
} |
|||
|
|||
public function encode_feedStory($feed, $next) { |
|||
return json_encode( |
|||
array('method' => 'feedStory', |
|||
'content' => |
|||
array('next' => $next, |
|||
'feed' => $feed))); |
|||
} |
|||
|
|||
public function create_templatizedFeedStory($title_template, $title_data=array(), |
|||
$body_template='', $body_data = array(), $body_general=null, |
|||
$image_1=null, $image_1_link=null, |
|||
$image_2=null, $image_2_link=null, |
|||
$image_3=null, $image_3_link=null, |
|||
$image_4=null, $image_4_link=null) { |
|||
return array('title_template'=> $title_template, |
|||
'title_data' => $title_data, |
|||
'body_template'=> $body_template, |
|||
'body_data' => $body_data, |
|||
'body_general' => $body_general, |
|||
'image_1' => $image_1, |
|||
'image_1_link' => $image_1_link, |
|||
'image_2' => $image_2, |
|||
'image_2_link' => $image_2_link, |
|||
'image_3' => $image_3, |
|||
'image_3_link' => $image_3_link, |
|||
'image_4' => $image_4, |
|||
'image_4_link' => $image_4_link); |
|||
} |
|||
|
|||
|
|||
} |
|||
|
@ -0,0 +1,104 @@ |
|||
<?php |
|||
// Copyright 2004-2008 Facebook. All Rights Reserved. |
|||
// |
|||
// +---------------------------------------------------------------------------+ |
|||
// | Facebook Platform PHP5 client | |
|||
// +---------------------------------------------------------------------------+ |
|||
// | Copyright (c) 2007 Facebook, Inc. | |
|||
// | All rights reserved. | |
|||
// | | |
|||
// | Redistribution and use in source and binary forms, with or without | |
|||
// | modification, are permitted provided that the following conditions | |
|||
// | are met: | |
|||
// | | |
|||
// | 1. Redistributions of source code must retain the above copyright | |
|||
// | notice, this list of conditions and the following disclaimer. | |
|||
// | 2. Redistributions in binary form must reproduce the above copyright | |
|||
// | notice, this list of conditions and the following disclaimer in the | |
|||
// | documentation and/or other materials provided with the distribution. | |
|||
// | | |
|||
// | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | |
|||
// | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
|||
// | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |
|||
// | IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | |
|||
// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
|||
// | NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
|||
// | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
|||
// | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
|||
// | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |
|||
// | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
|||
// +---------------------------------------------------------------------------+ |
|||
// | For help with this library, contact developers-help@facebook.com | |
|||
// +---------------------------------------------------------------------------+ |
|||
// |
|||
|
|||
/** |
|||
* This class extends and modifies the "Facebook" class to better |
|||
* suit desktop apps. |
|||
*/ |
|||
class FacebookDesktop extends Facebook { |
|||
// the application secret, which differs from the session secret |
|||
public $app_secret; |
|||
public $verify_sig; |
|||
|
|||
public function __construct($api_key, $secret) { |
|||
$this->app_secret = $secret; |
|||
$this->verify_sig = false; |
|||
parent::__construct($api_key, $secret); |
|||
} |
|||
|
|||
public function do_get_session($auth_token) { |
|||
$this->api_client->secret = $this->app_secret; |
|||
$this->api_client->session_key = null; |
|||
$session_info = parent::do_get_session($auth_token); |
|||
if (!empty($session_info['secret'])) { |
|||
// store the session secret |
|||
$this->set_session_secret($session_info['secret']); |
|||
} |
|||
return $session_info; |
|||
} |
|||
|
|||
public function set_session_secret($session_secret) { |
|||
$this->secret = $session_secret; |
|||
$this->api_client->secret = $session_secret; |
|||
} |
|||
|
|||
public function require_login() { |
|||
if ($this->get_loggedin_user()) { |
|||
try { |
|||
// try a session-based API call to ensure that we have the correct |
|||
// session secret |
|||
$user = $this->api_client->users_getLoggedInUser(); |
|||
|
|||
// now that we have a valid session secret, verify the signature |
|||
$this->verify_sig = true; |
|||
if ($this->validate_fb_params(false)) { |
|||
return $user; |
|||
} else { |
|||
// validation failed |
|||
return null; |
|||
} |
|||
} catch (FacebookRestClientException $ex) { |
|||
if (isset($_GET['auth_token'])) { |
|||
// if we have an auth_token, use it to establish a session |
|||
$session_info = $this->do_get_session($_GET['auth_token']); |
|||
if ($session_info) { |
|||
return $session_info['uid']; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
// if we get here, we need to redirect the user to log in |
|||
$this->redirect($this->get_login_url(self::current_url(), $this->in_fb_canvas())); |
|||
} |
|||
|
|||
public function verify_signature($fb_params, $expected_sig) { |
|||
// we don't want to verify the signature until we have a valid |
|||
// session secret |
|||
if ($this->verify_sig) { |
|||
return parent::verify_signature($fb_params, $expected_sig); |
|||
} else { |
|||
return true; |
|||
} |
|||
} |
|||
} |
File diff suppressed because it is too large
@ -0,0 +1,806 @@ |
|||
<?php |
|||
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ |
|||
|
|||
/** |
|||
* Converts to and from JSON format. |
|||
* |
|||
* JSON (JavaScript Object Notation) is a lightweight data-interchange |
|||
* format. It is easy for humans to read and write. It is easy for machines |
|||
* to parse and generate. It is based on a subset of the JavaScript |
|||
* Programming Language, Standard ECMA-262 3rd Edition - December 1999. |
|||
* This feature can also be found in Python. JSON is a text format that is |
|||
* completely language independent but uses conventions that are familiar |
|||
* to programmers of the C-family of languages, including C, C++, C#, Java, |
|||
* JavaScript, Perl, TCL, and many others. These properties make JSON an |
|||
* ideal data-interchange language. |
|||
* |
|||
* This package provides a simple encoder and decoder for JSON notation. It |
|||
* is intended for use with client-side Javascript applications that make |
|||
* use of HTTPRequest to perform server communication functions - data can |
|||
* be encoded into JSON notation for use in a client-side javascript, or |
|||
* decoded from incoming Javascript requests. JSON format is native to |
|||
* Javascript, and can be directly eval()'ed with no further parsing |
|||
* overhead |
|||
* |
|||
* All strings should be in ASCII or UTF-8 format! |
|||
* |
|||
* LICENSE: Redistribution and use in source and binary forms, with or |
|||
* without modification, are permitted provided that the following |
|||
* conditions are met: Redistributions of source code must retain the |
|||
* above copyright notice, this list of conditions and the following |
|||
* disclaimer. Redistributions in binary form must reproduce the above |
|||
* copyright notice, this list of conditions and the following disclaimer |
|||
* in the documentation and/or other materials provided with the |
|||
* distribution. |
|||
* |
|||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED |
|||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
|||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN |
|||
* NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
|||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
|||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS |
|||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
|||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR |
|||
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE |
|||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
|||
* DAMAGE. |
|||
* |
|||
* @category |
|||
* @package Services_JSON |
|||
* @author Michal Migurski <mike-json@teczno.com> |
|||
* @author Matt Knapp <mdknapp[at]gmail[dot]com> |
|||
* @author Brett Stimmerman <brettstimmerman[at]gmail[dot]com> |
|||
* @copyright 2005 Michal Migurski |
|||
* @version CVS: $Id: JSON.php,v 1.31 2006/06/28 05:54:17 migurski Exp $ |
|||
* @license http://www.opensource.org/licenses/bsd-license.php |
|||
* @link http://pear.php.net/pepr/pepr-proposal-show.php?id=198 |
|||
*/ |
|||
|
|||
/** |
|||
* Marker constant for Services_JSON::decode(), used to flag stack state |
|||
*/ |
|||
define('SERVICES_JSON_SLICE', 1); |
|||
|
|||
/** |
|||
* Marker constant for Services_JSON::decode(), used to flag stack state |
|||
*/ |
|||
define('SERVICES_JSON_IN_STR', 2); |
|||
|
|||
/** |
|||
* Marker constant for Services_JSON::decode(), used to flag stack state |
|||
*/ |
|||
define('SERVICES_JSON_IN_ARR', 3); |
|||
|
|||
/** |
|||
* Marker constant for Services_JSON::decode(), used to flag stack state |
|||
*/ |
|||
define('SERVICES_JSON_IN_OBJ', 4); |
|||
|
|||
/** |
|||
* Marker constant for Services_JSON::decode(), used to flag stack state |
|||
*/ |
|||
define('SERVICES_JSON_IN_CMT', 5); |
|||
|
|||
/** |
|||
* Behavior switch for Services_JSON::decode() |
|||
*/ |
|||
define('SERVICES_JSON_LOOSE_TYPE', 16); |
|||
|
|||
/** |
|||
* Behavior switch for Services_JSON::decode() |
|||
*/ |
|||
define('SERVICES_JSON_SUPPRESS_ERRORS', 32); |
|||
|
|||
/** |
|||
* Converts to and from JSON format. |
|||
* |
|||
* Brief example of use: |
|||
* |
|||
* <code> |
|||
* // create a new instance of Services_JSON |
|||
* $json = new Services_JSON(); |
|||
* |
|||
* // convert a complexe value to JSON notation, and send it to the browser |
|||
* $value = array('foo', 'bar', array(1, 2, 'baz'), array(3, array(4))); |
|||
* $output = $json->encode($value); |
|||
* |
|||
* print($output); |
|||
* // prints: ["foo","bar",[1,2,"baz"],[3,[4]]] |
|||
* |
|||
* // accept incoming POST data, assumed to be in JSON notation |
|||
* $input = file_get_contents('php://input', 1000000); |
|||
* $value = $json->decode($input); |
|||
* </code> |
|||
*/ |
|||
class Services_JSON |
|||
{ |
|||
/** |
|||
* constructs a new JSON instance |
|||
* |
|||
* @param int $use object behavior flags; combine with boolean-OR |
|||
* |
|||
* possible values: |
|||
* - SERVICES_JSON_LOOSE_TYPE: loose typing. |
|||
* "{...}" syntax creates associative arrays |
|||
* instead of objects in decode(). |
|||
* - SERVICES_JSON_SUPPRESS_ERRORS: error suppression. |
|||
* Values which can't be encoded (e.g. resources) |
|||
* appear as NULL instead of throwing errors. |
|||
* By default, a deeply-nested resource will |
|||
* bubble up with an error, so all return values |
|||
* from encode() should be checked with isError() |
|||
*/ |
|||
function Services_JSON($use = 0) |
|||
{ |
|||
$this->use = $use; |
|||
} |
|||
|
|||
/** |
|||
* convert a string from one UTF-16 char to one UTF-8 char |
|||
* |
|||
* Normally should be handled by mb_convert_encoding, but |
|||
* provides a slower PHP-only method for installations |
|||
* that lack the multibye string extension. |
|||
* |
|||
* @param string $utf16 UTF-16 character |
|||
* @return string UTF-8 character |
|||
* @access private |
|||
*/ |
|||
function utf162utf8($utf16) |
|||
{ |
|||
// oh please oh please oh please oh please oh please |
|||
if(function_exists('mb_convert_encoding')) { |
|||
return mb_convert_encoding($utf16, 'UTF-8', 'UTF-16'); |
|||
} |
|||
|
|||
$bytes = (ord($utf16{0}) << 8) | ord($utf16{1}); |
|||
|
|||
switch(true) { |
|||
case ((0x7F & $bytes) == $bytes): |
|||
// this case should never be reached, because we are in ASCII range |
|||
// see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
|||
return chr(0x7F & $bytes); |
|||
|
|||
case (0x07FF & $bytes) == $bytes: |
|||
// return a 2-byte UTF-8 character |
|||
// see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
|||
return chr(0xC0 | (($bytes >> 6) & 0x1F)) |
|||
. chr(0x80 | ($bytes & 0x3F)); |
|||
|
|||
case (0xFFFF & $bytes) == $bytes: |
|||
// return a 3-byte UTF-8 character |
|||
// see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
|||
return chr(0xE0 | (($bytes >> 12) & 0x0F)) |
|||
. chr(0x80 | (($bytes >> 6) & 0x3F)) |
|||
. chr(0x80 | ($bytes & 0x3F)); |
|||
} |
|||
|
|||
// ignoring UTF-32 for now, sorry |
|||
return ''; |
|||
} |
|||
|
|||
/** |
|||
* convert a string from one UTF-8 char to one UTF-16 char |
|||
* |
|||
* Normally should be handled by mb_convert_encoding, but |
|||
* provides a slower PHP-only method for installations |
|||
* that lack the multibye string extension. |
|||
* |
|||
* @param string $utf8 UTF-8 character |
|||
* @return string UTF-16 character |
|||
* @access private |
|||
*/ |
|||
function utf82utf16($utf8) |
|||
{ |
|||
// oh please oh please oh please oh please oh please |
|||
if(function_exists('mb_convert_encoding')) { |
|||
return mb_convert_encoding($utf8, 'UTF-16', 'UTF-8'); |
|||
} |
|||
|
|||
switch(strlen($utf8)) { |
|||
case 1: |
|||
// this case should never be reached, because we are in ASCII range |
|||
// see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
|||
return $utf8; |
|||
|
|||
case 2: |
|||
// return a UTF-16 character from a 2-byte UTF-8 char |
|||
// see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
|||
return chr(0x07 & (ord($utf8{0}) >> 2)) |
|||
. chr((0xC0 & (ord($utf8{0}) << 6)) |
|||
| (0x3F & ord($utf8{1}))); |
|||
|
|||
case 3: |
|||
// return a UTF-16 character from a 3-byte UTF-8 char |
|||
// see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
|||
return chr((0xF0 & (ord($utf8{0}) << 4)) |
|||
| (0x0F & (ord($utf8{1}) >> 2))) |
|||
. chr((0xC0 & (ord($utf8{1}) << 6)) |
|||
| (0x7F & ord($utf8{2}))); |
|||
} |
|||
|
|||
// ignoring UTF-32 for now, sorry |
|||
return ''; |
|||
} |
|||
|
|||
/** |
|||
* encodes an arbitrary variable into JSON format |
|||
* |
|||
* @param mixed $var any number, boolean, string, array, or object to be encoded. |
|||
* see argument 1 to Services_JSON() above for array-parsing behavior. |
|||
* if var is a strng, note that encode() always expects it |
|||
* to be in ASCII or UTF-8 format! |
|||
* |
|||
* @return mixed JSON string representation of input var or an error if a problem occurs |
|||
* @access public |
|||
*/ |
|||
function encode($var) |
|||
{ |
|||
switch (gettype($var)) { |
|||
case 'boolean': |
|||
return $var ? 'true' : 'false'; |
|||
|
|||
case 'NULL': |
|||
return 'null'; |
|||
|
|||
case 'integer': |
|||
return (int) $var; |
|||
|
|||
case 'double': |
|||
case 'float': |
|||
return (float) $var; |
|||
|
|||
case 'string': |
|||
// STRINGS ARE EXPECTED TO BE IN ASCII OR UTF-8 FORMAT |
|||
$ascii = ''; |
|||
$strlen_var = strlen($var); |
|||
|
|||
/* |
|||
* Iterate over every character in the string, |
|||
* escaping with a slash or encoding to UTF-8 where necessary |
|||
*/ |
|||
for ($c = 0; $c < $strlen_var; ++$c) { |
|||
|
|||
$ord_var_c = ord($var{$c}); |
|||
|
|||
switch (true) { |
|||
case $ord_var_c == 0x08: |
|||
$ascii .= '\b'; |
|||
break; |
|||
case $ord_var_c == 0x09: |
|||
$ascii .= '\t'; |
|||
break; |
|||
case $ord_var_c == 0x0A: |
|||
$ascii .= '\n'; |
|||
break; |
|||
case $ord_var_c == 0x0C: |
|||
$ascii .= '\f'; |
|||
break; |
|||
case $ord_var_c == 0x0D: |
|||
$ascii .= '\r'; |
|||
break; |
|||
|
|||
case $ord_var_c == 0x22: |
|||
case $ord_var_c == 0x2F: |
|||
case $ord_var_c == 0x5C: |
|||
// double quote, slash, slosh |
|||
$ascii .= '\\'.$var{$c}; |
|||
break; |
|||
|
|||
case (($ord_var_c >= 0x20) && ($ord_var_c <= 0x7F)): |
|||
// characters U-00000000 - U-0000007F (same as ASCII) |
|||
$ascii .= $var{$c}; |
|||
break; |
|||
|
|||
case (($ord_var_c & 0xE0) == 0xC0): |
|||
// characters U-00000080 - U-000007FF, mask 110XXXXX |
|||
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
|||
$char = pack('C*', $ord_var_c, ord($var{$c + 1})); |
|||
$c += 1; |
|||
$utf16 = $this->utf82utf16($char); |
|||
$ascii .= sprintf('\u%04s', bin2hex($utf16)); |
|||
break; |
|||
|
|||
case (($ord_var_c & 0xF0) == 0xE0): |
|||
// characters U-00000800 - U-0000FFFF, mask 1110XXXX |
|||
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
|||
$char = pack('C*', $ord_var_c, |
|||
ord($var{$c + 1}), |
|||
ord($var{$c + 2})); |
|||
$c += 2; |
|||
$utf16 = $this->utf82utf16($char); |
|||
$ascii .= sprintf('\u%04s', bin2hex($utf16)); |
|||
break; |
|||
|
|||
case (($ord_var_c & 0xF8) == 0xF0): |
|||
// characters U-00010000 - U-001FFFFF, mask 11110XXX |
|||
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
|||
$char = pack('C*', $ord_var_c, |
|||
ord($var{$c + 1}), |
|||
ord($var{$c + 2}), |
|||
ord($var{$c + 3})); |
|||
$c += 3; |
|||
$utf16 = $this->utf82utf16($char); |
|||
$ascii .= sprintf('\u%04s', bin2hex($utf16)); |
|||
break; |
|||
|
|||
case (($ord_var_c & 0xFC) == 0xF8): |
|||
// characters U-00200000 - U-03FFFFFF, mask 111110XX |
|||
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
|||
$char = pack('C*', $ord_var_c, |
|||
ord($var{$c + 1}), |
|||
ord($var{$c + 2}), |
|||
ord($var{$c + 3}), |
|||
ord($var{$c + 4})); |
|||
$c += 4; |
|||
$utf16 = $this->utf82utf16($char); |
|||
$ascii .= sprintf('\u%04s', bin2hex($utf16)); |
|||
break; |
|||
|
|||
case (($ord_var_c & 0xFE) == 0xFC): |
|||
// characters U-04000000 - U-7FFFFFFF, mask 1111110X |
|||
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
|||
$char = pack('C*', $ord_var_c, |
|||
ord($var{$c + 1}), |
|||
ord($var{$c + 2}), |
|||
ord($var{$c + 3}), |
|||
ord($var{$c + 4}), |
|||
ord($var{$c + 5})); |
|||
$c += 5; |
|||
$utf16 = $this->utf82utf16($char); |
|||
$ascii .= sprintf('\u%04s', bin2hex($utf16)); |
|||
break; |
|||
} |
|||
} |
|||
|
|||
return '"'.$ascii.'"'; |
|||
|
|||
case 'array': |
|||
/* |
|||
* As per JSON spec if any array key is not an integer |
|||
* we must treat the the whole array as an object. We |
|||
* also try to catch a sparsely populated associative |
|||
* array with numeric keys here because some JS engines |
|||
* will create an array with empty indexes up to |
|||
* max_index which can cause memory issues and because |
|||
* the keys, which may be relevant, will be remapped |
|||
* otherwise. |
|||
* |
|||
* As per the ECMA and JSON specification an object may |
|||
* have any string as a property. Unfortunately due to |
|||
* a hole in the ECMA specification if the key is a |
|||
* ECMA reserved word or starts with a digit the |
|||
* parameter is only accessible using ECMAScript's |
|||
* bracket notation. |
|||
*/ |
|||
|
|||
// treat as a JSON object |
|||
if (is_array($var) && count($var) && (array_keys($var) !== range(0, sizeof($var) - 1))) { |
|||
$properties = array_map(array($this, 'name_value'), |
|||
array_keys($var), |
|||
array_values($var)); |
|||
|
|||
foreach($properties as $property) { |
|||
if(Services_JSON::isError($property)) { |
|||
return $property; |
|||
} |
|||
} |
|||
|
|||
return '{' . join(',', $properties) . '}'; |
|||
} |
|||
|
|||
// treat it like a regular array |
|||
$elements = array_map(array($this, 'encode'), $var); |
|||
|
|||
foreach($elements as $element) { |
|||
if(Services_JSON::isError($element)) { |
|||
return $element; |
|||
} |
|||
} |
|||
|
|||
return '[' . join(',', $elements) . ']'; |
|||
|
|||
case 'object': |
|||
$vars = get_object_vars($var); |
|||
|
|||
$properties = array_map(array($this, 'name_value'), |
|||
array_keys($vars), |
|||
array_values($vars)); |
|||
|
|||
foreach($properties as $property) { |
|||
if(Services_JSON::isError($property)) { |
|||
return $property; |
|||
} |
|||
} |
|||
|
|||
return '{' . join(',', $properties) . '}'; |
|||
|
|||
default: |
|||
return ($this->use & SERVICES_JSON_SUPPRESS_ERRORS) |
|||
? 'null' |
|||
: new Services_JSON_Error(gettype($var)." can not be encoded as JSON string"); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* array-walking function for use in generating JSON-formatted name-value pairs |
|||
* |
|||
* @param string $name name of key to use |
|||
* @param mixed $value reference to an array element to be encoded |
|||
* |
|||
* @return string JSON-formatted name-value pair, like '"name":value' |
|||
* @access private |
|||
*/ |
|||
function name_value($name, $value) |
|||
{ |
|||
$encoded_value = $this->encode($value); |
|||
|
|||
if(Services_JSON::isError($encoded_value)) { |
|||
return $encoded_value; |
|||
} |
|||
|
|||
return $this->encode(strval($name)) . ':' . $encoded_value; |
|||
} |
|||
|
|||
/** |
|||
* reduce a string by removing leading and trailing comments and whitespace |
|||
* |
|||
* @param $str string string value to strip of comments and whitespace |
|||
* |
|||
* @return string string value stripped of comments and whitespace |
|||
* @access private |
|||
*/ |
|||
function reduce_string($str) |
|||
{ |
|||
$str = preg_replace(array( |
|||
|
|||
// eliminate single line comments in '// ...' form |
|||
'#^\s*//(.+)$#m', |
|||
|
|||
// eliminate multi-line comments in '/* ... */' form, at start of string |
|||
'#^\s*/\*(.+)\*/#Us', |
|||
|
|||
// eliminate multi-line comments in '/* ... */' form, at end of string |
|||
'#/\*(.+)\*/\s*$#Us' |
|||
|
|||
), '', $str); |
|||
|
|||
// eliminate extraneous space |
|||
return trim($str); |
|||
} |
|||
|
|||
/** |
|||
* decodes a JSON string into appropriate variable |
|||
* |
|||
* @param string $str JSON-formatted string |
|||
* |
|||
* @return mixed number, boolean, string, array, or object |
|||
* corresponding to given JSON input string. |
|||
* See argument 1 to Services_JSON() above for object-output behavior. |
|||
* Note that decode() always returns strings |
|||
* in ASCII or UTF-8 format! |
|||
* @access public |
|||
*/ |
|||
function decode($str) |
|||
{ |
|||
$str = $this->reduce_string($str); |
|||
|
|||
switch (strtolower($str)) { |
|||
case 'true': |
|||
return true; |
|||
|
|||
case 'false': |
|||
return false; |
|||
|
|||
case 'null': |
|||
return null; |
|||
|
|||
default: |
|||
$m = array(); |
|||
|
|||
if (is_numeric($str)) { |
|||
// Lookie-loo, it's a number |
|||
|
|||
// This would work on its own, but I'm trying to be |
|||
// good about returning integers where appropriate: |
|||
// return (float)$str; |
|||
|
|||
// Return float or int, as appropriate |
|||
return ((float)$str == (integer)$str) |
|||
? (integer)$str |
|||
: (float)$str; |
|||
|
|||
} elseif (preg_match('/^("|\').*(\1)$/s', $str, $m) && $m[1] == $m[2]) { |
|||
// STRINGS RETURNED IN UTF-8 FORMAT |
|||
$delim = substr($str, 0, 1); |
|||
$chrs = substr($str, 1, -1); |
|||
$utf8 = ''; |
|||
$strlen_chrs = strlen($chrs); |
|||
|
|||
for ($c = 0; $c < $strlen_chrs; ++$c) { |
|||
|
|||
$substr_chrs_c_2 = substr($chrs, $c, 2); |
|||
$ord_chrs_c = ord($chrs{$c}); |
|||
|
|||
switch (true) { |
|||
case $substr_chrs_c_2 == '\b': |
|||
$utf8 .= chr(0x08); |
|||
++$c; |
|||
break; |
|||
case $substr_chrs_c_2 == '\t': |
|||
$utf8 .= chr(0x09); |
|||
++$c; |
|||
break; |
|||
case $substr_chrs_c_2 == '\n': |
|||
$utf8 .= chr(0x0A); |
|||
++$c; |
|||
break; |
|||
case $substr_chrs_c_2 == '\f': |
|||
$utf8 .= chr(0x0C); |
|||
++$c; |
|||
break; |
|||
case $substr_chrs_c_2 == '\r': |
|||
$utf8 .= chr(0x0D); |
|||
++$c; |
|||
break; |
|||
|
|||
case $substr_chrs_c_2 == '\\"': |
|||
case $substr_chrs_c_2 == '\\\'': |
|||
case $substr_chrs_c_2 == '\\\\': |
|||
case $substr_chrs_c_2 == '\\/': |
|||
if (($delim == '"' && $substr_chrs_c_2 != '\\\'') || |
|||
($delim == "'" && $substr_chrs_c_2 != '\\"')) { |
|||
$utf8 .= $chrs{++$c}; |
|||
} |
|||
break; |
|||
|
|||
case preg_match('/\\\u[0-9A-F]{4}/i', substr($chrs, $c, 6)): |
|||
// single, escaped unicode character |
|||
$utf16 = chr(hexdec(substr($chrs, ($c + 2), 2))) |
|||
. chr(hexdec(substr($chrs, ($c + 4), 2))); |
|||
$utf8 .= $this->utf162utf8($utf16); |
|||
$c += 5; |
|||
break; |
|||
|
|||
case ($ord_chrs_c >= 0x20) && ($ord_chrs_c <= 0x7F): |
|||
$utf8 .= $chrs{$c}; |
|||
break; |
|||
|
|||
case ($ord_chrs_c & 0xE0) == 0xC0: |
|||
// characters U-00000080 - U-000007FF, mask 110XXXXX |
|||
//see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
|||
$utf8 .= substr($chrs, $c, 2); |
|||
++$c; |
|||
break; |
|||
|
|||
case ($ord_chrs_c & 0xF0) == 0xE0: |
|||
// characters U-00000800 - U-0000FFFF, mask 1110XXXX |
|||
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
|||
$utf8 .= substr($chrs, $c, 3); |
|||
$c += 2; |
|||
break; |
|||
|
|||
case ($ord_chrs_c & 0xF8) == 0xF0: |
|||
// characters U-00010000 - U-001FFFFF, mask 11110XXX |
|||
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
|||
$utf8 .= substr($chrs, $c, 4); |
|||
$c += 3; |
|||
break; |
|||
|
|||
case ($ord_chrs_c & 0xFC) == 0xF8: |
|||
// characters U-00200000 - U-03FFFFFF, mask 111110XX |
|||
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
|||
$utf8 .= substr($chrs, $c, 5); |
|||
$c += 4; |
|||
break; |
|||
|
|||
case ($ord_chrs_c & 0xFE) == 0xFC: |
|||
// characters U-04000000 - U-7FFFFFFF, mask 1111110X |
|||
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
|||
$utf8 .= substr($chrs, $c, 6); |
|||
$c += 5; |
|||
break; |
|||
|
|||
} |
|||
|
|||
} |
|||
|
|||
return $utf8; |
|||
|
|||
} elseif (preg_match('/^\[.*\]$/s', $str) || preg_match('/^\{.*\}$/s', $str)) { |
|||
// array, or object notation |
|||
|
|||
if ($str{0} == '[') { |
|||
$stk = array(SERVICES_JSON_IN_ARR); |
|||
$arr = array(); |
|||
} else { |
|||
if ($this->use & SERVICES_JSON_LOOSE_TYPE) { |
|||
$stk = array(SERVICES_JSON_IN_OBJ); |
|||
$obj = array(); |
|||
} else { |
|||
$stk = array(SERVICES_JSON_IN_OBJ); |
|||
$obj = new stdClass(); |
|||
} |
|||
} |
|||
|
|||
array_push($stk, array('what' => SERVICES_JSON_SLICE, |
|||
'where' => 0, |
|||
'delim' => false)); |
|||
|
|||
$chrs = substr($str, 1, -1); |
|||
$chrs = $this->reduce_string($chrs); |
|||
|
|||
if ($chrs == '') { |
|||
if (reset($stk) == SERVICES_JSON_IN_ARR) { |
|||
return $arr; |
|||
|
|||
} else { |
|||
return $obj; |
|||
|
|||
} |
|||
} |
|||
|
|||
//print("\nparsing {$chrs}\n"); |
|||
|
|||
$strlen_chrs = strlen($chrs); |
|||
|
|||
for ($c = 0; $c <= $strlen_chrs; ++$c) { |
|||
|
|||
$top = end($stk); |
|||
$substr_chrs_c_2 = substr($chrs, $c, 2); |
|||
|
|||
if (($c == $strlen_chrs) || (($chrs{$c} == ',') && ($top['what'] == SERVICES_JSON_SLICE))) { |
|||
// found a comma that is not inside a string, array, etc., |
|||
// OR we've reached the end of the character list |
|||
$slice = substr($chrs, $top['where'], ($c - $top['where'])); |
|||
array_push($stk, array('what' => SERVICES_JSON_SLICE, 'where' => ($c + 1), 'delim' => false)); |
|||
//print("Found split at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n"); |
|||
|
|||
if (reset($stk) == SERVICES_JSON_IN_ARR) { |
|||
// we are in an array, so just push an element onto the stack |
|||
array_push($arr, $this->decode($slice)); |
|||
|
|||
} elseif (reset($stk) == SERVICES_JSON_IN_OBJ) { |
|||
// we are in an object, so figure |
|||
// out the property name and set an |
|||
// element in an associative array, |
|||
// for now |
|||
$parts = array(); |
|||
|
|||
if (preg_match('/^\s*(["\'].*[^\\\]["\'])\s*:\s*(\S.*),?$/Uis', $slice, $parts)) { |
|||
// "name":value pair |
|||
$key = $this->decode($parts[1]); |
|||
$val = $this->decode($parts[2]); |
|||
|
|||
if ($this->use & SERVICES_JSON_LOOSE_TYPE) { |
|||
$obj[$key] = $val; |
|||
} else { |
|||
$obj->$key = $val; |
|||
} |
|||
} elseif (preg_match('/^\s*(\w+)\s*:\s*(\S.*),?$/Uis', $slice, $parts)) { |
|||
// name:value pair, where name is unquoted |
|||
$key = $parts[1]; |
|||
$val = $this->decode($parts[2]); |
|||
|
|||
if ($this->use & SERVICES_JSON_LOOSE_TYPE) { |
|||
$obj[$key] = $val; |
|||
} else { |
|||
$obj->$key = $val; |
|||
} |
|||
} |
|||
|
|||
} |
|||
|
|||
} elseif ((($chrs{$c} == '"') || ($chrs{$c} == "'")) && ($top['what'] != SERVICES_JSON_IN_STR)) { |
|||
// found a quote, and we are not inside a string |
|||
array_push($stk, array('what' => SERVICES_JSON_IN_STR, 'where' => $c, 'delim' => $chrs{$c})); |
|||
//print("Found start of string at {$c}\n"); |
|||
|
|||
} elseif (($chrs{$c} == $top['delim']) && |
|||
($top['what'] == SERVICES_JSON_IN_STR) && |
|||
((strlen(substr($chrs, 0, $c)) - strlen(rtrim(substr($chrs, 0, $c), '\\'))) % 2 != 1)) { |
|||
// found a quote, we're in a string, and it's not escaped |
|||
// we know that it's not escaped becase there is _not_ an |
|||
// odd number of backslashes at the end of the string so far |
|||
array_pop($stk); |
|||
//print("Found end of string at {$c}: ".substr($chrs, $top['where'], (1 + 1 + $c - $top['where']))."\n"); |
|||
|
|||
} elseif (($chrs{$c} == '[') && |
|||
in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) { |
|||
// found a left-bracket, and we are in an array, object, or slice |
|||
array_push($stk, array('what' => SERVICES_JSON_IN_ARR, 'where' => $c, 'delim' => false)); |
|||
//print("Found start of array at {$c}\n"); |
|||
|
|||
} elseif (($chrs{$c} == ']') && ($top['what'] == SERVICES_JSON_IN_ARR)) { |
|||
// found a right-bracket, and we're in an array |
|||
array_pop($stk); |
|||
//print("Found end of array at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n"); |
|||
|
|||
} elseif (($chrs{$c} == '{') && |
|||
in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) { |
|||
// found a left-brace, and we are in an array, object, or slice |
|||
array_push($stk, array('what' => SERVICES_JSON_IN_OBJ, 'where' => $c, 'delim' => false)); |
|||
//print("Found start of object at {$c}\n"); |
|||
|
|||
} elseif (($chrs{$c} == '}') && ($top['what'] == SERVICES_JSON_IN_OBJ)) { |
|||
// found a right-brace, and we're in an object |
|||
array_pop($stk); |
|||
//print("Found end of object at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n"); |
|||
|
|||
} elseif (($substr_chrs_c_2 == '/*') && |
|||
in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) { |
|||
// found a comment start, and we are in an array, object, or slice |
|||
array_push($stk, array('what' => SERVICES_JSON_IN_CMT, 'where' => $c, 'delim' => false)); |
|||
$c++; |
|||
//print("Found start of comment at {$c}\n"); |
|||
|
|||
} elseif (($substr_chrs_c_2 == '*/') && ($top['what'] == SERVICES_JSON_IN_CMT)) { |
|||
// found a comment end, and we're in one now |
|||
array_pop($stk); |
|||
$c++; |
|||
|
|||
for ($i = $top['where']; $i <= $c; ++$i) |
|||
$chrs = substr_replace($chrs, ' ', $i, 1); |
|||
|
|||
//print("Found end of comment at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n"); |
|||
|
|||
} |
|||
|
|||
} |
|||
|
|||
if (reset($stk) == SERVICES_JSON_IN_ARR) { |
|||
return $arr; |
|||
|
|||
} elseif (reset($stk) == SERVICES_JSON_IN_OBJ) { |
|||
return $obj; |
|||
|
|||
} |
|||
|
|||
} |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* @todo Ultimately, this should just call PEAR::isError() |
|||
*/ |
|||
function isError($data, $code = null) |
|||
{ |
|||
if (class_exists('pear')) { |
|||
return PEAR::isError($data, $code); |
|||
} elseif (is_object($data) && (get_class($data) == 'services_json_error' || |
|||
is_subclass_of($data, 'services_json_error'))) { |
|||
return true; |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
} |
|||
|
|||
if (class_exists('PEAR_Error')) { |
|||
|
|||
class Services_JSON_Error extends PEAR_Error |
|||
{ |
|||
function Services_JSON_Error($message = 'unknown error', $code = null, |
|||
$mode = null, $options = null, $userinfo = null) |
|||
{ |
|||
parent::PEAR_Error($message, $code, $mode, $options, $userinfo); |
|||
} |
|||
} |
|||
|
|||
} else { |
|||
|
|||
/** |
|||
* @todo Ultimately, this class shall be descended from PEAR_Error |
|||
*/ |
|||
class Services_JSON_Error |
|||
{ |
|||
function Services_JSON_Error($message = 'unknown error', $code = null, |
|||
$mode = null, $options = null, $userinfo = null) |
|||
{ |
|||
|
|||
} |
|||
} |
|||
|
|||
} |
|||
|
|||
?> |
@ -0,0 +1,21 @@ |
|||
Redistribution and use in source and binary forms, with or without |
|||
modification, are permitted provided that the following conditions are |
|||
met: |
|||
|
|||
Redistributions of source code must retain the above copyright notice, |
|||
this list of conditions and the following disclaimer. |
|||
|
|||
Redistributions in binary form must reproduce the above copyright |
|||
notice, this list of conditions and the following disclaimer in the |
|||
documentation and/or other materials provided with the distribution. |
|||
|
|||
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED |
|||
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
|||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN |
|||
NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
|||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
|||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF |
|||
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON |
|||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
|||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
@ -0,0 +1,6 @@ |
|||
<?php |
|||
# In PHP 5.2 or higher we don't need to bring this in |
|||
if (!function_exists('json_encode')) { |
|||
require_once 'jsonwrapper_inner.php'; |
|||
} |
|||
?> |
@ -0,0 +1,23 @@ |
|||
<?php |
|||
|
|||
require_once 'JSON/JSON.php'; |
|||
|
|||
function json_encode($arg) |
|||
{ |
|||
global $services_json; |
|||
if (!isset($services_json)) { |
|||
$services_json = new Services_JSON(); |
|||
} |
|||
return $services_json->encode($arg); |
|||
} |
|||
|
|||
function json_decode($arg) |
|||
{ |
|||
global $services_json; |
|||
if (!isset($services_json)) { |
|||
$services_json = new Services_JSON(); |
|||
} |
|||
return $services_json->decode($arg); |
|||
} |
|||
|
|||
?> |
@ -0,0 +1,6 @@ |
|||
The contents of fb/ are copyright (c) 2004-2008 Facebook (All Rights |
|||
Reserved.) They are NOT part of Sex, but an integral part of the |
|||
communication with Facebook, and have been supplied by Facebook. |
|||
I have left them in because Sex doesn't work without them; I have no |
|||
connection to Facebook and they are part of Facebook's licence; see |
|||
individual files for license. |
@ -0,0 +1,3 @@ |
|||
default: |
|||
gcc -Wall -O3 -pedantic -ansi -fasm -fomit-frame-pointer -ffast-math -funroll-loops -o gifbar.cgi gifbar.c |
|||
chmod 755 gifbar.cgi |
@ -0,0 +1,313 @@ |
|||
/* I was looking though old code, and the one is genius, if a do say so myself.
|
|||
I cleaned it up. |
|||
-Neil |
|||
|
|||
Multi-byte fields are LSB first |
|||
header: 6 bytes (one header per data stream) |
|||
Signature: 3 bytes, 'GIF' |
|||
Version: 3 bytes, '87a' or '89a' |
|||
logical screen descriptor (one per data stream, follow header) |
|||
Logical screen width: 2 bytes |
|||
Logical screen height: 2 bytes |
|||
Packed Data: 1 byte |
|||
Global colour table flag: 1 bit (global table follows?) |
|||
Colour resolution - 1: 3 bits |
|||
Sort flag: 1 bit (important colours first? 0 in 87a) |
|||
Size of global colour table: 3 bits (size is 2^(x+1)) |
|||
Background colour: 1 byte |
|||
Pixel aspect ratio: 1 byte (0 = ignore 0 in 87a) |
|||
global colour table: 3 * 2 ^ (size of table + 1) bytes if table flag |
|||
RGB: 3 bytes |
|||
[ |
|||
image descriptor: (one per image) |
|||
Image separator: 1 byte 0x2C |
|||
Image left position: 2 bytes |
|||
Image top position: 2 bytes |
|||
Image width: 2 bytes |
|||
Image height: 2 bytes |
|||
Packed data: |
|||
Local colour table?: 1 bit |
|||
Interlace?: 1 bit |
|||
Sorted palette?: 1 bit |
|||
Reserved = 0: 2 bits |
|||
Local colour table size: 3 bits |
|||
local colour table: 3 * 2 ^ (size of table + 1) bytes if table flag |
|||
RGB: 3 bytes |
|||
code size: 1 byte |
|||
repeated data sub-blocks: terminated by zero-size sub-block |
|||
Size: 1 byte |
|||
Data: Size bytes |
|||
] |
|||
trailer: (one per data stream) |
|||
GIF trailer: 1 byte, 0x3B ';' |
|||
*/ |
|||
|
|||
#include <stdlib.h> /* getenv(), atoi() */ |
|||
#include <stdio.h> /* printf(), putchar(), fwrite() */ |
|||
#include <string.h> /* strcmp() */ |
|||
|
|||
typedef struct tagCode Code; |
|||
|
|||
struct tagCode { |
|||
Code *child; |
|||
Code *next; |
|||
unsigned char suffix; |
|||
unsigned long code; |
|||
unsigned int code_size; |
|||
}; |
|||
|
|||
static void print_gif(unsigned char parm); |
|||
|
|||
int main(int argc, char **argv) { |
|||
char *env; |
|||
|
|||
if(!(env = getenv("REQUEST_METHOD")) |
|||
|| (strcmp(env, "get") && strcmp(env, "GET")) |
|||
|| !(env = getenv("QUERY_STRING"))) { |
|||
printf("Status: 400 Missing required argument.\n\n"); |
|||
return EXIT_FAILURE; |
|||
} |
|||
printf("Content-type: image/gif\n\n"); |
|||
/* may need to set STDOUT to binary mode to avoid line feed translation
|
|||
if your OS sucks (you know who you are!) |
|||
if(setmode(stdout, O_BINARY) == -1) return 1; */ |
|||
print_gif(atoi(env)); |
|||
|
|||
return EXIT_SUCCESS; |
|||
} |
|||
|
|||
static void print_gif(unsigned char parm) { |
|||
/* this is the gif binary output; mine, you could use whatever and paste it
|
|||
here from the hex editor, just make it 00-FF as it goes across the image */ |
|||
static unsigned char image_data[] = { |
|||
0x08, 0xFE, 0x00, 0x5B, 0x38, 0x18, 0x80, 0xC0, 0x02, 0x8A, 0x18, 0x39, |
|||
0x8A, 0x20, 0xA9, 0xB1, 0xA1, 0xC2, 0x05, 0x0C, 0x16, 0x24, 0x38, 0x60, |
|||
0xD0, 0xE0, 0x41, 0x84, 0x09, 0x15, 0x34, 0x98, 0xE8, 0xC1, 0xA4, 0x09, |
|||
0x13, 0x23, 0x3A, 0x5E, 0x98, 0xF8, 0xD0, 0x01, 0x04, 0x8B, 0x24, 0x56, |
|||
0x9C, 0x10, 0x21, 0x72, 0x85, 0x4C, 0x19, 0x30, 0x54, 0x96, 0xF0, 0xA0, |
|||
0x81, 0x83, 0xC7, 0x8E, 0x21, 0x59, 0xB4, 0x14, 0xD9, 0x81, 0xE3, 0xC6, |
|||
0x0D, 0x1C, 0x39, 0x72, 0xE8, 0xD8, 0xD1, 0x83, 0x67, 0x8E, 0x1E, 0x3D, |
|||
0x74, 0x00, 0xE5, 0x11, 0x44, 0x88, 0x10, 0x22, 0x47, 0x8E, 0x00, 0xE1, |
|||
0xC1, 0xA3, 0xC7, 0x8F, 0x1F, 0x42, 0x9E, 0xB8, 0xC9, 0xA3, 0xA6, 0x4B, |
|||
0x95, 0x27, 0x4B, 0x9A, 0x40, 0xB9, 0xD2, 0x65, 0xCC, 0x18, 0x2E, 0x5F, |
|||
0x3B, 0x42, 0xB1, 0xD2, 0x45, 0x0C, 0x1A, 0x39, 0x7F, 0x18, 0x05, 0x22, |
|||
0xB3, 0xA5, 0x0B, 0x98, 0x32, 0x79, 0x22, 0x59, 0x42, 0x14, 0x67, 0x4D, |
|||
0x9B, 0x3C, 0x89, 0x1A, 0xED, 0x49, 0x43, 0x86, 0x4D, 0x20, 0x49, 0x96, |
|||
0x3A, 0x95, 0x2A, 0x95, 0x09, 0x50, 0x1C, 0x37, 0x6E, 0xDE, 0xC0, 0x89, |
|||
0x03, 0xE7, 0x8D, 0x65, 0x38, 0x74, 0xF2, 0x08, 0x7A, 0xE4, 0x89, 0x95, |
|||
0x2A, 0x4A, 0x83, 0x0C, 0x85, 0x8A, 0xC5, 0x8A, 0xD4, 0xA9, 0x59, 0xB6, |
|||
0x50, 0x71, 0x62, 0x65, 0xAB, 0x15, 0xAA, 0x55, 0xB2, 0x62, 0xB5, 0x5A, |
|||
0xC5, 0x2A, 0x96, 0xAE, 0x61, 0xC6, 0x90, 0x25, 0x43, 0x76, 0x2C, 0x19, |
|||
0xB3, 0x66, 0xCE, 0x9C, 0x3D, 0x73, 0x86, 0xCC, 0xD7, 0xAF, 0x65, 0xD2, |
|||
0xA4, 0x2D, 0xFB, 0xB5, 0x8B, 0x17, 0xB1, 0x67, 0xD2, 0xA0, 0x45, 0xB3, |
|||
0x96, 0x2D, 0x5B, 0x35, 0x64, 0xBD, 0x7A, 0x0D, 0x4B, 0xD6, 0xAC, 0xDA, |
|||
0xB6, 0x66, 0xB1, 0x64, 0xFE, 0x39, 0xCB, 0x16, 0x2C, 0x15, 0xA8, 0x4F, |
|||
0xA0, 0x42, 0x89, 0x2A, 0xC5, 0x8A, 0x56, 0x2E, 0x5C, 0xB4, 0x66, 0xAB, |
|||
0x52, 0xC5, 0xEA, 0x95, 0x2D, 0x5D, 0xC2, 0xB2, 0xB5, 0x13, 0x38, 0x80, |
|||
0xC0, 0x02, 0x08, 0x14, 0x78, 0xA0, 0x03, 0x10, 0x27, 0x50, 0x70, 0xD1, |
|||
0x04, 0x12, 0x3C, 0xC0, 0xC0, 0x82, 0x0E, 0x3C, 0x20, 0x01, 0x05, 0x17, |
|||
0x70, 0x80, 0x02, 0x11, 0x4D, 0x10, 0xB1, 0x43, 0x0D, 0x31, 0xA0, 0xE0, |
|||
0x81, 0x06, 0x1C, 0x9C, 0x10, 0x84, 0x11, 0x31, 0xA8, 0x10, 0x03, 0x14, |
|||
0x62, 0x8C, 0xA1, 0x85, 0x12, 0x3F, 0xDC, 0x20, 0x03, 0x0D, 0x37, 0xD4, |
|||
0x90, 0x03, 0x14, 0x53, 0xFC, 0x80, 0x03, 0x0D, 0x31, 0xC8, 0x50, 0x03, |
|||
0x0E, 0x40, 0xED, 0xC0, 0x83, 0x0E, 0x3E, 0xED, 0xB0, 0x43, 0x0E, 0x3D, |
|||
0x62, 0x25, 0xC4, 0x10, 0x47, 0x20, 0x31, 0x84, 0x4D, 0x3C, 0xF8, 0xE0, |
|||
0x03, 0x10, 0x4D, 0xAC, 0xF1, 0x46, 0x15, 0x4C, 0x24, 0x81, 0x44, 0x12, |
|||
0x4A, 0x28, 0xC1, 0xC4, 0x58, 0x5E, 0x78, 0xE5, 0x44, 0x47, 0x4F, 0x44, |
|||
0x31, 0x45, 0x15, 0x56, 0x68, 0x51, 0x46, 0x20, 0x7C, 0x7C, 0x51, 0x45, |
|||
0x15, 0x59, 0x8C, 0xE1, 0x47, 0x24, 0x8A, 0xC8, 0x61, 0x06, 0x1A, 0x6E, |
|||
0xD4, 0xF1, 0x47, 0x22, 0x7C, 0xA4, 0x31, 0x86, 0x1A, 0x7A, 0x0C, 0x02, |
|||
0x48, 0x24, 0xA2, 0x84, 0xE2, 0x88, 0x1D, 0x6E, 0xB0, 0xB1, 0x86, 0x1A, |
|||
0x6A, 0xAC, 0x31, 0x68, 0xA1, 0x6D, 0xC8, 0x71, 0x47, 0x1F, 0x88, 0x68, |
|||
0xA2, 0xCA, 0x2A, 0x9B, 0x28, 0x92, 0x48, 0x27, 0xA8, 0x64, 0x72, 0x88, |
|||
0x22, 0xA4, 0xC0, 0x02, 0xCA, 0x24, 0xA7, 0xA4, 0xF2, 0x48, 0x22, 0x8E, |
|||
0x68, 0xA2, 0x89, 0x24, 0x8F, 0x48, 0xD2, 0xC9, 0x2B, 0xBE, 0x10, 0x53, |
|||
0xCC, 0xAA, 0xC4, 0xF4, 0xA6, 0x8C, 0x32, 0xFE, 0xCB, 0x38, 0xC3, 0x0C, |
|||
0x2F, 0xA1, 0x84, 0xE2, 0xCB, 0x70, 0xC3, 0xC8, 0x02, 0xCB, 0x2D, 0xC3, |
|||
0x2C, 0x43, 0x4C, 0x2F, 0xC2, 0x30, 0x13, 0x4D, 0x35, 0xD5, 0x28, 0xF3, |
|||
0x0B, 0x7C, 0xB1, 0xD8, 0x92, 0x0C, 0x36, 0xC8, 0xB0, 0xD2, 0x8A, 0x32, |
|||
0xCE, 0xC8, 0x42, 0xCA, 0x27, 0x9E, 0xA0, 0x17, 0x0A, 0x29, 0xAA, 0x24, |
|||
0x5B, 0x0B, 0x69, 0xF3, 0x3D, 0xEA, 0xCA, 0x2C, 0xB7, 0xF0, 0xB2, 0xCC, |
|||
0x39, 0xFC, 0x0D, 0x50, 0x00, 0x02, 0x0D, 0x68, 0x80, 0x83, 0x0D, 0x1A, |
|||
0x3C, 0x60, 0x51, 0x04, 0x10, 0x34, 0xB0, 0x20, 0x45, 0x16, 0x4D, 0x40, |
|||
0x41, 0x05, 0x20, 0xF8, 0x50, 0xC4, 0x0A, 0x23, 0x94, 0xC0, 0x42, 0x0A, |
|||
0x1E, 0x60, 0xA0, 0x01, 0x09, 0x03, 0xAE, 0x50, 0xC2, 0x0B, 0x50, 0x7C, |
|||
0xC1, 0x45, 0x4C, 0x3F, 0xD0, 0xF0, 0x02, 0x0C, 0x34, 0xB8, 0x98, 0x04, |
|||
0x13, 0x3C, 0xD8, 0x30, 0x83, 0x0C, 0x33, 0xD8, 0xE0, 0x13, 0x50, 0x4A, |
|||
0xFD, 0xA4, 0x83, 0x52, 0x36, 0xD8, 0xA0, 0x03, 0x56, 0x41, 0x00, 0x51, |
|||
0x44, 0x12, 0x45, 0xF8, 0xA0, 0x63, 0x0F, 0x3E, 0x04, 0xE1, 0x04, 0x1B, |
|||
0x6E, 0x48, 0x71, 0x04, 0x11, 0x0A, 0x49, 0xA9, 0x04, 0x14, 0x59, 0x84, |
|||
0xC1, 0x85, 0x14, 0x1E, 0x35, 0xF1, 0xC4, 0xCF, 0x4E, 0x3C, 0x41, 0x85, |
|||
0x18, 0x80, 0xEC, 0xD1, 0x85, 0x14, 0x51, 0x54, 0x01, 0xC6, 0x1E, 0x8C, |
|||
0x00, 0xC2, 0x86, 0x19, 0x6D, 0xE0, 0xA1, 0x07, 0x20, 0x8B, 0xFC, 0x91, |
|||
0x86, 0x18, 0x6A, 0xEC, 0x41, 0xC8, 0x61, 0xA2, 0x78, 0x62, 0x48, 0x1C, |
|||
0x84, 0x0E, 0x9A, 0xC6, 0xD8, 0x68, 0xA0, 0x91, 0x06, 0x1B, 0x71, 0xD0, |
|||
0x41, 0x87, 0x1E, 0x8C, 0x98, 0x82, 0xCA, 0x24, 0x82, 0xCC, 0xF9, 0xC9, |
|||
0x25, 0x83, 0x0C, 0x82, 0x49, 0x2B, 0xA2, 0x4C, 0x52, 0x0A, 0xFE, 0x29, |
|||
0x8A, 0x18, 0xC2, 0x08, 0xA9, 0x92, 0x52, 0x92, 0xCA, 0x2C, 0xB4, 0xC0, |
|||
0xE2, 0xCA, 0x2B, 0xA8, 0xED, 0xB2, 0x0B, 0x2E, 0xB5, 0xEC, 0x72, 0xCC, |
|||
0x32, 0xB7, 0x68, 0xB2, 0x09, 0x2E, 0xC8, 0xFC, 0x02, 0x4B, 0x28, 0x9E, |
|||
0x90, 0xC2, 0x4B, 0x31, 0xB7, 0x24, 0xDB, 0x4B, 0x30, 0xCD, 0x50, 0xC3, |
|||
0xCC, 0x2E, 0xAE, 0xA8, 0x82, 0xCA, 0x2B, 0xC9, 0x58, 0x33, 0x4C, 0x2A, |
|||
0xAA, 0x18, 0x93, 0x0C, 0xDE, 0x9E, 0x54, 0x8B, 0x9E, 0x28, 0xA6, 0xB0, |
|||
0x82, 0xDA, 0x2C, 0xAC, 0xAC, 0xB2, 0x8A, 0xB7, 0xB2, 0x34, 0xEE, 0x4C, |
|||
0x3A, 0xE5, 0x1A, 0xB0, 0x40, 0x05, 0x2B, 0xF8, 0x10, 0x83, 0x05, 0x0E, |
|||
0x40, 0x10, 0x81, 0x04, 0x11, 0x4C, 0xB4, 0x60, 0x45, 0x11, 0x44, 0x4F, |
|||
0xC1, 0x07, 0x3D, 0x00, 0x41, 0x82, 0x06, 0x1E, 0xA4, 0xA0, 0xC2, 0x07, |
|||
0x18, 0x64, 0x10, 0xC2, 0x0C, 0x43, 0xD4, 0x00, 0x03, 0x10, 0x57, 0x64, |
|||
0x81, 0x84, 0x0F, 0x3F, 0xE4, 0x10, 0x62, 0x0A, 0x2E, 0xD0, 0xA0, 0xC3, |
|||
0x11, 0x46, 0xE4, 0x30, 0x43, 0x0D, 0x1A, 0xDB, 0x40, 0x43, 0xC4, 0x36, |
|||
0xD4, 0x10, 0xF1, 0x0D, 0x1F, 0xB7, 0x68, 0xC3, 0x0E, 0x40, 0x98, 0xCA, |
|||
0x0E, 0x7E, 0x10, 0x95, 0xA9, 0x20, 0xE5, 0x07, 0x44, 0x90, 0x82, 0x1B, |
|||
0xE2, 0xA0, 0x05, 0x27, 0x1C, 0xA1, 0x08, 0x47, 0x48, 0x42, 0x13, 0xA6, |
|||
0xB0, 0x85, 0x31, 0x80, 0xE1, 0x0A, 0x4F, 0x60, 0xC2, 0x12, 0x98, 0xE0, |
|||
0x04, 0x28, 0x48, 0x61, 0x0A, 0x54, 0xD0, 0x82, 0x1C, 0x12, 0xD1, 0x07, |
|||
0x2F, 0x50, 0x61, 0x0A, 0x56, 0xF0, 0x82, 0x1B, 0x04, 0x71, 0x08, 0x3F, |
|||
0xD8, 0x41, 0x0F, 0x7E, 0xF0, 0xC3, 0x21, 0x1E, 0xD1, 0x07, 0x34, 0x88, |
|||
0x61, 0x0D, 0x85, 0xA0, 0x04, 0x25, 0x36, 0x21, 0x8A, 0x4D, 0xFC, 0xE1, |
|||
0x69, 0xFE, 0x68, 0x58, 0x83, 0xA0, 0x08, 0xA5, 0x86, 0x34, 0xA8, 0xA1, |
|||
0x0D, 0x71, 0x90, 0x43, 0x1C, 0xEE, 0xE0, 0x88, 0x53, 0x7C, 0x82, 0x10, |
|||
0x78, 0xA8, 0x83, 0x1F, 0x28, 0xD1, 0x89, 0x46, 0x28, 0xC2, 0x12, 0xBB, |
|||
0xF3, 0xC4, 0xEE, 0x2C, 0x81, 0x89, 0x51, 0x78, 0xE2, 0x11, 0x8A, 0x68, |
|||
0xC4, 0x28, 0x68, 0xA1, 0x0A, 0x4B, 0x40, 0xC2, 0x11, 0x8F, 0x98, 0x44, |
|||
0x26, 0x3E, 0xD1, 0x89, 0x4C, 0x24, 0x66, 0x17, 0xCA, 0xA0, 0x55, 0x28, |
|||
0x78, 0xD1, 0x0B, 0x52, 0x70, 0x02, 0x13, 0x95, 0xE0, 0x04, 0x2C, 0x80, |
|||
0xA1, 0x0B, 0x5A, 0xCC, 0x22, 0x16, 0xB3, 0x38, 0x46, 0x34, 0x8C, 0x71, |
|||
0x0B, 0xC3, 0xBD, 0xA2, 0x17, 0xD1, 0x88, 0x86, 0x2D, 0x4A, 0xD1, 0xBA, |
|||
0x66, 0x61, 0x4E, 0x76, 0xA0, 0x10, 0x05, 0x29, 0x52, 0x11, 0x8B, 0xF7, |
|||
0xC0, 0x22, 0x77, 0xBA, 0x6B, 0x05, 0x2C, 0x6A, 0xE1, 0x8B, 0x6C, 0xBC, |
|||
0x83, 0x3F, 0x05, 0x68, 0xC0, 0x05, 0x54, 0xC0, 0x32, 0x14, 0x54, 0x40, |
|||
0x79, 0x12, 0xB0, 0x57, 0xBC, 0x18, 0xA4, 0x3C, 0xE5, 0x55, 0x60, 0x04, |
|||
0x25, 0x23, 0x41, 0x06, 0x24, 0xA4, 0x82, 0x10, 0x68, 0x00, 0x7B, 0x2C, |
|||
0x18, 0x42, 0x07, 0xC3, 0x14, 0x85, 0x1B, 0xB4, 0xC0, 0x05, 0x30, 0x80, |
|||
0xC1, 0x0A, 0x4C, 0x80, 0x82, 0x17, 0xE4, 0x40, 0x09, 0x47, 0xB0, 0x01, |
|||
0x0C, 0x62, 0x40, 0x83, 0x8B, 0x2D, 0xB3, 0x99, 0x31, 0xA8, 0x91, 0x8B, |
|||
0x78, 0x54, 0x83, 0x1B, 0x54, 0xCF, 0x07, 0x40, 0xEA, 0x81, 0x11, 0xA4, |
|||
0x42, 0x15, 0xAB, 0x14, 0x81, 0x0A, 0x6D, 0x70, 0x43, 0x18, 0xAC, 0xD0, |
|||
0x04, 0xF8, 0x29, 0x41, 0x0A, 0x5B, 0x00, 0x43, 0x17, 0xAE, 0x00, 0x85, |
|||
0x25, 0x54, 0x69, 0x09, 0x4E, 0x98, 0x42, 0x16, 0xBA, 0xF0, 0x05, 0x33, |
|||
0x08, 0xC2, 0x11, 0x7C, 0xFE, 0x10, 0x83, 0x16, 0xB2, 0x90, 0x4E, 0x33, |
|||
0x8C, 0xD0, 0x11, 0x82, 0xA8, 0x43, 0x1C, 0xF2, 0xB0, 0x08, 0x46, 0xC8, |
|||
0x81, 0x0C, 0x60, 0x58, 0x83, 0x22, 0x30, 0x71, 0x46, 0x4B, 0x58, 0x82, |
|||
0x0F, 0x6B, 0x70, 0x49, 0x10, 0xD9, 0x20, 0x28, 0x43, 0xF9, 0x05, 0x0E, |
|||
0x72, 0x98, 0xC3, 0x1E, 0x2E, 0x51, 0x8A, 0x48, 0xF0, 0x61, 0x0E, 0x4B, |
|||
0x34, 0x04, 0x27, 0x46, 0xF1, 0x89, 0x4F, 0x7C, 0x6B, 0x93, 0xB3, 0xF8, |
|||
0x96, 0x2D, 0x56, 0x31, 0x89, 0x46, 0x4C, 0xA2, 0x15, 0xAE, 0x98, 0x04, |
|||
0x22, 0x06, 0x21, 0x88, 0xD0, 0x80, 0x2A, 0x12, 0x8F, 0x60, 0x04, 0x25, |
|||
0x68, 0xA1, 0x0C, 0xEC, 0xF4, 0x82, 0x73, 0x9C, 0xB0, 0x44, 0x25, 0x76, |
|||
0xC8, 0x0A, 0x5E, 0xE4, 0x82, 0x16, 0xB2, 0x70, 0x45, 0x2C, 0x8A, 0xB1, |
|||
0x0C, 0x5C, 0xB8, 0x02, 0xA6, 0xB6, 0x58, 0xC6, 0x34, 0x84, 0xC1, 0x8A, |
|||
0x51, 0xB4, 0xEE, 0x75, 0x5D, 0x83, 0xA4, 0x24, 0x4F, 0x87, 0x0B, 0x5E, |
|||
0xD4, 0xA2, 0x15, 0x8F, 0xA2, 0xCD, 0xAE, 0x86, 0x21, 0x0E, 0x79, 0x08, |
|||
0xC4, 0x3F, 0x1B, 0x98, 0x01, 0x10, 0x82, 0x10, 0x03, 0x0E, 0x4C, 0x20, |
|||
0x7A, 0x12, 0x70, 0x08, 0x05, 0x26, 0x52, 0x11, 0x08, 0xD8, 0x75, 0x7A, |
|||
0x33, 0x50, 0x42, 0x10, 0x4A, 0xC0, 0x01, 0x0F, 0x9C, 0xC0, 0x60, 0x1E, |
|||
0xE8, 0xEB, 0x09, 0x72, 0x40, 0x85, 0x2F, 0x68, 0x41, 0x0A, 0x4B, 0xB0, |
|||
0x41, 0x0A, 0x4E, 0xC0, 0x02, 0x18, 0xB8, 0xE0, 0x04, 0x26, 0x58, 0xC1, |
|||
0x0D, 0x3C, 0x62, 0x83, 0x16, 0xB0, 0xE0, 0x97, 0x2E, 0x78, 0x41, 0x0C, |
|||
0x9C, 0xF9, 0x4C, 0x1C, 0x80, 0x0C, 0x07, 0xE8, 0xDB, 0xC1, 0x4F, 0x7C, |
|||
0x60, 0x04, 0x23, 0xFC, 0x60, 0x65, 0xFA, 0xAA, 0xC2, 0x1A, 0xC6, 0x70, |
|||
0x05, 0x2C, 0xC4, 0xE4, 0x08, 0x4B, 0xA0, 0xFE, 0x42, 0x16, 0xAE, 0x30, |
|||
0x05, 0xB0, 0x28, 0x81, 0x4A, 0xF0, 0xB4, 0xC2, 0x17, 0xC8, 0xA0, 0x06, |
|||
0x3C, 0x28, 0x82, 0x11, 0x79, 0x28, 0x43, 0x18, 0x4A, 0x24, 0x06, 0x30, |
|||
0xA0, 0x81, 0x10, 0x8C, 0xB8, 0xC3, 0xA0, 0xEE, 0xD0, 0x88, 0x43, 0xAC, |
|||
0xE1, 0x0B, 0x5F, 0x58, 0x03, 0x22, 0x1E, 0x61, 0x07, 0x39, 0xAC, 0xC9, |
|||
0x10, 0x6F, 0x28, 0x03, 0x19, 0xCC, 0x90, 0x06, 0x21, 0x52, 0x94, 0xA2, |
|||
0x6D, 0x78, 0x43, 0xDA, 0xFC, 0xB0, 0x89, 0x50, 0x18, 0x42, 0x0F, 0x20, |
|||
0xA5, 0x83, 0x1F, 0x1E, 0xC1, 0xC8, 0x55, 0x24, 0xEB, 0x3D, 0xB4, 0xC0, |
|||
0xC5, 0x2E, 0x74, 0x01, 0x0B, 0x4F, 0x68, 0xC2, 0x14, 0xB4, 0x30, 0x05, |
|||
< |