parent
4bb9c4a42e
commit
b4bf6a8d3a
@ -0,0 +1,203 @@ |
||||
Apache License |
||||
Version 2.0, January 2004 |
||||
http://www.apache.org/licenses/ |
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION |
||||
|
||||
1. Definitions. |
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction, |
||||
and distribution as defined by Sections 1 through 9 of this document. |
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by |
||||
the copyright owner that is granting the License. |
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all |
||||
other entities that control, are controlled by, or are under common |
||||
control with that entity. For the purposes of this definition, |
||||
"control" means (i) the power, direct or indirect, to cause the |
||||
direction or management of such entity, whether by contract or |
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the |
||||
outstanding shares, or (iii) beneficial ownership of such entity. |
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity |
||||
exercising permissions granted by this License. |
||||
|
||||
"Source" form shall mean the preferred form for making modifications, |
||||
including but not limited to software source code, documentation |
||||
source, and configuration files. |
||||
|
||||
"Object" form shall mean any form resulting from mechanical |
||||
transformation or translation of a Source form, including but |
||||
not limited to compiled object code, generated documentation, |
||||
and conversions to other media types. |
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or |
||||
Object form, made available under the License, as indicated by a |
||||
copyright notice that is included in or attached to the work |
||||
(an example is provided in the Appendix below). |
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object |
||||
form, that is based on (or derived from) the Work and for which the |
||||
editorial revisions, annotations, elaborations, or other modifications |
||||
represent, as a whole, an original work of authorship. For the purposes |
||||
of this License, Derivative Works shall not include works that remain |
||||
separable from, or merely link (or bind by name) to the interfaces of, |
||||
the Work and Derivative Works thereof. |
||||
|
||||
"Contribution" shall mean any work of authorship, including |
||||
the original version of the Work and any modifications or additions |
||||
to that Work or Derivative Works thereof, that is intentionally |
||||
submitted to Licensor for inclusion in the Work by the copyright owner |
||||
or by an individual or Legal Entity authorized to submit on behalf of |
||||
the copyright owner. For the purposes of this definition, "submitted" |
||||
means any form of electronic, verbal, or written communication sent |
||||
to the Licensor or its representatives, including but not limited to |
||||
communication on electronic mailing lists, source code control systems, |
||||
and issue tracking systems that are managed by, or on behalf of, the |
||||
Licensor for the purpose of discussing and improving the Work, but |
||||
excluding communication that is conspicuously marked or otherwise |
||||
designated in writing by the copyright owner as "Not a Contribution." |
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity |
||||
on behalf of whom a Contribution has been received by Licensor and |
||||
subsequently incorporated within the Work. |
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of |
||||
this License, each Contributor hereby grants to You a perpetual, |
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable |
||||
copyright license to reproduce, prepare Derivative Works of, |
||||
publicly display, publicly perform, sublicense, and distribute the |
||||
Work and such Derivative Works in Source or Object form. |
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of |
||||
this License, each Contributor hereby grants to You a perpetual, |
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable |
||||
(except as stated in this section) patent license to make, have made, |
||||
use, offer to sell, sell, import, and otherwise transfer the Work, |
||||
where such license applies only to those patent claims licensable |
||||
by such Contributor that are necessarily infringed by their |
||||
Contribution(s) alone or by combination of their Contribution(s) |
||||
with the Work to which such Contribution(s) was submitted. If You |
||||
institute patent litigation against any entity (including a |
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work |
||||
or a Contribution incorporated within the Work constitutes direct |
||||
or contributory patent infringement, then any patent licenses |
||||
granted to You under this License for that Work shall terminate |
||||
as of the date such litigation is filed. |
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the |
||||
Work or Derivative Works thereof in any medium, with or without |
||||
modifications, and in Source or Object form, provided that You |
||||
meet the following conditions: |
||||
|
||||
(a) You must give any other recipients of the Work or |
||||
Derivative Works a copy of this License; and |
||||
|
||||
(b) You must cause any modified files to carry prominent notices |
||||
stating that You changed the files; and |
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works |
||||
that You distribute, all copyright, patent, trademark, and |
||||
attribution notices from the Source form of the Work, |
||||
excluding those notices that do not pertain to any part of |
||||
the Derivative Works; and |
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its |
||||
distribution, then any Derivative Works that You distribute must |
||||
include a readable copy of the attribution notices contained |
||||
within such NOTICE file, excluding those notices that do not |
||||
pertain to any part of the Derivative Works, in at least one |
||||
of the following places: within a NOTICE text file distributed |
||||
as part of the Derivative Works; within the Source form or |
||||
documentation, if provided along with the Derivative Works; or, |
||||
within a display generated by the Derivative Works, if and |
||||
wherever such third-party notices normally appear. The contents |
||||
of the NOTICE file are for informational purposes only and |
||||
do not modify the License. You may add Your own attribution |
||||
notices within Derivative Works that You distribute, alongside |
||||
or as an addendum to the NOTICE text from the Work, provided |
||||
that such additional attribution notices cannot be construed |
||||
as modifying the License. |
||||
|
||||
You may add Your own copyright statement to Your modifications and |
||||
may provide additional or different license terms and conditions |
||||
for use, reproduction, or distribution of Your modifications, or |
||||
for any such Derivative Works as a whole, provided Your use, |
||||
reproduction, and distribution of the Work otherwise complies with |
||||
the conditions stated in this License. |
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise, |
||||
any Contribution intentionally submitted for inclusion in the Work |
||||
by You to the Licensor shall be under the terms and conditions of |
||||
this License, without any additional terms or conditions. |
||||
Notwithstanding the above, nothing herein shall supersede or modify |
||||
the terms of any separate license agreement you may have executed |
||||
with Licensor regarding such Contributions. |
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade |
||||
names, trademarks, service marks, or product names of the Licensor, |
||||
except as required for reasonable and customary use in describing the |
||||
origin of the Work and reproducing the content of the NOTICE file. |
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or |
||||
agreed to in writing, Licensor provides the Work (and each |
||||
Contributor provides its Contributions) on an "AS IS" BASIS, |
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or |
||||
implied, including, without limitation, any warranties or conditions |
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A |
||||
PARTICULAR PURPOSE. You are solely responsible for determining the |
||||
appropriateness of using or redistributing the Work and assume any |
||||
risks associated with Your exercise of permissions under this License. |
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory, |
||||
whether in tort (including negligence), contract, or otherwise, |
||||
unless required by applicable law (such as deliberate and grossly |
||||
negligent acts) or agreed to in writing, shall any Contributor be |
||||
liable to You for damages, including any direct, indirect, special, |
||||
incidental, or consequential damages of any character arising as a |
||||
result of this License or out of the use or inability to use the |
||||
Work (including but not limited to damages for loss of goodwill, |
||||
work stoppage, computer failure or malfunction, or any and all |
||||
other commercial damages or losses), even if such Contributor |
||||
has been advised of the possibility of such damages. |
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing |
||||
the Work or Derivative Works thereof, You may choose to offer, |
||||
and charge a fee for, acceptance of support, warranty, indemnity, |
||||
or other liability obligations and/or rights consistent with this |
||||
License. However, in accepting such obligations, You may act only |
||||
on Your own behalf and on Your sole responsibility, not on behalf |
||||
of any other Contributor, and only if You agree to indemnify, |
||||
defend, and hold each Contributor harmless for any liability |
||||
incurred by, or claims asserted against, such Contributor by reason |
||||
of your accepting any such warranty or additional liability. |
||||
|
||||
END OF TERMS AND CONDITIONS |
||||
|
||||
APPENDIX: How to apply the Apache License to your work. |
||||
|
||||
To apply the Apache License to your work, attach the following |
||||
boilerplate notice, with the fields enclosed by brackets "[]" |
||||
replaced with your own identifying information. (Don't include |
||||
the brackets!) The text should be enclosed in the appropriate |
||||
comment syntax for the file format. We also recommend that a |
||||
file or class name and description of purpose be included on the |
||||
same "printed page" as the copyright notice for easier |
||||
identification within third-party archives. |
||||
|
||||
Copyright [yyyy] [name of copyright owner] |
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); |
||||
you may not use this file except in compliance with the License. |
||||
You may obtain a copy of the License at |
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0 |
||||
|
||||
Unless required by applicable law or agreed to in writing, software |
||||
distributed under the License is distributed on an "AS IS" BASIS, |
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
See the License for the specific language governing permissions and |
||||
limitations under the License. |
||||
|
||||
|
@ -0,0 +1,4 @@ |
||||
This product contains the following libraries: |
||||
|
||||
XRDS-Simple library from http://code.google.com/p/diso/ |
||||
Apache License 2.0 |
@ -0,0 +1,40 @@ |
||||
Google APIs Client Library for PHP |
||||
===================================== |
||||
|
||||
== Description |
||||
The Google API Client Library enables you to work with Google APIs such as Google+, Drive, Tasks, or Latitude on your server. |
||||
|
||||
Requirements: |
||||
PHP 5.2.x or higher [http://www.php.net/] |
||||
PHP Curl extension [http://www.php.net/manual/en/intro.curl.php] |
||||
PHP JSON extension [http://php.net/manual/en/book.json.php] |
||||
|
||||
Project page: |
||||
http://code.google.com/p/google-api-php-client |
||||
|
||||
OAuth 2 instructions: |
||||
http://code.google.com/p/google-api-php-client/wiki/OAuth2 |
||||
|
||||
Report a defect or feature request here: |
||||
http://code.google.com/p/google-api-php-client/issues/entry |
||||
|
||||
Subscribe to project updates in your feed reader: |
||||
http://code.google.com/feeds/p/google-api-php-client/updates/basic |
||||
|
||||
Supported sample applications: |
||||
http://code.google.com/p/google-api-php-client/wiki/Samples |
||||
|
||||
== Basic Example |
||||
<?php |
||||
require_once 'path/to/src/Google_Client.php'; |
||||
require_once 'path/to/src/contrib/apiBooksService.php'; |
||||
|
||||
$client = new Google_Client(); |
||||
$service = new Google_BooksService($client); |
||||
|
||||
$optParams = array('filter' => 'free-ebooks'); |
||||
$results = $service->volumes->listVolumes('Henry David Thoreau', $optParams); |
||||
|
||||
foreach ($results['items'] as $item) { |
||||
print($item['volumeInfo']['title'] . '<br>'); |
||||
} |
@ -0,0 +1,462 @@ |
||||
<?php |
||||
/* |
||||
* Copyright 2010 Google Inc. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0 |
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
// Check for the required json and curl extensions, the Google APIs PHP Client |
||||
// won't function without them. |
||||
if (! function_exists('curl_init')) { |
||||
throw new Exception('Google PHP API Client requires the CURL PHP extension'); |
||||
} |
||||
|
||||
if (! function_exists('json_decode')) { |
||||
throw new Exception('Google PHP API Client requires the JSON PHP extension'); |
||||
} |
||||
|
||||
if (! function_exists('http_build_query')) { |
||||
throw new Exception('Google PHP API Client requires http_build_query()'); |
||||
} |
||||
|
||||
if (! ini_get('date.timezone') && function_exists('date_default_timezone_set')) { |
||||
date_default_timezone_set('UTC'); |
||||
} |
||||
|
||||
// hack around with the include paths a bit so the library 'just works' |
||||
set_include_path(dirname(__FILE__) . PATH_SEPARATOR . get_include_path()); |
||||
|
||||
require_once "config.php"; |
||||
// If a local configuration file is found, merge it's values with the default configuration |
||||
if (file_exists(dirname(__FILE__) . '/local_config.php')) { |
||||
$defaultConfig = $apiConfig; |
||||
require_once (dirname(__FILE__) . '/local_config.php'); |
||||
$apiConfig = array_merge($defaultConfig, $apiConfig); |
||||
} |
||||
|
||||
// Include the top level classes, they each include their own dependencies |
||||
require_once 'service/Google_Model.php'; |
||||
require_once 'service/Google_Service.php'; |
||||
require_once 'service/Google_ServiceResource.php'; |
||||
require_once 'auth/Google_AssertionCredentials.php'; |
||||
require_once 'auth/Google_Signer.php'; |
||||
require_once 'auth/Google_P12Signer.php'; |
||||
require_once 'service/Google_BatchRequest.php'; |
||||
require_once 'external/URITemplateParser.php'; |
||||
require_once 'auth/Google_Auth.php'; |
||||
require_once 'cache/Google_Cache.php'; |
||||
require_once 'io/Google_IO.php'; |
||||
require_once('service/Google_MediaFileUpload.php'); |
||||
|
||||
/** |
||||
* The Google API Client |
||||
* http://code.google.com/p/google-api-php-client/ |
||||
* |
||||
* @author Chris Chabot <chabotc@google.com> |
||||
* @author Chirag Shah <chirags@google.com> |
||||
*/ |
||||
class Google_Client { |
||||
/** |
||||
* @static |
||||
* @var Google_Auth $auth |
||||
*/ |
||||
static $auth; |
||||
|
||||
/** |
||||
* @static |
||||
* @var Google_IO $io |
||||
*/ |
||||
static $io; |
||||
|
||||
/** |
||||
* @static |
||||
* @var Google_Cache $cache |
||||
*/ |
||||
static $cache; |
||||
|
||||
/** |
||||
* @static |
||||
* @var boolean $useBatch |
||||
*/ |
||||
static $useBatch = false; |
||||
|
||||
/** @var array $scopes */ |
||||
protected $scopes = array(); |
||||
|
||||
/** @var bool $useObjects */ |
||||
protected $useObjects = false; |
||||
|
||||
// definitions of services that are discovered. |
||||
protected $services = array(); |
||||
|
||||
// Used to track authenticated state, can't discover services after doing authenticate() |
||||
private $authenticated = false; |
||||
|
||||
public function __construct($config = array()) { |
||||
global $apiConfig; |
||||
$apiConfig = array_merge($apiConfig, $config); |
||||
self::$cache = new $apiConfig['cacheClass'](); |
||||
self::$auth = new $apiConfig['authClass'](); |
||||
self::$io = new $apiConfig['ioClass'](); |
||||
} |
||||
|
||||
/** |
||||
* Add a service |
||||
*/ |
||||
public function addService($service, $version = false) { |
||||
global $apiConfig; |
||||
if ($this->authenticated) { |
||||
throw new Google_Exception('Cant add services after having authenticated'); |
||||
} |
||||
$this->services[$service] = array(); |
||||
if (isset($apiConfig['services'][$service])) { |
||||
// Merge the service descriptor with the default values |
||||
$this->services[$service] = array_merge($this->services[$service], $apiConfig['services'][$service]); |
||||
} |
||||
} |
||||
|
||||
public function authenticate($code = null) { |
||||
$service = $this->prepareService(); |
||||
$this->authenticated = true; |
||||
return self::$auth->authenticate($service, $code); |
||||
} |
||||
|
||||
/** |
||||
* @return array |
||||
* @visible For Testing |
||||
*/ |
||||
public function prepareService() { |
||||
$service = array(); |
||||
$scopes = array(); |
||||
if ($this->scopes) { |
||||
$scopes = $this->scopes; |
||||
} else { |
||||
foreach ($this->services as $key => $val) { |
||||
if (isset($val['scope'])) { |
||||
if (is_array($val['scope'])) { |
||||
$scopes = array_merge($val['scope'], $scopes); |
||||
} else { |
||||
$scopes[] = $val['scope']; |
||||
} |
||||
} else { |
||||
$scopes[] = 'https://www.googleapis.com/auth/' . $key; |
||||
} |
||||
unset($val['discoveryURI']); |
||||
unset($val['scope']); |
||||
$service = array_merge($service, $val); |
||||
} |
||||
} |
||||
$service['scope'] = implode(' ', $scopes); |
||||
return $service; |
||||
} |
||||
|
||||
/** |
||||
* Set the OAuth 2.0 access token using the string that resulted from calling authenticate() |
||||
* or Google_Client#getAccessToken(). |
||||
* @param string $accessToken JSON encoded string containing in the following format: |
||||
* {"access_token":"TOKEN", "refresh_token":"TOKEN", "token_type":"Bearer", |
||||
* "expires_in":3600, "id_token":"TOKEN", "created":1320790426} |
||||
*/ |
||||
public function setAccessToken($accessToken) { |
||||
if ($accessToken == null || 'null' == $accessToken) { |
||||
$accessToken = null; |
||||
} |
||||
self::$auth->setAccessToken($accessToken); |
||||
} |
||||
|
||||
/** |
||||
* Set the type of Auth class the client should use. |
||||
* @param string $authClassName |
||||
*/ |
||||
public function setAuthClass($authClassName) { |
||||
self::$auth = new $authClassName(); |
||||
} |
||||
|
||||
/** |
||||
* Construct the OAuth 2.0 authorization request URI. |
||||
* @return string |
||||
*/ |
||||
public function createAuthUrl() { |
||||
$service = $this->prepareService(); |
||||
return self::$auth->createAuthUrl($service['scope']); |
||||
} |
||||
|
||||
/** |
||||
* Get the OAuth 2.0 access token. |
||||
* @return string $accessToken JSON encoded string in the following format: |
||||
* {"access_token":"TOKEN", "refresh_token":"TOKEN", "token_type":"Bearer", |
||||
* "expires_in":3600,"id_token":"TOKEN", "created":1320790426} |
||||
*/ |
||||
public function getAccessToken() { |
||||
$token = self::$auth->getAccessToken(); |
||||
return (null == $token || 'null' == $token) ? null : $token; |
||||
} |
||||
|
||||
/** |
||||
* Returns if the access_token is expired. |
||||
* @return bool Returns True if the access_token is expired. |
||||
*/ |
||||
public function isAccessTokenExpired() { |
||||
return self::$auth->isAccessTokenExpired(); |
||||
} |
||||
|
||||
/** |
||||
* Set the developer key to use, these are obtained through the API Console. |
||||
* @see http://code.google.com/apis/console-help/#generatingdevkeys |
||||
* @param string $developerKey |
||||
*/ |
||||
public function setDeveloperKey($developerKey) { |
||||
self::$auth->setDeveloperKey($developerKey); |
||||
} |
||||
|
||||
/** |
||||
* Set OAuth 2.0 "state" parameter to achieve per-request customization. |
||||
* @see http://tools.ietf.org/html/draft-ietf-oauth-v2-22#section-3.1.2.2 |
||||
* @param string $state |
||||
*/ |
||||
public function setState($state) { |
||||
self::$auth->setState($state); |
||||
} |
||||
|
||||
/** |
||||
* @param string $accessType Possible values for access_type include: |
||||
* {@code "offline"} to request offline access from the user. (This is the default value) |
||||
* {@code "online"} to request online access from the user. |
||||
*/ |
||||
public function setAccessType($accessType) { |
||||
self::$auth->setAccessType($accessType); |
||||
} |
||||
|
||||
/** |
||||
* @param string $approvalPrompt Possible values for approval_prompt include: |
||||
* {@code "force"} to force the approval UI to appear. (This is the default value) |
||||
* {@code "auto"} to request auto-approval when possible. |
||||
*/ |
||||
public function setApprovalPrompt($approvalPrompt) { |
||||
self::$auth->setApprovalPrompt($approvalPrompt); |
||||
} |
||||
|
||||
/** |
||||
* Set the application name, this is included in the User-Agent HTTP header. |
||||
* @param string $applicationName |
||||
*/ |
||||
public function setApplicationName($applicationName) { |
||||
global $apiConfig; |
||||
$apiConfig['application_name'] = $applicationName; |
||||
} |
||||
|
||||
/** |
||||
* Set the OAuth 2.0 Client ID. |
||||
* @param string $clientId |
||||
*/ |
||||
public function setClientId($clientId) { |
||||
global $apiConfig; |
||||
$apiConfig['oauth2_client_id'] = $clientId; |
||||
self::$auth->clientId = $clientId; |
||||
} |
||||
|
||||
/** |
||||
* Get the OAuth 2.0 Client ID. |
||||
*/ |
||||
public function getClientId() { |
||||
return self::$auth->clientId; |
||||
} |
||||
|
||||
/** |
||||
* Set the OAuth 2.0 Client Secret. |
||||
* @param string $clientSecret |
||||
*/ |
||||
public function setClientSecret($clientSecret) { |
||||
global $apiConfig; |
||||
$apiConfig['oauth2_client_secret'] = $clientSecret; |
||||
self::$auth->clientSecret = $clientSecret; |
||||
} |
||||
|
||||
/** |
||||
* Get the OAuth 2.0 Client Secret. |
||||
*/ |
||||
public function getClientSecret() { |
||||
return self::$auth->clientSecret; |
||||
} |
||||
|
||||
/** |
||||
* Set the OAuth 2.0 Redirect URI. |
||||
* @param string $redirectUri |
||||
*/ |
||||
public function setRedirectUri($redirectUri) { |
||||
global $apiConfig; |
||||
$apiConfig['oauth2_redirect_uri'] = $redirectUri; |
||||
self::$auth->redirectUri = $redirectUri; |
||||
} |
||||
|
||||
/** |
||||
* Get the OAuth 2.0 Redirect URI. |
||||
*/ |
||||
public function getRedirectUri() { |
||||
return self::$auth->redirectUri; |
||||
} |
||||
|
||||
/** |
||||
* Fetches a fresh OAuth 2.0 access token with the given refresh token. |
||||
* @param string $refreshToken |
||||
* @return void |
||||
*/ |
||||
public function refreshToken($refreshToken) { |
||||
self::$auth->refreshToken($refreshToken); |
||||
} |
||||
|
||||
/** |
||||
* Revoke an OAuth2 access token or refresh token. This method will revoke the current access |
||||
* token, if a token isn't provided. |
||||
* @throws Google_AuthException |
||||
* @param string|null $token The token (access token or a refresh token) that should be revoked. |
||||
* @return boolean Returns True if the revocation was successful, otherwise False. |
||||
*/ |
||||
public function revokeToken($token = null) { |
||||
self::$auth->revokeToken($token); |
||||
} |
||||
|
||||
/** |
||||
* Verify an id_token. This method will verify the current id_token, if one |
||||
* isn't provided. |
||||
* @throws Google_AuthException |
||||
* @param string|null $token The token (id_token) that should be verified. |
||||
* @return Google_LoginTicket Returns an apiLoginTicket if the verification was |
||||
* successful. |
||||
*/ |
||||
public function verifyIdToken($token = null) { |
||||
return self::$auth->verifyIdToken($token); |
||||
} |
||||
|
||||
/** |
||||
* @param Google_AssertionCredentials $creds |
||||
* @return void |
||||
*/ |
||||
public function setAssertionCredentials(Google_AssertionCredentials $creds) { |
||||
self::$auth->setAssertionCredentials($creds); |
||||
} |
||||
|
||||
/** |
||||
* This function allows you to overrule the automatically generated scopes, |
||||
* so that you can ask for more or less permission in the auth flow |
||||
* Set this before you call authenticate() though! |
||||
* @param array $scopes, ie: array('https://www.googleapis.com/auth/plus.me', 'https://www.googleapis.com/auth/moderator') |
||||
*/ |
||||
public function setScopes($scopes) { |
||||
$this->scopes = is_string($scopes) ? explode(" ", $scopes) : $scopes; |
||||
} |
||||
|
||||
/** |
||||
* Returns the list of scopes set on the client |
||||
* @return array the list of scopes |
||||
* |
||||
*/ |
||||
public function getScopes() { |
||||
return $this->scopes; |
||||
} |
||||
|
||||
/** |
||||
* Declare if objects should be returned by the api service classes. |
||||
* |
||||
* @param boolean $useObjects True if objects should be returned by the service classes. |
||||
* False if associative arrays should be returned (default behavior). |
||||
* @experimental |
||||
*/ |
||||
public function setUseObjects($useObjects) { |
||||
global $apiConfig; |
||||
$apiConfig['use_objects'] = $useObjects; |
||||
} |
||||
|
||||
/** |
||||
* Declare if objects should be returned by the api service classes. |
||||
* |
||||
* @param boolean $useBatch True if the experimental batch support should |
||||
* be enabled. Defaults to False. |
||||
* @experimental |
||||
*/ |
||||
public function setUseBatch($useBatch) { |
||||
self::$useBatch = $useBatch; |
||||
} |
||||
|
||||
/** |
||||
* @static |
||||
* @return Google_Auth the implementation of apiAuth. |
||||
*/ |
||||
public static function getAuth() { |
||||
return Google_Client::$auth; |
||||
} |
||||
|
||||
/** |
||||
* @static |
||||
* @return Google_IO the implementation of apiIo. |
||||
*/ |
||||
public static function getIo() { |
||||
return Google_Client::$io; |
||||
} |
||||
|
||||
/** |
||||
* @return Google_Cache the implementation of apiCache. |
||||
*/ |
||||
public function getCache() { |
||||
return Google_Client::$cache; |
||||
} |
||||
} |
||||
|
||||
// Exceptions that the Google PHP API Library can throw |
||||
class Google_Exception extends Exception {} |
||||
class Google_AuthException extends Google_Exception {} |
||||
class Google_CacheException extends Google_Exception {} |
||||
class Google_IOException extends Google_Exception {} |
||||
class Google_ServiceException extends Google_Exception { |
||||
/** |
||||
* Optional list of errors returned in a JSON body of an HTTP error response. |
||||
*/ |
||||
protected $errors = array(); |
||||
|
||||
/** |
||||
* Override default constructor to add ability to set $errors. |
||||
* |
||||
* @param string $message |
||||
* @param int $code |
||||
* @param Exception|null $previous |
||||
* @param [{string, string}] errors List of errors returned in an HTTP |
||||
* response. Defaults to []. |
||||
*/ |
||||
public function __construct($message, $code = 0, Exception $previous = null, |
||||
$errors = array()) { |
||||
if(version_compare(PHP_VERSION, '5.3.0') >= 0) { |
||||
parent::__construct($message, $code, $previous); |
||||
} else { |
||||
parent::__construct($message, $code); |
||||
} |
||||
|
||||
$this->errors = $errors; |
||||
} |
||||
|
||||
/** |
||||
* An example of the possible errors returned. |
||||
* |
||||
* { |
||||
* "domain": "global", |
||||
* "reason": "authError", |
||||
* "message": "Invalid Credentials", |
||||
* "locationType": "header", |
||||
* "location": "Authorization", |
||||
* } |
||||
* |
||||
* @return [{string, string}] List of errors return in an HTTP response or []. |
||||
*/ |
||||
public function getErrors() { |
||||
return $this->errors; |
||||
} |
||||
} |
@ -0,0 +1,104 @@ |
||||
<?php |
||||
/* |
||||
* Copyright 2012 Google Inc. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0 |
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
/** |
||||
* Credentials object used for OAuth 2.0 Signed JWT assertion grants. |
||||
* |
||||
* @author Chirag Shah <chirags@google.com> |
||||
*/ |
||||
class Google_AssertionCredentials { |
||||
const MAX_TOKEN_LIFETIME_SECS = 3600; |
||||
|
||||
public $serviceAccountName; |
||||
public $scopes; |
||||
public $privateKey; |
||||
public $privateKeyPassword; |
||||
public $assertionType; |
||||
public $sub; |
||||
/** |
||||
* @deprecated |
||||
* @link http://tools.ietf.org/html/draft-ietf-oauth-json-web-token-06 |
||||
*/ |
||||
public $prn; |
||||
|
||||
/** |
||||
* @param $serviceAccountName |
||||
* @param $scopes array List of scopes |
||||
* @param $privateKey |
||||
* @param string $privateKeyPassword |
||||
* @param string $assertionType |
||||
* @param bool|string $sub The email address of the user for which the |
||||
* application is requesting delegated access. |
||||
* |
||||
*/ |
||||
public function __construct( |
||||
$serviceAccountName, |
||||
$scopes, |
||||
$privateKey, |
||||
$privateKeyPassword = 'notasecret', |
||||
$assertionType = 'http://oauth.net/grant_type/jwt/1.0/bearer', |
||||
$sub = false) { |
||||
$this->serviceAccountName = $serviceAccountName; |
||||
$this->scopes = is_string($scopes) ? $scopes : implode(' ', $scopes); |
||||
$this->privateKey = $privateKey; |
||||
$this->privateKeyPassword = $privateKeyPassword; |
||||
$this->assertionType = $assertionType; |
||||
$this->sub = $sub; |
||||
$this->prn = $sub; |
||||
} |
||||
|
||||
public function generateAssertion() { |
||||
$now = time(); |
||||
|
||||
$jwtParams = array( |
||||
'aud' => Google_OAuth2::OAUTH2_TOKEN_URI, |
||||
'scope' => $this->scopes, |
||||
'iat' => $now, |
||||
'exp' => $now + self::MAX_TOKEN_LIFETIME_SECS, |
||||
'iss' => $this->serviceAccountName, |
||||
); |
||||
|
||||
if ($this->sub !== false) { |
||||
$jwtParams['sub'] = $this->sub; |
||||
} else if ($this->prn !== false) { |
||||
$jwtParams['prn'] = $this->prn; |
||||
} |
||||
|
||||
return $this->makeSignedJwt($jwtParams); |
||||
} |
||||
|
||||
/** |
||||
* Creates a signed JWT. |
||||
* @param array $payload |
||||
* @return string The signed JWT. |
||||
*/ |
||||
private function makeSignedJwt($payload) { |
||||
$header = array('typ' => 'JWT', 'alg' => 'RS256'); |
||||
|
||||
$segments = array( |
||||
Google_Utils::urlSafeB64Encode(json_encode($header)), |
||||
Google_Utils::urlSafeB64Encode(json_encode($payload)) |
||||
); |
||||
|
||||
$signingInput = implode('.', $segments); |
||||
$signer = new Google_P12Signer($this->privateKey, $this->privateKeyPassword); |
||||
$signature = $signer->sign($signingInput); |
||||
$segments[] = Google_Utils::urlSafeB64Encode($signature); |
||||
|
||||
return implode(".", $segments); |
||||
} |
||||
} |
@ -0,0 +1,36 @@ |
||||
<?php |
||||
/* |
||||
* Copyright 2010 Google Inc. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0 |
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
require_once "Google_AuthNone.php"; |
||||
require_once "Google_OAuth2.php"; |
||||
|
||||
/** |
||||
* Abstract class for the Authentication in the API client |
||||
* @author Chris Chabot <chabotc@google.com> |
||||
* |
||||
*/ |
||||
abstract class Google_Auth { |
||||
abstract public function authenticate($service); |
||||
abstract public function sign(Google_HttpRequest $request); |
||||
abstract public function createAuthUrl($scope); |
||||
|
||||
abstract public function getAccessToken(); |
||||
abstract public function setAccessToken($accessToken); |
||||
abstract public function setDeveloperKey($developerKey); |
||||
abstract public function refreshToken($refreshToken); |
||||
abstract public function revokeToken(); |
||||
} |
@ -0,0 +1,48 @@ |
||||
<?php |
||||
/* |
||||
* Copyright 2010 Google Inc. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0 |
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
/** |
||||
* Do-nothing authentication implementation, use this if you want to make un-authenticated calls |
||||
* @author Chris Chabot <chabotc@google.com> |
||||
* @author Chirag Shah <chirags@google.com> |
||||
*/ |
||||
class Google_AuthNone extends Google_Auth { |
||||
public $key = null; |
||||
|
||||
public function __construct() { |
||||
global $apiConfig; |
||||
if (!empty($apiConfig['developer_key'])) { |
||||
$this->setDeveloperKey($apiConfig['developer_key']); |
||||
} |
||||
} |
||||
|
||||
public function setDeveloperKey($key) {$this->key = $key;} |
||||
public function authenticate($service) {/*noop*/} |
||||
public function setAccessToken($accessToken) {/* noop*/} |
||||
public function getAccessToken() {return null;} |
||||
public function createAuthUrl($scope) {return null;} |
||||
public function refreshToken($refreshToken) {/* noop*/} |
||||
public function revokeToken() {/* noop*/} |
||||
|
||||
public function sign(Google_HttpRequest $request) { |
||||
if ($this->key) { |
||||
$request->setUrl($request->getUrl() . ((strpos($request->getUrl(), '?') === false) ? '?' : '&') |
||||
. 'key='.urlencode($this->key)); |
||||
} |
||||
return $request; |
||||
} |
||||
} |
@ -0,0 +1,63 @@ |
||||
<?php |
||||
/* |
||||
* Copyright 2011 Google Inc. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0 |
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
/** |
||||
* Class to hold information about an authenticated login. |
||||
* |
||||
* @author Brian Eaton <beaton@google.com> |
||||
*/ |
||||
class Google_LoginTicket { |
||||
const USER_ATTR = "id"; |
||||
|
||||
// Information from id token envelope. |
||||
private $envelope; |
||||
|
||||
// Information from id token payload. |
||||
private $payload; |
||||
|
||||
/** |
||||
* Creates a user based on the supplied token. |
||||
* |
||||
* @param string $envelope Header from a verified authentication token. |
||||
* @param string $payload Information from a verified authentication token. |
||||
*/ |
||||
public function __construct($envelope, $payload) { |
||||
$this->envelope = $envelope; |
||||
$this->payload = $payload; |
||||
} |
||||
|
||||
/** |
||||
* Returns the numeric identifier for the user. |
||||
* @throws Google_AuthException |
||||
* @return |
||||
*/ |
||||
public function getUserId() { |
||||
if (array_key_exists(self::USER_ATTR, $this->payload)) { |
||||
return $this->payload[self::USER_ATTR]; |
||||
} |
||||
throw new Google_AuthException("No user_id in token"); |
||||
} |
||||
|
||||
/** |
||||
* Returns attributes from the login ticket. This can contain |
||||
* various information about the user session. |
||||
* @return array |
||||
*/ |
||||
public function getAttributes() { |
||||
return array("envelope" => $this->envelope, "payload" => $this->payload); |
||||
} |
||||
} |
@ -0,0 +1,445 @@ |
||||
<?php |
||||
/* |
||||
* Copyright 2008 Google Inc. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0 |
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
require_once "Google_Verifier.php"; |
||||
require_once "Google_LoginTicket.php"; |
||||
require_once "service/Google_Utils.php"; |
||||
|
||||
/** |
||||
* Authentication class that deals with the OAuth 2 web-server authentication flow |
||||
* |
||||
* @author Chris Chabot <chabotc@google.com> |
||||
* @author Chirag Shah <chirags@google.com> |
||||
* |
||||
*/ |
||||
class Google_OAuth2 extends Google_Auth { |
||||
public $clientId; |
||||
public $clientSecret; |
||||
public $developerKey; |
||||
public $token; |
||||
public $redirectUri; |
||||
public $state; |
||||
public $accessType = 'offline'; |
||||
public $approvalPrompt = 'force'; |
||||
|
||||
/** @var Google_AssertionCredentials $assertionCredentials */ |
||||
public $assertionCredentials; |
||||
|
||||
const OAUTH2_REVOKE_URI = 'https://accounts.google.com/o/oauth2/revoke'; |
||||
const OAUTH2_TOKEN_URI = 'https://accounts.google.com/o/oauth2/token'; |
||||
const OAUTH2_AUTH_URL = 'https://accounts.google.com/o/oauth2/auth'; |
||||
const OAUTH2_FEDERATED_SIGNON_CERTS_URL = 'https://www.googleapis.com/oauth2/v1/certs'; |
||||
const CLOCK_SKEW_SECS = 300; // five minutes in seconds |
||||
const AUTH_TOKEN_LIFETIME_SECS = 300; // five minutes in seconds |
||||
const MAX_TOKEN_LIFETIME_SECS = 86400; // one day in seconds |
||||
|
||||
/** |
||||
* Instantiates the class, but does not initiate the login flow, leaving it |
||||
* to the discretion of the caller (which is done by calling authenticate()). |
||||
*/ |
||||
public function __construct() { |
||||
global $apiConfig; |
||||
|
||||
if (! empty($apiConfig['developer_key'])) { |
||||
$this->developerKey = $apiConfig['developer_key']; |
||||
} |
||||
|
||||
if (! empty($apiConfig['oauth2_client_id'])) { |
||||
$this->clientId = $apiConfig['oauth2_client_id']; |
||||
} |
||||
|
||||
if (! empty($apiConfig['oauth2_client_secret'])) { |
||||
$this->clientSecret = $apiConfig['oauth2_client_secret']; |
||||
} |
||||
|
||||
if (! empty($apiConfig['oauth2_redirect_uri'])) { |
||||
$this->redirectUri = $apiConfig['oauth2_redirect_uri']; |
||||
} |
||||
|
||||
if (! empty($apiConfig['oauth2_access_type'])) { |
||||
$this->accessType = $apiConfig['oauth2_access_type']; |
||||
} |
||||
|
||||
if (! empty($apiConfig['oauth2_approval_prompt'])) { |
||||
$this->approvalPrompt = $apiConfig['oauth2_approval_prompt']; |
||||
} |
||||
|
||||
} |
||||
|
||||
/** |
||||
* @param $service |
||||
* @param string|null $code |
||||
* @throws Google_AuthException |
||||
* @return string |
||||
*/ |
||||
public function authenticate($service, $code = null) { |
||||
if (!$code && isset($_GET['code'])) { |
||||
$code = $_GET['code']; |
||||
} |
||||
|
||||
if ($code) { |
||||
// We got here from the redirect from a successful authorization grant, fetch the access token |
||||
$request = Google_Client::$io->makeRequest(new Google_HttpRequest(self::OAUTH2_TOKEN_URI, 'POST', array(), array( |
||||
'code' => $code, |
||||
'grant_type' => 'authorization_code', |
||||
'redirect_uri' => $this->redirectUri, |
||||
'client_id' => $this->clientId, |
||||
'client_secret' => $this->clientSecret |
||||
))); |
||||
|
||||
if ($request->getResponseHttpCode() == 200) { |
||||
$this->setAccessToken($request->getResponseBody()); |
||||
$this->token['created'] = time(); |
||||
return $this->getAccessToken(); |
||||
} else { |
||||
$response = $request->getResponseBody(); |
||||
$decodedResponse = json_decode($response, true); |
||||
if ($decodedResponse != null && $decodedResponse['error']) { |
||||
$response = $decodedResponse['error']; |
||||
} |
||||
throw new Google_AuthException("Error fetching OAuth2 access token, message: '$response'", $request->getResponseHttpCode()); |
||||
} |
||||
} |
||||
|
||||
$authUrl = $this->createAuthUrl($service['scope']); |
||||
header('Location: ' . $authUrl); |
||||
return true; |
||||
} |
||||
|
||||
/** |
||||
* Create a URL to obtain user authorization. |
||||
* The authorization endpoint allows the user to first |
||||
* authenticate, and then grant/deny the access request. |
||||
* @param string $scope The scope is expressed as a list of space-delimited strings. |
||||
* @return string |
||||
*/ |
||||
public function createAuthUrl($scope) { |
||||
$params = array( |
||||
'response_type=code', |
||||
'redirect_uri=' . urlencode($this->redirectUri), |
||||
'client_id=' . urlencode($this->clientId), |
||||
'scope=' . urlencode($scope), |
||||
'access_type=' . urlencode($this->accessType), |
||||
'approval_prompt=' . urlencode($this->approvalPrompt), |
||||
); |
||||
|
||||
if (isset($this->state)) { |
||||
$params[] = 'state=' . urlencode($this->state); |
||||
} |
||||
$params = implode('&', $params); |
||||
return self::OAUTH2_AUTH_URL . "?$params"; |
||||
} |
||||
|
||||
/** |
||||
* @param string $token |
||||
* @throws Google_AuthException |
||||
*/ |
||||
public function setAccessToken($token) { |
||||
$token = json_decode($token, true); |
||||
if ($token == null) { |
||||
throw new Google_AuthException('Could not json decode the token'); |
||||
} |
||||
if (! isset($token['access_token'])) { |
||||
throw new Google_AuthException("Invalid token format"); |
||||
} |
||||
$this->token = $token; |
||||
} |
||||
|
||||
public function getAccessToken() { |
||||
return json_encode($this->token); |
||||
} |
||||
|
||||
public function setDeveloperKey($developerKey) { |
||||
$this->developerKey = $developerKey; |
||||
} |
||||
|
||||
public function setState($state) { |
||||
$this->state = $state; |
||||
} |
||||
|
||||
public function setAccessType($accessType) { |
||||
$this->accessType = $accessType; |
||||
} |
||||
|
||||
public function setApprovalPrompt($approvalPrompt) { |
||||
$this->approvalPrompt = $approvalPrompt; |
||||
} |
||||
|
||||
public function setAssertionCredentials(Google_AssertionCredentials $creds) { |
||||
$this->assertionCredentials = $creds; |
||||
} |
||||
|
||||
/** |
||||
* Include an accessToken in a given apiHttpRequest. |
||||
* @param Google_HttpRequest $request |
||||
* @return Google_HttpRequest |
||||
* @throws Google_AuthException |
||||
*/ |
||||
public function sign(Google_HttpRequest $request) { |
||||
// add the developer key to the request before signing it |
||||
if ($this->developerKey) { |
||||
$requestUrl = $request->getUrl(); |
||||
$requestUrl .= (strpos($request->getUrl(), '?') === false) ? '?' : '&'; |
||||
$requestUrl .= 'key=' . urlencode($this->developerKey); |
||||
$request->setUrl($requestUrl); |
||||
} |
||||
|
||||
// Cannot sign the request without an OAuth access token. |
||||
if (null == $this->token && null == $this->assertionCredentials) { |
||||
return $request; |
||||
} |
||||
|
||||
// Check if the token is set to expire in the next 30 seconds |
||||
// (or has already expired). |
||||
if ($this->isAccessTokenExpired()) { |
||||
if ($this->assertionCredentials) { |
||||
$this->refreshTokenWithAssertion(); |
||||
} else { |
||||
if (! array_key_exists('refresh_token', $this->token)) { |
||||
throw new Google_AuthException("The OAuth 2.0 access token has expired, " |
||||
. "and a refresh token is not available. Refresh tokens are not " |
||||
. "returned for responses that were auto-approved."); |
||||
} |
||||
$this->refreshToken($this->token['refresh_token']); |
||||
} |
||||
} |
||||
|
||||
// Add the OAuth2 header to the request |
||||
$request->setRequestHeaders( |
||||
array('Authorization' => 'Bearer ' . $this->token['access_token']) |
||||
); |
||||
|
||||
return $request; |
||||
} |
||||
|
||||
/** |
||||
* Fetches a fresh access token with the given refresh token. |
||||
* @param string $refreshToken |
||||
* @return void |
||||
*/ |
||||
public function refreshToken($refreshToken) { |
||||
$this->refreshTokenRequest(array( |
||||
'client_id' => $this->clientId, |
||||
'client_secret' => $this->clientSecret, |
||||
'refresh_token' => $refreshToken, |
||||
'grant_type' => 'refresh_token' |
||||
)); |
||||
} |
||||
|
||||
/** |
||||
* Fetches a fresh access token with a given assertion token. |
||||
* @param Google_AssertionCredentials $assertionCredentials optional. |
||||
* @return void |
||||
*/ |
||||
public function refreshTokenWithAssertion($assertionCredentials = null) { |
||||
if (!$assertionCredentials) { |
||||
$assertionCredentials = $this->assertionCredentials; |
||||
} |
||||
|
||||
$this->refreshTokenRequest(array( |
||||
'grant_type' => 'assertion', |
||||
'assertion_type' => $assertionCredentials->assertionType, |
||||
'assertion' => $assertionCredentials->generateAssertion(), |
||||
)); |
||||
} |
||||
|
||||
private function refreshTokenRequest($params) { |
||||
$http = new Google_HttpRequest(self::OAUTH2_TOKEN_URI, 'POST', array(), $params); |
||||
$request = Google_Client::$io->makeRequest($http); |
||||
|
||||
$code = $request->getResponseHttpCode(); |
||||
$body = $request->getResponseBody(); |
||||
if (200 == $code) { |
||||
$token = json_decode($body, true); |
||||
if ($token == null) { |
||||
throw new Google_AuthException("Could not json decode the access token"); |
||||
} |
||||
|
||||
if (! isset($token['access_token']) || ! isset($token['expires_in'])) { |
||||
throw new Google_AuthException("Invalid token format"); |
||||
} |
||||
|
||||
$this->token['access_token'] = $token['access_token']; |
||||
$this->token['expires_in'] = $token['expires_in']; |
||||
$this->token['created'] = time(); |
||||
} else { |
||||
throw new Google_AuthException("Error refreshing the OAuth2 token, message: '$body'", $code); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Revoke an OAuth2 access token or refresh token. This method will revoke the current access |
||||
* token, if a token isn't provided. |
||||
* @throws Google_AuthException |
||||
* @param string|null $token The token (access token or a refresh token) that should be revoked. |
||||
* @return boolean Returns True if the revocation was successful, otherwise False. |
||||
*/ |
||||
public function revokeToken($token = null) { |
||||
if (!$token) { |
||||
$token = $this->token['access_token']; |
||||
} |
||||
$request = new Google_HttpRequest(self::OAUTH2_REVOKE_URI, 'POST', array(), "token=$token"); |
||||
$response = Google_Client::$io->makeRequest($request); |
||||
$code = $response->getResponseHttpCode(); |
||||
if ($code == 200) { |
||||
$this->token = null; |
||||
return true; |
||||
} |
||||
|
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* Returns if the access_token is expired. |
||||
* @return bool Returns True if the access_token is expired. |
||||
*/ |
||||
public function isAccessTokenExpired() { |
||||
if (null == $this->token) { |
||||
return true; |
||||
} |
||||
|
||||
// If the token is set to expire in the next 30 seconds. |
||||
$expired = ($this->token['created'] |
||||
+ ($this->token['expires_in'] - 30)) < time(); |
||||
|
||||
return $expired; |
||||
} |
||||
|
||||
// Gets federated sign-on certificates to use for verifying identity tokens. |
||||
// Returns certs as array structure, where keys are key ids, and values |
||||
// are PEM encoded certificates. |
||||
private function getFederatedSignOnCerts() { |
||||
// This relies on makeRequest caching certificate responses. |
||||
$request = Google_Client::$io->makeRequest(new Google_HttpRequest( |
||||
self::OAUTH2_FEDERATED_SIGNON_CERTS_URL)); |
||||
if ($request->getResponseHttpCode() == 200) { |
||||
$certs = json_decode($request->getResponseBody(), true); |
||||
if ($certs) { |
||||
return $certs; |
||||
} |
||||
} |
||||
throw new Google_AuthException( |
||||
"Failed to retrieve verification certificates: '" . |
||||
$request->getResponseBody() . "'.", |
||||
$request->getResponseHttpCode()); |
||||
} |
||||
|
||||
/** |
||||
* Verifies an id token and returns the authenticated apiLoginTicket. |
||||
* Throws an exception if the id token is not valid. |
||||
* The audience parameter can be used to control which id tokens are |
||||
* accepted. By default, the id token must have been issued to this OAuth2 client. |
||||
* |
||||
* @param $id_token |
||||
* @param $audience |
||||
* @return Google_LoginTicket |
||||
*/ |
||||
public function verifyIdToken($id_token = null, $audience = null) { |
||||
if (!$id_token) { |
||||
$id_token = $this->token['id_token']; |
||||
} |
||||
|
||||
$certs = $this->getFederatedSignonCerts(); |
||||
if (!$audience) { |
||||
$audience = $this->clientId; |
||||
} |
||||
return $this->verifySignedJwtWithCerts($id_token, $certs, $audience); |
||||
} |
||||
|
||||
// Verifies the id token, returns the verified token contents. |
||||
// Visible for testing. |
||||
function verifySignedJwtWithCerts($jwt, $certs, $required_audience) { |
||||
$segments = explode(".", $jwt); |
||||
if (count($segments) != 3) { |
||||
throw new Google_AuthException("Wrong number of segments in token: $jwt"); |
||||
} |
||||
$signed = $segments[0] . "." . $segments[1]; |
||||
$signature = Google_Utils::urlSafeB64Decode($segments[2]); |
||||
|
||||
// Parse envelope. |
||||
$envelope = json_decode(Google_Utils::urlSafeB64Decode($segments[0]), true); |
||||
if (!$envelope) { |
||||
throw new Google_AuthException("Can't parse token envelope: " . $segments[0]); |
||||
} |
||||
|
||||
// Parse token |
||||
$json_body = Google_Utils::urlSafeB64Decode($segments[1]); |
||||
$payload = json_decode($json_body, true); |
||||
if (!$payload) { |
||||
throw new Google_AuthException("Can't parse token payload: " . $segments[1]); |
||||
} |
||||
|
||||
// Check signature |
||||
$verified = false; |
||||
foreach ($certs as $keyName => $pem) { |
||||
$public_key = new Google_PemVerifier($pem); |
||||
if ($public_key->verify($signed, $signature)) { |
||||
$verified = true; |
||||
break; |
||||
} |
||||
} |
||||
|
||||
if (!$verified) { |
||||
throw new Google_AuthException("Invalid token signature: $jwt"); |
||||
} |
||||
|
||||
// Check issued-at timestamp |
||||
$iat = 0; |
||||
if (array_key_exists("iat", $payload)) { |
||||
$iat = $payload["iat"]; |
||||
} |
||||
if (!$iat) { |
||||
throw new Google_AuthException("No issue time in token: $json_body"); |
||||
} |
||||
$earliest = $iat - self::CLOCK_SKEW_SECS; |
||||
|
||||
// Check expiration timestamp |
||||
$now = time(); |
||||
$exp = 0; |
||||
if (array_key_exists("exp", $payload)) { |
||||
$exp = $payload["exp"]; |
||||
} |
||||
if (!$exp) { |
||||
throw new Google_AuthException("No expiration time in token: $json_body"); |
||||
} |
||||
if ($exp >= $now + self::MAX_TOKEN_LIFETIME_SECS) { |
||||
throw new Google_AuthException( |
||||
"Expiration time too far in future: $json_body"); |
||||
} |
||||
|
||||
$latest = $exp + self::CLOCK_SKEW_SECS; |
||||
if ($now < $earliest) { |
||||
throw new Google_AuthException( |
||||
"Token used too early, $now < $earliest: $json_body"); |
||||
} |
||||
if ($now > $latest) { |
||||
throw new Google_AuthException( |
||||
"Token used too late, $now > $latest: $json_body"); |
||||
} |
||||
|
||||
// TODO(beaton): check issuer field? |
||||
|
||||
// Check audience |
||||
$aud = $payload["aud"]; |
||||
if ($aud != $required_audience) { |
||||
throw new Google_AuthException("Wrong recipient, $aud != $required_audience: $json_body"); |
||||
} |
||||
|
||||
// All good. |
||||
return new Google_LoginTicket($envelope, $payload); |
||||
} |
||||
} |
@ -0,0 +1,70 @@ |
||||
<?php |
||||
/* |
||||
* Copyright 2011 Google Inc. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0 |
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
/** |
||||
* Signs data. |
||||
* |
||||
* Only used for testing. |
||||
* |
||||
* @author Brian Eaton <beaton@google.com> |
||||
*/ |
||||
class Google_P12Signer extends Google_Signer { |
||||
// OpenSSL private key resource |
||||
private $privateKey; |
||||
|
||||
// Creates a new signer from a .p12 file. |
||||
function __construct($p12, $password) { |
||||
if (!function_exists('openssl_x509_read')) { |
||||
throw new Exception( |
||||
'The Google PHP API library needs the openssl PHP extension'); |
||||
} |
||||
|
||||
// This throws on error |
||||
$certs = array(); |
||||
if (!openssl_pkcs12_read($p12, $certs, $password)) { |
||||
throw new Google_AuthException("Unable to parse the p12 file. " . |
||||
"Is this a .p12 file? Is the password correct? OpenSSL error: " . |
||||
openssl_error_string()); |
||||
} |
||||
// TODO(beaton): is this part of the contract for the openssl_pkcs12_read |
||||
// method? What happens if there are multiple private keys? Do we care? |
||||
if (!array_key_exists("pkey", $certs) || !$certs["pkey"]) { |
||||
throw new Google_AuthException("No private key found in p12 file."); |
||||
} |
||||
$this->privateKey = openssl_pkey_get_private($certs["pkey"]); |
||||
if (!$this->privateKey) { |
||||
throw new Google_AuthException("Unable to load private key in "); |
||||
} |
||||
} |
||||
|
||||
function __destruct() { |
||||
if ($this->privateKey) { |
||||
openssl_pkey_free($this->privateKey); |
||||
} |
||||
} |
||||
|
||||
function sign($data) { |
||||
if(version_compare(PHP_VERSION, '5.3.0') < 0) { |
||||
throw new Google_AuthException( |
||||
"PHP 5.3.0 or higher is required to use service accounts."); |
||||
} |
||||
if (!openssl_sign($data, $signature, $this->privateKey, "sha256")) { |
||||
throw new Google_AuthException("Unable to sign data"); |
||||
} |
||||
return $signature; |
||||
} |
||||
} |
@ -0,0 +1,66 @@ |
||||
<?php |
||||
/* |
||||
* Copyright 2011 Google Inc. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0 |
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
/** |
||||
* Verifies signatures using PEM encoded certificates. |
||||
* |
||||
* @author Brian Eaton <beaton@google.com> |
||||
*/ |
||||
class Google_PemVerifier extends Google_Verifier { |
||||
private $publicKey; |
||||
|
||||
/** |
||||
* Constructs a verifier from the supplied PEM-encoded certificate. |
||||
* |
||||
* $pem: a PEM encoded certificate (not a file). |
||||
* @param $pem |
||||
* @throws Google_AuthException |
||||
* @throws Google_Exception |
||||
*/ |
||||
function __construct($pem) { |
||||
if (!function_exists('openssl_x509_read')) { |
||||
throw new Google_Exception('Google API PHP client needs the openssl PHP extension'); |
||||
} |
||||
$this->publicKey = openssl_x509_read($pem); |
||||
if (!$this->publicKey) { |
||||
throw new Google_AuthException("Unable to parse PEM: $pem"); |
||||
} |
||||
} |
||||
|
||||
function __destruct() { |
||||
if ($this->publicKey) { |
||||
openssl_x509_free($this->publicKey); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Verifies the signature on data. |
||||
* |
||||
* Returns true if the signature is valid, false otherwise. |
||||
* @param $data |
||||
* @param $signature |
||||
* @throws Google_AuthException |
||||
* @return bool |
||||
*/ |
||||
function verify($data, $signature) { |
||||
$status = openssl_verify($data, $signature, $this->publicKey, "sha256"); |
||||
if ($status === -1) { |
||||
throw new Google_AuthException('Signature verification error: ' . openssl_error_string()); |
||||
} |
||||
return $status === 1; |
||||
} |
||||
} |
@ -0,0 +1,30 @@ |
||||
<?php |
||||
/* |
||||
* Copyright 2011 Google Inc. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0 |
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
require_once "Google_P12Signer.php"; |
||||
|
||||
/** |
||||
* Signs data. |
||||
* |
||||
* @author Brian Eaton <beaton@google.com> |
||||
*/ |
||||
abstract class Google_Signer { |
||||
/** |
||||
* Signs data, returns the signature as binary data. |
||||
*/ |
||||
abstract public function sign($data); |
||||
} |
@ -0,0 +1,31 @@ |
||||
<?php |
||||
/* |
||||
* Copyright 2011 Google Inc. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0 |
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
require_once "Google_PemVerifier.php"; |
||||
|
||||
/** |
||||
* Verifies signatures. |
||||
* |
||||
* @author Brian Eaton <beaton@google.com> |
||||
*/ |
||||
abstract class Google_Verifier { |
||||
/** |
||||
* Checks a signature, returns true if the signature is correct, |
||||
* false otherwise. |
||||
*/ |
||||
abstract public function verify($data, $signature); |
||||
} |
@ -0,0 +1,98 @@ |
||||
<?php |
||||
/* |
||||
* Copyright 2010 Google Inc. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0 |
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
/** |
||||
* A persistent storage class based on the APC cache, which is not |
||||
* really very persistent, as soon as you restart your web server |
||||
* the storage will be wiped, however for debugging and/or speed |
||||
* it can be useful, kinda, and cache is a lot cheaper then storage. |
||||
* |
||||
* @author Chris Chabot <chabotc@google.com> |
||||
*/ |
||||
class googleApcCache extends Google_Cache { |
||||
|
||||
public function __construct() { |
||||
if (! function_exists('apc_add')) { |
||||
throw new Google_CacheException("Apc functions not available"); |
||||
} |
||||
} |
||||
|
||||
private function isLocked($key) { |
||||
if ((@apc_fetch($key . '.lock')) === false) { |
||||
return false; |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
private function createLock($key) { |
||||
// the interesting thing is that this could fail if the lock was created in the meantime.. |
||||
// but we'll ignore that out of convenience |
||||
@apc_add($key . '.lock', '', 5); |
||||
} |
||||
|
||||
private function removeLock($key) { |
||||
// suppress all warnings, if some other process removed it that's ok too |
||||
@apc_delete($key . '.lock'); |
||||
} |
||||
|
||||
private function waitForLock($key) { |
||||
// 20 x 250 = 5 seconds |
||||
$tries = 20; |
||||
$cnt = 0; |
||||
do { |
||||
// 250 ms is a long time to sleep, but it does stop the server from burning all resources on polling locks.. |
||||
usleep(250); |
||||
$cnt ++; |
||||
} while ($cnt <= $tries && $this->isLocked($key)); |
||||
if ($this->isLocked($key)) { |
||||
// 5 seconds passed, assume the owning process died off and remove it |
||||
$this->removeLock($key); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* @inheritDoc |
||||
*/ |
||||
public function get($key, $expiration = false) { |
||||
|
||||
if (($ret = @apc_fetch($key)) === false) { |
||||
return false; |
||||
} |
||||
if (!$expiration || (time() - $ret['time'] > $expiration)) { |
||||
$this->delete($key); |
||||
return false; |
||||
} |
||||
return unserialize($ret['data']); |
||||
} |
||||
|
||||
/** |
||||
* @inheritDoc |
||||
*/ |
||||
public function set($key, $value) { |
||||
if (@apc_store($key, array('time' => time(), 'data' => serialize($value))) == false) { |
||||
throw new Google_CacheException("Couldn't store data"); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* @inheritDoc |
||||
* @param String $key |
||||
*/ |
||||
public function delete($key) { |
||||
@apc_delete($key); |
||||
} |
||||
} |
@ -0,0 +1,55 @@ |
||||
<?php |
||||
/* |
||||
* Copyright 2008 Google Inc. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0 |
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
require_once "Google_FileCache.php"; |
||||
require_once "Google_MemcacheCache.php"; |
||||
|
||||
/** |
||||
* Abstract storage class |
||||
* |
||||
* @author Chris Chabot <chabotc@google.com> |
||||
*/ |
||||
abstract class Google_Cache { |
||||
|
||||
/** |
||||
* Retrieves the data for the given key, or false if they |
||||
* key is unknown or expired |
||||
* |
||||
* @param String $key The key who's data to retrieve |
||||
* @param boolean|int $expiration Expiration time in seconds |
||||
* |
||||
*/ |
||||
abstract function get($key, $expiration = false); |
||||
|
||||
/** |
||||
* Store the key => $value set. The $value is serialized |
||||
* by this function so can be of any type |
||||
* |
||||
* @param string $key Key of the data |
||||
* @param string $value data |
||||
*/ |
||||
abstract function set($key, $value); |
||||
|
||||
/** |
||||
* Removes the key/data pair for the given $key |
||||
* |
||||
* @param String $key |
||||
*/ |
||||
abstract function delete($key); |
||||
} |
||||
|
||||
|
@ -0,0 +1,137 @@ |
||||
<?php |
||||
/* |
||||
* Copyright 2008 Google Inc. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0 |
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
/* |
||||
* This class implements a basic on disk storage. While that does |
||||
* work quite well it's not the most elegant and scalable solution. |
||||
* It will also get you into a heap of trouble when you try to run |
||||
* this in a clustered environment. In those cases please use the |
||||
* MySql back-end |
||||
* |
||||
* @author Chris Chabot <chabotc@google.com> |
||||
*/ |
||||
class Google_FileCache extends Google_Cache { |
||||
private $path; |
||||
|
||||
public function __construct() { |
||||
global $apiConfig; |
||||
$this->path = $apiConfig['ioFileCache_directory']; |
||||
} |
||||
|
||||
private function isLocked($storageFile) { |
||||
// our lock file convention is simple: /the/file/path.lock |
||||
return file_exists($storageFile . '.lock'); |
||||
} |
||||
|
||||
private function createLock($storageFile) { |
||||
$storageDir = dirname($storageFile); |
||||
if (! is_dir($storageDir)) { |
||||
// @codeCoverageIgnoreStart |
||||
if (! @mkdir($storageDir, 0755, true)) { |
||||
// make sure the failure isn't because of a concurrency issue |
||||
if (! is_dir($storageDir)) { |
||||
throw new Google_CacheException("Could not create storage directory: $storageDir"); |
||||
} |
||||
} |
||||
// @codeCoverageIgnoreEnd |
||||
} |
||||
@touch($storageFile . '.lock'); |
||||
} |
||||
|
||||
private function removeLock($storageFile) { |
||||
// suppress all warnings, if some other process removed it that's ok too |
||||
@unlink($storageFile . '.lock'); |
||||
} |
||||
|
||||
private function waitForLock($storageFile) { |
||||
// 20 x 250 = 5 seconds |
||||
$tries = 20; |
||||
$cnt = 0; |
||||
do { |
||||
// make sure PHP picks up on file changes. This is an expensive action but really can't be avoided |
||||
clearstatcache(); |
||||
// 250 ms is a long time to sleep, but it does stop the server from burning all resources on polling locks.. |
||||
usleep(250); |
||||
$cnt ++; |
||||
} while ($cnt <= $tries && $this->isLocked($storageFile)); |
||||
if ($this->isLocked($storageFile)) { |
||||
// 5 seconds passed, assume the owning process died off and remove it |
||||
$this->removeLock($storageFile); |
||||
} |
||||
} |
||||
|
||||
private function getCacheDir($hash) { |
||||
// use the first 2 characters of the hash as a directory prefix |
||||
// this should prevent slowdowns due to huge directory listings |
||||
// and thus give some basic amount of scalability |
||||
return $this->path . '/' . substr($hash, 0, 2); |
||||
} |
||||
|
||||
private function getCacheFile($hash) { |
||||
return $this->getCacheDir($hash) . '/' . $hash; |
||||
} |
||||
|
||||
public function get($key, $expiration = false) { |
||||
$storageFile = $this->getCacheFile(md5($key)); |
||||
// See if this storage file is locked, if so we wait up to 5 seconds for the lock owning process to |
||||
// complete it's work. If the lock is not released within that time frame, it's cleaned up. |
||||
// This should give us a fair amount of 'Cache Stampeding' protection |
||||
if ($this->isLocked($storageFile)) { |
||||
$this->waitForLock($storageFile); |
||||
} |
||||
if (file_exists($storageFile) && is_readable($storageFile)) { |
||||
$now = time(); |
||||
if (! $expiration || (($mtime = @filemtime($storageFile)) !== false && ($now - $mtime) < $expiration)) { |
||||
if (($data = @file_get_contents($storageFile)) !== false) { |
||||
$data = unserialize($data); |
||||
return $data; |
||||
} |
||||
} |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
public function set($key, $value) { |
||||
$storageDir = $this->getCacheDir(md5($key)); |
||||
$storageFile = $this->getCacheFile(md5($key)); |
||||
if ($this->isLocked($storageFile)) { |
||||
// some other process is writing to this file too, wait until it's done to prevent hiccups |
||||
$this->waitForLock($storageFile); |
||||
} |
||||
if (! is_dir($storageDir)) { |
||||
if (! @mkdir($storageDir, 0755, true)) { |
||||
throw new Google_CacheException("Could not create storage directory: $storageDir"); |
||||
} |
||||
} |
||||
// we serialize the whole request object, since we don't only want the |
||||
// responseContent but also the postBody used, headers, size, etc |
||||
$data = serialize($value); |
||||
$this->createLock($storageFile); |
||||
if (! @file_put_contents($storageFile, $data)) { |
||||
$this->removeLock($storageFile); |
||||
throw new Google_CacheException("Could not store data in the file"); |
||||
} |
||||
$this->removeLock($storageFile); |
||||
} |
||||
|
||||
public function delete($key) { |
||||
$file = $this->getCacheFile(md5($key)); |
||||
if (! @unlink($file)) { |
||||
throw new Google_CacheException("Cache file could not be deleted"); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,130 @@ |
||||
<?php |
||||
/* |
||||
* Copyright 2008 Google Inc. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0 |
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
/** |
||||
* A persistent storage class based on the memcache, which is not |
||||
* really very persistent, as soon as you restart your memcache daemon |
||||
* the storage will be wiped, however for debugging and/or speed |
||||
* it can be useful, kinda, and cache is a lot cheaper then storage. |
||||
* |
||||
* @author Chris Chabot <chabotc@google.com> |
||||
*/ |
||||
class Google_MemcacheCache extends Google_Cache { |
||||
private $connection = false; |
||||
|
||||
public function __construct() { |
||||
global $apiConfig; |
||||
if (! function_exists('memcache_connect')) { |
||||
throw new Google_CacheException("Memcache functions not available"); |
||||
} |
||||
$this->host = $apiConfig['ioMemCacheCache_host']; |
||||
$this->port = $apiConfig['ioMemCacheCache_port']; |
||||
if (empty($this->host) || empty($this->port)) { |
||||
throw new Google_CacheException("You need to supply a valid memcache host and port"); |
||||
} |
||||
} |
||||
|
||||
private function isLocked($key) { |
||||
$this->check(); |
||||
if ((@memcache_get($this->connection, $key . '.lock')) === false) { |
||||
return false; |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
private function createLock($key) { |
||||
$this->check(); |
||||
// the interesting thing is that this could fail if the lock was created in the meantime.. |
||||
// but we'll ignore that out of convenience |
||||
@memcache_add($this->connection, $key . '.lock', '', 0, 5); |
||||
} |
||||
|
||||
private function removeLock($key) { |
||||
$this->check(); |
||||
// suppress all warnings, if some other process removed it that's ok too |
||||
@memcache_delete($this->connection, $key . '.lock'); |
||||
} |
||||
|
||||
private function waitForLock($key) { |
||||
$this->check(); |
||||
// 20 x 250 = 5 seconds |
||||
$tries = 20; |
||||
$cnt = 0; |
||||
do { |
||||
// 250 ms is a long time to sleep, but it does stop the server from burning all resources on polling locks.. |
||||
usleep(250); |
||||
$cnt ++; |
||||
} while ($cnt <= $tries && $this->isLocked($key)); |
||||
if ($this->isLocked($key)) { |
||||
// 5 seconds passed, assume the owning process died off and remove it |
||||
$this->removeLock($key); |
||||
} |
||||
} |
||||
|
||||
// I prefer lazy initialization since the cache isn't used every request |
||||
// so this potentially saves a lot of overhead |
||||
private function connect() { |
||||
if (! $this->connection = @memcache_pconnect($this->host, $this->port)) { |
||||
throw new Google_CacheException("Couldn't connect to memcache server"); |
||||
} |
||||
} |
||||
|
||||
private function check() { |
||||
if (! $this->connection) { |
||||
$this->connect(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* @inheritDoc |
||||
*/ |
||||
public function get($key, $expiration = false) { |
||||
$this->check(); |
||||
if (($ret = @memcache_get($this->connection, $key)) === false) { |
||||
return false; |
||||
} |
||||
if (! $expiration || (time() - $ret['time'] > $expiration)) { |
||||
$this->delete($key); |
||||
return false; |
||||
} |
||||
return $ret['data']; |
||||
} |
||||
|
||||
/** |
||||
* @inheritDoc |
||||
* @param string $key |
||||
* @param string $value |
||||
* @throws Google_CacheException |
||||
*/ |
||||
public function set($key, $value) { |
||||
$this->check(); |
||||
// we store it with the cache_time default expiration so objects will at least get cleaned eventually. |
||||
if (@memcache_set($this->connection, $key, array('time' => time(), |
||||
'data' => $value), false) == false) { |
||||
throw new Google_CacheException("Couldn't store data in cache"); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* @inheritDoc |
||||
* @param String $key |
||||
*/ |
||||
public function delete($key) { |
||||
$this->check(); |
||||
@memcache_delete($this->connection, $key); |
||||
} |
||||
} |
@ -0,0 +1,81 @@ |
||||
<?php |
||||
/* |
||||
* Copyright 2010 Google Inc. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0 |
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
global $apiConfig; |
||||
$apiConfig = array( |
||||
// True if objects should be returned by the service classes. |
||||
// False if associative arrays should be returned (default behavior). |
||||
'use_objects' => false, |
||||
|
||||
// The application_name is included in the User-Agent HTTP header. |
||||
'application_name' => '', |
||||
|
||||
// OAuth2 Settings, you can get these keys at https://code.google.com/apis/console |
||||
'oauth2_client_id' => '', |
||||
'oauth2_client_secret' => '', |
||||
'oauth2_redirect_uri' => '', |
||||
|
||||
// The developer key, you get this at https://code.google.com/apis/console |
||||
'developer_key' => '', |
||||
|
||||
// Site name to show in the Google's OAuth 1 authentication screen. |
||||
'site_name' => 'www.example.org', |
||||
|
||||
// Which Authentication, Storage and HTTP IO classes to use. |
||||
'authClass' => 'Google_OAuth2', |
||||
'ioClass' => 'Google_CurlIO', |
||||
'cacheClass' => 'Google_FileCache', |
||||
|
||||
// Don't change these unless you're working against a special development or testing environment. |
||||
'basePath' => 'https://www.googleapis.com', |
||||
|
||||
// IO Class dependent configuration, you only have to configure the values |
||||
// for the class that was configured as the ioClass above |
||||
'ioFileCache_directory' => |
||||
(function_exists('sys_get_temp_dir') ? |
||||
sys_get_temp_dir() . '/Google_Client' : |
||||
'/tmp/Google_Client'), |
||||
|
||||
// Definition of service specific values like scopes, oauth token URLs, etc |
||||
'services' => array( |
||||
'analytics' => array('scope' => 'https://www.googleapis.com/auth/analytics.readonly'), |
||||
'calendar' => array( |
||||
'scope' => array( |
||||
"https://www.googleapis.com/auth/calendar", |
||||
"https://www.googleapis.com/auth/calendar.readonly", |
||||
) |
||||
), |
||||
'books' => array('scope' => 'https://www.googleapis.com/auth/books'), |
||||
'latitude' => array( |
||||
'scope' => array( |
||||
'https://www.googleapis.com/auth/latitude.all.best', |
||||
'https://www.googleapis.com/auth/latitude.all.city', |
||||
) |
||||
), |
||||
'moderator' => array('scope' => 'https://www.googleapis.com/auth/moderator'), |
||||
'oauth2' => array( |
||||
'scope' => array( |
||||
'https://www.googleapis.com/auth/userinfo.profile', |
||||
'https://www.googleapis.com/auth/userinfo.email', |
||||
) |
||||
), |
||||
'plus' => array('scope' => 'https://www.googleapis.com/auth/plus.login'), |
||||
'siteVerification' => array('scope' => 'https://www.googleapis.com/auth/siteverification'), |
||||
'tasks' => array('scope' => 'https://www.googleapis.com/auth/tasks'), |
||||
'urlshortener' => array('scope' => 'https://www.googleapis.com/auth/urlshortener') |
||||
) |
||||
); |
File diff suppressed because one or more lines are too long
@ -0,0 +1,209 @@ |
||||
<?php |
||||
/* |
||||
Copyright (c) 2010 Kevin M Burns Jr, http://kevburnsjr.com/ |
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining |
||||
a copy of this software and associated documentation files (the |
||||
"Software"), to deal in the Software without restriction, including |
||||
without limitation the rights to use, copy, modify, merge, publish, |
||||
distribute, sublicense, and/or sell copies of the Software, and to |
||||
permit persons to whom the Software is furnished to do so, subject to |
||||
the following conditions: |
||||
|
||||
The above copyright notice and this permission notice shall be |
||||
included in all copies or substantial portions of the Software. |
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE |
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION |
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
||||
*/ |
||||
|
||||
/** |
||||
* A URI Template Parser which is used by the apiREST class to resolve the REST requests |
||||
* Blogpost: http://lab.kevburnsjr.com/php-uri-template-parser |
||||
* Source: http://github.com/KevBurnsJr/php-uri-template-parser |
||||
*/ |
||||
class URI_Template_Parser { |
||||
|
||||
public static $operators = array('+', ';', '?', '/', '.'); |
||||
public static $reserved_operators = array('|', '!', '@'); |
||||
public static $explode_modifiers = array('+', '*'); |
||||
public static $partial_modifiers = array(':', '^'); |
||||
|
||||
public static $gen_delims = array(':', '/', '?', '#', '[', ']', '@'); |
||||
public static $gen_delims_pct = array('%3A', '%2F', '%3F', '%23', '%5B', '%5D', '%40'); |
||||
public static $sub_delims = array('!', '$', '&', '\'', '(', ')', '*', '+', ',', ';', '='); |
||||
public static $sub_delims_pct = array('%21', '%24', '%26', '%27', '%28', '%29', '%2A', '%2B', '%2C', '%3B', '%3D'); |
||||
public static $reserved; |
||||
public static $reserved_pct; |
||||
|
||||
public function __construct($template) { |
||||
self::$reserved = array_merge(self::$gen_delims, self::$sub_delims); |
||||
self::$reserved_pct = array_merge(self::$gen_delims_pct, self::$sub_delims_pct); |
||||
$this->template = $template; |
||||
} |
||||
|
||||
public function expand($data) { |
||||
// Modification to make this a bit more performant (since gettype is very slow) |
||||
if (! is_array($data)) { |
||||
$data = (array)$data; |
||||
} |
||||
/* |
||||
// Original code, which uses a slow gettype() statement, kept in place for if the assumption that is_array always works here is incorrect |
||||
switch (gettype($data)) { |
||||
case "boolean": |
||||
case "integer": |
||||
case "double": |
||||
case "string": |
||||
case "object": |
||||
$data = (array)$data; |
||||
break; |
||||
} |
||||
*/ |
||||
|
||||
// Resolve template vars |
||||
preg_match_all('/\{([^\}]*)\}/', $this->template, $em); |
||||
|
||||
foreach ($em[1] as $i => $bare_expression) { |
||||
preg_match('/^([\+\;\?\/\.]{1})?(.*)$/', $bare_expression, $lm); |
||||
$exp = new StdClass(); |
||||
$exp->expression = $em[0][$i]; |
||||
$exp->operator = $lm[1]; |
||||
$exp->variable_list = $lm[2]; |
||||
$exp->varspecs = explode(',', $exp->variable_list); |
||||
$exp->vars = array(); |
||||
foreach ($exp->varspecs as $varspec) { |
||||
preg_match('/^([a-zA-Z0-9_]+)([\*\+]{1})?([\:\^][0-9-]+)?(\=[^,]+)?$/', $varspec, $vm); |
||||
$var = new StdClass(); |
||||
$var->name = $vm[1]; |
||||
$var->modifier = isset($vm[2]) && $vm[2] ? $vm[2] : null; |
||||
$var->modifier = isset($vm[3]) && $vm[3] ? $vm[3] : $var->modifier; |
||||
$var->default = isset($vm[4]) ? substr($vm[4], 1) : null; |
||||
$exp->vars[] = $var; |
||||
} |
||||
|
||||
// Add processing flags |
||||
$exp->reserved = false; |
||||
$exp->prefix = ''; |
||||
$exp->delimiter = ','; |
||||
switch ($exp->operator) { |
||||
case '+': |
||||
$exp->reserved = 'true'; |
||||
break; |
||||
case ';': |
||||
$exp->prefix = ';'; |
||||
$exp->delimiter = ';'; |
||||
break; |
||||
case '?': |
||||
$exp->prefix = '?'; |
||||
$exp->delimiter = '&'; |
||||
break; |
||||
case '/': |
||||
$exp->prefix = '/'; |
||||
$exp->delimiter = '/'; |
||||
break; |
||||
case '.': |
||||
$exp->prefix = '.'; |
||||
$exp->delimiter = '.'; |
||||
break; |
||||
} |
||||
$expressions[] = $exp; |
||||
} |
||||
|
||||
// Expansion |
||||
$this->expansion = $this->template; |
||||
|
||||
foreach ($expressions as $exp) { |
||||
$part = $exp->prefix; |
||||
$exp->one_var_defined = false; |
||||
foreach ($exp->vars as $var) { |
||||
$val = ''; |
||||
if ($exp->one_var_defined && isset($data[$var->name])) { |
||||
$part .= $exp->delimiter; |
||||
} |
||||
// Variable present |
||||
if (isset($data[$var->name])) { |
||||
$exp->one_var_defined = true; |
||||
$var->data = $data[$var->name]; |
||||
|
||||
$val = self::val_from_var($var, $exp); |
||||
|
||||
// Variable missing |
||||
} else { |
||||
if ($var->default) { |
||||
$exp->one_var_defined = true; |
||||
$val = $var->default; |
||||
} |
||||
} |
||||
$part .= $val; |
||||
} |
||||
if (! $exp->one_var_defined) $part = ''; |
||||
$this->expansion = str_replace($exp->expression, $part, $this->expansion); |
||||
} |
||||
|
||||
return $this->expansion; |
||||
} |
||||
|
||||
private function val_from_var($var, $exp) { |
||||
$val = ''; |
||||
if (is_array($var->data)) { |
||||
$i = 0; |
||||
if ($exp->operator == '?' && ! $var->modifier) { |
||||
$val .= $var->name . '='; |
||||
} |
||||
foreach ($var->data as $k => $v) { |
||||
$del = $var->modifier ? $exp->delimiter : ','; |
||||
$ek = rawurlencode($k); |
||||
$ev = rawurlencode($v); |
||||
|
||||
// Array |
||||
if ($k !== $i) { |
||||
if ($var->modifier == '+') { |
||||
$val .= $var->name . '.'; |
||||
} |
||||
if ($exp->operator == '?' && $var->modifier || $exp->operator == ';' && $var->modifier == '*' || $exp->operator == ';' && $var->modifier == '+') { |
||||
$val .= $ek . '='; |
||||
} else { |
||||
$val .= $ek . $del; |
||||
} |
||||
|
||||
// List |
||||
} else { |
||||
if ($var->modifier == '+') { |
||||
if ($exp->operator == ';' && $var->modifier == '*' || $exp->operator == ';' && $var->modifier == '+' || $exp->operator == '?' && $var->modifier == '+') { |
||||
$val .= $var->name . '='; |
||||
} else { |
||||
$val .= $var->name . '.'; |
||||
} |
||||
} |
||||
} |
||||
$val .= $ev . $del; |
||||
$i ++; |
||||
} |
||||
$val = trim($val, $del); |
||||
|
||||
// Strings, numbers, etc. |
||||
} else { |
||||
if ($exp->operator == '?') { |
||||
$val = $var->name . (isset($var->data) ? '=' : ''); |
||||
} else if ($exp->operator == ';') { |
||||
$val = $var->name . ($var->data ? '=' : ''); |
||||
} |
||||
$val .= rawurlencode($var->data); |
||||
if ($exp->operator == '+') { |
||||
$val = str_replace(self::$reserved_pct, self::$reserved, $val); |
||||
} |
||||
} |
||||
return $val; |
||||
} |
||||
|
||||
public function match($uri) {} |
||||
|
||||
public function __toString() { |
||||
return $this->template; |
||||
} |
||||
} |
@ -0,0 +1,173 @@ |
||||
<?php |
||||
/* |
||||
* Copyright 2012 Google Inc. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0 |
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
/** |
||||
* Implement the caching directives specified in rfc2616. This |
||||
* implementation is guided by the guidance offered in rfc2616-sec13. |
||||
* @author Chirag Shah <chirags@google.com> |
||||
*/ |
||||
class Google_CacheParser { |
||||
public static $CACHEABLE_HTTP_METHODS = array('GET', 'HEAD'); |
||||
public static $CACHEABLE_STATUS_CODES = array('200', '203', '300', '301'); |
||||
|
||||
private function __construct() {} |
||||
|
||||
/** |
||||
* Check if an HTTP request can be cached by a private local cache. |
||||
* |
||||
* @static |
||||
* @param Google_HttpRequest $resp |
||||
* @return bool True if the request is cacheable. |
||||
* False if the request is uncacheable. |
||||
*/ |
||||
public static function isRequestCacheable (Google_HttpRequest $resp) { |
||||
$method = $resp->getRequestMethod(); |
||||
if (! in_array($method, self::$CACHEABLE_HTTP_METHODS)) { |
||||
return false; |
||||
} |
||||
|
||||
// Don't cache authorized requests/responses. |
||||
// [rfc2616-14.8] When a shared cache receives a request containing an |
||||
// Authorization field, it MUST NOT return the corresponding response |
||||
// as a reply to any other request... |
||||
if ($resp->getRequestHeader("authorization")) { |
||||
return false; |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
|
||||
/** |
||||
* Check if an HTTP response can be cached by a private local cache. |
||||
* |
||||
* @static |
||||
* @param Google_HttpRequest $resp |
||||
* @return bool True if the response is cacheable. |
||||
* False if the response is un-cacheable. |
||||
*/ |
||||
public static function isResponseCacheable (Google_HttpRequest $resp) { |
||||
// First, check if the HTTP request was cacheable before inspecting the |
||||
// HTTP response. |
||||
if (false == self::isRequestCacheable($resp)) { |
||||
return false; |
||||
} |
||||
|
||||
$code = $resp->getResponseHttpCode(); |
||||
if (! in_array($code, self::$CACHEABLE_STATUS_CODES)) { |
||||
return false; |
||||
} |
||||
|
||||
// The resource is uncacheable if the resource is already expired and |
||||
// the resource doesn't have an ETag for revalidation. |
||||
$etag = $resp->getResponseHeader("etag"); |
||||
if (self::isExpired($resp) && $etag == false) { |
||||
return false; |
||||
} |
||||
|
||||
// [rfc2616-14.9.2] If [no-store is] sent in a response, a cache MUST NOT |
||||
// store any part of either this response or the request that elicited it. |
||||
$cacheControl = $resp->getParsedCacheControl(); |
||||
if (isset($cacheControl['no-store'])) { |
||||
return false; |
||||
} |
||||
|
||||
// Pragma: no-cache is an http request directive, but is occasionally |
||||
// used as a response header incorrectly. |
||||
$pragma = $resp->getResponseHeader('pragma'); |
||||
if ($pragma == 'no-cache' || strpos($pragma, 'no-cache') !== false) { |
||||
return false; |
||||
} |
||||
|
||||
// [rfc2616-14.44] Vary: * is extremely difficult to cache. "It implies that |
||||
// a cache cannot determine from the request headers of a subsequent request |
||||
// whether this response is the appropriate representation." |
||||
// Given this, we deem responses with the Vary header as uncacheable. |
||||
$vary = $resp->getResponseHeader('vary'); |
||||
if ($vary) { |
||||
return false; |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
|
||||
/** |
||||
* @static |
||||
* @param Google_HttpRequest $resp |
||||
* @return bool True if the HTTP response is considered to be expired. |
||||
* False if it is considered to be fresh. |
||||
*/ |
||||
public static function isExpired(Google_HttpRequest $resp) { |
||||
// HTTP/1.1 clients and caches MUST treat other invalid date formats, |
||||
// especially including the value “0”, as in the past. |
||||
$parsedExpires = false; |
||||
$responseHeaders = $resp->getResponseHeaders(); |
||||
if (isset($responseHeaders['expires'])) { |
||||
$rawExpires = $responseHeaders['expires']; |
||||
// Check for a malformed expires header first. |
||||
if (empty($rawExpires) || (is_numeric($rawExpires) && $rawExpires <= 0)) { |
||||
return true; |
||||
} |
||||
|
||||
// See if we can parse the expires header. |
||||
$parsedExpires = strtotime($rawExpires); |
||||
if (false == $parsedExpires || $parsedExpires <= 0) { |
||||
return true; |
||||
} |
||||
} |
||||
|
||||
// Calculate the freshness of an http response. |
||||
$freshnessLifetime = false; |
||||
$cacheControl = $resp->getParsedCacheControl(); |
||||
if (isset($cacheControl['max-age'])) { |
||||
$freshnessLifetime = $cacheControl['max-age']; |
||||
} |
||||
|
||||
$rawDate = $resp->getResponseHeader('date'); |
||||
$parsedDate = strtotime($rawDate); |
||||
|
||||
if (empty($rawDate) || false == $parsedDate) { |
||||
$parsedDate = time(); |
||||
} |
||||
if (false == $freshnessLifetime && isset($responseHeaders['expires'])) { |
||||
$freshnessLifetime = $parsedExpires - $parsedDate; |
||||
} |
||||
|
||||
if (false == $freshnessLifetime) { |
||||
return true; |
||||
} |
||||
|
||||
// Calculate the age of an http response. |
||||
$age = max(0, time() - $parsedDate); |
||||
if (isset($responseHeaders['age'])) { |
||||
$age = max($age, strtotime($responseHeaders['age'])); |
||||
} |
||||
|
||||
return $freshnessLifetime <= $age; |
||||
} |
||||
|
||||
/** |
||||
* Determine if a cache entry should be revalidated with by the origin. |
||||
* |
||||
* @param Google_HttpRequest $response |
||||
* @return bool True if the entry is expired, else return false. |
||||
*/ |
||||
public static function mustRevalidate(Google_HttpRequest $response) { |
||||
// [13.3] When a cache has a stale entry that it would like to use as a |
||||
// response to a client's request, it first has to check with the origin |
||||
// server to see if its cached entry is still usable. |
||||
return self::isExpired($response); |
||||
} |
||||
} |
@ -0,0 +1,278 @@ |
||||
<?php |
||||
/* |
||||
* Copyright 2010 Google Inc. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0 |
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
/** |
||||
* Curl based implementation of apiIO. |
||||
* |
||||
* @author Chris Chabot <chabotc@google.com> |
||||
* @author Chirag Shah <chirags@google.com> |
||||
*/ |
||||
|
||||
require_once 'Google_CacheParser.php'; |
||||
|
||||
class Google_CurlIO implements Google_IO { |
||||
const CONNECTION_ESTABLISHED = "HTTP/1.0 200 Connection established\r\n\r\n"; |
||||
const FORM_URLENCODED = 'application/x-www-form-urlencoded'; |
||||
|
||||
private static $ENTITY_HTTP_METHODS = array("POST" => null, "PUT" => null); |
||||
private static $HOP_BY_HOP = array( |
||||
'connection', 'keep-alive', 'proxy-authenticate', 'proxy-authorization', |
||||
'te', 'trailers', 'transfer-encoding', 'upgrade'); |
||||
|
||||
private $curlParams = array ( |
||||
CURLOPT_RETURNTRANSFER => true, |
||||
CURLOPT_FOLLOWLOCATION => 0, |
||||
CURLOPT_FAILONERROR => false, |
||||
CURLOPT_SSL_VERIFYPEER => true, |
||||
CURLOPT_HEADER => true, |
||||
CURLOPT_VERBOSE => false, |
||||
); |
||||
|
||||
/** |
||||
* Perform an authenticated / signed apiHttpRequest. |
||||
* This function takes the apiHttpRequest, calls apiAuth->sign on it |
||||
* (which can modify the request in what ever way fits the auth mechanism) |
||||
* and then calls apiCurlIO::makeRequest on the signed request |
||||
* |
||||
* @param Google_HttpRequest $request |
||||
* @return Google_HttpRequest The resulting HTTP response including the |
||||
* responseHttpCode, responseHeaders and responseBody. |
||||
*/ |
||||
public function authenticatedRequest(Google_HttpRequest $request) { |
||||
$request = Google_Client::$auth->sign($request); |
||||
return $this->makeRequest($request); |
||||
} |
||||
|
||||
/** |
||||
* Execute a apiHttpRequest |
||||
* |
||||
* @param Google_HttpRequest $request the http request to be executed |
||||
* @return Google_HttpRequest http request with the response http code, response |
||||
* headers and response body filled in |
||||
* @throws Google_IOException on curl or IO error |
||||
*/ |
||||
public function makeRequest(Google_HttpRequest $request) { |
||||
// First, check to see if we have a valid cached version. |
||||
$cached = $this->getCachedRequest($request); |
||||
if ($cached !== false) { |
||||
if (Google_CacheParser::mustRevalidate($cached)) { |
||||
$addHeaders = array(); |
||||
if ($cached->getResponseHeader('etag')) { |
||||
// [13.3.4] If an entity tag has been provided by the origin server, |
||||
// we must use that entity tag in any cache-conditional request. |
||||
$addHeaders['If-None-Match'] = $cached->getResponseHeader('etag'); |
||||
} elseif ($cached->getResponseHeader('date')) { |
||||
$addHeaders['If-Modified-Since'] = $cached->getResponseHeader('date'); |
||||
} |
||||
|
||||
$request->setRequestHeaders($addHeaders); |
||||
} else { |
||||
// No need to revalidate the request, return it directly |
||||
return $cached; |
||||
} |
||||
} |
||||
|
||||
if (array_key_exists($request->getRequestMethod(), |
||||
self::$ENTITY_HTTP_METHODS)) { |
||||
$request = $this->processEntityRequest($request); |
||||
} |
||||
|
||||
$ch = curl_init(); |
||||
curl_setopt_array($ch, $this->curlParams); |
||||
curl_setopt($ch, CURLOPT_URL, $request->getUrl()); |
||||
if ($request->getPostBody()) { |
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $request->getPostBody()); |
||||
} |
||||
|
||||
$requestHeaders = $request->getRequestHeaders(); |
||||
if ($requestHeaders && is_array($requestHeaders)) { |
||||
$parsed = array(); |
||||
foreach ($requestHeaders as $k => $v) { |
||||
$parsed[] = "$k: $v"; |
||||
} |
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $parsed); |
||||
} |
||||
|
||||
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $request->getRequestMethod()); |
||||
curl_setopt($ch, CURLOPT_USERAGENT, $request->getUserAgent()); |
||||
$respData = curl_exec($ch); |
||||
|
||||
// Retry if certificates are missing. |
||||
if (curl_errno($ch) == CURLE_SSL_CACERT) { |
||||
error_log('SSL certificate problem, verify that the CA cert is OK.' |
||||
. ' Retrying with the CA cert bundle from google-api-php-client.'); |
||||
curl_setopt($ch, CURLOPT_CAINFO, dirname(__FILE__) . '/cacerts.pem'); |
||||
$respData = curl_exec($ch); |
||||
} |
||||
|
||||
$respHeaderSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE); |
||||
$respHttpCode = (int) curl_getinfo($ch, CURLINFO_HTTP_CODE); |
||||
$curlErrorNum = curl_errno($ch); |
||||
$curlError = curl_error($ch); |
||||
curl_close($ch); |
||||
if ($curlErrorNum != CURLE_OK) { |
||||
throw new Google_IOException("HTTP Error: ($respHttpCode) $curlError"); |
||||
} |
||||
|
||||
// Parse out the raw response into usable bits |
||||
list($responseHeaders, $responseBody) = |
||||
self::parseHttpResponse($respData, $respHeaderSize); |
||||
|
||||
if ($respHttpCode == 304 && $cached) { |
||||
// If the server responded NOT_MODIFIED, return the cached request. |
||||
if (isset($responseHeaders['connection'])) { |
||||
$hopByHop = array_merge( |
||||
self::$HOP_BY_HOP, |
||||
explode(',', $responseHeaders['connection']) |
||||
); |
||||
|
||||
$endToEnd = array(); |
||||
foreach($hopByHop as $key) { |
||||
if (isset($responseHeaders[$key])) { |
||||
$endToEnd[$key] = $responseHeaders[$key]; |
||||
} |
||||
} |
||||
$cached->setResponseHeaders($endToEnd); |
||||
} |
||||
return $cached; |
||||
} |
||||
|
||||
// Fill in the apiHttpRequest with the response values |
||||
$request->setResponseHttpCode($respHttpCode); |
||||
$request->setResponseHeaders($responseHeaders); |
||||
$request->setResponseBody($responseBody); |
||||
// Store the request in cache (the function checks to see if the request |
||||
// can actually be cached) |
||||
$this->setCachedRequest($request); |
||||
// And finally return it |
||||
return $request; |
||||
} |
||||
|
||||
/** |
||||
* @visible for testing. |
||||
* Cache the response to an HTTP request if it is cacheable. |
||||
* @param Google_HttpRequest $request |
||||
* @return bool Returns true if the insertion was successful. |
||||
* Otherwise, return false. |
||||
*/ |
||||
public function setCachedRequest(Google_HttpRequest $request) { |
||||
// Determine if the request is cacheable. |
||||
if (Google_CacheParser::isResponseCacheable($request)) { |
||||
Google_Client::$cache->set($request->getCacheKey(), $request); |
||||
return true; |
||||
} |
||||
|
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* @visible for testing. |
||||
* @param Google_HttpRequest $request |
||||
* @return Google_HttpRequest|bool Returns the cached object or |
||||
* false if the operation was unsuccessful. |
||||
*/ |
||||
public function getCachedRequest(Google_HttpRequest $request) { |
||||
if (false == Google_CacheParser::isRequestCacheable($request)) { |
||||
false; |
||||
} |
||||
|
||||
return Google_Client::$cache->get($request->getCacheKey()); |
||||
} |
||||
|
||||
/** |
||||
* @param $respData |
||||
* @param $headerSize |
||||
* @return array |
||||
*/ |
||||
public static function parseHttpResponse($respData, $headerSize) { |
||||
if (stripos($respData, self::CONNECTION_ESTABLISHED) !== false) { |
||||
$respData = str_ireplace(self::CONNECTION_ESTABLISHED, '', $respData); |
||||
} |
||||
|
||||
if ($headerSize) { |
||||
$responseBody = substr($respData, $headerSize); |
||||
$responseHeaders = substr($respData, 0, $headerSize); |
||||
} else { |
||||
list($responseHeaders, $responseBody) = explode("\r\n\r\n", $respData, 2); |
||||
} |
||||
|
||||
$responseHeaders = self::parseResponseHeaders($responseHeaders); |
||||
return array($responseHeaders, $responseBody); |
||||
} |
||||
|
||||
public static function parseResponseHeaders($rawHeaders) { |
||||
$responseHeaders = array(); |
||||
|
||||
$responseHeaderLines = explode("\r\n", $rawHeaders); |
||||
foreach ($responseHeaderLines as $headerLine) { |
||||
if ($headerLine && strpos($headerLine, ':') !== false) { |
||||
list($header, $value) = explode(': ', $headerLine, 2); |
||||
$header = strtolower($header); |
||||
if (isset($responseHeaders[$header])) { |
||||
$responseHeaders[$header] .= "\n" . $value; |
||||
} else { |
||||
$responseHeaders[$header] = $value; |
||||
} |
||||
} |
||||
} |
||||
return $responseHeaders; |
||||
} |
||||
|
||||
/** |
||||
* @visible for testing |
||||
* Process an http request that contains an enclosed entity. |
||||
* @param Google_HttpRequest $request |
||||
* @return Google_HttpRequest Processed request with the enclosed entity. |
||||
*/ |
||||
public function processEntityRequest(Google_HttpRequest $request) { |
||||
$postBody = $request->getPostBody(); |
||||
$contentType = $request->getRequestHeader("content-type"); |
||||
|
||||
// Set the default content-type as application/x-www-form-urlencoded. |
||||
if (false == $contentType) { |
||||
$contentType = self::FORM_URLENCODED; |
||||
$request->setRequestHeaders(array('content-type' => $contentType)); |
||||
} |
||||
|
||||
// Force the payload to match the content-type asserted in the header. |
||||
if ($contentType == self::FORM_URLENCODED && is_array($postBody)) { |
||||
$postBody = http_build_query($postBody, '', '&'); |
||||
$request->setPostBody($postBody); |
||||
} |
||||
|
||||
// Make sure the content-length header is set. |
||||
if (!$postBody || is_string($postBody)) { |
||||
$postsLength = strlen($postBody); |
||||
$request->setRequestHeaders(array('content-length' => $postsLength)); |
||||
} |
||||
|
||||
return $request; |
||||
} |
||||
|
||||
/** |
||||
* Set options that update cURL's default behavior. |
||||
* The list of accepted options are: |
||||
* {@link http://php.net/manual/en/function.curl-setopt.php] |
||||
* |
||||
* @param array $optCurlParams Multiple options used by a cURL session. |
||||
*/ |
||||
public function setOptions($optCurlParams) { |
||||
foreach ($optCurlParams as $key => $val) { |
||||
$this->curlParams[$key] = $val; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,304 @@ |
||||
<?php |
||||
/* |
||||
* Copyright 2010 Google Inc. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0 |
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
/** |
||||
* HTTP Request to be executed by apiIO classes. Upon execution, the |
||||
* responseHttpCode, responseHeaders and responseBody will be filled in. |
||||
* |
||||
* @author Chris Chabot <chabotc@google.com> |
||||
* @author Chirag Shah <chirags@google.com> |
||||
* |
||||
*/ |
||||
class Google_HttpRequest { |
||||
const USER_AGENT_SUFFIX = "google-api-php-client/0.6.0"; |
||||
private $batchHeaders = array( |
||||
'Content-Type' => 'application/http', |
||||
'Content-Transfer-Encoding' => 'binary', |
||||
'MIME-Version' => '1.0', |
||||
'Content-Length' => '' |
||||
); |
||||
|
||||
protected $url; |
||||
protected $requestMethod; |
||||
protected $requestHeaders; |
||||
protected $postBody; |
||||
protected $userAgent; |
||||
|
||||
protected $responseHttpCode; |
||||
protected $responseHeaders; |
||||
protected $responseBody; |
||||
|
||||
public $accessKey; |
||||
|
||||
public function __construct($url, $method = 'GET', $headers = array(), $postBody = null) { |
||||
$this->setUrl($url); |
||||
$this->setRequestMethod($method); |
||||
$this->setRequestHeaders($headers); |
||||
$this->setPostBody($postBody); |
||||
|
||||
global $apiConfig; |
||||
if (empty($apiConfig['application_name'])) { |
||||
$this->userAgent = self::USER_AGENT_SUFFIX; |
||||
} else { |
||||
$this->userAgent = $apiConfig['application_name'] . " " . self::USER_AGENT_SUFFIX; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Misc function that returns the base url component of the $url |
||||
* used by the OAuth signing class to calculate the base string |
||||
* @return string The base url component of the $url. |
||||
* @see http://oauth.net/core/1.0a/#anchor13 |
||||
*/ |
||||
public function getBaseUrl() { |
||||
if ($pos = strpos($this->url, '?')) { |
||||
return substr($this->url, 0, $pos); |
||||
} |
||||
return $this->url; |
||||
} |
||||
|
||||
/** |
||||
* Misc function that returns an array of the query parameters of the current |
||||
* url used by the OAuth signing class to calculate the signature |
||||
* @return array Query parameters in the query string. |
||||
*/ |
||||
public function getQueryParams() { |
||||
if ($pos = strpos($this->url, '?')) { |
||||
$queryStr = substr($this->url, $pos + 1); |
||||
$params = array(); |
||||
parse_str($queryStr, $params); |
||||
return $params; |
||||
} |
||||
return array(); |
||||
} |
||||
|
||||
/** |
||||
* @return string HTTP Response Code. |
||||
*/ |
||||
public function getResponseHttpCode() { |
||||
return (int) $this->responseHttpCode; |
||||
} |
||||
|
||||
/** |
||||
* @param int $responseHttpCode HTTP Response Code. |
||||
*/ |
||||
public function setResponseHttpCode($responseHttpCode) { |
||||
$this->responseHttpCode = $responseHttpCode; |
||||
} |
||||
|
||||
/** |
||||
* @return $responseHeaders (array) HTTP Response Headers. |
||||
*/ |
||||
public function getResponseHeaders() { |
||||
return $this->responseHeaders; |
||||
} |
||||
|
||||
/** |
||||
* @return string HTTP Response Body |
||||
*/ |
||||
public function getResponseBody() { |
||||
return $this->responseBody; |
||||
} |
||||
|
||||
/** |
||||
* @param array $headers The HTTP response headers |
||||
* to be normalized. |
||||
*/ |
||||
public function setResponseHeaders($headers) { |
||||
$headers = Google_Utils::normalize($headers); |
||||
if ($this->responseHeaders) { |
||||
$headers = array_merge($this->responseHeaders, $headers); |
||||
} |
||||
|
||||
$this->responseHeaders = $headers; |
||||
} |
||||
|
||||
/** |
||||
* @param string $key |
||||
* @return array|boolean Returns the requested HTTP header or |
||||
* false if unavailable. |
||||
*/ |
||||
public function getResponseHeader($key) { |
||||
return isset($this->responseHeaders[$key]) |
||||
? $this->responseHeaders[$key] |
||||
: false; |
||||
} |
||||
|
||||
/** |
||||
* @param string $responseBody The HTTP response body. |
||||
*/ |
||||
public function setResponseBody($responseBody) { |
||||
$this->responseBody = $responseBody; |
||||
} |
||||
|
||||
/** |
||||
* @return string $url The request URL. |
||||
*/ |
||||
|
||||
public function getUrl() { |
||||
return $this->url; |
||||
} |
||||
|
||||
/** |
||||
* @return string $method HTTP Request Method. |
||||
*/ |
||||
public function getRequestMethod() { |
||||
return $this->requestMethod; |
||||
} |
||||
|
||||
/** |
||||
* @return array $headers HTTP Request Headers. |
||||
*/ |
||||
public function getRequestHeaders() { |
||||
return $this->requestHeaders; |
||||
} |
||||
|
||||
/** |
||||
* @param string $key |
||||
* @return array|boolean Returns the requested HTTP header or |
||||
* false if unavailable. |
||||
*/ |
||||
public function getRequestHeader($key) { |
||||
return isset($this->requestHeaders[$key]) |
||||
? $this->requestHeaders[$key] |
||||
: false; |
||||
} |
||||
|
||||
/** |
||||
* @return string $postBody HTTP Request Body. |
||||
*/ |
||||
public function getPostBody() { |
||||
return $this->postBody; |
||||
} |
||||
|
||||
/** |
||||
* @param string $url the url to set |
||||
*/ |
||||
public function setUrl($url) { |
||||
if (substr($url, 0, 4) == 'http') { |
||||
$this->url = $url; |
||||
} else { |
||||
// Force the path become relative. |
||||
if (substr($url, 0, 1) !== '/') { |
||||
$url = '/' . $url; |
||||
} |
||||
global $apiConfig; |
||||
$this->url = $apiConfig['basePath'] . $url; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* @param string $method Set he HTTP Method and normalize |
||||
* it to upper-case, as required by HTTP. |
||||
* |
||||
*/ |
||||
public function setRequestMethod($method) { |
||||
$this->requestMethod = strtoupper($method); |
||||
} |
||||
|
||||
/** |
||||
* @param array $headers The HTTP request headers |
||||
* to be set and normalized. |
||||
*/ |
||||
public function setRequestHeaders($headers) { |
||||
$headers = Google_Utils::normalize($headers); |
||||
if ($this->requestHeaders) { |
||||
$headers = array_merge($this->requestHeaders, $headers); |
||||
} |
||||
$this->requestHeaders = $headers; |
||||
} |
||||
|
||||
/** |
||||
* @param string $postBody the postBody to set |
||||
*/ |
||||
public function setPostBody($postBody) { |
||||
$this->postBody = $postBody; |
||||
} |
||||
|
||||
/** |
||||
* Set the User-Agent Header. |
||||
* @param string $userAgent The User-Agent. |
||||
*/ |
||||
public function setUserAgent($userAgent) { |
||||
$this->userAgent = $userAgent; |
||||
} |
||||
|
||||
/** |
||||
* @return string The User-Agent. |
||||
*/ |
||||
public function getUserAgent() { |
||||
return $this->userAgent; |
||||
} |
||||
|
||||
/** |
||||
* Returns a cache key depending on if this was an OAuth signed request |
||||
* in which case it will use the non-signed url and access key to make this |
||||
* cache key unique per authenticated user, else use the plain request url |
||||
* @return string The md5 hash of the request cache key. |
||||
*/ |
||||
public function getCacheKey() { |
||||
$key = $this->getUrl(); |
||||
|
||||
if (isset($this->accessKey)) { |
||||
$key .= $this->accessKey; |
||||
} |
||||
|
||||
if (isset($this->requestHeaders['authorization'])) { |
||||
$key .= $this->requestHeaders['authorization']; |
||||
} |
||||
|
||||
return md5($key); |
||||
} |
||||
|
||||
public function getParsedCacheControl() { |
||||
$parsed = array(); |
||||
$rawCacheControl = $this->getResponseHeader('cache-control'); |
||||
if ($rawCacheControl) { |
||||
$rawCacheControl = str_replace(', ', '&', $rawCacheControl); |
||||
parse_str($rawCacheControl, $parsed); |
||||
} |
||||
|
||||
return $parsed; |
||||
} |
||||
|
||||
/** |
||||
* @param string $id |
||||
* @return string A string representation of the HTTP Request. |
||||
*/ |
||||
public function toBatchString($id) { |
||||
$str = ''; |
||||
foreach($this->batchHeaders as $key => $val) { |
||||
$str .= $key . ': ' . $val . "\n"; |
||||
} |
||||
|
||||
$str .= "Content-ID: $id\n"; |
||||
$str .= "\n"; |
||||
|
||||
$path = parse_url($this->getUrl(), PHP_URL_PATH); |
||||
$str .= $this->getRequestMethod() . ' ' . $path . " HTTP/1.1\n"; |
||||
foreach($this->getRequestHeaders() as $key => $val) { |
||||
$str .= $key . ': ' . $val . "\n"; |
||||
} |
||||
|
||||
if ($this->getPostBody()) { |
||||
$str .= "\n"; |
||||
$str .= $this->getPostBody(); |
||||
} |
||||
|
||||
return $str; |
||||
} |
||||
} |
@ -0,0 +1,49 @@ |
||||
<?php |
||||
/** |
||||
* Copyright 2010 Google Inc. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0 |
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
require_once 'io/Google_HttpRequest.php'; |
||||
require_once 'io/Google_CurlIO.php'; |
||||
require_once 'io/Google_REST.php'; |
||||
|
||||
/** |
||||
* Abstract IO class |
||||
* |
||||
* @author Chris Chabot <chabotc@google.com> |
||||
*/ |
||||
interface Google_IO { |
||||
/** |
||||
* An utility function that first calls $this->auth->sign($request) and then executes makeRequest() |
||||
* on that signed request. Used for when a request should be authenticated |
||||
* @param Google_HttpRequest $request |
||||
* @return Google_HttpRequest $request |
||||
*/ |
||||
public function authenticatedRequest(Google_HttpRequest $request); |
||||
|
||||
/** |
||||
* Executes a apIHttpRequest and returns the resulting populated httpRequest |
||||
* @param Google_HttpRequest $request |
||||
* @return Google_HttpRequest $request |
||||
*/ |
||||
public function makeRequest(Google_HttpRequest $request); |
||||
|
||||
/** |
||||
* Set options that update the transport implementation's behavior. |
||||
* @param $options |
||||
*/ |
||||
public function setOptions($options); |
||||
|
||||
} |
@ -0,0 +1,128 @@ |
||||
<?php |
||||
/* |
||||
* Copyright 2010 Google Inc. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0 |
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
/** |
||||
* This class implements the RESTful transport of apiServiceRequest()'s |
||||
* |
||||
* @author Chris Chabot <chabotc@google.com> |
||||
* @author Chirag Shah <chirags@google.com> |
||||
*/ |
||||
class Google_REST { |
||||
/** |
||||
* Executes a apiServiceRequest using a RESTful call by transforming it into |
||||
* an apiHttpRequest, and executed via apiIO::authenticatedRequest(). |
||||
* |
||||
* @param Google_HttpRequest $req |
||||
* @return array decoded result |
||||
* @throws Google_ServiceException on server side error (ie: not authenticated, |
||||
* invalid or malformed post body, invalid url) |
||||
*/ |
||||
static public function execute(Google_HttpRequest $req) { |
||||
$httpRequest = Google_Client::$io->makeRequest($req); |
||||
$decodedResponse = self::decodeHttpResponse($httpRequest); |
||||
$ret = isset($decodedResponse['data']) |
||||
? $decodedResponse['data'] : $decodedResponse; |
||||
return $ret; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Decode an HTTP Response. |
||||
* @static |
||||
* @throws Google_ServiceException |
||||
* @param Google_HttpRequest $response The http response to be decoded. |
||||
* @return mixed|null |
||||
*/ |
||||
public static function decodeHttpResponse($response) { |
||||
$code = $response->getResponseHttpCode(); |
||||
$body = $response->getResponseBody(); |
||||
$decoded = null; |
||||
|
||||
if ((intVal($code)) >= 300) { |
||||
$decoded = json_decode($body, true); |
||||
$err = 'Error calling ' . $response->getRequestMethod() . ' ' . $response->getUrl(); |
||||
if ($decoded != null && isset($decoded['error']['message']) && isset($decoded['error']['code'])) { |
||||
// if we're getting a json encoded error definition, use that instead of the raw response |
||||
// body for improved readability |
||||
$err .= ": ({$decoded['error']['code']}) {$decoded['error']['message']}"; |
||||
} else { |
||||
$err .= ": ($code) $body"; |
||||
} |
||||
|
||||
throw new Google_ServiceException($err, $code, null, $decoded['error']['errors']); |
||||
} |
||||
|
||||
// Only attempt to decode the response, if the response code wasn't (204) 'no content' |
||||
if ($code != '204') { |
||||
$decoded = json_decode($body, true); |
||||
if ($decoded === null || $decoded === "") { |
||||
throw new Google_ServiceException("Invalid json in service response: $body"); |
||||
} |
||||
} |
||||
return $decoded; |
||||
} |
||||
|
||||
/** |
||||
* Parse/expand request parameters and create a fully qualified |
||||
* request uri. |
||||
* @static |
||||
* @param string $servicePath |
||||
* @param string $restPath |
||||
* @param array $params |
||||
* @return string $requestUrl |
||||
*/ |
||||
static function createRequestUri($servicePath, $restPath, $params) { |
||||
$requestUrl = $servicePath . $restPath; |
||||
$uriTemplateVars = array(); |
||||
$queryVars = array(); |
||||
foreach ($params as $paramName => $paramSpec) { |
||||
// Discovery v1.0 puts the canonical location under the 'location' field. |
||||
if (! isset($paramSpec['location'])) { |
||||
$paramSpec['location'] = $paramSpec['restParameterType']; |
||||
} |
||||
|
||||
if ($paramSpec['type'] == 'boolean') { |
||||
$paramSpec['value'] = ($paramSpec['value']) ? 'true' : 'false'; |
||||
} |
||||
if ($paramSpec['location'] == 'path') { |
||||
$uriTemplateVars[$paramName] = $paramSpec['value']; |
||||
} else { |
||||
if (isset($paramSpec['repeated']) && is_array($paramSpec['value'])) { |
||||
foreach ($paramSpec['value'] as $value) { |
||||
$queryVars[] = $paramName . '=' . rawurlencode($value); |
||||
} |
||||
} else { |
||||
$queryVars[] = $paramName . '=' . rawurlencode($paramSpec['value']); |
||||
} |
||||
} |
||||
} |
||||
|
||||
if (count($uriTemplateVars)) { |
||||
$uriTemplateParser = new URI_Template_Parser($requestUrl); |
||||
$requestUrl = $uriTemplateParser->expand($uriTemplateVars); |
||||
} |
||||
//FIXME work around for the the uri template lib which url encodes |
||||
// the @'s & confuses our servers. |
||||
$requestUrl = str_replace('%40', '@', $requestUrl); |
||||
|
||||
if (count($queryVars)) { |
||||
$requestUrl .= '?' . implode($queryVars, '&'); |
||||
} |
||||
|
||||
return $requestUrl; |
||||
} |
||||
} |
@ -0,0 +1,714 @@ |
||||
# Certifcate Authority certificates for validating SSL connections. |
||||
# |
||||
# This file contains PEM format certificates generated from |
||||
# http://mxr.mozilla.org/seamonkey/source/security/nss/lib/ckfw/builtins/certdata.txt |
||||
# |
||||
# ***** BEGIN LICENSE BLOCK ***** |
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1 |
||||
# |
||||
# The contents of this file are subject to the Mozilla Public License Version |
||||
# 1.1 (the "License"); you may not use this file except in compliance with |
||||
# the License. You may obtain a copy of the License at |
||||
# http://www.mozilla.org/MPL/ |
||||
# |
||||
# Software distributed under the License is distributed on an "AS IS" basis, |
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License |
||||
# for the specific language governing rights and limitations under the |
||||
# License. |
||||
# |
||||
# The Original Code is the Netscape security libraries. |
||||
# |
||||
# The Initial Developer of the Original Code is |
||||
# Netscape Communications Corporation. |
||||
# Portions created by the Initial Developer are Copyright (C) 1994-2000 |
||||
# the Initial Developer. All Rights Reserved. |
||||
# |
||||
# Contributor(s): |
||||
# |
||||
# Alternatively, the contents of this file may be used under the terms of |
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or |
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), |
||||
# in which case the provisions of the GPL or the LGPL are applicable instead |
||||
# of those above. If you wish to allow use of your version of this file only |
||||
# under the terms of either the GPL or the LGPL, and not to allow others to |
||||
# use your version of this file under the terms of the MPL, indicate your |
||||
# decision by deleting the provisions above and replace them with the notice |
||||
# and other provisions required by the GPL or the LGPL. If you do not delete |
||||
# the provisions above, a recipient may use your version of this file under |
||||
# the terms of any one of the MPL, the GPL or the LGPL. |
||||
# |
||||
# ***** END LICENSE BLOCK ***** |
||||
|
||||
Verisign/RSA Secure Server CA |
||||
============================= |
||||
|
||||
-----BEGIN CERTIFICATE----- |
||||
MIICNDCCAaECEAKtZn5ORf5eV288mBle3cAwDQYJKoZIhvcNAQECBQAwXzELMAkG |
||||
A1UEBhMCVVMxIDAeBgNVBAoTF1JTQSBEYXRhIFNlY3VyaXR5LCBJbmMuMS4wLAYD |
||||
VQQLEyVTZWN1cmUgU2VydmVyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk0 |
||||
MTEwOTAwMDAwMFoXDTEwMDEwNzIzNTk1OVowXzELMAkGA1UEBhMCVVMxIDAeBgNV |
||||
BAoTF1JTQSBEYXRhIFNlY3VyaXR5LCBJbmMuMS4wLAYDVQQLEyVTZWN1cmUgU2Vy |
||||
dmVyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGbMA0GCSqGSIb3DQEBAQUAA4GJ |
||||
ADCBhQJ+AJLOesGugz5aqomDV6wlAXYMra6OLDfO6zV4ZFQD5YRAUcm/jwjiioII |
||||
0haGN1XpsSECrXZogZoFokvJSyVmIlZsiAeP94FZbYQHZXATcXY+m3dM41CJVphI |
||||
uR2nKRoTLkoRWZweFdVJVCxzOmmCsZc5nG1wZ0jl3S3WyB57AgMBAAEwDQYJKoZI |
||||
hvcNAQECBQADfgBl3X7hsuyw4jrg7HFGmhkRuNPHoLQDQCYCPgmc4RKz0Vr2N6W3 |
||||
YQO2WxZpO8ZECAyIUwxrl0nHPjXcbLm7qt9cuzovk2C2qUtN8iD3zV9/ZHuO3ABc |
||||
1/p3yjkWWW8O6tO1g39NTUJWdrTJXwT4OPjr0l91X817/OWOgHz8UA== |
||||
-----END CERTIFICATE----- |
||||
|
||||
Thawte Personal Basic CA |
||||
======================== |
||||
|
||||
-----BEGIN CERTIFICATE----- |
||||
MIIDITCCAoqgAwIBAgIBADANBgkqhkiG9w0BAQQFADCByzELMAkGA1UEBhMCWkEx |
||||
FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMRowGAYD |
||||
VQQKExFUaGF3dGUgQ29uc3VsdGluZzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBT |
||||
ZXJ2aWNlcyBEaXZpc2lvbjEhMB8GA1UEAxMYVGhhd3RlIFBlcnNvbmFsIEJhc2lj |
||||
IENBMSgwJgYJKoZIhvcNAQkBFhlwZXJzb25hbC1iYXNpY0B0aGF3dGUuY29tMB4X |
||||
DTk2MDEwMTAwMDAwMFoXDTIwMTIzMTIzNTk1OVowgcsxCzAJBgNVBAYTAlpBMRUw |
||||
EwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNVBAcTCUNhcGUgVG93bjEaMBgGA1UE |
||||
ChMRVGhhd3RlIENvbnN1bHRpbmcxKDAmBgNVBAsTH0NlcnRpZmljYXRpb24gU2Vy |
||||
dmljZXMgRGl2aXNpb24xITAfBgNVBAMTGFRoYXd0ZSBQZXJzb25hbCBCYXNpYyBD |
||||
QTEoMCYGCSqGSIb3DQEJARYZcGVyc29uYWwtYmFzaWNAdGhhd3RlLmNvbTCBnzAN |
||||
BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAvLyTU23AUE+CFeZIlDWmWr5vQvoPR+53 |
||||
dXLdjUmbllegeNTKP1GzaQuRdhciB5dqxFGTS+CN7zeVoQxN2jSQHReJl+A1OFdK |
||||
wPQIcOk8RHtQfmGakOMj04gRRif1CwcOu93RfyAKiLlWCy4cgNrx454p7xS9CkT7 |
||||
G1sY0b8jkyECAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQQF |
||||
AAOBgQAt4plrsD16iddZopQBHyvdEktTwq1/qqcAXJFAVyVKOKqEcLnZgA+le1z7 |
||||
c8a914phXAPjLSeoF+CEhULcXpvGt7Jtu3Sv5D/Lp7ew4F2+eIMllNLbgQ95B21P |
||||
9DkVWlIBe94y1k049hJcBlDfBVu9FEuh3ym6O0GN92NWod8isQ== |
||||
-----END CERTIFICATE----- |
||||
|
||||
Thawte Personal Premium CA |
||||
========================== |
||||
|
||||
-----BEGIN CERTIFICATE----- |
||||
MIIDKTCCApKgAwIBAgIBADANBgkqhkiG9w0BAQQFADCBzzELMAkGA1UEBhMCWkEx |
||||
FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMRowGAYD |
||||
VQQKExFUaGF3dGUgQ29uc3VsdGluZzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBT |
||||
ZXJ2aWNlcyBEaXZpc2lvbjEjMCEGA1UEAxMaVGhhd3RlIFBlcnNvbmFsIFByZW1p |
||||
dW0gQ0ExKjAoBgkqhkiG9w0BCQEWG3BlcnNvbmFsLXByZW1pdW1AdGhhd3RlLmNv |
||||
bTAeFw05NjAxMDEwMDAwMDBaFw0yMDEyMzEyMzU5NTlaMIHPMQswCQYDVQQGEwJa |
||||
QTEVMBMGA1UECBMMV2VzdGVybiBDYXBlMRIwEAYDVQQHEwlDYXBlIFRvd24xGjAY |
||||
BgNVBAoTEVRoYXd0ZSBDb25zdWx0aW5nMSgwJgYDVQQLEx9DZXJ0aWZpY2F0aW9u |
||||
IFNlcnZpY2VzIERpdmlzaW9uMSMwIQYDVQQDExpUaGF3dGUgUGVyc29uYWwgUHJl |
||||
bWl1bSBDQTEqMCgGCSqGSIb3DQEJARYbcGVyc29uYWwtcHJlbWl1bUB0aGF3dGUu |
||||
Y29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDJZtn4B0TPuYwu8KHvE0Vs |
||||
Bd/eJxZRNkERbGw77f4QfRKe5ZtCmv5gMcNmt3M6SK5O0DI3lIi1DbbZ8/JE2dWI |
||||
Et12TfIa/G8jHnrx2JhFTgcQ7xZC0EN1bUre4qrJMf8fAHB8Zs8QJQi6+u4A6UYD |
||||
ZicRFTuqW/KY3TZCstqIdQIDAQABoxMwETAPBgNVHRMBAf8EBTADAQH/MA0GCSqG |
||||
SIb3DQEBBAUAA4GBAGk2ifc0KjNyL2071CKyuG+axTZmDhs8obF1Wub9NdP4qPIH |
||||
b4Vnjt4rueIXsDqg8A6iAJrf8xQVbrvIhVqYgPn/vnQdPfP+MCXRNzRn+qVxeTBh |
||||
KXLA4CxM+1bkOqhv5TJZUtt1KFBZDPgLGeSs2a+WjS9Q2wfD6h+rM+D1KzGJ |
||||
-----END CERTIFICATE----- |
||||
|
||||
Thawte Personal Freemail CA |
||||
=========================== |
||||
|
||||
-----BEGIN CERTIFICATE----- |
||||
MIIDLTCCApagAwIBAgIBADANBgkqhkiG9w0BAQQFADCB0TELMAkGA1UEBhMCWkEx |
||||
FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMRowGAYD |
||||
VQQKExFUaGF3dGUgQ29uc3VsdGluZzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBT |
||||
ZXJ2aWNlcyBEaXZpc2lvbjEkMCIGA1UEAxMbVGhhd3RlIFBlcnNvbmFsIEZyZWVt |
||||
YWlsIENBMSswKQYJKoZIhvcNAQkBFhxwZXJzb25hbC1mcmVlbWFpbEB0aGF3dGUu |
||||
Y29tMB4XDTk2MDEwMTAwMDAwMFoXDTIwMTIzMTIzNTk1OVowgdExCzAJBgNVBAYT |
||||
AlpBMRUwEwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNVBAcTCUNhcGUgVG93bjEa |
||||
MBgGA1UEChMRVGhhd3RlIENvbnN1bHRpbmcxKDAmBgNVBAsTH0NlcnRpZmljYXRp |
||||
b24gU2VydmljZXMgRGl2aXNpb24xJDAiBgNVBAMTG1RoYXd0ZSBQZXJzb25hbCBG |
||||
cmVlbWFpbCBDQTErMCkGCSqGSIb3DQEJARYccGVyc29uYWwtZnJlZW1haWxAdGhh |
||||
d3RlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1GnX1LCUZFtx6UfY |
||||
DFG26nKRsIRefS0Nj3sS34UldSh0OkIsYyeflXtL734Zhx2G6qPduc6WZBrCFG5E |
||||
rHzmj+hND3EfQDimAKOHePb5lIZererAXnbr2RSjXW56fAylS1V/Bhkpf56aJtVq |
||||
uzgkCGqYx7Hao5iR/Xnb5VrEHLkCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zAN |
||||
BgkqhkiG9w0BAQQFAAOBgQDH7JJ+Tvj1lqVnYiqk8E0RYNBvjWBYYawmu1I1XAjP |
||||
MPuoSpaKH2JCI4wXD/S6ZJwXrEcp352YXtJsYHFcoqzceePnbgBHH7UNKOgCneSa |
||||
/RP0ptl8sfjcXyMmCZGAc9AUG95DqYMl8uacLxXK/qarigd1iwzdUYRr5PjRznei |
||||
gQ== |
||||
-----END CERTIFICATE----- |
||||
|
||||
Thawte Server CA |
||||
================ |
||||
|
||||
-----BEGIN CERTIFICATE----- |
||||
MIIDEzCCAnygAwIBAgIBATANBgkqhkiG9w0BAQQFADCBxDELMAkGA1UEBhMCWkEx |
||||
FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYD |
||||
VQQKExRUaGF3dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlv |
||||
biBTZXJ2aWNlcyBEaXZpc2lvbjEZMBcGA1UEAxMQVGhhd3RlIFNlcnZlciBDQTEm |
||||
MCQGCSqGSIb3DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0ZS5jb20wHhcNOTYwODAx |
||||
MDAwMDAwWhcNMjAxMjMxMjM1OTU5WjCBxDELMAkGA1UEBhMCWkExFTATBgNVBAgT |
||||
DFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYDVQQKExRUaGF3 |
||||
dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNl |
||||
cyBEaXZpc2lvbjEZMBcGA1UEAxMQVGhhd3RlIFNlcnZlciBDQTEmMCQGCSqGSIb3 |
||||
DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0ZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQAD |
||||
gY0AMIGJAoGBANOkUG7I/1Zr5s9dtuoMaHVHoqrC2oQl/Kj0R1HahbUgdJSGHg91 |
||||
yekIYfUGbTBuFRkC6VLAYttNmZ7iagxEOM3+vuNkCXDF/rFrKbYvScg71CcEJRCX |
||||
L+eQbcAoQpnXTEPew/UhbVSfXcNY4cDk2VuwuNy0e982OsK1ZiIS1ocNAgMBAAGj |
||||
EzARMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEEBQADgYEAB/pMaVz7lcxG |
||||
7oWDTSEwjsrZqG9JGubaUeNgcGyEYRGhGshIPllDfU+VPaGLtwtimHp1it2ITk6e |
||||
QNuozDJ0uW8NxuOzRAvZim+aKZuZGCg70eNAKJpaPNW15yAbi8qkq43pUdniTCxZ |
||||
qdq5snUb9kLy78fyGPmJvKP/iiMucEc= |
||||
-----END CERTIFICATE----- |
||||
|
||||
Thawte Premium Server CA |
||||
======================== |
||||
|
||||
-----BEGIN CERTIFICATE----- |
||||
MIIDJzCCApCgAwIBAgIBATANBgkqhkiG9w0BAQQFADCBzjELMAkGA1UEBhMCWkEx |
||||
FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYD |
||||
VQQKExRUaGF3dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlv |
||||
biBTZXJ2aWNlcyBEaXZpc2lvbjEhMB8GA1UEAxMYVGhhd3RlIFByZW1pdW0gU2Vy |
||||
dmVyIENBMSgwJgYJKoZIhvcNAQkBFhlwcmVtaXVtLXNlcnZlckB0aGF3dGUuY29t |
||||
MB4XDTk2MDgwMTAwMDAwMFoXDTIwMTIzMTIzNTk1OVowgc4xCzAJBgNVBAYTAlpB |
||||
MRUwEwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNVBAcTCUNhcGUgVG93bjEdMBsG |
||||
A1UEChMUVGhhd3RlIENvbnN1bHRpbmcgY2MxKDAmBgNVBAsTH0NlcnRpZmljYXRp |
||||
b24gU2VydmljZXMgRGl2aXNpb24xITAfBgNVBAMTGFRoYXd0ZSBQcmVtaXVtIFNl |
||||
cnZlciBDQTEoMCYGCSqGSIb3DQEJARYZcHJlbWl1bS1zZXJ2ZXJAdGhhd3RlLmNv |
||||
bTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0jY2aovXwlue2oFBYo847kkE |
||||
VdbQ7xwblRZH7xhINTpS9CtqBo87L+pW46+GjZ4X9560ZXUCTe/LCaIhUdib0GfQ |
||||
ug2SBhRz1JPLlyoAnFxODLz6FVL88kRu2hFKbgifLy3j+ao6hnO2RlNYyIkFvYMR |
||||
uHM/qgeN9EJN50CdHDcCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG |
||||
9w0BAQQFAAOBgQAmSCwWwlj66BZ0DKqqX1Q/8tfJeGBeXm43YyJ3Nn6yF8Q0ufUI |
||||
hfzJATj/Tb7yFkJD57taRvvBxhEf8UqwKEbJw8RCfbz6q1lu1bdRiBHjpIUZa4JM |
||||
pAwSremkrj/xw0llmozFyD4lt5SZu5IycQfwhl7tUCemDaYj+bvLpgcUQg== |
||||
-----END CERTIFICATE----- |
||||
|
||||
Equifax Secure CA |
||||
================= |
||||
|
||||
-----BEGIN CERTIFICATE----- |
||||
MIIDIDCCAomgAwIBAgIENd70zzANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJV |
||||
UzEQMA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2Vy |
||||
dGlmaWNhdGUgQXV0aG9yaXR5MB4XDTk4MDgyMjE2NDE1MVoXDTE4MDgyMjE2NDE1 |
||||
MVowTjELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0VxdWlmYXgxLTArBgNVBAsTJEVx |
||||
dWlmYXggU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eTCBnzANBgkqhkiG9w0B |
||||
AQEFAAOBjQAwgYkCgYEAwV2xWGcIYu6gmi0fCG2RFGiYCh7+2gRvE4RiIcPRfM6f |
||||
BeC4AfBONOziipUEZKzxa1NfBbPLZ4C/QgKO/t0BCezhABRP/PvwDN1Dulsr4R+A |
||||
cJkVV5MW8Q+XarfCaCMczE1ZMKxRHjuvK9buY0V7xdlfUNLjUA86iOe/FP3gx7kC |
||||
AwEAAaOCAQkwggEFMHAGA1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEQ |
||||
MA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2VydGlm |
||||
aWNhdGUgQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMBoGA1UdEAQTMBGBDzIwMTgw |
||||
ODIyMTY0MTUxWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUSOZo+SvSspXXR9gj |
||||
IBBPM5iQn9QwHQYDVR0OBBYEFEjmaPkr0rKV10fYIyAQTzOYkJ/UMAwGA1UdEwQF |
||||
MAMBAf8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUA |
||||
A4GBAFjOKer89961zgK5F7WF0bnj4JXMJTENAKaSbn+2kmOeUJXRmm/kEd5jhW6Y |
||||
7qj/WsjTVbJmcVfewCHrPSqnI0kBBIZCe/zuf6IWUrVnZ9NA2zsmWLIodz2uFHdh |
||||
1voqZiegDfqnc1zqcPGUIWVEX/r87yloqaKHee9570+sB3c4 |
||||
-----END CERTIFICATE----- |
||||
|
||||
Verisign Class 1 Public Primary Certification Authority |
||||
======================================================= |
||||
|
||||
-----BEGIN CERTIFICATE----- |
||||
MIICPTCCAaYCEQDNun9W8N/kvFT+IqyzcqpVMA0GCSqGSIb3DQEBAgUAMF8xCzAJ |
||||
BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE3MDUGA1UECxMuQ2xh |
||||
c3MgMSBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw05 |
||||
NjAxMjkwMDAwMDBaFw0yODA4MDEyMzU5NTlaMF8xCzAJBgNVBAYTAlVTMRcwFQYD |
||||
VQQKEw5WZXJpU2lnbiwgSW5jLjE3MDUGA1UECxMuQ2xhc3MgMSBQdWJsaWMgUHJp |
||||
bWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCBnzANBgkqhkiG9w0BAQEFAAOB |
||||
jQAwgYkCgYEA5Rm/baNWYS2ZSHH2Z965jeu3noaACpEO+jglr0aIguVzqKCbJF0N |
||||
H8xlbgyw0FaEGIeaBpsQoXPftFg5a27B9hXVqKg/qhIGjTGsf7A01480Z4gJzRQR |
||||
4k5FVmkfeAKA2txHkSm7NsljXMXg1y2He6G3MrB7MLoqLzGq7qNn2tsCAwEAATAN |
||||
BgkqhkiG9w0BAQIFAAOBgQBMP7iLxmjf7kMzDl3ppssHhE16M/+SG/Q2rdiVIjZo |
||||
EWx8QszznC7EBz8UsA9P/5CSdvnivErpj82ggAr3xSnxgiJduLHdgSOjeyUVRjB5 |
||||
FvjqBUuUfx3CHMjjt/QQQDwTw18fU+hI5Ia0e6E1sHslurjTjqs/OJ0ANACY89Fx |
||||
lA== |
||||
-----END CERTIFICATE----- |
||||
|
||||
Verisign Class 2 Public Primary Certification Authority |
||||
======================================================= |
||||
|
||||
-----BEGIN CERTIFICATE----- |
||||
MIICPDCCAaUCEC0b/EoXjaOR6+f/9YtFvgswDQYJKoZIhvcNAQECBQAwXzELMAkG |
||||
A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz |
||||
cyAyIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2 |
||||
MDEyOTAwMDAwMFoXDTI4MDgwMTIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV |
||||
BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAyIFB1YmxpYyBQcmlt |
||||
YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN |
||||
ADCBiQKBgQC2WoujDWojg4BrzzmH9CETMwZMJaLtVRKXxaeAufqDwSCg+i8VDXyh |
||||
YGt+eSz6Bg86rvYbb7HS/y8oUl+DfUvEerf4Zh+AVPy3wo5ZShRXRtGak75BkQO7 |
||||
FYCTXOvnzAhsPz6zSvz/S2wj1VCCJkQZjiPDceoZJEcEnnW/yKYAHwIDAQABMA0G |
||||
CSqGSIb3DQEBAgUAA4GBAIobK/o5wXTXXtgZZKJYSi034DNHD6zt96rbHuSLBlxg |
||||
J8pFUs4W7z8GZOeUaHxgMxURaa+dYo2jA1Rrpr7l7gUYYAS/QoD90KioHgE796Nc |
||||
r6Pc5iaAIzy4RHT3Cq5Ji2F4zCS/iIqnDupzGUH9TQPwiNHleI2lKk/2lw0Xd8rY |
||||
-----END CERTIFICATE----- |
||||
|
||||
Verisign Class 3 Public Primary Certification Authority |
||||
======================================================= |
||||
|
||||
-----BEGIN CERTIFICATE----- |
||||
MIICPDCCAaUCEHC65B0Q2Sk0tjjKewPMur8wDQYJKoZIhvcNAQECBQAwXzELMAkG |
||||
A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz |
||||
cyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2 |
||||
MDEyOTAwMDAwMFoXDTI4MDgwMTIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV |
||||
BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmlt |
||||
YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN |
||||
ADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhE |
||||
BarsAx94f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/is |
||||
I19wKTakyYbnsZogy1Olhec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0G |
||||
CSqGSIb3DQEBAgUAA4GBALtMEivPLCYATxQT3ab7/AoRhIzzKBxnki98tsX63/Do |
||||
lbwdj2wsqFHMc9ikwFPwTtYmwHYBV4GSXiHx0bH/59AhWM1pF+NEHJwZRDmJXNyc |
||||
AA9WjQKZ7aKQRUzkuxCkPfAyAw7xzvjoyVGM5mKf5p/AfbdynMk2OmufTqj/ZA1k |
||||
-----END CERTIFICATE----- |
||||
|
||||
Verisign Class 1 Public Primary Certification Authority - G2 |
||||
============================================================ |
||||
|
||||
-----BEGIN CERTIFICATE----- |
||||
MIIDAjCCAmsCEEzH6qqYPnHTkxD4PTqJkZIwDQYJKoZIhvcNAQEFBQAwgcExCzAJ |
||||
BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xh |
||||
c3MgMSBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcy |
||||
MTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3Jp |
||||
emVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMB4X |
||||
DTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVowgcExCzAJBgNVBAYTAlVTMRcw |
||||
FQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMSBQdWJsaWMg |
||||
UHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEo |
||||
YykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5 |
||||
MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEB |
||||
AQUAA4GNADCBiQKBgQCq0Lq+Fi24g9TK0g+8djHKlNgdk4xWArzZbxpvUjZudVYK |
||||
VdPfQ4chEWWKfo+9Id5rMj8bhDSVBZ1BNeuS65bdqlk/AVNtmU/t5eIqWpDBucSm |
||||
Fc/IReumXY6cPvBkJHalzasab7bYe1FhbqZ/h8jit+U03EGI6glAvnOSPWvndQID |
||||
AQABMA0GCSqGSIb3DQEBBQUAA4GBAKlPww3HZ74sy9mozS11534Vnjty637rXC0J |
||||
h9ZrbWB85a7FkCMMXErQr7Fd88e2CtvgFZMN3QO8x3aKtd1Pw5sTdbgBwObJW2ul |
||||
uIncrKTdcu1OofdPvAbT6shkdHvClUGcZXNY8ZCaPGqxmMnEh7zPRW1F4m4iP/68 |
||||
DzFc6PLZ |
||||
-----END CERTIFICATE----- |
||||
|
||||
Verisign Class 2 Public Primary Certification Authority - G2 |
||||
============================================================ |
||||
|
||||
-----BEGIN CERTIFICATE----- |
||||
MIIDAzCCAmwCEQC5L2DMiJ+hekYJuFtwbIqvMA0GCSqGSIb3DQEBBQUAMIHBMQsw |
||||
CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xPDA6BgNVBAsTM0Ns |
||||
YXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBH |
||||
MjE6MDgGA1UECxMxKGMpIDE5OTggVmVyaVNpZ24sIEluYy4gLSBGb3IgYXV0aG9y |
||||
aXplZCB1c2Ugb25seTEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazAe |
||||
Fw05ODA1MTgwMDAwMDBaFw0yODA4MDEyMzU5NTlaMIHBMQswCQYDVQQGEwJVUzEX |
||||
MBUGA1UEChMOVmVyaVNpZ24sIEluYy4xPDA6BgNVBAsTM0NsYXNzIDIgUHVibGlj |
||||
IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMjE6MDgGA1UECxMx |
||||
KGMpIDE5OTggVmVyaVNpZ24sIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25s |
||||
eTEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazCBnzANBgkqhkiG9w0B |
||||
AQEFAAOBjQAwgYkCgYEAp4gBIXQs5xoD8JjhlzwPIQjxnNuX6Zr8wgQGE75fUsjM |
||||
HiwSViy4AWkszJkfrbCWrnkE8hM5wXuYuggs6MKEEyyqaekJ9MepAqRCwiNPStjw |
||||
DqL7MWzJ5m+ZJwf15vRMeJ5t60aG+rmGyVTyssSv1EYcWskVMP8NbPUtDm3Of3cC |
||||
AwEAATANBgkqhkiG9w0BAQUFAAOBgQByLvl/0fFx+8Se9sVeUYpAmLho+Jscg9ji |
||||
nb3/7aHmZuovCfTK1+qlK5X2JGCGTUQug6XELaDTrnhpb3LabK4I8GOSN+a7xDAX |
||||
rXfMSTWqz9iP0b63GJZHc2pUIjRkLbYWm1lbtFFZOrMLFPQS32eg9K0yZF6xRnIn |
||||
jBJ7xUS0rg== |
||||
-----END CERTIFICATE----- |
||||
|
||||
Verisign Class 3 Public Primary Certification Authority - G2 |
||||
============================================================ |
||||
|
||||
-----BEGIN CERTIFICATE----- |
||||
MIIDAjCCAmsCEH3Z/gfPqB63EHln+6eJNMYwDQYJKoZIhvcNAQEFBQAwgcExCzAJ |
||||
BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xh |
||||
c3MgMyBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcy |
||||
MTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3Jp |
||||
emVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMB4X |
||||
DTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVowgcExCzAJBgNVBAYTAlVTMRcw |
||||
FQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMyBQdWJsaWMg |
||||
UHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEo |
||||
YykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5 |
||||
MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEB |
||||
AQUAA4GNADCBiQKBgQDMXtERXVxp0KvTuWpMmR9ZmDCOFoUgRm1HP9SFIIThbbP4 |
||||
pO0M8RcPO/mn+SXXwc+EY/J8Y8+iR/LGWzOOZEAEaMGAuWQcRXfH2G71lSk8UOg0 |
||||
13gfqLptQ5GVj0VXXn7F+8qkBOvqlzdUMG+7AUcyM83cV5tkaWH4mx0ciU9cZwID |
||||
AQABMA0GCSqGSIb3DQEBBQUAA4GBAFFNzb5cy5gZnBWyATl4Lk0PZ3BwmcYQWpSk |
||||
U01UbSuvDV1Ai2TT1+7eVmGSX6bEHRBhNtMsJzzoKQm5EWR0zLVznxxIqbxhAe7i |
||||
F6YM40AIOw7n60RzKprxaZLvcRTDOaxxp5EJb+RxBrO6WVcmeQD2+A2iMzAo1KpY |
||||
oJ2daZH9 |
||||
-----END CERTIFICATE----- |
||||
|
||||
Verisign Class 4 Public Primary Certification Authority - G2 |
||||
============================================================ |
||||
|
||||
-----BEGIN CERTIFICATE----- |
||||
MIIDAjCCAmsCEDKIjprS9esTR/h/xCA3JfgwDQYJKoZIhvcNAQEFBQAwgcExCzAJ |
||||
BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xh |
||||
c3MgNCBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcy |
||||
MTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3Jp |
||||
emVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMB4X |
||||
DTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVowgcExCzAJBgNVBAYTAlVTMRcw |
||||
FQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgNCBQdWJsaWMg |
||||
UHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEo |
||||
YykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5 |
||||
MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEB |
||||
AQUAA4GNADCBiQKBgQC68OTP+cSuhVS5B1f5j8V/aBH4xBewRNzjMHPVKmIquNDM |
||||
HO0oW369atyzkSTKQWI8/AIBvxwWMZQFl3Zuoq29YRdsTjCG8FE3KlDHqGKB3FtK |
||||
qsGgtG7rL+VXxbErQHDbWk2hjh+9Ax/YA9SPTJlxvOKCzFjomDqG04Y48wApHwID |
||||
AQABMA0GCSqGSIb3DQEBBQUAA4GBAIWMEsGnuVAVess+rLhDityq3RS6iYF+ATwj |
||||
cSGIL4LcY/oCRaxFWdcqWERbt5+BO5JoPeI3JPV7bI92NZYJqFmduc4jq3TWg/0y |
||||
cyfYaT5DdPauxYma51N86Xv2S/PBZYPejYqcPIiNOVn8qj8ijaHBZlCBckztImRP |
||||
T8qAkbYp |
||||
-----END CERTIFICATE----- |
||||
|
||||
Verisign Class 1 Public Primary Certification Authority - G3 |
||||
============================================================ |
||||
|
||||
-----BEGIN CERTIFICATE----- |
||||
MIIEGjCCAwICEQCLW3VWhFSFCwDPrzhIzrGkMA0GCSqGSIb3DQEBBQUAMIHKMQsw |
||||
CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl |
||||
cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu |
||||
LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT |
||||
aWduIENsYXNzIDEgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp |
||||
dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD |
||||
VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT |
||||
aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ |
||||
bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu |
||||
IENsYXNzIDEgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg |
||||
LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAN2E1Lm0+afY8wR4 |
||||
nN493GwTFtl63SRRZsDHJlkNrAYIwpTRMx/wgzUfbhvI3qpuFU5UJ+/EbRrsC+MO |
||||
8ESlV8dAWB6jRx9x7GD2bZTIGDnt/kIYVt/kTEkQeE4BdjVjEjbdZrwBBDajVWjV |
||||
ojYJrKshJlQGrT/KFOCsyq0GHZXi+J3x4GD/wn91K0zM2v6HmSHquv4+VNfSWXjb |
||||
PG7PoBMAGrgnoeS+Z5bKoMWznN3JdZ7rMJpfo83ZrngZPyPpXNspva1VyBtUjGP2 |
||||
6KbqxzcSXKMpHgLZ2x87tNcPVkeBFQRKr4Mn0cVYiMHd9qqnoxjaaKptEVHhv2Vr |
||||
n5Z20T0CAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAq2aN17O6x5q25lXQBfGfMY1a |
||||
qtmqRiYPce2lrVNWYgFHKkTp/j90CxObufRNG7LRX7K20ohcs5/Ny9Sn2WCVhDr4 |
||||
wTcdYcrnsMXlkdpUpqwxga6X3s0IrLjAl4B/bnKk52kTlWUfxJM8/XmPBNQ+T+r3 |
||||
ns7NZ3xPZQL/kYVUc8f/NveGLezQXk//EZ9yBta4GvFMDSZl4kSAHsef493oCtrs |
||||
pSCAaWihT37ha88HQfqDjrw43bAuEbFrskLMmrz5SCJ5ShkPshw+IHTZasO+8ih4 |
||||
E1Z5T21Q6huwtVexN2ZYI/PcD98Kh8TvhgXVOBRgmaNL3gaWcSzy27YfpO8/7g== |
||||
-----END CERTIFICATE----- |
||||
|
||||
Verisign Class 2 Public Primary Certification Authority - G3 |
||||
============================================================ |
||||
|
||||
-----BEGIN CERTIFICATE----- |
||||
MIIEGTCCAwECEGFwy0mMX5hFKeewptlQW3owDQYJKoZIhvcNAQEFBQAwgcoxCzAJ |
||||
BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVy |
||||
aVNpZ24gVHJ1c3QgTmV0d29yazE6MDgGA1UECxMxKGMpIDE5OTkgVmVyaVNpZ24s |
||||
IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTFFMEMGA1UEAxM8VmVyaVNp |
||||
Z24gQ2xhc3MgMiBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0 |
||||
eSAtIEczMB4XDTk5MTAwMTAwMDAwMFoXDTM2MDcxNjIzNTk1OVowgcoxCzAJBgNV |
||||
BAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVyaVNp |
||||
Z24gVHJ1c3QgTmV0d29yazE6MDgGA1UECxMxKGMpIDE5OTkgVmVyaVNpZ24sIElu |
||||
Yy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTFFMEMGA1UEAxM8VmVyaVNpZ24g |
||||
Q2xhc3MgMiBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAt |
||||
IEczMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArwoNwtUs22e5LeWU |
||||
J92lvuCwTY+zYVY81nzD9M0+hsuiiOLh2KRpxbXiv8GmR1BeRjmL1Za6tW8UvxDO |
||||
JxOeBUebMXoT2B/Z0wI3i60sR/COgQanDTAM6/c8DyAd3HJG7qUCyFvDyVZpTMUY |
||||
wZF7C9UTAJu878NIPkZgIIUq1ZC2zYugzDLdt/1AVbJQHFauzI13TccgTacxdu9o |
||||
koqQHgiBVrKtaaNS0MscxCM9H5n+TOgWY47GCI72MfbS+uV23bUckqNJzc0BzWjN |
||||
qWm6o+sdDZykIKbBoMXRRkwXbdKsZj+WjOCE1Db/IlnF+RFgqF8EffIa9iVCYQ/E |
||||
Srg+iQIDAQABMA0GCSqGSIb3DQEBBQUAA4IBAQA0JhU8wI1NQ0kdvekhktdmnLfe |
||||
xbjQ5F1fdiLAJvmEOjr5jLX77GDx6M4EsMjdpwOPMPOY36TmpDHf0xwLRtxyID+u |
||||
7gU8pDM/CzmscHhzS5kr3zDCVLCoO1Wh/hYozUK9dG6A2ydEp85EXdQbkJgNHkKU |
||||
sQAsBNB0owIFImNjzYO1+8FtYmtpdf1dcEG59b98377BMnMiIYtYgXsVkXq642RI |
||||
sH/7NiXaldDxJBQX3RiAa0YjOVT1jmIJBB2UkKab5iXiQkWquJCtvgiPqQtCGJTP |
||||
cjnhsUPgKM+351psE2tJs//jGHyJizNdrDPXp/naOlXJWBD5qu9ats9LS98q |
||||
-----END CERTIFICATE----- |
||||
|
||||
Verisign Class 3 Public Primary Certification Authority - G3 |
||||
============================================================ |
||||
|
||||
-----BEGIN CERTIFICATE----- |
||||
MIIEGjCCAwICEQCbfgZJoz5iudXukEhxKe9XMA0GCSqGSIb3DQEBBQUAMIHKMQsw |
||||
CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl |
||||
cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu |
||||
LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT |
||||
aWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp |
||||
dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD |
||||
VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT |
||||
aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ |
||||
bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu |
||||
IENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg |
||||
LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMu6nFL8eB8aHm8b |
||||
N3O9+MlrlBIwT/A2R/XQkQr1F8ilYcEWQE37imGQ5XYgwREGfassbqb1EUGO+i2t |
||||
KmFZpGcmTNDovFJbcCAEWNF6yaRpvIMXZK0Fi7zQWM6NjPXr8EJJC52XJ2cybuGu |
||||
kxUccLwgTS8Y3pKI6GyFVxEa6X7jJhFUokWWVYPKMIno3Nij7SqAP395ZVc+FSBm |
||||
CC+Vk7+qRy+oRpfwEuL+wgorUeZ25rdGt+INpsyow0xZVYnm6FNcHOqd8GIWC6fJ |
||||
Xwzw3sJ2zq/3avL6QaaiMxTJ5Xpj055iN9WFZZ4O5lMkdBteHRJTW8cs54NJOxWu |
||||
imi5V5cCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAERSWwauSCPc/L8my/uRan2Te |
||||
2yFPhpk0djZX3dAVL8WtfxUfN2JzPtTnX84XA9s1+ivbrmAJXx5fj267Cz3qWhMe |
||||
DGBvtcC1IyIuBwvLqXTLR7sdwdela8wv0kL9Sd2nic9TutoAWii/gt/4uhMdUIaC |
||||
/Y4wjylGsB49Ndo4YhYYSq3mtlFs3q9i6wHQHiT+eo8SGhJouPtmmRQURVyu565p |
||||
F4ErWjfJXir0xuKhXFSbplQAz/DxwceYMBo7Nhbbo27q/a2ywtrvAkcTisDxszGt |
||||
TxzhT5yvDwyd93gN2PQ1VoDat20Xj50egWTh/sVFuq1ruQp6Tk9LhO5L8X3dEQ== |
||||
-----END CERTIFICATE----- |
||||
|
||||
Verisign Class 4 Public Primary Certification Authority - G3 |
||||
============================================================ |
||||
|
||||
-----BEGIN CERTIFICATE----- |
||||
MIIEGjCCAwICEQDsoKeLbnVqAc/EfMwvlF7XMA0GCSqGSIb3DQEBBQUAMIHKMQsw |
||||
CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl |
||||
cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu |
||||
LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT |
||||
aWduIENsYXNzIDQgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp |
||||
dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD |
||||
VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT |
||||
aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ |
||||
bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu |
||||
IENsYXNzIDQgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg |
||||
LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK3LpRFpxlmr8Y+1 |
||||
GQ9Wzsy1HyDkniYlS+BzZYlZ3tCD5PUPtbut8XzoIfzk6AzufEUiGXaStBO3IFsJ |
||||
+mGuqPKljYXCKtbeZjbSmwL0qJJgfJxptI8kHtCGUvYynEFYHiK9zUVilQhu0Gbd |
||||
U6LM8BDcVHOLBKFGMzNcF0C5nk3T875Vg+ixiY5afJqWIpA7iCXy0lOIAgwLePLm |
||||
NxdLMEYH5IBtptiWLugs+BGzOA1mppvqySNb247i8xOOGlktqgLw7KSHZtzBP/XY |
||||
ufTsgsbSPZUd5cBPhMnZo0QoBmrXRazwa2rvTl/4EYIeOGM0ZlDUPpNz+jDDZq3/ |
||||
ky2X7wMCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAj/ola09b5KROJ1WrIhVZPMq1 |
||||
CtRK26vdoV9TxaBXOcLORyu+OshWv8LZJxA6sQU8wHcxuzrTBXttmhwwjIDLk5Mq |
||||
g6sFUYICABFna/OIYUdfA5PVWw3g8dShMjWFsjrbsIKr0csKvE+MW8VLADsfKoKm |
||||
fjaF3H48ZwC15DtS4KjrXRX5xm3wrR0OhbepmnMUWluPQSjA1egtTaRezarZ7c7c |
||||
2NU8Qh0XwRJdRTjDOPP8hS6DRkiy1yBfkjaP53kPmF6Z6PDQpLv1U70qzlmwr25/ |
||||
bLvSHgCwIe34QWKCudiyxLtGUPMxxY8BqHTr9Xgn2uf3ZkPznoM+IKrDNWCRzg== |
||||
-----END CERTIFICATE----- |
||||
|
||||
Equifax Secure Global eBusiness CA |
||||
================================== |
||||
|
||||
-----BEGIN CERTIFICATE----- |
||||
MIICkDCCAfmgAwIBAgIBATANBgkqhkiG9w0BAQQFADBaMQswCQYDVQQGEwJVUzEc |
||||
MBoGA1UEChMTRXF1aWZheCBTZWN1cmUgSW5jLjEtMCsGA1UEAxMkRXF1aWZheCBT |
||||
ZWN1cmUgR2xvYmFsIGVCdXNpbmVzcyBDQS0xMB4XDTk5MDYyMTA0MDAwMFoXDTIw |
||||
MDYyMTA0MDAwMFowWjELMAkGA1UEBhMCVVMxHDAaBgNVBAoTE0VxdWlmYXggU2Vj |
||||
dXJlIEluYy4xLTArBgNVBAMTJEVxdWlmYXggU2VjdXJlIEdsb2JhbCBlQnVzaW5l |
||||
c3MgQ0EtMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAuucXkAJlsTRVPEnC |
||||
UdXfp9E3j9HngXNBUmCbnaEXJnitx7HoJpQytd4zjTov2/KaelpzmKNc6fuKcxtc |
||||
58O/gGzNqfTWK8D3+ZmqY6KxRwIP1ORROhI8bIpaVIRw28HFkM9yRcuoWcDNM50/ |
||||
o5brhTMhHD4ePmBudpxnhcXIw2ECAwEAAaNmMGQwEQYJYIZIAYb4QgEBBAQDAgAH |
||||
MA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUvqigdHJQa0S3ySPY+6j/s1dr |
||||
aGwwHQYDVR0OBBYEFL6ooHRyUGtEt8kj2Puo/7NXa2hsMA0GCSqGSIb3DQEBBAUA |
||||
A4GBADDiAVGqx+pf2rnQZQ8w1j7aDRRJbpGTJxQx78T3LUX47Me/okENI7SS+RkA |
||||
Z70Br83gcfxaz2TE4JaY0KNA4gGK7ycH8WUBikQtBmV1UsCGECAhX2xrD2yuCRyv |
||||
8qIYNMR1pHMc8Y3c7635s3a0kr/clRAevsvIO1qEYBlWlKlV |
||||
-----END CERTIFICATE----- |
||||
|
||||
Equifax Secure eBusiness CA 1 |
||||
============================= |
||||
|
||||
-----BEGIN CERTIFICATE----- |
||||
MIICgjCCAeugAwIBAgIBBDANBgkqhkiG9w0BAQQFADBTMQswCQYDVQQGEwJVUzEc |
||||
MBoGA1UEChMTRXF1aWZheCBTZWN1cmUgSW5jLjEmMCQGA1UEAxMdRXF1aWZheCBT |
||||
ZWN1cmUgZUJ1c2luZXNzIENBLTEwHhcNOTkwNjIxMDQwMDAwWhcNMjAwNjIxMDQw |
||||
MDAwWjBTMQswCQYDVQQGEwJVUzEcMBoGA1UEChMTRXF1aWZheCBTZWN1cmUgSW5j |
||||
LjEmMCQGA1UEAxMdRXF1aWZheCBTZWN1cmUgZUJ1c2luZXNzIENBLTEwgZ8wDQYJ |
||||
KoZIhvcNAQEBBQADgY0AMIGJAoGBAM4vGbwXt3fek6lfWg0XTzQaDJj0ItlZ1MRo |
||||
RvC0NcWFAyDGr0WlIVFFQesWWDYyb+JQYmT5/VGcqiTZ9J2DKocKIdMSODRsjQBu |
||||
WqDZQu4aIZX5UkxVWsUPOE9G+m34LjXWHXzr4vCwdYDIqROsvojvOm6rXyo4YgKw |
||||
Env+j6YDAgMBAAGjZjBkMBEGCWCGSAGG+EIBAQQEAwIABzAPBgNVHRMBAf8EBTAD |
||||
AQH/MB8GA1UdIwQYMBaAFEp4MlIR21kWNl7fwRQ2QGpHfEyhMB0GA1UdDgQWBBRK |
||||
eDJSEdtZFjZe38EUNkBqR3xMoTANBgkqhkiG9w0BAQQFAAOBgQB1W6ibAxHm6VZM |
||||
zfmpTMANmvPMZWnmJXbMWbfWVMMdzZmsGd20hdXgPfxiIKeES1hl8eL5lSE/9dR+ |
||||
WB5Hh1Q+WKG1tfgq73HnvMP2sUlG4tega+VWeponmHxGYhTnyfxuAxJ5gDgdSIKN |
||||
/Bf+KpYrtWKmpj29f5JZzVoqgrI3eQ== |
||||
-----END CERTIFICATE----- |
||||
|
||||
Equifax Secure eBusiness CA 2 |
||||
============================= |
||||
|
||||
-----BEGIN CERTIFICATE----- |
||||
MIIDIDCCAomgAwIBAgIEN3DPtTANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJV |
||||
UzEXMBUGA1UEChMORXF1aWZheCBTZWN1cmUxJjAkBgNVBAsTHUVxdWlmYXggU2Vj |
||||
dXJlIGVCdXNpbmVzcyBDQS0yMB4XDTk5MDYyMzEyMTQ0NVoXDTE5MDYyMzEyMTQ0 |
||||
NVowTjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkVxdWlmYXggU2VjdXJlMSYwJAYD |
||||
VQQLEx1FcXVpZmF4IFNlY3VyZSBlQnVzaW5lc3MgQ0EtMjCBnzANBgkqhkiG9w0B |
||||
AQEFAAOBjQAwgYkCgYEA5Dk5kx5SBhsoNviyoynF7Y6yEb3+6+e0dMKP/wXn2Z0G |
||||
vxLIPw7y1tEkshHe0XMJitSxLJgJDR5QRrKDpkWNYmi7hRsgcDKqQM2mll/EcTc/ |
||||
BPO3QSQ5BxoeLmFYoBIL5aXfxavqN3HMHMg3OrmXUqesxWoklE6ce8/AatbfIb0C |
||||
AwEAAaOCAQkwggEFMHAGA1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEX |
||||
MBUGA1UEChMORXF1aWZheCBTZWN1cmUxJjAkBgNVBAsTHUVxdWlmYXggU2VjdXJl |
||||
IGVCdXNpbmVzcyBDQS0yMQ0wCwYDVQQDEwRDUkwxMBoGA1UdEAQTMBGBDzIwMTkw |
||||
NjIzMTIxNDQ1WjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUUJ4L6q9euSBIplBq |
||||
y/3YIHqngnYwHQYDVR0OBBYEFFCeC+qvXrkgSKZQasv92CB6p4J2MAwGA1UdEwQF |
||||
MAMBAf8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUA |
||||
A4GBAAyGgq3oThr1jokn4jVYPSm0B482UJW/bsGe68SQsoWou7dC4A8HOd/7npCy |
||||
0cE+U58DRLB+S/Rv5Hwf5+Kx5Lia78O9zt4LMjTZ3ijtM2vE1Nc9ElirfQkty3D1 |
||||
E4qUoSek1nDFbZS1yX2doNLGCEnZZpum0/QL3MUmV+GRMOrN |
||||
-----END CERTIFICATE----- |
||||
|
||||
Thawte Time Stamping CA |
||||
======================= |
||||
|
||||
-----BEGIN CERTIFICATE----- |
||||
MIICoTCCAgqgAwIBAgIBADANBgkqhkiG9w0BAQQFADCBizELMAkGA1UEBhMCWkEx |
||||
FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTEUMBIGA1UEBxMLRHVyYmFudmlsbGUxDzAN |
||||
BgNVBAoTBlRoYXd0ZTEdMBsGA1UECxMUVGhhd3RlIENlcnRpZmljYXRpb24xHzAd |
||||
BgNVBAMTFlRoYXd0ZSBUaW1lc3RhbXBpbmcgQ0EwHhcNOTcwMTAxMDAwMDAwWhcN |
||||
MjAxMjMxMjM1OTU5WjCBizELMAkGA1UEBhMCWkExFTATBgNVBAgTDFdlc3Rlcm4g |
||||
Q2FwZTEUMBIGA1UEBxMLRHVyYmFudmlsbGUxDzANBgNVBAoTBlRoYXd0ZTEdMBsG |
||||
A1UECxMUVGhhd3RlIENlcnRpZmljYXRpb24xHzAdBgNVBAMTFlRoYXd0ZSBUaW1l |
||||
c3RhbXBpbmcgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANYrWHhhRYZT |
||||
6jR7UZztsOYuGA7+4F+oJ9O0yeB8WU4WDnNUYMF/9p8u6TqFJBU820cEY8OexJQa |
||||
Wt9MevPZQx08EHp5JduQ/vBR5zDWQQD9nyjfeb6Uu522FOMjhdepQeBMpHmwKxqL |
||||
8vg7ij5FrHGSALSQQZj7X+36ty6K+Ig3AgMBAAGjEzARMA8GA1UdEwEB/wQFMAMB |
||||
Af8wDQYJKoZIhvcNAQEEBQADgYEAZ9viwuaHPUCDhjc1fR/OmsMMZiCouqoEiYbC |
||||
9RAIDb/LogWK0E02PvTX72nGXuSwlG9KuefeW4i2e9vjJ+V2w/A1wcu1J5szedyQ |
||||
pgCed/r8zSeUQhac0xxo7L9c3eWpexAKMnRUEzGLhQOEkbdYATAUOK8oyvyxUBkZ |
||||
CayJSdM= |
||||
-----END CERTIFICATE----- |
||||
|
||||
thawte Primary Root CA |
||||
====================== |
||||
|
||||
-----BEGIN CERTIFICATE----- |
||||
MIIEIDCCAwigAwIBAgIQNE7VVyDV7exJ9C/ON9srbTANBgkqhkiG9w0BAQUFADCB |
||||
qTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMf |
||||
Q2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIw |
||||
MDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxHzAdBgNV |
||||
BAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwHhcNMDYxMTE3MDAwMDAwWhcNMzYw |
||||
NzE2MjM1OTU5WjCBqTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5j |
||||
LjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYG |
||||
A1UECxMvKGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl |
||||
IG9ubHkxHzAdBgNVBAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwggEiMA0GCSqG |
||||
SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCsoPD7gFnUnMekz52hWXMJEEUMDSxuaPFs |
||||
W0hoSVk3/AszGcJ3f8wQLZU0HObrTQmnHNK4yZc2AreJ1CRfBsDMRJSUjQJib+ta |
||||
3RGNKJpchJAQeg29dGYvajig4tVUROsdB58Hum/u6f1OCyn1PoSgAfGcq/gcfomk |
||||
6KHYcWUNo1F77rzSImANuVud37r8UVsLr5iy6S7pBOhih94ryNdOwUxkHt3Ph1i6 |
||||
Sk/KaAcdHJ1KxtUvkcx8cXIcxcBn6zL9yZJclNqFwJu/U30rCfSMnZEfl2pSy94J |
||||
NqR32HuHUETVPm4pafs5SSYeCaWAe0At6+gnhcn+Yf1+5nyXHdWdAgMBAAGjQjBA |
||||
MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBR7W0XP |
||||
r87Lev0xkhpqtvNG61dIUDANBgkqhkiG9w0BAQUFAAOCAQEAeRHAS7ORtvzw6WfU |
||||
DW5FvlXok9LOAz/t2iWwHVfLHjp2oEzsUHboZHIMpKnxuIvW1oeEuzLlQRHAd9mz |
||||
YJ3rG9XRbkREqaYB7FViHXe4XI5ISXycO1cRrK1zN44veFyQaEfZYGDm/Ac9IiAX |
||||
xPcW6cTYcvnIc3zfFi8VqT79aie2oetaupgf1eNNZAqdE8hhuvU5HIe6uL17In/2 |
||||
/qxAeeWsEG89jxt5dovEN7MhGITlNgDrYyCZuen+MwS7QcjBAvlEYyCegc5C09Y/ |
||||
LHbTY5xZ3Y+m4Q6gLkH3LpVHz7z9M/P2C2F+fpErgUfCJzDupxBdN49cOSvkBPB7 |
||||
jVaMaA== |
||||
-----END CERTIFICATE----- |
||||
|
||||
VeriSign Class 3 Public Primary Certification Authority - G5 |
||||
============================================================ |
||||
|
||||
-----BEGIN CERTIFICATE----- |
||||
MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCB |
||||
yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL |
||||
ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJp |
||||
U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxW |
||||
ZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0 |
||||
aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCByjEL |
||||
MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW |
||||
ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2ln |
||||
biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJp |
||||
U2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9y |
||||
aXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvJAgIKXo1 |
||||
nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKzj/i5Vbex |
||||
t0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIz |
||||
SdhDY2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQG |
||||
BO+QueQA5N06tRn/Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+ |
||||
rCpSx4/VBEnkjWNHiDxpg8v+R70rfk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/ |
||||
NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8E |
||||
BAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEwHzAH |
||||
BgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy |
||||
aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKv |
||||
MzEzMA0GCSqGSIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzE |
||||
p6B4Eq1iDkVwZMXnl2YtmAl+X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y |
||||
5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKEKQsTb47bDN0lAtukixlE0kF6BWlK |
||||
WE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiCKm0oHw0LxOXnGiYZ |
||||
4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vEZV8N |
||||
hnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq |
||||
-----END CERTIFICATE----- |
||||
|
||||
Entrust.net Secure Server Certification Authority |
||||
================================================= |
||||
|
||||
-----BEGIN CERTIFICATE----- |
||||
MIIE2DCCBEGgAwIBAgIEN0rSQzANBgkqhkiG9w0BAQUFADCBwzELMAkGA1UEBhMC |
||||
VVMxFDASBgNVBAoTC0VudHJ1c3QubmV0MTswOQYDVQQLEzJ3d3cuZW50cnVzdC5u |
||||
ZXQvQ1BTIGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMc |
||||
KGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDE6MDgGA1UEAxMxRW50cnVzdC5u |
||||
ZXQgU2VjdXJlIFNlcnZlciBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw05OTA1 |
||||
MjUxNjA5NDBaFw0xOTA1MjUxNjM5NDBaMIHDMQswCQYDVQQGEwJVUzEUMBIGA1UE |
||||
ChMLRW50cnVzdC5uZXQxOzA5BgNVBAsTMnd3dy5lbnRydXN0Lm5ldC9DUFMgaW5j |
||||
b3JwLiBieSByZWYuIChsaW1pdHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBF |
||||
bnRydXN0Lm5ldCBMaW1pdGVkMTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUg |
||||
U2VydmVyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGdMA0GCSqGSIb3DQEBAQUA |
||||
A4GLADCBhwKBgQDNKIM0VBuJ8w+vN5Ex/68xYMmo6LIQaO2f55M28Qpku0f1BBc/ |
||||
I0dNxScZgSYMVHINiC3ZH5oSn7yzcdOAGT9HZnuMNSjSuQrfJNqc1lB5gXpa0zf3 |
||||
wkrYKZImZNHkmGw6AIr1NJtl+O3jEP/9uElY3KDegjlrgbEWGWG5VLbmQwIBA6OC |
||||
AdcwggHTMBEGCWCGSAGG+EIBAQQEAwIABzCCARkGA1UdHwSCARAwggEMMIHeoIHb |
||||
oIHYpIHVMIHSMQswCQYDVQQGEwJVUzEUMBIGA1UEChMLRW50cnVzdC5uZXQxOzA5 |
||||
BgNVBAsTMnd3dy5lbnRydXN0Lm5ldC9DUFMgaW5jb3JwLiBieSByZWYuIChsaW1p |
||||
dHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBFbnRydXN0Lm5ldCBMaW1pdGVk |
||||
MTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUgU2VydmVyIENlcnRpZmljYXRp |
||||
b24gQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMCmgJ6AlhiNodHRwOi8vd3d3LmVu |
||||
dHJ1c3QubmV0L0NSTC9uZXQxLmNybDArBgNVHRAEJDAigA8xOTk5MDUyNTE2MDk0 |
||||
MFqBDzIwMTkwNTI1MTYwOTQwWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAU8Bdi |
||||
E1U9s/8KAGv7UISX8+1i0BowHQYDVR0OBBYEFPAXYhNVPbP/CgBr+1CEl/PtYtAa |
||||
MAwGA1UdEwQFMAMBAf8wGQYJKoZIhvZ9B0EABAwwChsEVjQuMAMCBJAwDQYJKoZI |
||||
hvcNAQEFBQADgYEAkNwwAvpkdMKnCqV8IY00F6j7Rw7/JXyNEwr75Ji174z4xRAN |
||||
95K+8cPV1ZVqBLssziY2ZcgxxufuP+NXdYR6Ee9GTxj005i7qIcyunL2POI9n9cd |
||||
2cNgQ4xYDiKWL2KjLB+6rQXvqzJ4h6BUcxm1XAX5Uj5tLUUL9wqT6u0G+bI= |
||||
-----END CERTIFICATE----- |
||||
|
||||
Go Daddy Certification Authority Root Certificate Bundle |
||||
======================================================== |
||||
|
||||
-----BEGIN CERTIFICATE----- |
||||
MIIE3jCCA8agAwIBAgICAwEwDQYJKoZIhvcNAQEFBQAwYzELMAkGA1UEBhMCVVMx |
||||
ITAfBgNVBAoTGFRoZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28g |
||||
RGFkZHkgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjExMTYw |
||||
MTU0MzdaFw0yNjExMTYwMTU0MzdaMIHKMQswCQYDVQQGEwJVUzEQMA4GA1UECBMH |
||||
QXJpem9uYTETMBEGA1UEBxMKU2NvdHRzZGFsZTEaMBgGA1UEChMRR29EYWRkeS5j |
||||
b20sIEluYy4xMzAxBgNVBAsTKmh0dHA6Ly9jZXJ0aWZpY2F0ZXMuZ29kYWRkeS5j |
||||
b20vcmVwb3NpdG9yeTEwMC4GA1UEAxMnR28gRGFkZHkgU2VjdXJlIENlcnRpZmlj |
||||
YXRpb24gQXV0aG9yaXR5MREwDwYDVQQFEwgwNzk2OTI4NzCCASIwDQYJKoZIhvcN |
||||
AQEBBQADggEPADCCAQoCggEBAMQt1RWMnCZM7DI161+4WQFapmGBWTtwY6vj3D3H |
||||
KrjJM9N55DrtPDAjhI6zMBS2sofDPZVUBJ7fmd0LJR4h3mUpfjWoqVTr9vcyOdQm |
||||
VZWt7/v+WIbXnvQAjYwqDL1CBM6nPwT27oDyqu9SoWlm2r4arV3aLGbqGmu75RpR |
||||
SgAvSMeYddi5Kcju+GZtCpyz8/x4fKL4o/K1w/O5epHBp+YlLpyo7RJlbmr2EkRT |
||||
cDCVw5wrWCs9CHRK8r5RsL+H0EwnWGu1NcWdrxcx+AuP7q2BNgWJCJjPOq8lh8BJ |
||||
6qf9Z/dFjpfMFDniNoW1fho3/Rb2cRGadDAW/hOUoz+EDU8CAwEAAaOCATIwggEu |
||||
MB0GA1UdDgQWBBT9rGEyk2xF1uLuhV+auud2mWjM5zAfBgNVHSMEGDAWgBTSxLDS |
||||
kdRMEXGzYcs9of7dqGrU4zASBgNVHRMBAf8ECDAGAQH/AgEAMDMGCCsGAQUFBwEB |
||||
BCcwJTAjBggrBgEFBQcwAYYXaHR0cDovL29jc3AuZ29kYWRkeS5jb20wRgYDVR0f |
||||
BD8wPTA7oDmgN4Y1aHR0cDovL2NlcnRpZmljYXRlcy5nb2RhZGR5LmNvbS9yZXBv |
||||
c2l0b3J5L2dkcm9vdC5jcmwwSwYDVR0gBEQwQjBABgRVHSAAMDgwNgYIKwYBBQUH |
||||
AgEWKmh0dHA6Ly9jZXJ0aWZpY2F0ZXMuZ29kYWRkeS5jb20vcmVwb3NpdG9yeTAO |
||||
BgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQEFBQADggEBANKGwOy9+aG2Z+5mC6IG |
||||
OgRQjhVyrEp0lVPLN8tESe8HkGsz2ZbwlFalEzAFPIUyIXvJxwqoJKSQ3kbTJSMU |
||||
A2fCENZvD117esyfxVgqwcSeIaha86ykRvOe5GPLL5CkKSkB2XIsKd83ASe8T+5o |
||||
0yGPwLPk9Qnt0hCqU7S+8MxZC9Y7lhyVJEnfzuz9p0iRFEUOOjZv2kWzRaJBydTX |
||||
RE4+uXR21aITVSzGh6O1mawGhId/dQb8vxRMDsxuxN89txJx9OjxUUAiKEngHUuH |
||||
qDTMBqLdElrRhjZkAzVvb3du6/KFUJheqwNTrZEjYx8WnM25sgVjOuH0aBsXBTWV |
||||
U+4= |
||||
-----END CERTIFICATE----- |
||||
-----BEGIN CERTIFICATE----- |
||||
MIIE+zCCBGSgAwIBAgICAQ0wDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1Zh |
||||
bGlDZXJ0IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIElu |
||||
Yy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIgUG9saWN5IFZhbGlkYXRpb24g |
||||
QXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAe |
||||
BgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTA0MDYyOTE3MDYyMFoX |
||||
DTI0MDYyOTE3MDYyMFowYzELMAkGA1UEBhMCVVMxITAfBgNVBAoTGFRoZSBHbyBE |
||||
YWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28gRGFkZHkgQ2xhc3MgMiBDZXJ0 |
||||
aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQADggENADCCAQgC |
||||
ggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCAPVYYYwhv |
||||
2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6wwdhFJ2+q |
||||
N1j3hybX2C32qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXiEqITLdiO |
||||
r18SPaAIBQi2XKVlOARFmR6jYGB0xUGlcmIbYsUfb18aQr4CUWWoriMYavx4A6lN |
||||
f4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmYvLEHZ6IVDd2gWMZEewo+YihfukEH |
||||
U1jPEX44dMX4/7VpkI+EdOqXG68CAQOjggHhMIIB3TAdBgNVHQ4EFgQU0sSw0pHU |
||||
TBFxs2HLPaH+3ahq1OMwgdIGA1UdIwSByjCBx6GBwaSBvjCBuzEkMCIGA1UEBxMb |
||||
VmFsaUNlcnQgVmFsaWRhdGlvbiBOZXR3b3JrMRcwFQYDVQQKEw5WYWxpQ2VydCwg |
||||
SW5jLjE1MDMGA1UECxMsVmFsaUNlcnQgQ2xhc3MgMiBQb2xpY3kgVmFsaWRhdGlv |
||||
biBBdXRob3JpdHkxITAfBgNVBAMTGGh0dHA6Ly93d3cudmFsaWNlcnQuY29tLzEg |
||||
MB4GCSqGSIb3DQEJARYRaW5mb0B2YWxpY2VydC5jb22CAQEwDwYDVR0TAQH/BAUw |
||||
AwEB/zAzBggrBgEFBQcBAQQnMCUwIwYIKwYBBQUHMAGGF2h0dHA6Ly9vY3NwLmdv |
||||
ZGFkZHkuY29tMEQGA1UdHwQ9MDswOaA3oDWGM2h0dHA6Ly9jZXJ0aWZpY2F0ZXMu |
||||
Z29kYWRkeS5jb20vcmVwb3NpdG9yeS9yb290LmNybDBLBgNVHSAERDBCMEAGBFUd |
||||
IAAwODA2BggrBgEFBQcCARYqaHR0cDovL2NlcnRpZmljYXRlcy5nb2RhZGR5LmNv |
||||
bS9yZXBvc2l0b3J5MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOBgQC1 |
||||
QPmnHfbq/qQaQlpE9xXUhUaJwL6e4+PrxeNYiY+Sn1eocSxI0YGyeR+sBjUZsE4O |
||||
WBsUs5iB0QQeyAfJg594RAoYC5jcdnplDQ1tgMQLARzLrUc+cb53S8wGd9D0Vmsf |
||||
SxOaFIqII6hR8INMqzW/Rn453HWkrugp++85j09VZw== |
||||
-----END CERTIFICATE----- |
||||
-----BEGIN CERTIFICATE----- |
||||
MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0 |
||||
IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAz |
||||
BgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9y |
||||
aXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG |
||||
9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAwMTk1NFoXDTE5MDYy |
||||
NjAwMTk1NFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29y |
||||
azEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs |
||||
YXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw |
||||
Oi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl |
||||
cnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOOnHK5avIWZJV16vY |
||||
dA757tn2VUdZZUcOBVXc65g2PFxTXdMwzzjsvUGJ7SVCCSRrCl6zfN1SLUzm1NZ9 |
||||
WlmpZdRJEy0kTRxQb7XBhVQ7/nHk01xC+YDgkRoKWzk2Z/M/VXwbP7RfZHM047QS |
||||
v4dk+NoS/zcnwbNDu+97bi5p9wIDAQABMA0GCSqGSIb3DQEBBQUAA4GBADt/UG9v |
||||
UJSZSWI4OB9L+KXIPqeCgfYrx+jFzug6EILLGACOTb2oWH+heQC1u+mNr0HZDzTu |
||||
IYEZoDJJKPTEjlbVUjP9UNV+mWwD5MlM/Mtsq2azSiGM5bUMMj4QssxsodyamEwC |
||||
W/POuZ6lcg5Ktz885hZo+L7tdEy8W9ViH0Pd |
||||
-----END CERTIFICATE----- |
||||
|
@ -0,0 +1,110 @@ |
||||
<?php |
||||
/* |
||||
* Copyright 2012 Google Inc. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0 |
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
/** |
||||
* @author Chirag Shah <chirags@google.com> |
||||
*/ |
||||
class Google_BatchRequest { |
||||
/** @var string Multipart Boundary. */ |
||||
private $boundary; |
||||
|
||||
/** @var array service requests to be executed. */ |
||||
private $requests = array(); |
||||
|
||||
public function __construct($boundary = false) { |
||||
$boundary = (false == $boundary) ? mt_rand() : $boundary; |
||||
$this->boundary = str_replace('"', '', $boundary); |
||||
} |
||||
|
||||
public function add(Google_HttpRequest $request, $key = false) { |
||||
if (false == $key) { |
||||
$key = mt_rand(); |
||||
} |
||||
|
||||
$this->requests[$key] = $request; |
||||
} |
||||
|
||||
public function execute() { |
||||
$body = ''; |
||||
|
||||
/** @var Google_HttpRequest $req */ |
||||
foreach($this->requests as $key => $req) { |
||||
$body .= "--{$this->boundary}\n"; |
||||
$body .= $req->toBatchString($key) . "\n"; |
||||
} |
||||
|
||||
$body = rtrim($body); |
||||
$body .= "\n--{$this->boundary}--"; |
||||
|
||||
global $apiConfig; |
||||
$url = $apiConfig['basePath'] . '/batch'; |
||||
$httpRequest = new Google_HttpRequest($url, 'POST'); |
||||
$httpRequest->setRequestHeaders(array( |
||||
'Content-Type' => 'multipart/mixed; boundary=' . $this->boundary)); |
||||
|
||||
$httpRequest->setPostBody($body); |
||||
$response = Google_Client::$io->makeRequest($httpRequest); |
||||
|
||||
$response = $this->parseResponse($response); |
||||
return $response; |
||||
} |
||||
|
||||
public function parseResponse(Google_HttpRequest $response) { |
||||
$contentType = $response->getResponseHeader('content-type'); |
||||
$contentType = explode(';', $contentType); |
||||
$boundary = false; |
||||
foreach($contentType as $part) { |
||||
$part = (explode('=', $part, 2)); |
||||
if (isset($part[0]) && 'boundary' == trim($part[0])) { |
||||
$boundary = $part[1]; |
||||
} |
||||
} |
||||
|
||||
$body = $response->getResponseBody(); |
||||
if ($body) { |
||||
$body = str_replace("--$boundary--", "--$boundary", $body); |
||||
$parts = explode("--$boundary", $body); |
||||
$responses = array(); |
||||
|
||||
foreach($parts as $part) { |
||||
$part = trim($part); |
||||
if (!empty($part)) { |
||||
list($metaHeaders, $part) = explode("\r\n\r\n", $part, 2); |
||||
$metaHeaders = Google_CurlIO::parseResponseHeaders($metaHeaders); |
||||
|
||||
$status = substr($part, 0, strpos($part, "\n")); |
||||
$status = explode(" ", $status); |
||||
$status = $status[1]; |
||||
|
||||
list($partHeaders, $partBody) = Google_CurlIO::parseHttpResponse($part, false); |
||||
$response = new Google_HttpRequest(""); |
||||
$response->setResponseHttpCode($status); |
||||
$response->setResponseHeaders($partHeaders); |
||||
$response->setResponseBody($partBody); |
||||
$response = Google_REST::decodeHttpResponse($response); |
||||
|
||||
// Need content id. |
||||
$responses[$metaHeaders['content-id']] = $response; |
||||
} |
||||
} |
||||
|
||||
return $responses; |
||||
} |
||||
|
||||
return null; |
||||
} |
||||
} |
@ -0,0 +1,262 @@ |
||||
<?php |
||||
/** |
||||
* Copyright 2012 Google Inc. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0 |
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
/** |
||||
* @author Chirag Shah <chirags@google.com> |
||||
* |
||||
*/ |
||||
class Google_MediaFileUpload { |
||||
const UPLOAD_MEDIA_TYPE = 'media'; |
||||
const UPLOAD_MULTIPART_TYPE = 'multipart'; |
||||
const UPLOAD_RESUMABLE_TYPE = 'resumable'; |
||||
|
||||
/** @var string $mimeType */ |
||||
public $mimeType; |
||||
|
||||
/** @var string $data */ |
||||
public $data; |
||||
|
||||
/** @var bool $resumable */ |
||||
public $resumable; |
||||
|
||||
/** @var int $chunkSize */ |
||||
public $chunkSize; |
||||
|
||||
/** @var int $size */ |
||||
public $size; |
||||
|
||||
/** @var string $resumeUri */ |
||||
public $resumeUri; |
||||
|
||||
/** @var int $progress */ |
||||
public $progress; |
||||
|
||||
/** |
||||
* @param $mimeType string |
||||
* @param $data string The bytes you want to upload. |
||||
* @param $resumable bool |
||||
* @param bool $chunkSize File will be uploaded in chunks of this many bytes. |
||||
* only used if resumable=True |
||||
*/ |
||||
public function __construct($mimeType, $data, $resumable=false, $chunkSize=false) { |
||||
$this->mimeType = $mimeType; |
||||
$this->data = $data; |
||||
$this->size = strlen($this->data); |
||||
$this->resumable = $resumable; |
||||
if(!$chunkSize) { |
||||
$chunkSize = 256 * 1024; |
||||
} |
||||
$this->chunkSize = $chunkSize; |
||||
$this->progress = 0; |
||||
} |
||||
|
||||
public function setFileSize($size) { |
||||
$this->size = $size; |
||||
} |
||||
|
||||
/** |
||||
* @static |
||||
* @param $meta |
||||
* @param $params |
||||
* @return array|bool |
||||
*/ |
||||
public static function process($meta, &$params) { |
||||
$payload = array(); |
||||
$meta = is_string($meta) ? json_decode($meta, true) : $meta; |
||||
$uploadType = self::getUploadType($meta, $payload, $params); |
||||
if (!$uploadType) { |
||||
// Process as a normal API request. |
||||
return false; |
||||
} |
||||
|
||||
// Process as a media upload request. |
||||
$params['uploadType'] = array( |
||||
'type' => 'string', |
||||
'location' => 'query', |
||||
'value' => $uploadType, |
||||
); |
||||
|
||||
$mimeType = isset($params['mimeType']) |
||||
? $params['mimeType']['value'] |
||||
: false; |
||||
unset($params['mimeType']); |
||||
|
||||
if (!$mimeType) { |
||||
$mimeType = $payload['content-type']; |
||||
} |
||||
|
||||
if (isset($params['file'])) { |
||||
// This is a standard file upload with curl. |
||||
$file = $params['file']['value']; |
||||
unset($params['file']); |
||||
return self::processFileUpload($file, $mimeType); |
||||
} |
||||
|
||||
$data = isset($params['data']) |
||||
? $params['data']['value'] |
||||
: false; |
||||
unset($params['data']); |
||||
|
||||
if (self::UPLOAD_RESUMABLE_TYPE == $uploadType) { |
||||
$payload['content-type'] = $mimeType; |
||||
$payload['postBody'] = is_string($meta) ? $meta : json_encode($meta); |
||||
|
||||
} elseif (self::UPLOAD_MEDIA_TYPE == $uploadType) { |
||||
// This is a simple media upload. |
||||
$payload['content-type'] = $mimeType; |
||||
$payload['postBody'] = $data; |
||||
} |
||||
|
||||
elseif (self::UPLOAD_MULTIPART_TYPE == $uploadType) { |
||||
// This is a multipart/related upload. |
||||
$boundary = isset($params['boundary']['value']) ? $params['boundary']['value'] : mt_rand(); |
||||
$boundary = str_replace('"', '', $boundary); |
||||
$payload['content-type'] = 'multipart/related; boundary=' . $boundary; |
||||
$related = "--$boundary\r\n"; |
||||
$related .= "Content-Type: application/json; charset=UTF-8\r\n"; |
||||
$related .= "\r\n" . json_encode($meta) . "\r\n"; |
||||
$related .= "--$boundary\r\n"; |
||||
$related .= "Content-Type: $mimeType\r\n"; |
||||
$related .= "Content-Transfer-Encoding: base64\r\n"; |
||||
$related .= "\r\n" . base64_encode($data) . "\r\n"; |
||||
$related .= "--$boundary--"; |
||||
$payload['postBody'] = $related; |
||||
} |
||||
|
||||
return $payload; |
||||
} |
||||
|
||||
/** |
||||
* Prepares a standard file upload via cURL. |
||||
* @param $file |
||||
* @param $mime |
||||
* @return array Includes the processed file name. |
||||
* @visible For testing. |
||||
*/ |
||||
public static function processFileUpload($file, $mime) { |
||||
if (!$file) return array(); |
||||
if (substr($file, 0, 1) != '@') { |
||||
$file = '@' . $file; |
||||
} |
||||
|
||||
// This is a standard file upload with curl. |
||||
$params = array('postBody' => array('file' => $file)); |
||||
if ($mime) { |
||||
$params['content-type'] = $mime; |
||||
} |
||||
|
||||
return $params; |
||||
} |
||||
|
||||
/** |
||||
* Valid upload types: |
||||
* - resumable (UPLOAD_RESUMABLE_TYPE) |
||||
* - media (UPLOAD_MEDIA_TYPE) |
||||
* - multipart (UPLOAD_MULTIPART_TYPE) |
||||
* - none (false) |
||||
* @param $meta |
||||
* @param $payload |
||||
* @param $params |
||||
* @return bool|string |
||||
*/ |
||||
public static function getUploadType($meta, &$payload, &$params) { |
||||
if (isset($params['mediaUpload']) |
||||
&& get_class($params['mediaUpload']['value']) == 'Google_MediaFileUpload') { |
||||
$upload = $params['mediaUpload']['value']; |
||||
unset($params['mediaUpload']); |
||||
$payload['content-type'] = $upload->mimeType; |
||||
if (isset($upload->resumable) && $upload->resumable) { |
||||
return self::UPLOAD_RESUMABLE_TYPE; |
||||
} |
||||
} |
||||
|
||||
// Allow the developer to override the upload type. |
||||
if (isset($params['uploadType'])) { |
||||
return $params['uploadType']['value']; |
||||
} |
||||
|
||||
$data = isset($params['data']['value']) |
||||
? $params['data']['value'] : false; |
||||
|
||||
if (false == $data && false == isset($params['file'])) { |
||||
// No upload data available. |
||||
return false; |
||||
} |
||||
|
||||
if (isset($params['file'])) { |
||||
return self::UPLOAD_MEDIA_TYPE; |
||||
} |
||||
|
||||
if (false == $meta) { |
||||
return self::UPLOAD_MEDIA_TYPE; |
||||
} |
||||
|
||||
return self::UPLOAD_MULTIPART_TYPE; |
||||
} |
||||
|
||||
|
||||
public function nextChunk(Google_HttpRequest $req, $chunk=false) { |
||||
if (false == $this->resumeUri) { |
||||
$this->resumeUri = $this->getResumeUri($req); |
||||
} |
||||
|
||||
if (false == $chunk) { |
||||
$chunk = substr($this->data, $this->progress, $this->chunkSize); |
||||
} |
||||
|
||||
$lastBytePos = $this->progress + strlen($chunk) - 1; |
||||
$headers = array( |
||||
'content-range' => "bytes $this->progress-$lastBytePos/$this->size", |
||||
'content-type' => $req->getRequestHeader('content-type'), |
||||
'content-length' => $this->chunkSize, |
||||
'expect' => '', |
||||
); |
||||
|
||||
$httpRequest = new Google_HttpRequest($this->resumeUri, 'PUT', $headers, $chunk); |
||||
$response = Google_Client::$io->authenticatedRequest($httpRequest); |
||||
$code = $response->getResponseHttpCode(); |
||||
if (308 == $code) { |
||||
$range = explode('-', $response->getResponseHeader('range')); |
||||
$this->progress = $range[1] + 1; |
||||
return false; |
||||
} else { |
||||
return Google_REST::decodeHttpResponse($response); |
||||
} |
||||
} |
||||
|
||||
private function getResumeUri(Google_HttpRequest $httpRequest) { |
||||
$result = null; |
||||
$body = $httpRequest->getPostBody(); |
||||
if ($body) { |
||||
$httpRequest->setRequestHeaders(array( |
||||
'content-type' => 'application/json; charset=UTF-8', |
||||
'content-length' => Google_Utils::getStrLen($body), |
||||
'x-upload-content-type' => $this->mimeType, |
||||
'x-upload-content-length' => $this->size, |
||||
'expect' => '', |
||||
)); |
||||
} |
||||
|
||||
$response = Google_Client::$io->makeRequest($httpRequest); |
||||
$location = $response->getResponseHeader('location'); |
||||
$code = $response->getResponseHttpCode(); |
||||
if (200 == $code && true == $location) { |
||||
return $location; |
||||
} |
||||
throw new Google_Exception("Failed to start the resumable upload"); |
||||
} |
||||
} |
@ -0,0 +1,115 @@ |
||||
<?php |
||||
/* |
||||
* Copyright 2011 Google Inc. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0 |
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
/** |
||||
* This class defines attributes, valid values, and usage which is generated from |
||||
* a given json schema. http://tools.ietf.org/html/draft-zyp-json-schema-03#section-5 |
||||
* |
||||
* @author Chirag Shah <chirags@google.com> |
||||
* |
||||
*/ |
||||
class Google_Model { |
||||
public function __construct( /* polymorphic */ ) { |
||||
if (func_num_args() == 1 && is_array(func_get_arg(0))) { |
||||
// Initialize the model with the array's contents. |
||||
$array = func_get_arg(0); |
||||
$this->mapTypes($array); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Initialize this object's properties from an array. |
||||
* |
||||
* @param array $array Used to seed this object's properties. |
||||
* @return void |
||||
*/ |
||||
protected function mapTypes($array) { |
||||
foreach ($array as $key => $val) { |
||||
$this->$key = $val; |
||||
|
||||
$keyTypeName = "__$key" . 'Type'; |
||||
$keyDataType = "__$key" . 'DataType'; |
||||
if ($this->useObjects() && property_exists($this, $keyTypeName)) { |
||||
if ($this->isAssociativeArray($val)) { |
||||
if (isset($this->$keyDataType) && 'map' == $this->$keyDataType) { |
||||
foreach($val as $arrayKey => $arrayItem) { |
||||
$val[$arrayKey] = $this->createObjectFromName($keyTypeName, $arrayItem); |
||||
} |
||||
$this->$key = $val; |
||||
} else { |
||||
$this->$key = $this->createObjectFromName($keyTypeName, $val); |
||||
} |
||||
} else if (is_array($val)) { |
||||
$arrayObject = array(); |
||||
foreach ($val as $arrayIndex => $arrayItem) { |
||||
$arrayObject[$arrayIndex] = $this->createObjectFromName($keyTypeName, $arrayItem); |
||||
} |
||||
$this->$key = $arrayObject; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Returns true only if the array is associative. |
||||
* @param array $array |
||||
* @return bool True if the array is associative. |
||||
*/ |
||||
protected function isAssociativeArray($array) { |
||||
if (!is_array($array)) { |
||||
return false; |
||||
} |
||||
$keys = array_keys($array); |
||||
foreach($keys as $key) { |
||||
if (is_string($key)) { |
||||
return true; |
||||
} |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* Given a variable name, discover its type. |
||||
* |
||||
* @param $name |
||||
* @param $item |
||||
* @return object The object from the item. |
||||
*/ |
||||
private function createObjectFromName($name, $item) { |
||||
$type = $this->$name; |
||||
return new $type($item); |
||||
} |
||||
|
||||
protected function useObjects() { |
||||
global $apiConfig; |
||||
return (isset($apiConfig['use_objects']) && $apiConfig['use_objects']); |
||||
} |
||||
|
||||
/** |
||||
* Verify if $obj is an array. |
||||
* @throws Google_Exception Thrown if $obj isn't an array. |
||||
* @param array $obj Items that should be validated. |
||||
* @param string $type Array items should be of this type. |
||||
* @param string $method Method expecting an array as an argument. |
||||
*/ |
||||
public function assertIsArray($obj, $type, $method) { |
||||
if ($obj && !is_array($obj)) { |
||||
throw new Google_Exception("Incorrect parameter type passed to $method(), expected an" |
||||
. " array containing items of type $type."); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,22 @@ |
||||
<?php |
||||
/* |
||||
* Copyright 2010 Google Inc. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0 |
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
class Google_Service { |
||||
public $version; |
||||
public $servicePath; |
||||
public $resource; |
||||
} |
@ -0,0 +1,205 @@ |
||||
<?php |
||||
/** |
||||
* Copyright 2010 Google Inc. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0 |
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
/** |
||||
* Implements the actual methods/resources of the discovered Google API using magic function |
||||
* calling overloading (__call()), which on call will see if the method name (plus.activities.list) |
||||
* is available in this service, and if so construct an apiHttpRequest representing it. |
||||
* |
||||
* @author Chris Chabot <chabotc@google.com> |
||||
* @author Chirag Shah <chirags@google.com> |
||||
* |
||||
*/ |
||||
class Google_ServiceResource { |
||||
// Valid query parameters that work, but don't appear in discovery. |
||||
private $stackParameters = array( |
||||
'alt' => array('type' => 'string', 'location' => 'query'), |
||||
'boundary' => array('type' => 'string', 'location' => 'query'), |
||||
'fields' => array('type' => 'string', 'location' => 'query'), |
||||
'trace' => array('type' => 'string', 'location' => 'query'), |
||||
'userIp' => array('type' => 'string', 'location' => 'query'), |
||||
'userip' => array('type' => 'string', 'location' => 'query'), |
||||
'quotaUser' => array('type' => 'string', 'location' => 'query'), |
||||
'file' => array('type' => 'complex', 'location' => 'body'), |
||||
'data' => array('type' => 'string', 'location' => 'body'), |
||||
'mimeType' => array('type' => 'string', 'location' => 'header'), |
||||
'uploadType' => array('type' => 'string', 'location' => 'query'), |
||||
'mediaUpload' => array('type' => 'complex', 'location' => 'query'), |
||||
); |
||||
|
||||
/** @var Google_Service $service */ |
||||
private $service; |
||||
|
||||
/** @var string $serviceName */ |
||||
private $serviceName; |
||||
|
||||
/** @var string $resourceName */ |
||||
private $resourceName; |
||||
|
||||
/** @var array $methods */ |
||||
private $methods; |
||||
|
||||
public function __construct($service, $serviceName, $resourceName, $resource) { |
||||
$this->service = $service; |
||||
$this->serviceName = $serviceName; |
||||
$this->resourceName = $resourceName; |
||||
$this->methods = isset($resource['methods']) ? $resource['methods'] : array($resourceName => $resource); |
||||
} |
||||
|
||||
/** |
||||
* @param $name |
||||
* @param $arguments |
||||
* @return Google_HttpRequest|array |
||||
* @throws Google_Exception |
||||
*/ |
||||
public function __call($name, $arguments) { |
||||
if (! isset($this->methods[$name])) { |
||||
throw new Google_Exception("Unknown function: {$this->serviceName}->{$this->resourceName}->{$name}()"); |
||||
} |
||||
$method = $this->methods[$name]; |
||||
$parameters = $arguments[0]; |
||||
|
||||
// postBody is a special case since it's not defined in the discovery document as parameter, but we abuse the param entry for storing it |
||||
$postBody = null; |
||||
if (isset($parameters['postBody'])) { |
||||
if (is_object($parameters['postBody'])) { |
||||
$this->stripNull($parameters['postBody']); |
||||
} |
||||
|
||||
// Some APIs require the postBody to be set under the data key. |
||||
if (is_array($parameters['postBody']) && 'latitude' == $this->serviceName) { |
||||
if (!isset($parameters['postBody']['data'])) { |
||||
$rawBody = $parameters['postBody']; |
||||
unset($parameters['postBody']); |
||||
$parameters['postBody']['data'] = $rawBody; |
||||
} |
||||
} |
||||
|
||||
$postBody = is_array($parameters['postBody']) || is_object($parameters['postBody']) |
||||
? json_encode($parameters['postBody']) |
||||
: $parameters['postBody']; |
||||
unset($parameters['postBody']); |
||||
|
||||
if (isset($parameters['optParams'])) { |
||||
$optParams = $parameters['optParams']; |
||||
unset($parameters['optParams']); |
||||
$parameters = array_merge($parameters, $optParams); |
||||
} |
||||
} |
||||
|
||||
if (!isset($method['parameters'])) { |
||||
$method['parameters'] = array(); |
||||
} |
||||
|
||||
$method['parameters'] = array_merge($method['parameters'], $this->stackParameters); |
||||
foreach ($parameters as $key => $val) { |
||||
if ($key != 'postBody' && ! isset($method['parameters'][$key])) { |
||||
throw new Google_Exception("($name) unknown parameter: '$key'"); |
||||
} |
||||
} |
||||
if (isset($method['parameters'])) { |
||||
foreach ($method['parameters'] as $paramName => $paramSpec) { |
||||
if (isset($paramSpec['required']) && $paramSpec['required'] && ! isset($parameters[$paramName])) { |
||||
throw new Google_Exception("($name) missing required param: '$paramName'"); |
||||
} |
||||
if (isset($parameters[$paramName])) { |
||||
$value = $parameters[$paramName]; |
||||
$parameters[$paramName] = $paramSpec; |
||||
$parameters[$paramName]['value'] = $value; |
||||
unset($parameters[$paramName]['required']); |
||||
} else { |
||||
unset($parameters[$paramName]); |
||||
} |
||||
} |
||||
} |
||||
|
||||
// Discovery v1.0 puts the canonical method id under the 'id' field. |
||||
if (! isset($method['id'])) { |
||||
$method['id'] = $method['rpcMethod']; |
||||
} |
||||
|
||||
// Discovery v1.0 puts the canonical path under the 'path' field. |
||||
if (! isset($method['path'])) { |
||||
$method['path'] = $method['restPath']; |
||||
} |
||||
|
||||
$servicePath = $this->service->servicePath; |
||||
|
||||
// Process Media Request |
||||
$contentType = false; |
||||
if (isset($method['mediaUpload'])) { |
||||
$media = Google_MediaFileUpload::process($postBody, $parameters); |
||||
if ($media) { |
||||
$contentType = isset($media['content-type']) ? $media['content-type']: null; |
||||
$postBody = isset($media['postBody']) ? $media['postBody'] : null; |
||||
$servicePath = $method['mediaUpload']['protocols']['simple']['path']; |
||||
$method['path'] = ''; |
||||
} |
||||
} |
||||
|
||||
$url = Google_REST::createRequestUri($servicePath, $method['path'], $parameters); |
||||
$httpRequest = new Google_HttpRequest($url, $method['httpMethod'], null, $postBody); |
||||
if ($postBody) { |
||||
$contentTypeHeader = array(); |
||||
if (isset($contentType) && $contentType) { |
||||
$contentTypeHeader['content-type'] = $contentType; |
||||
} else { |
||||
$contentTypeHeader['content-type'] = 'application/json; charset=UTF-8'; |
||||
$contentTypeHeader['content-length'] = Google_Utils::getStrLen($postBody); |
||||
} |
||||
$httpRequest->setRequestHeaders($contentTypeHeader); |
||||
} |
||||
|
||||
$httpRequest = Google_Client::$auth->sign($httpRequest); |
||||
if (Google_Client::$useBatch) { |
||||
return $httpRequest; |
||||
} |
||||
|
||||
// Terminate immediately if this is a resumable request. |
||||
if (isset($parameters['uploadType']['value']) |
||||
&& Google_MediaFileUpload::UPLOAD_RESUMABLE_TYPE == $parameters['uploadType']['value']) { |
||||
$contentTypeHeader = array(); |
||||
if (isset($contentType) && $contentType) { |
||||
$contentTypeHeader['content-type'] = $contentType; |
||||
} |
||||
$httpRequest->setRequestHeaders($contentTypeHeader); |
||||
if ($postBody) { |
||||
$httpRequest->setPostBody($postBody); |
||||
} |
||||
return $httpRequest; |
||||
} |
||||
|
||||
return Google_REST::execute($httpRequest); |
||||
} |
||||
|
||||
public function useObjects() { |
||||
global $apiConfig; |
||||
return (isset($apiConfig['use_objects']) && $apiConfig['use_objects']); |
||||
} |
||||
|
||||
protected function stripNull(&$o) { |
||||
$o = (array) $o; |
||||
foreach ($o as $k => $v) { |
||||
if ($v === null || strstr($k, "\0*\0__")) { |
||||
unset($o[$k]); |
||||
} |
||||
elseif (is_object($v) || is_array($v)) { |
||||
$this->stripNull($o[$k]); |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,117 @@ |
||||
<?php |
||||
/* |
||||
* Copyright 2011 Google Inc. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0 |
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
/** |
||||
* Collection of static utility methods used for convenience across |
||||
* the client library. |
||||
* |
||||
* @author Chirag Shah <chirags@google.com> |
||||
*/ |
||||
class Google_Utils { |
||||
public static function urlSafeB64Encode($data) { |
||||
$b64 = base64_encode($data); |
||||
$b64 = str_replace(array('+', '/', '\r', '\n', '='), |
||||
array('-', '_'), |
||||
$b64); |
||||
return $b64; |
||||
} |
||||
|
||||
public static function urlSafeB64Decode($b64) { |
||||
$b64 = str_replace(array('-', '_'), |
||||
array('+', '/'), |
||||
$b64); |
||||
return base64_decode($b64); |
||||
} |
||||
|
||||
/** |
||||
* Misc function used to count the number of bytes in a post body, in the world of multi-byte chars |
||||
* and the unpredictability of strlen/mb_strlen/sizeof, this is the only way to do that in a sane |
||||
* manner at the moment. |
||||
* |
||||
* This algorithm was originally developed for the |
||||
* Solar Framework by Paul M. Jones |
||||
* |
||||
* @link http://solarphp.com/ |
||||
* @link http://svn.solarphp.com/core/trunk/Solar/Json.php |
||||
* @link http://framework.zend.com/svn/framework/standard/trunk/library/Zend/Json/Decoder.php |
||||
* @param string $str |
||||
* @return int The number of bytes in a string. |
||||
*/ |
||||
static public function getStrLen($str) { |
||||
$strlenVar = strlen($str); |
||||
$d = $ret = 0; |
||||
for ($count = 0; $count < $strlenVar; ++ $count) { |
||||
$ordinalValue = ord($str{$ret}); |
||||
switch (true) { |
||||
case (($ordinalValue >= 0x20) && ($ordinalValue <= 0x7F)): |
||||
// characters U-00000000 - U-0000007F (same as ASCII) |
||||
$ret ++; |
||||
break; |
||||
|
||||
case (($ordinalValue & 0xE0) == 0xC0): |
||||
// characters U-00000080 - U-000007FF, mask 110XXXXX |
||||
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
||||
$ret += 2; |
||||
break; |
||||
|
||||
case (($ordinalValue & 0xF0) == 0xE0): |
||||
// characters U-00000800 - U-0000FFFF, mask 1110XXXX |
||||
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
||||
$ret += 3; |
||||
break; |
||||
|
||||
case (($ordinalValue & 0xF8) == 0xF0): |
||||
// characters U-00010000 - U-001FFFFF, mask 11110XXX |
||||
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
||||
$ret += 4; |
||||
break; |
||||
|
||||
case (($ordinalValue & 0xFC) == 0xF8): |
||||
// characters U-00200000 - U-03FFFFFF, mask 111110XX |
||||
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
||||
$ret += 5; |
||||
break; |
||||
|
||||
case (($ordinalValue & 0xFE) == 0xFC): |
||||
// characters U-04000000 - U-7FFFFFFF, mask 1111110X |
||||
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
||||
$ret += 6; |
||||
break; |
||||
default: |
||||
$ret ++; |
||||
} |
||||
} |
||||
return $ret; |
||||
} |
||||
|
||||
/** |
||||
* Normalize all keys in an array to lower-case. |
||||
* @param array $arr |
||||
* @return array Normalized array. |
||||
*/ |
||||
public static function normalize($arr) { |
||||
if (!is_array($arr)) { |
||||
return array(); |
||||
} |
||||
|
||||
$normalized = array(); |
||||
foreach ($arr as $key => $val) { |
||||
$normalized[strtolower($key)] = $val; |
||||
} |
||||
return $normalized; |
||||
} |
||||
} |
Loading…
Reference in new issue