├── .gitignore ├── README ├── config └── googleplus.php ├── libraries └── Googleplus.php └── third_party └── google-api-php-client ├── LICENSE ├── NOTICE ├── README └── src ├── Google_Client.php ├── auth ├── Google_AssertionCredentials.php ├── Google_Auth.php ├── Google_AuthNone.php ├── Google_LoginTicket.php ├── Google_OAuth2.php ├── Google_P12Signer.php ├── Google_PemVerifier.php ├── Google_Signer.php └── Google_Verifier.php ├── cache ├── Google_ApcCache.php ├── Google_Cache.php ├── Google_FileCache.php └── Google_MemcacheCache.php ├── config.php ├── contrib └── Google_PlusService.php ├── external ├── OAuth.php └── URITemplateParser.php ├── io ├── Google_CacheParser.php ├── Google_CurlIO.php ├── Google_HttpRequest.php ├── Google_IO.php ├── Google_REST.php └── cacerts.pem └── service ├── Google_BatchRequest.php ├── Google_MediaFileUpload.php ├── Google_Model.php ├── Google_Service.php ├── Google_ServiceResource.php └── Google_Utils.php /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Just upload these files into your CodeIgniter application folder and set the config variables. You can then load the library like this 2 | $this->load->library('googleplus'); 3 | 4 | Example usage: 5 | $this->googleplus->people->get('me'); // when authorized 6 | $this->googleplus->people->get('115414977082318263605'); // that's me :-) 7 | 8 | Read the full API docs on the Google+ website http://developers.google.com/+/api 9 | 10 | Uses the Google APIs Client Library for PHP 11 | http://code.google.com/p/google-api-php-client/ -------------------------------------------------------------------------------- /config/googleplus.php: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /libraries/Googleplus.php: -------------------------------------------------------------------------------- 1 | config->load('googleplus'); 9 | 10 | require APPPATH .'third_party/google-api-php-client/src/Google_Client.php'; 11 | require APPPATH .'third_party/google-api-php-client/src/contrib/Google_PlusService.php'; 12 | 13 | $cache_path = $CI->config->item('cache_path'); 14 | $GLOBALS['apiConfig']['ioFileCache_directory'] = ($cache_path == '') ? APPPATH .'cache/' : $cache_path; 15 | 16 | $this->client = new Google_Client(); 17 | $this->client->setApplicationName($CI->config->item('application_name', 'googleplus')); 18 | $this->client->setClientId($CI->config->item('client_id', 'googleplus')); 19 | $this->client->setClientSecret($CI->config->item('client_secret', 'googleplus')); 20 | $this->client->setRedirectUri($CI->config->item('redirect_uri', 'googleplus')); 21 | $this->client->setDeveloperKey($CI->config->item('api_key', 'googleplus')); 22 | 23 | $this->plus = new Google_PlusService($this->client); 24 | 25 | } 26 | 27 | public function __get($name) { 28 | 29 | if(isset($this->plus->$name)) { 30 | return $this->plus->$name; 31 | } 32 | return false; 33 | 34 | } 35 | 36 | public function __call($name, $arguments) { 37 | 38 | if(method_exists($this->plus, $name)) { 39 | return call_user_func(array($this->plus, $name), $arguments); 40 | } 41 | return false; 42 | 43 | } 44 | 45 | } 46 | ?> -------------------------------------------------------------------------------- /third_party/google-api-php-client/LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | 203 | 204 | -------------------------------------------------------------------------------- /third_party/google-api-php-client/NOTICE: -------------------------------------------------------------------------------- 1 | This product contains the following libraries: 2 | 3 | XRDS-Simple library from http://code.google.com/p/diso/ 4 | Apache License 2.0 5 | -------------------------------------------------------------------------------- /third_party/google-api-php-client/README: -------------------------------------------------------------------------------- 1 | Google APIs Client Library for PHP 2 | ===================================== 3 | 4 | == Description 5 | The Google API Client Library enables you to work with Google APIs such as Google+, Drive, Tasks, or Latitude on your server. 6 | 7 | Requirements: 8 | PHP 5.2.x or higher [http://www.php.net/] 9 | PHP Curl extension [http://www.php.net/manual/en/intro.curl.php] 10 | PHP JSON extension [http://php.net/manual/en/book.json.php] 11 | 12 | Project page: 13 | http://code.google.com/p/google-api-php-client 14 | 15 | OAuth 2 instructions: 16 | http://code.google.com/p/google-api-php-client/wiki/OAuth2 17 | 18 | Report a defect or feature request here: 19 | http://code.google.com/p/google-api-php-client/issues/entry 20 | 21 | Subscribe to project updates in your feed reader: 22 | http://code.google.com/feeds/p/google-api-php-client/updates/basic 23 | 24 | Supported sample applications: 25 | http://code.google.com/p/google-api-php-client/wiki/Samples 26 | 27 | == Basic Example 28 | 'free-ebooks'); 36 | $results = $service->volumes->listVolumes('Henry David Thoreau', $optParams); 37 | 38 | foreach ($results['items'] as $item) { 39 | print($item['volumeInfo']['title'] . '
'); 40 | } 41 | -------------------------------------------------------------------------------- /third_party/google-api-php-client/src/Google_Client.php: -------------------------------------------------------------------------------- 1 | 66 | * @author Chirag Shah 67 | */ 68 | class Google_Client { 69 | /** 70 | * @static 71 | * @var Google_Auth $auth 72 | */ 73 | static $auth; 74 | 75 | /** 76 | * @static 77 | * @var Google_IO $io 78 | */ 79 | static $io; 80 | 81 | /** 82 | * @static 83 | * @var Google_Cache $cache 84 | */ 85 | static $cache; 86 | 87 | /** 88 | * @static 89 | * @var boolean $useBatch 90 | */ 91 | static $useBatch = false; 92 | 93 | /** @var array $scopes */ 94 | protected $scopes = array(); 95 | 96 | /** @var bool $useObjects */ 97 | protected $useObjects = false; 98 | 99 | // definitions of services that are discovered. 100 | protected $services = array(); 101 | 102 | // Used to track authenticated state, can't discover services after doing authenticate() 103 | private $authenticated = false; 104 | 105 | public function __construct($config = array()) { 106 | global $apiConfig; 107 | $apiConfig = array_merge($apiConfig, $config); 108 | self::$cache = new $apiConfig['cacheClass'](); 109 | self::$auth = new $apiConfig['authClass'](); 110 | self::$io = new $apiConfig['ioClass'](); 111 | } 112 | 113 | /** 114 | * Add a service 115 | */ 116 | public function addService($service, $version = false) { 117 | global $apiConfig; 118 | if ($this->authenticated) { 119 | throw new Google_Exception('Cant add services after having authenticated'); 120 | } 121 | $this->services[$service] = array(); 122 | if (isset($apiConfig['services'][$service])) { 123 | // Merge the service descriptor with the default values 124 | $this->services[$service] = array_merge($this->services[$service], $apiConfig['services'][$service]); 125 | } 126 | } 127 | 128 | public function authenticate($code = null) { 129 | $service = $this->prepareService(); 130 | $this->authenticated = true; 131 | return self::$auth->authenticate($service, $code); 132 | } 133 | 134 | /** 135 | * @return array 136 | * @visible For Testing 137 | */ 138 | public function prepareService() { 139 | $service = array(); 140 | $scopes = array(); 141 | if ($this->scopes) { 142 | $scopes = $this->scopes; 143 | } else { 144 | foreach ($this->services as $key => $val) { 145 | if (isset($val['scope'])) { 146 | if (is_array($val['scope'])) { 147 | $scopes = array_merge($val['scope'], $scopes); 148 | } else { 149 | $scopes[] = $val['scope']; 150 | } 151 | } else { 152 | $scopes[] = 'https://www.googleapis.com/auth/' . $key; 153 | } 154 | unset($val['discoveryURI']); 155 | unset($val['scope']); 156 | $service = array_merge($service, $val); 157 | } 158 | } 159 | $service['scope'] = implode(' ', $scopes); 160 | return $service; 161 | } 162 | 163 | /** 164 | * Set the OAuth 2.0 access token using the string that resulted from calling authenticate() 165 | * or Google_Client#getAccessToken(). 166 | * @param string $accessToken JSON encoded string containing in the following format: 167 | * {"access_token":"TOKEN", "refresh_token":"TOKEN", "token_type":"Bearer", 168 | * "expires_in":3600, "id_token":"TOKEN", "created":1320790426} 169 | */ 170 | public function setAccessToken($accessToken) { 171 | if ($accessToken == null || 'null' == $accessToken) { 172 | $accessToken = null; 173 | } 174 | self::$auth->setAccessToken($accessToken); 175 | } 176 | 177 | /** 178 | * Set the type of Auth class the client should use. 179 | * @param string $authClassName 180 | */ 181 | public function setAuthClass($authClassName) { 182 | self::$auth = new $authClassName(); 183 | } 184 | 185 | /** 186 | * Construct the OAuth 2.0 authorization request URI. 187 | * @return string 188 | */ 189 | public function createAuthUrl() { 190 | $service = $this->prepareService(); 191 | return self::$auth->createAuthUrl($service['scope']); 192 | } 193 | 194 | /** 195 | * Get the OAuth 2.0 access token. 196 | * @return string $accessToken JSON encoded string in the following format: 197 | * {"access_token":"TOKEN", "refresh_token":"TOKEN", "token_type":"Bearer", 198 | * "expires_in":3600,"id_token":"TOKEN", "created":1320790426} 199 | */ 200 | public function getAccessToken() { 201 | $token = self::$auth->getAccessToken(); 202 | return (null == $token || 'null' == $token) ? null : $token; 203 | } 204 | 205 | /** 206 | * Returns if the access_token is expired. 207 | * @return bool Returns True if the access_token is expired. 208 | */ 209 | public function isAccessTokenExpired() { 210 | return self::$auth->isAccessTokenExpired(); 211 | } 212 | 213 | /** 214 | * Set the developer key to use, these are obtained through the API Console. 215 | * @see http://code.google.com/apis/console-help/#generatingdevkeys 216 | * @param string $developerKey 217 | */ 218 | public function setDeveloperKey($developerKey) { 219 | self::$auth->setDeveloperKey($developerKey); 220 | } 221 | 222 | /** 223 | * Set OAuth 2.0 "state" parameter to achieve per-request customization. 224 | * @see http://tools.ietf.org/html/draft-ietf-oauth-v2-22#section-3.1.2.2 225 | * @param string $state 226 | */ 227 | public function setState($state) { 228 | self::$auth->setState($state); 229 | } 230 | 231 | /** 232 | * @param string $accessType Possible values for access_type include: 233 | * {@code "offline"} to request offline access from the user. (This is the default value) 234 | * {@code "online"} to request online access from the user. 235 | */ 236 | public function setAccessType($accessType) { 237 | self::$auth->setAccessType($accessType); 238 | } 239 | 240 | /** 241 | * @param string $approvalPrompt Possible values for approval_prompt include: 242 | * {@code "force"} to force the approval UI to appear. (This is the default value) 243 | * {@code "auto"} to request auto-approval when possible. 244 | */ 245 | public function setApprovalPrompt($approvalPrompt) { 246 | self::$auth->setApprovalPrompt($approvalPrompt); 247 | } 248 | 249 | /** 250 | * Set the application name, this is included in the User-Agent HTTP header. 251 | * @param string $applicationName 252 | */ 253 | public function setApplicationName($applicationName) { 254 | global $apiConfig; 255 | $apiConfig['application_name'] = $applicationName; 256 | } 257 | 258 | /** 259 | * Set the OAuth 2.0 Client ID. 260 | * @param string $clientId 261 | */ 262 | public function setClientId($clientId) { 263 | global $apiConfig; 264 | $apiConfig['oauth2_client_id'] = $clientId; 265 | self::$auth->clientId = $clientId; 266 | } 267 | 268 | /** 269 | * Get the OAuth 2.0 Client ID. 270 | */ 271 | public function getClientId() { 272 | return self::$auth->clientId; 273 | } 274 | 275 | /** 276 | * Set the OAuth 2.0 Client Secret. 277 | * @param string $clientSecret 278 | */ 279 | public function setClientSecret($clientSecret) { 280 | global $apiConfig; 281 | $apiConfig['oauth2_client_secret'] = $clientSecret; 282 | self::$auth->clientSecret = $clientSecret; 283 | } 284 | 285 | /** 286 | * Get the OAuth 2.0 Client Secret. 287 | */ 288 | public function getClientSecret() { 289 | return self::$auth->clientSecret; 290 | } 291 | 292 | /** 293 | * Set the OAuth 2.0 Redirect URI. 294 | * @param string $redirectUri 295 | */ 296 | public function setRedirectUri($redirectUri) { 297 | global $apiConfig; 298 | $apiConfig['oauth2_redirect_uri'] = $redirectUri; 299 | self::$auth->redirectUri = $redirectUri; 300 | } 301 | 302 | /** 303 | * Get the OAuth 2.0 Redirect URI. 304 | */ 305 | public function getRedirectUri() { 306 | return self::$auth->redirectUri; 307 | } 308 | 309 | /** 310 | * Fetches a fresh OAuth 2.0 access token with the given refresh token. 311 | * @param string $refreshToken 312 | * @return void 313 | */ 314 | public function refreshToken($refreshToken) { 315 | self::$auth->refreshToken($refreshToken); 316 | } 317 | 318 | /** 319 | * Revoke an OAuth2 access token or refresh token. This method will revoke the current access 320 | * token, if a token isn't provided. 321 | * @throws Google_AuthException 322 | * @param string|null $token The token (access token or a refresh token) that should be revoked. 323 | * @return boolean Returns True if the revocation was successful, otherwise False. 324 | */ 325 | public function revokeToken($token = null) { 326 | self::$auth->revokeToken($token); 327 | } 328 | 329 | /** 330 | * Verify an id_token. This method will verify the current id_token, if one 331 | * isn't provided. 332 | * @throws Google_AuthException 333 | * @param string|null $token The token (id_token) that should be verified. 334 | * @return Google_LoginTicket Returns an apiLoginTicket if the verification was 335 | * successful. 336 | */ 337 | public function verifyIdToken($token = null) { 338 | return self::$auth->verifyIdToken($token); 339 | } 340 | 341 | /** 342 | * @param Google_AssertionCredentials $creds 343 | * @return void 344 | */ 345 | public function setAssertionCredentials(Google_AssertionCredentials $creds) { 346 | self::$auth->setAssertionCredentials($creds); 347 | } 348 | 349 | /** 350 | * This function allows you to overrule the automatically generated scopes, 351 | * so that you can ask for more or less permission in the auth flow 352 | * Set this before you call authenticate() though! 353 | * @param array $scopes, ie: array('https://www.googleapis.com/auth/plus.me', 'https://www.googleapis.com/auth/moderator') 354 | */ 355 | public function setScopes($scopes) { 356 | $this->scopes = is_string($scopes) ? explode(" ", $scopes) : $scopes; 357 | } 358 | 359 | /** 360 | * Declare if objects should be returned by the api service classes. 361 | * 362 | * @param boolean $useObjects True if objects should be returned by the service classes. 363 | * False if associative arrays should be returned (default behavior). 364 | * @experimental 365 | */ 366 | public function setUseObjects($useObjects) { 367 | global $apiConfig; 368 | $apiConfig['use_objects'] = $useObjects; 369 | } 370 | 371 | /** 372 | * Declare if objects should be returned by the api service classes. 373 | * 374 | * @param boolean $useBatch True if the experimental batch support should 375 | * be enabled. Defaults to False. 376 | * @experimental 377 | */ 378 | public function setUseBatch($useBatch) { 379 | self::$useBatch = $useBatch; 380 | } 381 | 382 | /** 383 | * @static 384 | * @return Google_Auth the implementation of apiAuth. 385 | */ 386 | public static function getAuth() { 387 | return Google_Client::$auth; 388 | } 389 | 390 | /** 391 | * @static 392 | * @return Google_IO the implementation of apiIo. 393 | */ 394 | public static function getIo() { 395 | return Google_Client::$io; 396 | } 397 | 398 | /** 399 | * @return Google_Cache the implementation of apiCache. 400 | */ 401 | public function getCache() { 402 | return Google_Client::$cache; 403 | } 404 | } 405 | 406 | // Exceptions that the Google PHP API Library can throw 407 | class Google_Exception extends Exception {} 408 | class Google_AuthException extends Google_Exception {} 409 | class Google_CacheException extends Google_Exception {} 410 | class Google_IOException extends Google_Exception {} 411 | class Google_ServiceException extends Google_Exception { 412 | /** 413 | * Optional list of errors returned in a JSON body of an HTTP error response. 414 | */ 415 | protected $errors = array(); 416 | 417 | /** 418 | * Override default constructor to add ability to set $errors. 419 | * 420 | * @param string $message 421 | * @param int $code 422 | * @param Exception|null $previous 423 | * @param [{string, string}] errors List of errors returned in an HTTP 424 | * response. Defaults to []. 425 | */ 426 | public function __construct($message, $code = 0, Exception $previous = null, 427 | $errors = array()) { 428 | if(version_compare(PHP_VERSION, '5.3.0') >= 0) { 429 | parent::__construct($message, $code, $previous); 430 | } else { 431 | parent::__construct($message, $code); 432 | } 433 | 434 | $this->errors = $errors; 435 | } 436 | 437 | /** 438 | * An example of the possible errors returned. 439 | * 440 | * { 441 | * "domain": "global", 442 | * "reason": "authError", 443 | * "message": "Invalid Credentials", 444 | * "locationType": "header", 445 | * "location": "Authorization", 446 | * } 447 | * 448 | * @return [{string, string}] List of errors return in an HTTP response or []. 449 | */ 450 | public function getErrors() { 451 | return $this->errors; 452 | } 453 | } 454 | -------------------------------------------------------------------------------- /third_party/google-api-php-client/src/auth/Google_AssertionCredentials.php: -------------------------------------------------------------------------------- 1 | 22 | */ 23 | class Google_AssertionCredentials { 24 | const MAX_TOKEN_LIFETIME_SECS = 3600; 25 | 26 | public $serviceAccountName; 27 | public $scopes; 28 | public $privateKey; 29 | public $privateKeyPassword; 30 | public $assertionType; 31 | public $prn; 32 | 33 | /** 34 | * @param $serviceAccountName 35 | * @param $scopes array List of scopes 36 | * @param $privateKey 37 | * @param string $privateKeyPassword 38 | * @param string $assertionType 39 | * @param bool|string $prn The email address of the user for which the 40 | * application is requesting delegated access. 41 | */ 42 | public function __construct( 43 | $serviceAccountName, 44 | $scopes, 45 | $privateKey, 46 | $privateKeyPassword = 'notasecret', 47 | $assertionType = 'http://oauth.net/grant_type/jwt/1.0/bearer', 48 | $prn = false) { 49 | $this->serviceAccountName = $serviceAccountName; 50 | $this->scopes = is_string($scopes) ? $scopes : implode(' ', $scopes); 51 | $this->privateKey = $privateKey; 52 | $this->privateKeyPassword = $privateKeyPassword; 53 | $this->assertionType = $assertionType; 54 | $this->prn = $prn; 55 | } 56 | 57 | public function generateAssertion() { 58 | $now = time(); 59 | 60 | $jwtParams = array( 61 | 'aud' => Google_OAuth2::OAUTH2_TOKEN_URI, 62 | 'scope' => $this->scopes, 63 | 'iat' => $now, 64 | 'exp' => $now + self::MAX_TOKEN_LIFETIME_SECS, 65 | 'iss' => $this->serviceAccountName, 66 | ); 67 | 68 | if ($this->prn !== false) { 69 | $jwtParams['prn'] = $this->prn; 70 | } 71 | 72 | return $this->makeSignedJwt($jwtParams); 73 | } 74 | 75 | /** 76 | * Creates a signed JWT. 77 | * @param array $payload 78 | * @return string The signed JWT. 79 | */ 80 | private function makeSignedJwt($payload) { 81 | $header = array('typ' => 'JWT', 'alg' => 'RS256'); 82 | 83 | $segments = array( 84 | Google_Utils::urlSafeB64Encode(json_encode($header)), 85 | Google_Utils::urlSafeB64Encode(json_encode($payload)) 86 | ); 87 | 88 | $signingInput = implode('.', $segments); 89 | $signer = new Google_P12Signer($this->privateKey, $this->privateKeyPassword); 90 | $signature = $signer->sign($signingInput); 91 | $segments[] = Google_Utils::urlSafeB64Encode($signature); 92 | 93 | return implode(".", $segments); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /third_party/google-api-php-client/src/auth/Google_Auth.php: -------------------------------------------------------------------------------- 1 | 24 | * 25 | */ 26 | abstract class Google_Auth { 27 | abstract public function authenticate($service); 28 | abstract public function sign(Google_HttpRequest $request); 29 | abstract public function createAuthUrl($scope); 30 | 31 | abstract public function getAccessToken(); 32 | abstract public function setAccessToken($accessToken); 33 | abstract public function setDeveloperKey($developerKey); 34 | abstract public function refreshToken($refreshToken); 35 | abstract public function revokeToken(); 36 | } 37 | -------------------------------------------------------------------------------- /third_party/google-api-php-client/src/auth/Google_AuthNone.php: -------------------------------------------------------------------------------- 1 | 21 | * @author Chirag Shah 22 | */ 23 | class Google_AuthNone extends Google_Auth { 24 | public $key = null; 25 | 26 | public function __construct() { 27 | global $apiConfig; 28 | if (!empty($apiConfig['developer_key'])) { 29 | $this->setDeveloperKey($apiConfig['developer_key']); 30 | } 31 | } 32 | 33 | public function setDeveloperKey($key) {$this->key = $key;} 34 | public function authenticate($service) {/*noop*/} 35 | public function setAccessToken($accessToken) {/* noop*/} 36 | public function getAccessToken() {return null;} 37 | public function createAuthUrl($scope) {return null;} 38 | public function refreshToken($refreshToken) {/* noop*/} 39 | public function revokeToken() {/* noop*/} 40 | 41 | public function sign(Google_HttpRequest $request) { 42 | if ($this->key) { 43 | $request->setUrl($request->getUrl() . ((strpos($request->getUrl(), '?') === false) ? '?' : '&') 44 | . 'key='.urlencode($this->key)); 45 | } 46 | return $request; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /third_party/google-api-php-client/src/auth/Google_LoginTicket.php: -------------------------------------------------------------------------------- 1 | 22 | */ 23 | class Google_LoginTicket { 24 | const USER_ATTR = "id"; 25 | 26 | // Information from id token envelope. 27 | private $envelope; 28 | 29 | // Information from id token payload. 30 | private $payload; 31 | 32 | /** 33 | * Creates a user based on the supplied token. 34 | * 35 | * @param string $envelope Header from a verified authentication token. 36 | * @param string $payload Information from a verified authentication token. 37 | */ 38 | public function __construct($envelope, $payload) { 39 | $this->envelope = $envelope; 40 | $this->payload = $payload; 41 | } 42 | 43 | /** 44 | * Returns the numeric identifier for the user. 45 | * @throws Google_AuthException 46 | * @return 47 | */ 48 | public function getUserId() { 49 | if (array_key_exists(self::USER_ATTR, $this->payload)) { 50 | return $this->payload[self::USER_ATTR]; 51 | } 52 | throw new Google_AuthException("No user_id in token"); 53 | } 54 | 55 | /** 56 | * Returns attributes from the login ticket. This can contain 57 | * various information about the user session. 58 | * @return array 59 | */ 60 | public function getAttributes() { 61 | return array("envelope" => $this->envelope, "payload" => $this->payload); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /third_party/google-api-php-client/src/auth/Google_OAuth2.php: -------------------------------------------------------------------------------- 1 | 26 | * @author Chirag Shah 27 | * 28 | */ 29 | class Google_OAuth2 extends Google_Auth { 30 | public $clientId; 31 | public $clientSecret; 32 | public $developerKey; 33 | public $token; 34 | public $redirectUri; 35 | public $state; 36 | public $accessType = 'offline'; 37 | public $approvalPrompt = 'force'; 38 | 39 | /** @var Google_AssertionCredentials $assertionCredentials */ 40 | public $assertionCredentials; 41 | 42 | const OAUTH2_REVOKE_URI = 'https://accounts.google.com/o/oauth2/revoke'; 43 | const OAUTH2_TOKEN_URI = 'https://accounts.google.com/o/oauth2/token'; 44 | const OAUTH2_AUTH_URL = 'https://accounts.google.com/o/oauth2/auth'; 45 | const OAUTH2_FEDERATED_SIGNON_CERTS_URL = 'https://www.googleapis.com/oauth2/v1/certs'; 46 | const CLOCK_SKEW_SECS = 300; // five minutes in seconds 47 | const AUTH_TOKEN_LIFETIME_SECS = 300; // five minutes in seconds 48 | const MAX_TOKEN_LIFETIME_SECS = 86400; // one day in seconds 49 | 50 | /** 51 | * Instantiates the class, but does not initiate the login flow, leaving it 52 | * to the discretion of the caller (which is done by calling authenticate()). 53 | */ 54 | public function __construct() { 55 | global $apiConfig; 56 | 57 | if (! empty($apiConfig['developer_key'])) { 58 | $this->developerKey = $apiConfig['developer_key']; 59 | } 60 | 61 | if (! empty($apiConfig['oauth2_client_id'])) { 62 | $this->clientId = $apiConfig['oauth2_client_id']; 63 | } 64 | 65 | if (! empty($apiConfig['oauth2_client_secret'])) { 66 | $this->clientSecret = $apiConfig['oauth2_client_secret']; 67 | } 68 | 69 | if (! empty($apiConfig['oauth2_redirect_uri'])) { 70 | $this->redirectUri = $apiConfig['oauth2_redirect_uri']; 71 | } 72 | 73 | if (! empty($apiConfig['oauth2_access_type'])) { 74 | $this->accessType = $apiConfig['oauth2_access_type']; 75 | } 76 | 77 | if (! empty($apiConfig['oauth2_approval_prompt'])) { 78 | $this->approvalPrompt = $apiConfig['oauth2_approval_prompt']; 79 | } 80 | } 81 | 82 | /** 83 | * @param $service 84 | * @param string|null $code 85 | * @throws Google_AuthException 86 | * @return string 87 | */ 88 | public function authenticate($service, $code = null) { 89 | if (!$code && isset($_GET['code'])) { 90 | $code = $_GET['code']; 91 | } 92 | 93 | if ($code) { 94 | // We got here from the redirect from a successful authorization grant, fetch the access token 95 | $request = Google_Client::$io->makeRequest(new Google_HttpRequest(self::OAUTH2_TOKEN_URI, 'POST', array(), array( 96 | 'code' => $code, 97 | 'grant_type' => 'authorization_code', 98 | 'redirect_uri' => $this->redirectUri, 99 | 'client_id' => $this->clientId, 100 | 'client_secret' => $this->clientSecret 101 | ))); 102 | 103 | if ($request->getResponseHttpCode() == 200) { 104 | $this->setAccessToken($request->getResponseBody()); 105 | $this->token['created'] = time(); 106 | return $this->getAccessToken(); 107 | } else { 108 | $response = $request->getResponseBody(); 109 | $decodedResponse = json_decode($response, true); 110 | if ($decodedResponse != null && $decodedResponse['error']) { 111 | $response = $decodedResponse['error']; 112 | } 113 | throw new Google_AuthException("Error fetching OAuth2 access token, message: '$response'", $request->getResponseHttpCode()); 114 | } 115 | } 116 | 117 | $authUrl = $this->createAuthUrl($service['scope']); 118 | header('Location: ' . $authUrl); 119 | return true; 120 | } 121 | 122 | /** 123 | * Create a URL to obtain user authorization. 124 | * The authorization endpoint allows the user to first 125 | * authenticate, and then grant/deny the access request. 126 | * @param string $scope The scope is expressed as a list of space-delimited strings. 127 | * @return string 128 | */ 129 | public function createAuthUrl($scope) { 130 | $params = array( 131 | 'response_type=code', 132 | 'redirect_uri=' . urlencode($this->redirectUri), 133 | 'client_id=' . urlencode($this->clientId), 134 | 'scope=' . urlencode($scope), 135 | 'access_type=' . urlencode($this->accessType), 136 | 'approval_prompt=' . urlencode($this->approvalPrompt) 137 | ); 138 | 139 | if (isset($this->state)) { 140 | $params[] = 'state=' . urlencode($this->state); 141 | } 142 | $params = implode('&', $params); 143 | return self::OAUTH2_AUTH_URL . "?$params"; 144 | } 145 | 146 | /** 147 | * @param string $token 148 | * @throws Google_AuthException 149 | */ 150 | public function setAccessToken($token) { 151 | $token = json_decode($token, true); 152 | if ($token == null) { 153 | throw new Google_AuthException('Could not json decode the token'); 154 | } 155 | if (! isset($token['access_token'])) { 156 | throw new Google_AuthException("Invalid token format"); 157 | } 158 | $this->token = $token; 159 | } 160 | 161 | public function getAccessToken() { 162 | return json_encode($this->token); 163 | } 164 | 165 | public function setDeveloperKey($developerKey) { 166 | $this->developerKey = $developerKey; 167 | } 168 | 169 | public function setState($state) { 170 | $this->state = $state; 171 | } 172 | 173 | public function setAccessType($accessType) { 174 | $this->accessType = $accessType; 175 | } 176 | 177 | public function setApprovalPrompt($approvalPrompt) { 178 | $this->approvalPrompt = $approvalPrompt; 179 | } 180 | 181 | public function setAssertionCredentials(Google_AssertionCredentials $creds) { 182 | $this->assertionCredentials = $creds; 183 | } 184 | 185 | /** 186 | * Include an accessToken in a given apiHttpRequest. 187 | * @param Google_HttpRequest $request 188 | * @return Google_HttpRequest 189 | * @throws Google_AuthException 190 | */ 191 | public function sign(Google_HttpRequest $request) { 192 | // add the developer key to the request before signing it 193 | if ($this->developerKey) { 194 | $requestUrl = $request->getUrl(); 195 | $requestUrl .= (strpos($request->getUrl(), '?') === false) ? '?' : '&'; 196 | $requestUrl .= 'key=' . urlencode($this->developerKey); 197 | $request->setUrl($requestUrl); 198 | } 199 | 200 | // Cannot sign the request without an OAuth access token. 201 | if (null == $this->token && null == $this->assertionCredentials) { 202 | return $request; 203 | } 204 | 205 | // Check if the token is set to expire in the next 30 seconds 206 | // (or has already expired). 207 | if ($this->isAccessTokenExpired()) { 208 | if ($this->assertionCredentials) { 209 | $this->refreshTokenWithAssertion(); 210 | } else { 211 | if (! array_key_exists('refresh_token', $this->token)) { 212 | throw new Google_AuthException("The OAuth 2.0 access token has expired, " 213 | . "and a refresh token is not available. Refresh tokens are not " 214 | . "returned for responses that were auto-approved."); 215 | } 216 | $this->refreshToken($this->token['refresh_token']); 217 | } 218 | } 219 | 220 | // Add the OAuth2 header to the request 221 | $request->setRequestHeaders( 222 | array('Authorization' => 'Bearer ' . $this->token['access_token']) 223 | ); 224 | 225 | return $request; 226 | } 227 | 228 | /** 229 | * Fetches a fresh access token with the given refresh token. 230 | * @param string $refreshToken 231 | * @return void 232 | */ 233 | public function refreshToken($refreshToken) { 234 | $this->refreshTokenRequest(array( 235 | 'client_id' => $this->clientId, 236 | 'client_secret' => $this->clientSecret, 237 | 'refresh_token' => $refreshToken, 238 | 'grant_type' => 'refresh_token' 239 | )); 240 | } 241 | 242 | /** 243 | * Fetches a fresh access token with a given assertion token. 244 | * @param Google_AssertionCredentials $assertionCredentials optional. 245 | * @return void 246 | */ 247 | public function refreshTokenWithAssertion($assertionCredentials = null) { 248 | if (!$assertionCredentials) { 249 | $assertionCredentials = $this->assertionCredentials; 250 | } 251 | 252 | $this->refreshTokenRequest(array( 253 | 'grant_type' => 'assertion', 254 | 'assertion_type' => $assertionCredentials->assertionType, 255 | 'assertion' => $assertionCredentials->generateAssertion(), 256 | )); 257 | } 258 | 259 | private function refreshTokenRequest($params) { 260 | $http = new Google_HttpRequest(self::OAUTH2_TOKEN_URI, 'POST', array(), $params); 261 | $request = Google_Client::$io->makeRequest($http); 262 | 263 | $code = $request->getResponseHttpCode(); 264 | $body = $request->getResponseBody(); 265 | if (200 == $code) { 266 | $token = json_decode($body, true); 267 | if ($token == null) { 268 | throw new Google_AuthException("Could not json decode the access token"); 269 | } 270 | 271 | if (! isset($token['access_token']) || ! isset($token['expires_in'])) { 272 | throw new Google_AuthException("Invalid token format"); 273 | } 274 | 275 | $this->token['access_token'] = $token['access_token']; 276 | $this->token['expires_in'] = $token['expires_in']; 277 | $this->token['created'] = time(); 278 | } else { 279 | throw new Google_AuthException("Error refreshing the OAuth2 token, message: '$body'", $code); 280 | } 281 | } 282 | 283 | /** 284 | * Revoke an OAuth2 access token or refresh token. This method will revoke the current access 285 | * token, if a token isn't provided. 286 | * @throws Google_AuthException 287 | * @param string|null $token The token (access token or a refresh token) that should be revoked. 288 | * @return boolean Returns True if the revocation was successful, otherwise False. 289 | */ 290 | public function revokeToken($token = null) { 291 | if (!$token) { 292 | $token = $this->token['access_token']; 293 | } 294 | $request = new Google_HttpRequest(self::OAUTH2_REVOKE_URI, 'POST', array(), "token=$token"); 295 | $response = Google_Client::$io->makeRequest($request); 296 | $code = $response->getResponseHttpCode(); 297 | if ($code == 200) { 298 | $this->token = null; 299 | return true; 300 | } 301 | 302 | return false; 303 | } 304 | 305 | /** 306 | * Returns if the access_token is expired. 307 | * @return bool Returns True if the access_token is expired. 308 | */ 309 | public function isAccessTokenExpired() { 310 | if (null == $this->token) { 311 | return true; 312 | } 313 | 314 | // If the token is set to expire in the next 30 seconds. 315 | $expired = ($this->token['created'] 316 | + ($this->token['expires_in'] - 30)) < time(); 317 | 318 | return $expired; 319 | } 320 | 321 | // Gets federated sign-on certificates to use for verifying identity tokens. 322 | // Returns certs as array structure, where keys are key ids, and values 323 | // are PEM encoded certificates. 324 | private function getFederatedSignOnCerts() { 325 | // This relies on makeRequest caching certificate responses. 326 | $request = Google_Client::$io->makeRequest(new Google_HttpRequest( 327 | self::OAUTH2_FEDERATED_SIGNON_CERTS_URL)); 328 | if ($request->getResponseHttpCode() == 200) { 329 | $certs = json_decode($request->getResponseBody(), true); 330 | if ($certs) { 331 | return $certs; 332 | } 333 | } 334 | throw new Google_AuthException( 335 | "Failed to retrieve verification certificates: '" . 336 | $request->getResponseBody() . "'.", 337 | $request->getResponseHttpCode()); 338 | } 339 | 340 | /** 341 | * Verifies an id token and returns the authenticated apiLoginTicket. 342 | * Throws an exception if the id token is not valid. 343 | * The audience parameter can be used to control which id tokens are 344 | * accepted. By default, the id token must have been issued to this OAuth2 client. 345 | * 346 | * @param $id_token 347 | * @param $audience 348 | * @return Google_LoginTicket 349 | */ 350 | public function verifyIdToken($id_token = null, $audience = null) { 351 | if (!$id_token) { 352 | $id_token = $this->token['id_token']; 353 | } 354 | 355 | $certs = $this->getFederatedSignonCerts(); 356 | if (!$audience) { 357 | $audience = $this->clientId; 358 | } 359 | return $this->verifySignedJwtWithCerts($id_token, $certs, $audience); 360 | } 361 | 362 | // Verifies the id token, returns the verified token contents. 363 | // Visible for testing. 364 | function verifySignedJwtWithCerts($jwt, $certs, $required_audience) { 365 | $segments = explode(".", $jwt); 366 | if (count($segments) != 3) { 367 | throw new Google_AuthException("Wrong number of segments in token: $jwt"); 368 | } 369 | $signed = $segments[0] . "." . $segments[1]; 370 | $signature = Google_Utils::urlSafeB64Decode($segments[2]); 371 | 372 | // Parse envelope. 373 | $envelope = json_decode(Google_Utils::urlSafeB64Decode($segments[0]), true); 374 | if (!$envelope) { 375 | throw new Google_AuthException("Can't parse token envelope: " . $segments[0]); 376 | } 377 | 378 | // Parse token 379 | $json_body = Google_Utils::urlSafeB64Decode($segments[1]); 380 | $payload = json_decode($json_body, true); 381 | if (!$payload) { 382 | throw new Google_AuthException("Can't parse token payload: " . $segments[1]); 383 | } 384 | 385 | // Check signature 386 | $verified = false; 387 | foreach ($certs as $keyName => $pem) { 388 | $public_key = new Google_PemVerifier($pem); 389 | if ($public_key->verify($signed, $signature)) { 390 | $verified = true; 391 | break; 392 | } 393 | } 394 | 395 | if (!$verified) { 396 | throw new Google_AuthException("Invalid token signature: $jwt"); 397 | } 398 | 399 | // Check issued-at timestamp 400 | $iat = 0; 401 | if (array_key_exists("iat", $payload)) { 402 | $iat = $payload["iat"]; 403 | } 404 | if (!$iat) { 405 | throw new Google_AuthException("No issue time in token: $json_body"); 406 | } 407 | $earliest = $iat - self::CLOCK_SKEW_SECS; 408 | 409 | // Check expiration timestamp 410 | $now = time(); 411 | $exp = 0; 412 | if (array_key_exists("exp", $payload)) { 413 | $exp = $payload["exp"]; 414 | } 415 | if (!$exp) { 416 | throw new Google_AuthException("No expiration time in token: $json_body"); 417 | } 418 | if ($exp >= $now + self::MAX_TOKEN_LIFETIME_SECS) { 419 | throw new Google_AuthException( 420 | "Expiration time too far in future: $json_body"); 421 | } 422 | 423 | $latest = $exp + self::CLOCK_SKEW_SECS; 424 | if ($now < $earliest) { 425 | throw new Google_AuthException( 426 | "Token used too early, $now < $earliest: $json_body"); 427 | } 428 | if ($now > $latest) { 429 | throw new Google_AuthException( 430 | "Token used too late, $now > $latest: $json_body"); 431 | } 432 | 433 | // TODO(beaton): check issuer field? 434 | 435 | // Check audience 436 | $aud = $payload["aud"]; 437 | if ($aud != $required_audience) { 438 | throw new Google_AuthException("Wrong recipient, $aud != $required_audience: $json_body"); 439 | } 440 | 441 | // All good. 442 | return new Google_LoginTicket($envelope, $payload); 443 | } 444 | } 445 | -------------------------------------------------------------------------------- /third_party/google-api-php-client/src/auth/Google_P12Signer.php: -------------------------------------------------------------------------------- 1 | 24 | */ 25 | class Google_P12Signer extends Google_Signer { 26 | // OpenSSL private key resource 27 | private $privateKey; 28 | 29 | // Creates a new signer from a .p12 file. 30 | function __construct($p12, $password) { 31 | if (!function_exists('openssl_x509_read')) { 32 | throw new Exception( 33 | 'The Google PHP API library needs the openssl PHP extension'); 34 | } 35 | 36 | // This throws on error 37 | $certs = array(); 38 | if (!openssl_pkcs12_read($p12, $certs, $password)) { 39 | throw new Google_AuthException("Unable to parse the p12 file. " . 40 | "Is this a .p12 file? Is the password correct? OpenSSL error: " . 41 | openssl_error_string()); 42 | } 43 | // TODO(beaton): is this part of the contract for the openssl_pkcs12_read 44 | // method? What happens if there are multiple private keys? Do we care? 45 | if (!array_key_exists("pkey", $certs) || !$certs["pkey"]) { 46 | throw new Google_AuthException("No private key found in p12 file."); 47 | } 48 | $this->privateKey = openssl_pkey_get_private($certs["pkey"]); 49 | if (!$this->privateKey) { 50 | throw new Google_AuthException("Unable to load private key in "); 51 | } 52 | } 53 | 54 | function __destruct() { 55 | if ($this->privateKey) { 56 | openssl_pkey_free($this->privateKey); 57 | } 58 | } 59 | 60 | function sign($data) { 61 | if(version_compare(PHP_VERSION, '5.3.0') < 0) { 62 | throw new Google_AuthException( 63 | "PHP 5.3.0 or higher is required to use service accounts."); 64 | } 65 | if (!openssl_sign($data, $signature, $this->privateKey, "sha256")) { 66 | throw new Google_AuthException("Unable to sign data"); 67 | } 68 | return $signature; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /third_party/google-api-php-client/src/auth/Google_PemVerifier.php: -------------------------------------------------------------------------------- 1 | 22 | */ 23 | class Google_PemVerifier extends Google_Verifier { 24 | private $publicKey; 25 | 26 | /** 27 | * Constructs a verifier from the supplied PEM-encoded certificate. 28 | * 29 | * $pem: a PEM encoded certificate (not a file). 30 | * @param $pem 31 | * @throws Google_AuthException 32 | * @throws Google_Exception 33 | */ 34 | function __construct($pem) { 35 | if (!function_exists('openssl_x509_read')) { 36 | throw new Google_Exception('Google API PHP client needs the openssl PHP extension'); 37 | } 38 | $this->publicKey = openssl_x509_read($pem); 39 | if (!$this->publicKey) { 40 | throw new Google_AuthException("Unable to parse PEM: $pem"); 41 | } 42 | } 43 | 44 | function __destruct() { 45 | if ($this->publicKey) { 46 | openssl_x509_free($this->publicKey); 47 | } 48 | } 49 | 50 | /** 51 | * Verifies the signature on data. 52 | * 53 | * Returns true if the signature is valid, false otherwise. 54 | * @param $data 55 | * @param $signature 56 | * @throws Google_AuthException 57 | * @return bool 58 | */ 59 | function verify($data, $signature) { 60 | $status = openssl_verify($data, $signature, $this->publicKey, "sha256"); 61 | if ($status === -1) { 62 | throw new Google_AuthException('Signature verification error: ' . openssl_error_string()); 63 | } 64 | return $status === 1; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /third_party/google-api-php-client/src/auth/Google_Signer.php: -------------------------------------------------------------------------------- 1 | 24 | */ 25 | abstract class Google_Signer { 26 | /** 27 | * Signs data, returns the signature as binary data. 28 | */ 29 | abstract public function sign($data); 30 | } 31 | -------------------------------------------------------------------------------- /third_party/google-api-php-client/src/auth/Google_Verifier.php: -------------------------------------------------------------------------------- 1 | 24 | */ 25 | abstract class Google_Verifier { 26 | /** 27 | * Checks a signature, returns true if the signature is correct, 28 | * false otherwise. 29 | */ 30 | abstract public function verify($data, $signature); 31 | } 32 | -------------------------------------------------------------------------------- /third_party/google-api-php-client/src/cache/Google_ApcCache.php: -------------------------------------------------------------------------------- 1 | 25 | */ 26 | class googleApcCache extends Google_Cache { 27 | 28 | public function __construct() { 29 | if (! function_exists('apc_add')) { 30 | throw new Google_CacheException("Apc functions not available"); 31 | } 32 | } 33 | 34 | private function isLocked($key) { 35 | if ((@apc_fetch($key . '.lock')) === false) { 36 | return false; 37 | } 38 | return true; 39 | } 40 | 41 | private function createLock($key) { 42 | // the interesting thing is that this could fail if the lock was created in the meantime.. 43 | // but we'll ignore that out of convenience 44 | @apc_add($key . '.lock', '', 5); 45 | } 46 | 47 | private function removeLock($key) { 48 | // suppress all warnings, if some other process removed it that's ok too 49 | @apc_delete($key . '.lock'); 50 | } 51 | 52 | private function waitForLock($key) { 53 | // 20 x 250 = 5 seconds 54 | $tries = 20; 55 | $cnt = 0; 56 | do { 57 | // 250 ms is a long time to sleep, but it does stop the server from burning all resources on polling locks.. 58 | usleep(250); 59 | $cnt ++; 60 | } while ($cnt <= $tries && $this->isLocked($key)); 61 | if ($this->isLocked($key)) { 62 | // 5 seconds passed, assume the owning process died off and remove it 63 | $this->removeLock($key); 64 | } 65 | } 66 | 67 | /** 68 | * @inheritDoc 69 | */ 70 | public function get($key, $expiration = false) { 71 | 72 | if (($ret = @apc_fetch($key)) === false) { 73 | return false; 74 | } 75 | if (!$expiration || (time() - $ret['time'] > $expiration)) { 76 | $this->delete($key); 77 | return false; 78 | } 79 | return unserialize($ret['data']); 80 | } 81 | 82 | /** 83 | * @inheritDoc 84 | */ 85 | public function set($key, $value) { 86 | if (@apc_store($key, array('time' => time(), 'data' => serialize($value))) == false) { 87 | throw new Google_CacheException("Couldn't store data"); 88 | } 89 | } 90 | 91 | /** 92 | * @inheritDoc 93 | * @param String $key 94 | */ 95 | public function delete($key) { 96 | @apc_delete($key); 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /third_party/google-api-php-client/src/cache/Google_Cache.php: -------------------------------------------------------------------------------- 1 | 25 | */ 26 | abstract class Google_Cache { 27 | 28 | /** 29 | * Retrieves the data for the given key, or false if they 30 | * key is unknown or expired 31 | * 32 | * @param String $key The key who's data to retrieve 33 | * @param boolean|int $expiration Expiration time in seconds 34 | * 35 | */ 36 | abstract function get($key, $expiration = false); 37 | 38 | /** 39 | * Store the key => $value set. The $value is serialized 40 | * by this function so can be of any type 41 | * 42 | * @param string $key Key of the data 43 | * @param string $value data 44 | */ 45 | abstract function set($key, $value); 46 | 47 | /** 48 | * Removes the key/data pair for the given $key 49 | * 50 | * @param String $key 51 | */ 52 | abstract function delete($key); 53 | } 54 | 55 | 56 | -------------------------------------------------------------------------------- /third_party/google-api-php-client/src/cache/Google_FileCache.php: -------------------------------------------------------------------------------- 1 | 26 | */ 27 | class Google_FileCache extends Google_Cache { 28 | private $path; 29 | 30 | public function __construct() { 31 | global $apiConfig; 32 | $this->path = $apiConfig['ioFileCache_directory']; 33 | } 34 | 35 | private function isLocked($storageFile) { 36 | // our lock file convention is simple: /the/file/path.lock 37 | return file_exists($storageFile . '.lock'); 38 | } 39 | 40 | private function createLock($storageFile) { 41 | $storageDir = dirname($storageFile); 42 | if (! is_dir($storageDir)) { 43 | // @codeCoverageIgnoreStart 44 | if (! @mkdir($storageDir, 0755, true)) { 45 | // make sure the failure isn't because of a concurrency issue 46 | if (! is_dir($storageDir)) { 47 | throw new Google_CacheException("Could not create storage directory: $storageDir"); 48 | } 49 | } 50 | // @codeCoverageIgnoreEnd 51 | } 52 | @touch($storageFile . '.lock'); 53 | } 54 | 55 | private function removeLock($storageFile) { 56 | // suppress all warnings, if some other process removed it that's ok too 57 | @unlink($storageFile . '.lock'); 58 | } 59 | 60 | private function waitForLock($storageFile) { 61 | // 20 x 250 = 5 seconds 62 | $tries = 20; 63 | $cnt = 0; 64 | do { 65 | // make sure PHP picks up on file changes. This is an expensive action but really can't be avoided 66 | clearstatcache(); 67 | // 250 ms is a long time to sleep, but it does stop the server from burning all resources on polling locks.. 68 | usleep(250); 69 | $cnt ++; 70 | } while ($cnt <= $tries && $this->isLocked($storageFile)); 71 | if ($this->isLocked($storageFile)) { 72 | // 5 seconds passed, assume the owning process died off and remove it 73 | $this->removeLock($storageFile); 74 | } 75 | } 76 | 77 | private function getCacheDir($hash) { 78 | // use the first 2 characters of the hash as a directory prefix 79 | // this should prevent slowdowns due to huge directory listings 80 | // and thus give some basic amount of scalability 81 | return $this->path . '/' . substr($hash, 0, 2); 82 | } 83 | 84 | private function getCacheFile($hash) { 85 | return $this->getCacheDir($hash) . '/' . $hash; 86 | } 87 | 88 | public function get($key, $expiration = false) { 89 | $storageFile = $this->getCacheFile(md5($key)); 90 | // See if this storage file is locked, if so we wait upto 5 seconds for the lock owning process to 91 | // complete it's work. If the lock is not released within that time frame, it's cleaned up. 92 | // This should give us a fair amount of 'Cache Stampeding' protection 93 | if ($this->isLocked($storageFile)) { 94 | $this->waitForLock($storageFile); 95 | } 96 | if (file_exists($storageFile) && is_readable($storageFile)) { 97 | $now = time(); 98 | if (! $expiration || (($mtime = @filemtime($storageFile)) !== false && ($now - $mtime) < $expiration)) { 99 | if (($data = @file_get_contents($storageFile)) !== false) { 100 | $data = unserialize($data); 101 | return $data; 102 | } 103 | } 104 | } 105 | return false; 106 | } 107 | 108 | public function set($key, $value) { 109 | $storageDir = $this->getCacheDir(md5($key)); 110 | $storageFile = $this->getCacheFile(md5($key)); 111 | if ($this->isLocked($storageFile)) { 112 | // some other process is writing to this file too, wait until it's done to prevent hickups 113 | $this->waitForLock($storageFile); 114 | } 115 | if (! is_dir($storageDir)) { 116 | if (! @mkdir($storageDir, 0755, true)) { 117 | throw new Google_CacheException("Could not create storage directory: $storageDir"); 118 | } 119 | } 120 | // we serialize the whole request object, since we don't only want the 121 | // responseContent but also the postBody used, headers, size, etc 122 | $data = serialize($value); 123 | $this->createLock($storageFile); 124 | if (! @file_put_contents($storageFile, $data)) { 125 | $this->removeLock($storageFile); 126 | throw new Google_CacheException("Could not store data in the file"); 127 | } 128 | $this->removeLock($storageFile); 129 | } 130 | 131 | public function delete($key) { 132 | $file = $this->getCacheFile(md5($key)); 133 | if (! @unlink($file)) { 134 | throw new Google_CacheException("Cache file could not be deleted"); 135 | } 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /third_party/google-api-php-client/src/cache/Google_MemcacheCache.php: -------------------------------------------------------------------------------- 1 | 25 | */ 26 | class Google_MemcacheCache extends Google_Cache { 27 | private $connection = false; 28 | 29 | public function __construct() { 30 | global $apiConfig; 31 | if (! function_exists('memcache_connect')) { 32 | throw new Google_CacheException("Memcache functions not available"); 33 | } 34 | $this->host = $apiConfig['ioMemCacheCache_host']; 35 | $this->port = $apiConfig['ioMemCacheCache_port']; 36 | if (empty($this->host) || empty($this->port)) { 37 | throw new Google_CacheException("You need to supply a valid memcache host and port"); 38 | } 39 | } 40 | 41 | private function isLocked($key) { 42 | $this->check(); 43 | if ((@memcache_get($this->connection, $key . '.lock')) === false) { 44 | return false; 45 | } 46 | return true; 47 | } 48 | 49 | private function createLock($key) { 50 | $this->check(); 51 | // the interesting thing is that this could fail if the lock was created in the meantime.. 52 | // but we'll ignore that out of convenience 53 | @memcache_add($this->connection, $key . '.lock', '', 0, 5); 54 | } 55 | 56 | private function removeLock($key) { 57 | $this->check(); 58 | // suppress all warnings, if some other process removed it that's ok too 59 | @memcache_delete($this->connection, $key . '.lock'); 60 | } 61 | 62 | private function waitForLock($key) { 63 | $this->check(); 64 | // 20 x 250 = 5 seconds 65 | $tries = 20; 66 | $cnt = 0; 67 | do { 68 | // 250 ms is a long time to sleep, but it does stop the server from burning all resources on polling locks.. 69 | usleep(250); 70 | $cnt ++; 71 | } while ($cnt <= $tries && $this->isLocked($key)); 72 | if ($this->isLocked($key)) { 73 | // 5 seconds passed, assume the owning process died off and remove it 74 | $this->removeLock($key); 75 | } 76 | } 77 | 78 | // I prefer lazy initialization since the cache isn't used every request 79 | // so this potentially saves a lot of overhead 80 | private function connect() { 81 | if (! $this->connection = @memcache_pconnect($this->host, $this->port)) { 82 | throw new Google_CacheException("Couldn't connect to memcache server"); 83 | } 84 | } 85 | 86 | private function check() { 87 | if (! $this->connection) { 88 | $this->connect(); 89 | } 90 | } 91 | 92 | /** 93 | * @inheritDoc 94 | */ 95 | public function get($key, $expiration = false) { 96 | $this->check(); 97 | if (($ret = @memcache_get($this->connection, $key)) === false) { 98 | return false; 99 | } 100 | if (! $expiration || (time() - $ret['time'] > $expiration)) { 101 | $this->delete($key); 102 | return false; 103 | } 104 | return $ret['data']; 105 | } 106 | 107 | /** 108 | * @inheritDoc 109 | * @param string $key 110 | * @param string $value 111 | * @throws Google_CacheException 112 | */ 113 | public function set($key, $value) { 114 | $this->check(); 115 | // we store it with the cache_time default expiration so objects will at least get cleaned eventually. 116 | if (@memcache_set($this->connection, $key, array('time' => time(), 117 | 'data' => $value), false) == false) { 118 | throw new Google_CacheException("Couldn't store data in cache"); 119 | } 120 | } 121 | 122 | /** 123 | * @inheritDoc 124 | * @param String $key 125 | */ 126 | public function delete($key) { 127 | $this->check(); 128 | @memcache_delete($this->connection, $key); 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /third_party/google-api-php-client/src/config.php: -------------------------------------------------------------------------------- 1 | false, 23 | 24 | // The application_name is included in the User-Agent HTTP header. 25 | 'application_name' => '', 26 | 27 | // OAuth2 Settings, you can get these keys at https://code.google.com/apis/console 28 | 'oauth2_client_id' => '', 29 | 'oauth2_client_secret' => '', 30 | 'oauth2_redirect_uri' => '', 31 | 32 | // The developer key, you get this at https://code.google.com/apis/console 33 | 'developer_key' => '', 34 | 35 | // Site name to show in the Google's OAuth 1 authentication screen. 36 | 'site_name' => 'www.example.org', 37 | 38 | // Which Authentication, Storage and HTTP IO classes to use. 39 | 'authClass' => 'Google_OAuth2', 40 | 'ioClass' => 'Google_CurlIO', 41 | 'cacheClass' => 'Google_FileCache', 42 | 43 | // Don't change these unless you're working against a special development or testing environment. 44 | 'basePath' => 'https://www.googleapis.com', 45 | 46 | // IO Class dependent configuration, you only have to configure the values 47 | // for the class that was configured as the ioClass above 48 | 'ioFileCache_directory' => 49 | (function_exists('sys_get_temp_dir') ? 50 | sys_get_temp_dir() . '/Google_Client' : 51 | '/tmp/Google_Client'), 52 | 53 | // Definition of service specific values like scopes, oauth token URLs, etc 54 | 'services' => array( 55 | 'analytics' => array('scope' => 'https://www.googleapis.com/auth/analytics.readonly'), 56 | 'calendar' => array( 57 | 'scope' => array( 58 | "https://www.googleapis.com/auth/calendar", 59 | "https://www.googleapis.com/auth/calendar.readonly", 60 | ) 61 | ), 62 | 'books' => array('scope' => 'https://www.googleapis.com/auth/books'), 63 | 'latitude' => array( 64 | 'scope' => array( 65 | 'https://www.googleapis.com/auth/latitude.all.best', 66 | 'https://www.googleapis.com/auth/latitude.all.city', 67 | ) 68 | ), 69 | 'moderator' => array('scope' => 'https://www.googleapis.com/auth/moderator'), 70 | 'oauth2' => array( 71 | 'scope' => array( 72 | 'https://www.googleapis.com/auth/userinfo.profile', 73 | 'https://www.googleapis.com/auth/userinfo.email', 74 | ) 75 | ), 76 | 'plus' => array('scope' => 'https://www.googleapis.com/auth/plus.me'), 77 | 'siteVerification' => array('scope' => 'https://www.googleapis.com/auth/siteverification'), 78 | 'tasks' => array('scope' => 'https://www.googleapis.com/auth/tasks'), 79 | 'urlshortener' => array('scope' => 'https://www.googleapis.com/auth/urlshortener') 80 | ) 81 | ); -------------------------------------------------------------------------------- /third_party/google-api-php-client/src/external/OAuth.php: -------------------------------------------------------------------------------- 1 | key = $key; 15 | $this->secret = $secret; 16 | $this->callback_url = $callback_url; 17 | } 18 | } 19 | 20 | class apiClientOAuthToken { 21 | // access tokens and request tokens 22 | public $key; 23 | public $secret; 24 | 25 | /** 26 | * key = the token 27 | * secret = the token secret 28 | */ 29 | function __construct($key, $secret) { 30 | $this->key = $key; 31 | $this->secret = $secret; 32 | } 33 | 34 | /** 35 | * generates the basic string serialization of a token that a server 36 | * would respond to request_token and access_token calls with 37 | */ 38 | function to_string() { 39 | return "oauth_token=" . apiClientOAuthUtil::urlencodeRFC3986($this->key) . 40 | "&oauth_token_secret=" . apiClientOAuthUtil::urlencodeRFC3986($this->secret); 41 | } 42 | 43 | function __toString() { 44 | return $this->to_string(); 45 | } 46 | } 47 | 48 | class apiClientOAuthSignatureMethod { 49 | public function check_signature(&$request, $consumer, $token, $signature) { 50 | $built = $this->build_signature($request, $consumer, $token); 51 | return $built == $signature; 52 | } 53 | } 54 | 55 | class apiClientOAuthSignatureMethod_HMAC_SHA1 extends apiClientOAuthSignatureMethod { 56 | function get_name() { 57 | return "HMAC-SHA1"; 58 | } 59 | 60 | public function build_signature($request, $consumer, $token, $privKey=NULL) { 61 | $base_string = $request->get_signature_base_string(); 62 | $request->base_string = $base_string; 63 | 64 | $key_parts = array( 65 | $consumer->secret, 66 | ($token) ? $token->secret : "" 67 | ); 68 | 69 | $key_parts = array_map(array('apiClientOAuthUtil','urlencodeRFC3986'), $key_parts); 70 | $key = implode('&', $key_parts); 71 | 72 | return base64_encode( hash_hmac('sha1', $base_string, $key, true)); 73 | } 74 | } 75 | 76 | class apiClientOAuthSignatureMethod_RSA_SHA1 extends apiClientOAuthSignatureMethod { 77 | public function get_name() { 78 | return "RSA-SHA1"; 79 | } 80 | 81 | protected function fetch_public_cert(&$request) { 82 | // not implemented yet, ideas are: 83 | // (1) do a lookup in a table of trusted certs keyed off of consumer 84 | // (2) fetch via http using a url provided by the requester 85 | // (3) some sort of specific discovery code based on request 86 | // 87 | // either way should return a string representation of the certificate 88 | throw Exception("fetch_public_cert not implemented"); 89 | } 90 | 91 | protected function fetch_private_cert($privKey) {//&$request) { 92 | // not implemented yet, ideas are: 93 | // (1) do a lookup in a table of trusted certs keyed off of consumer 94 | // 95 | // either way should return a string representation of the certificate 96 | throw Exception("fetch_private_cert not implemented"); 97 | } 98 | 99 | public function build_signature(&$request, $consumer, $token, $privKey) { 100 | $base_string = $request->get_signature_base_string(); 101 | 102 | // Fetch the private key cert based on the request 103 | //$cert = $this->fetch_private_cert($consumer->privKey); 104 | 105 | //Pull the private key ID from the certificate 106 | //$privatekeyid = openssl_get_privatekey($cert); 107 | 108 | // hacked in 109 | if ($privKey == '') { 110 | $fp = fopen($GLOBALS['PRIV_KEY_FILE'], "r"); 111 | $privKey = fread($fp, 8192); 112 | fclose($fp); 113 | } 114 | $privatekeyid = openssl_get_privatekey($privKey); 115 | 116 | //Check the computer signature against the one passed in the query 117 | $ok = openssl_sign($base_string, $signature, $privatekeyid); 118 | 119 | //Release the key resource 120 | openssl_free_key($privatekeyid); 121 | 122 | return base64_encode($signature); 123 | } 124 | 125 | public function check_signature(&$request, $consumer, $token, $signature) { 126 | $decoded_sig = base64_decode($signature); 127 | 128 | $base_string = $request->get_signature_base_string(); 129 | 130 | // Fetch the public key cert based on the request 131 | $cert = $this->fetch_public_cert($request); 132 | 133 | //Pull the public key ID from the certificate 134 | $publickeyid = openssl_get_publickey($cert); 135 | 136 | //Check the computer signature against the one passed in the query 137 | $ok = openssl_verify($base_string, $decoded_sig, $publickeyid); 138 | 139 | //Release the key resource 140 | openssl_free_key($publickeyid); 141 | 142 | return $ok == 1; 143 | } 144 | } 145 | 146 | class apiClientOAuthRequest { 147 | private $parameters; 148 | private $http_method; 149 | private $http_url; 150 | // for debug purposes 151 | public $base_string; 152 | public static $version = '1.0'; 153 | 154 | function __construct($http_method, $http_url, $parameters=NULL) { 155 | @$parameters or $parameters = array(); 156 | $this->parameters = $parameters; 157 | $this->http_method = $http_method; 158 | $this->http_url = $http_url; 159 | } 160 | 161 | 162 | /** 163 | * attempt to build up a request from what was passed to the server 164 | */ 165 | public static function from_request($http_method=NULL, $http_url=NULL, $parameters=NULL) { 166 | $scheme = (!isset($_SERVER['HTTPS']) || $_SERVER['HTTPS'] != "on") ? 'http' : 'https'; 167 | @$http_url or $http_url = $scheme . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']; 168 | @$http_method or $http_method = $_SERVER['REQUEST_METHOD']; 169 | 170 | $request_headers = apiClientOAuthRequest::get_headers(); 171 | 172 | // let the library user override things however they'd like, if they know 173 | // which parameters to use then go for it, for example XMLRPC might want to 174 | // do this 175 | if ($parameters) { 176 | $req = new apiClientOAuthRequest($http_method, $http_url, $parameters); 177 | } 178 | // next check for the auth header, we need to do some extra stuff 179 | // if that is the case, namely suck in the parameters from GET or POST 180 | // so that we can include them in the signature 181 | else if (@substr($request_headers['Authorization'], 0, 5) == "OAuth") { 182 | $header_parameters = apiClientOAuthRequest::split_header($request_headers['Authorization']); 183 | if ($http_method == "GET") { 184 | $req_parameters = $_GET; 185 | } 186 | else if ($http_method = "POST") { 187 | $req_parameters = $_POST; 188 | } 189 | $parameters = array_merge($header_parameters, $req_parameters); 190 | $req = new apiClientOAuthRequest($http_method, $http_url, $parameters); 191 | } 192 | else if ($http_method == "GET") { 193 | $req = new apiClientOAuthRequest($http_method, $http_url, $_GET); 194 | } 195 | else if ($http_method == "POST") { 196 | $req = new apiClientOAuthRequest($http_method, $http_url, $_POST); 197 | } 198 | return $req; 199 | } 200 | 201 | /** 202 | * pretty much a helper function to set up the request 203 | */ 204 | public static function from_consumer_and_token($consumer, $token, $http_method, $http_url, $parameters=NULL) { 205 | @$parameters or $parameters = array(); 206 | $defaults = array("oauth_version" => apiClientOAuthRequest::$version, 207 | "oauth_nonce" => apiClientOAuthRequest::generate_nonce(), 208 | "oauth_timestamp" => apiClientOAuthRequest::generate_timestamp(), 209 | "oauth_consumer_key" => $consumer->key); 210 | $parameters = array_merge($defaults, $parameters); 211 | 212 | if ($token) { 213 | $parameters['oauth_token'] = $token->key; 214 | } 215 | 216 | // oauth v1.0a 217 | /*if (isset($_REQUEST['oauth_verifier'])) { 218 | $parameters['oauth_verifier'] = $_REQUEST['oauth_verifier']; 219 | }*/ 220 | 221 | 222 | return new apiClientOAuthRequest($http_method, $http_url, $parameters); 223 | } 224 | 225 | public function set_parameter($name, $value) { 226 | $this->parameters[$name] = $value; 227 | } 228 | 229 | public function get_parameter($name) { 230 | return $this->parameters[$name]; 231 | } 232 | 233 | public function get_parameters() { 234 | return $this->parameters; 235 | } 236 | 237 | /** 238 | * Returns the normalized parameters of the request 239 | * 240 | * This will be all (except oauth_signature) parameters, 241 | * sorted first by key, and if duplicate keys, then by 242 | * value. 243 | * 244 | * The returned string will be all the key=value pairs 245 | * concated by &. 246 | * 247 | * @return string 248 | */ 249 | public function get_signable_parameters() { 250 | // Grab all parameters 251 | $params = $this->parameters; 252 | 253 | // Remove oauth_signature if present 254 | if (isset($params['oauth_signature'])) { 255 | unset($params['oauth_signature']); 256 | } 257 | 258 | // Urlencode both keys and values 259 | $keys = array_map(array('apiClientOAuthUtil', 'urlencodeRFC3986'), array_keys($params)); 260 | $values = array_map(array('apiClientOAuthUtil', 'urlencodeRFC3986'), array_values($params)); 261 | $params = array_combine($keys, $values); 262 | 263 | // Sort by keys (natsort) 264 | uksort($params, 'strnatcmp'); 265 | 266 | if(isset($params['title']) && isset($params['title-exact'])) { 267 | $temp = $params['title-exact']; 268 | $title = $params['title']; 269 | 270 | unset($params['title']); 271 | unset($params['title-exact']); 272 | 273 | $params['title-exact'] = $temp; 274 | $params['title'] = $title; 275 | } 276 | 277 | // Generate key=value pairs 278 | $pairs = array(); 279 | foreach ($params as $key=>$value ) { 280 | if (is_array($value)) { 281 | // If the value is an array, it's because there are multiple 282 | // with the same key, sort them, then add all the pairs 283 | natsort($value); 284 | foreach ($value as $v2) { 285 | $pairs[] = $key . '=' . $v2; 286 | } 287 | } else { 288 | $pairs[] = $key . '=' . $value; 289 | } 290 | } 291 | 292 | // Return the pairs, concated with & 293 | return implode('&', $pairs); 294 | } 295 | 296 | /** 297 | * Returns the base string of this request 298 | * 299 | * The base string defined as the method, the url 300 | * and the parameters (normalized), each urlencoded 301 | * and the concated with &. 302 | */ 303 | public function get_signature_base_string() { 304 | $parts = array( 305 | $this->get_normalized_http_method(), 306 | $this->get_normalized_http_url(), 307 | $this->get_signable_parameters() 308 | ); 309 | 310 | $parts = array_map(array('apiClientOAuthUtil', 'urlencodeRFC3986'), $parts); 311 | 312 | return implode('&', $parts); 313 | } 314 | 315 | /** 316 | * just uppercases the http method 317 | */ 318 | public function get_normalized_http_method() { 319 | return strtoupper($this->http_method); 320 | } 321 | 322 | /** 323 | * parses the url and rebuilds it to be 324 | * scheme://host/path 325 | */ 326 | public function get_normalized_http_url() { 327 | $parts = parse_url($this->http_url); 328 | 329 | // FIXME: port should handle according to http://groups.google.com/group/oauth/browse_thread/thread/1b203a51d9590226 330 | $port = (isset($parts['port']) && $parts['port'] != '80') ? ':' . $parts['port'] : ''; 331 | $path = (isset($parts['path'])) ? $parts['path'] : ''; 332 | 333 | return $parts['scheme'] . '://' . $parts['host'] . $port . $path; 334 | } 335 | 336 | /** 337 | * builds a url usable for a GET request 338 | */ 339 | public function to_url() { 340 | $out = $this->get_normalized_http_url() . "?"; 341 | $out .= $this->to_postdata(); 342 | return $out; 343 | } 344 | 345 | /** 346 | * builds the data one would send in a POST request 347 | */ 348 | public function to_postdata() { 349 | $total = array(); 350 | foreach ($this->parameters as $k => $v) { 351 | $total[] = apiClientOAuthUtil::urlencodeRFC3986($k) . "=" . apiClientOAuthUtil::urlencodeRFC3986($v); 352 | } 353 | $out = implode("&", $total); 354 | return $out; 355 | } 356 | 357 | /** 358 | * builds the Authorization: header 359 | */ 360 | public function to_header() { 361 | $out ='Authorization: OAuth '; 362 | $total = array(); 363 | foreach ($this->parameters as $k => $v) { 364 | if (substr($k, 0, 5) != "oauth") continue; 365 | $out .= apiClientOAuthUtil::urlencodeRFC3986($k) . '="' . apiClientOAuthUtil::urlencodeRFC3986($v) . '", '; 366 | } 367 | $out = substr_replace($out, '', strlen($out) - 2); 368 | return $out; 369 | } 370 | 371 | public function __toString() { 372 | return $this->to_url(); 373 | } 374 | 375 | 376 | public function sign_request($signature_method, $consumer, $token, $privKey=NULL) { 377 | $this->set_parameter("oauth_signature_method", $signature_method->get_name()); 378 | $signature = $this->build_signature($signature_method, $consumer, $token, $privKey); 379 | $this->set_parameter("oauth_signature", $signature); 380 | } 381 | 382 | public function build_signature($signature_method, $consumer, $token, $privKey=NULL) { 383 | $signature = $signature_method->build_signature($this, $consumer, $token, $privKey); 384 | return $signature; 385 | } 386 | 387 | /** 388 | * util function: current timestamp 389 | */ 390 | private static function generate_timestamp() { 391 | return time(); 392 | } 393 | 394 | /** 395 | * util function: current nonce 396 | */ 397 | private static function generate_nonce() { 398 | $mt = microtime(); 399 | $rand = mt_rand(); 400 | 401 | return md5($mt . $rand); // md5s look nicer than numbers 402 | } 403 | 404 | /** 405 | * util function for turning the Authorization: header into 406 | * parameters, has to do some unescaping 407 | */ 408 | private static function split_header($header) { 409 | // this should be a regex 410 | // error cases: commas in parameter values 411 | $parts = explode(",", $header); 412 | $out = array(); 413 | foreach ($parts as $param) { 414 | $param = ltrim($param); 415 | // skip the "realm" param, nobody ever uses it anyway 416 | if (substr($param, 0, 5) != "oauth") continue; 417 | 418 | $param_parts = explode("=", $param); 419 | 420 | // rawurldecode() used because urldecode() will turn a "+" in the 421 | // value into a space 422 | $out[$param_parts[0]] = rawurldecode(substr($param_parts[1], 1, -1)); 423 | } 424 | return $out; 425 | } 426 | 427 | /** 428 | * helper to try to sort out headers for people who aren't running apache 429 | */ 430 | private static function get_headers() { 431 | if (function_exists('apache_request_headers')) { 432 | // we need this to get the actual Authorization: header 433 | // because apache tends to tell us it doesn't exist 434 | return apache_request_headers(); 435 | } 436 | // otherwise we don't have apache and are just going to have to hope 437 | // that $_SERVER actually contains what we need 438 | $out = array(); 439 | foreach ($_SERVER as $key => $value) { 440 | if (substr($key, 0, 5) == "HTTP_") { 441 | // this is chaos, basically it is just there to capitalize the first 442 | // letter of every word that is not an initial HTTP and strip HTTP 443 | // code from przemek 444 | $key = str_replace(" ", "-", ucwords(strtolower(str_replace("_", " ", substr($key, 5))))); 445 | $out[$key] = $value; 446 | } 447 | } 448 | return $out; 449 | } 450 | } 451 | 452 | class apiClientOAuthDataStore { 453 | function lookup_consumer($consumer_key) { 454 | // implement me 455 | } 456 | 457 | function lookup_token($consumer, $token_type, $token) { 458 | // implement me 459 | } 460 | 461 | function lookup_nonce($consumer, $token, $nonce, $timestamp) { 462 | // implement me 463 | } 464 | 465 | function fetch_request_token($consumer) { 466 | // return a new token attached to this consumer 467 | } 468 | 469 | function fetch_access_token($token, $consumer) { 470 | // return a new access token attached to this consumer 471 | // for the user associated with this token if the request token 472 | // is authorized 473 | // should also invalidate the request token 474 | } 475 | 476 | } 477 | 478 | class apiClientOAuthUtil { 479 | public static function urlencodeRFC3986($string) { 480 | return str_replace('%7E', '~', rawurlencode($string)); 481 | } 482 | 483 | public static function urldecodeRFC3986($string) { 484 | return rawurldecode($string); 485 | } 486 | } 487 | -------------------------------------------------------------------------------- /third_party/google-api-php-client/src/external/URITemplateParser.php: -------------------------------------------------------------------------------- 1 | template = $template; 48 | } 49 | 50 | public function expand($data) { 51 | // Modification to make this a bit more performant (since gettype is very slow) 52 | if (! is_array($data)) { 53 | $data = (array)$data; 54 | } 55 | /* 56 | // Original code, which uses a slow gettype() statement, kept in place for if the assumption that is_array always works here is incorrect 57 | switch (gettype($data)) { 58 | case "boolean": 59 | case "integer": 60 | case "double": 61 | case "string": 62 | case "object": 63 | $data = (array)$data; 64 | break; 65 | } 66 | */ 67 | 68 | // Resolve template vars 69 | preg_match_all('/\{([^\}]*)\}/', $this->template, $em); 70 | 71 | foreach ($em[1] as $i => $bare_expression) { 72 | preg_match('/^([\+\;\?\/\.]{1})?(.*)$/', $bare_expression, $lm); 73 | $exp = new StdClass(); 74 | $exp->expression = $em[0][$i]; 75 | $exp->operator = $lm[1]; 76 | $exp->variable_list = $lm[2]; 77 | $exp->varspecs = explode(',', $exp->variable_list); 78 | $exp->vars = array(); 79 | foreach ($exp->varspecs as $varspec) { 80 | preg_match('/^([a-zA-Z0-9_]+)([\*\+]{1})?([\:\^][0-9-]+)?(\=[^,]+)?$/', $varspec, $vm); 81 | $var = new StdClass(); 82 | $var->name = $vm[1]; 83 | $var->modifier = isset($vm[2]) && $vm[2] ? $vm[2] : null; 84 | $var->modifier = isset($vm[3]) && $vm[3] ? $vm[3] : $var->modifier; 85 | $var->default = isset($vm[4]) ? substr($vm[4], 1) : null; 86 | $exp->vars[] = $var; 87 | } 88 | 89 | // Add processing flags 90 | $exp->reserved = false; 91 | $exp->prefix = ''; 92 | $exp->delimiter = ','; 93 | switch ($exp->operator) { 94 | case '+': 95 | $exp->reserved = 'true'; 96 | break; 97 | case ';': 98 | $exp->prefix = ';'; 99 | $exp->delimiter = ';'; 100 | break; 101 | case '?': 102 | $exp->prefix = '?'; 103 | $exp->delimiter = '&'; 104 | break; 105 | case '/': 106 | $exp->prefix = '/'; 107 | $exp->delimiter = '/'; 108 | break; 109 | case '.': 110 | $exp->prefix = '.'; 111 | $exp->delimiter = '.'; 112 | break; 113 | } 114 | $expressions[] = $exp; 115 | } 116 | 117 | // Expansion 118 | $this->expansion = $this->template; 119 | 120 | foreach ($expressions as $exp) { 121 | $part = $exp->prefix; 122 | $exp->one_var_defined = false; 123 | foreach ($exp->vars as $var) { 124 | $val = ''; 125 | if ($exp->one_var_defined && isset($data[$var->name])) { 126 | $part .= $exp->delimiter; 127 | } 128 | // Variable present 129 | if (isset($data[$var->name])) { 130 | $exp->one_var_defined = true; 131 | $var->data = $data[$var->name]; 132 | 133 | $val = self::val_from_var($var, $exp); 134 | 135 | // Variable missing 136 | } else { 137 | if ($var->default) { 138 | $exp->one_var_defined = true; 139 | $val = $var->default; 140 | } 141 | } 142 | $part .= $val; 143 | } 144 | if (! $exp->one_var_defined) $part = ''; 145 | $this->expansion = str_replace($exp->expression, $part, $this->expansion); 146 | } 147 | 148 | return $this->expansion; 149 | } 150 | 151 | private function val_from_var($var, $exp) { 152 | $val = ''; 153 | if (is_array($var->data)) { 154 | $i = 0; 155 | if ($exp->operator == '?' && ! $var->modifier) { 156 | $val .= $var->name . '='; 157 | } 158 | foreach ($var->data as $k => $v) { 159 | $del = $var->modifier ? $exp->delimiter : ','; 160 | $ek = rawurlencode($k); 161 | $ev = rawurlencode($v); 162 | 163 | // Array 164 | if ($k !== $i) { 165 | if ($var->modifier == '+') { 166 | $val .= $var->name . '.'; 167 | } 168 | if ($exp->operator == '?' && $var->modifier || $exp->operator == ';' && $var->modifier == '*' || $exp->operator == ';' && $var->modifier == '+') { 169 | $val .= $ek . '='; 170 | } else { 171 | $val .= $ek . $del; 172 | } 173 | 174 | // List 175 | } else { 176 | if ($var->modifier == '+') { 177 | if ($exp->operator == ';' && $var->modifier == '*' || $exp->operator == ';' && $var->modifier == '+' || $exp->operator == '?' && $var->modifier == '+') { 178 | $val .= $var->name . '='; 179 | } else { 180 | $val .= $var->name . '.'; 181 | } 182 | } 183 | } 184 | $val .= $ev . $del; 185 | $i ++; 186 | } 187 | $val = trim($val, $del); 188 | 189 | // Strings, numbers, etc. 190 | } else { 191 | if ($exp->operator == '?') { 192 | $val = $var->name . (isset($var->data) ? '=' : ''); 193 | } else if ($exp->operator == ';') { 194 | $val = $var->name . ($var->data ? '=' : ''); 195 | } 196 | $val .= rawurlencode($var->data); 197 | if ($exp->operator == '+') { 198 | $val = str_replace(self::$reserved_pct, self::$reserved, $val); 199 | } 200 | } 201 | return $val; 202 | } 203 | 204 | public function match($uri) {} 205 | 206 | public function __toString() { 207 | return $this->template; 208 | } 209 | } 210 | -------------------------------------------------------------------------------- /third_party/google-api-php-client/src/io/Google_CacheParser.php: -------------------------------------------------------------------------------- 1 | 21 | */ 22 | class Google_CacheParser { 23 | public static $CACHEABLE_HTTP_METHODS = array('GET', 'HEAD'); 24 | public static $CACHEABLE_STATUS_CODES = array('200', '203', '300', '301'); 25 | 26 | private function __construct() {} 27 | 28 | /** 29 | * Check if an HTTP request can be cached by a private local cache. 30 | * 31 | * @static 32 | * @param Google_HttpRequest $resp 33 | * @return bool True if the request is cacheable. 34 | * False if the request is uncacheable. 35 | */ 36 | public static function isRequestCacheable (Google_HttpRequest $resp) { 37 | $method = $resp->getRequestMethod(); 38 | if (! in_array($method, self::$CACHEABLE_HTTP_METHODS)) { 39 | return false; 40 | } 41 | 42 | // Don't cache authorized requests/responses. 43 | // [rfc2616-14.8] When a shared cache receives a request containing an 44 | // Authorization field, it MUST NOT return the corresponding response 45 | // as a reply to any other request... 46 | if ($resp->getRequestHeader("authorization")) { 47 | return false; 48 | } 49 | 50 | return true; 51 | } 52 | 53 | /** 54 | * Check if an HTTP response can be cached by a private local cache. 55 | * 56 | * @static 57 | * @param Google_HttpRequest $resp 58 | * @return bool True if the response is cacheable. 59 | * False if the response is un-cacheable. 60 | */ 61 | public static function isResponseCacheable (Google_HttpRequest $resp) { 62 | // First, check if the HTTP request was cacheable before inspecting the 63 | // HTTP response. 64 | if (false == self::isRequestCacheable($resp)) { 65 | return false; 66 | } 67 | 68 | $code = $resp->getResponseHttpCode(); 69 | if (! in_array($code, self::$CACHEABLE_STATUS_CODES)) { 70 | return false; 71 | } 72 | 73 | // The resource is uncacheable if the resource is already expired and 74 | // the resource doesn't have an ETag for revalidation. 75 | $etag = $resp->getResponseHeader("etag"); 76 | if (self::isExpired($resp) && $etag == false) { 77 | return false; 78 | } 79 | 80 | // [rfc2616-14.9.2] If [no-store is] sent in a response, a cache MUST NOT 81 | // store any part of either this response or the request that elicited it. 82 | $cacheControl = $resp->getParsedCacheControl(); 83 | if (isset($cacheControl['no-store'])) { 84 | return false; 85 | } 86 | 87 | // Pragma: no-cache is an http request directive, but is occasionally 88 | // used as a response header incorrectly. 89 | $pragma = $resp->getResponseHeader('pragma'); 90 | if ($pragma == 'no-cache' || strpos($pragma, 'no-cache') !== false) { 91 | return false; 92 | } 93 | 94 | // [rfc2616-14.44] Vary: * is extremely difficult to cache. "It implies that 95 | // a cache cannot determine from the request headers of a subsequent request 96 | // whether this response is the appropriate representation." 97 | // Given this, we deem responses with the Vary header as uncacheable. 98 | $vary = $resp->getResponseHeader('vary'); 99 | if ($vary) { 100 | return false; 101 | } 102 | 103 | return true; 104 | } 105 | 106 | /** 107 | * @static 108 | * @param Google_HttpRequest $resp 109 | * @return bool True if the HTTP response is considered to be expired. 110 | * False if it is considered to be fresh. 111 | */ 112 | public static function isExpired(Google_HttpRequest $resp) { 113 | // HTTP/1.1 clients and caches MUST treat other invalid date formats, 114 | // especially including the value “0”, as in the past. 115 | $parsedExpires = false; 116 | $responseHeaders = $resp->getResponseHeaders(); 117 | if (isset($responseHeaders['expires'])) { 118 | $rawExpires = $responseHeaders['expires']; 119 | // Check for a malformed expires header first. 120 | if (empty($rawExpires) || (is_numeric($rawExpires) && $rawExpires <= 0)) { 121 | return true; 122 | } 123 | 124 | // See if we can parse the expires header. 125 | $parsedExpires = strtotime($rawExpires); 126 | if (false == $parsedExpires || $parsedExpires <= 0) { 127 | return true; 128 | } 129 | } 130 | 131 | // Calculate the freshness of an http response. 132 | $freshnessLifetime = false; 133 | $cacheControl = $resp->getParsedCacheControl(); 134 | if (isset($cacheControl['max-age'])) { 135 | $freshnessLifetime = $cacheControl['max-age']; 136 | } 137 | 138 | $rawDate = $resp->getResponseHeader('date'); 139 | $parsedDate = strtotime($rawDate); 140 | 141 | if (empty($rawDate) || false == $parsedDate) { 142 | $parsedDate = time(); 143 | } 144 | if (false == $freshnessLifetime && isset($responseHeaders['expires'])) { 145 | $freshnessLifetime = $parsedExpires - $parsedDate; 146 | } 147 | 148 | if (false == $freshnessLifetime) { 149 | return true; 150 | } 151 | 152 | // Calculate the age of an http response. 153 | $age = max(0, time() - $parsedDate); 154 | if (isset($responseHeaders['age'])) { 155 | $age = max($age, strtotime($responseHeaders['age'])); 156 | } 157 | 158 | return $freshnessLifetime <= $age; 159 | } 160 | 161 | /** 162 | * Determine if a cache entry should be revalidated with by the origin. 163 | * 164 | * @param Google_HttpRequest $response 165 | * @return bool True if the entry is expired, else return false. 166 | */ 167 | public static function mustRevalidate(Google_HttpRequest $response) { 168 | // [13.3] When a cache has a stale entry that it would like to use as a 169 | // response to a client's request, it first has to check with the origin 170 | // server to see if its cached entry is still usable. 171 | return self::isExpired($response); 172 | } 173 | } -------------------------------------------------------------------------------- /third_party/google-api-php-client/src/io/Google_CurlIO.php: -------------------------------------------------------------------------------- 1 | 22 | * @author Chirag Shah 23 | */ 24 | 25 | require_once 'Google_CacheParser.php'; 26 | 27 | class Google_CurlIO implements Google_IO { 28 | const CONNECTION_ESTABLISHED = "HTTP/1.0 200 Connection established\r\n\r\n"; 29 | const FORM_URLENCODED = 'application/x-www-form-urlencoded'; 30 | 31 | private static $ENTITY_HTTP_METHODS = array("POST" => null, "PUT" => null); 32 | private static $HOP_BY_HOP = array( 33 | 'connection', 'keep-alive', 'proxy-authenticate', 'proxy-authorization', 34 | 'te', 'trailers', 'transfer-encoding', 'upgrade'); 35 | 36 | private $curlParams = array ( 37 | CURLOPT_RETURNTRANSFER => true, 38 | CURLOPT_FOLLOWLOCATION => 0, 39 | CURLOPT_FAILONERROR => false, 40 | CURLOPT_SSL_VERIFYPEER => true, 41 | CURLOPT_HEADER => true, 42 | CURLOPT_VERBOSE => false, 43 | ); 44 | 45 | /** 46 | * Perform an authenticated / signed apiHttpRequest. 47 | * This function takes the apiHttpRequest, calls apiAuth->sign on it 48 | * (which can modify the request in what ever way fits the auth mechanism) 49 | * and then calls apiCurlIO::makeRequest on the signed request 50 | * 51 | * @param Google_HttpRequest $request 52 | * @return Google_HttpRequest The resulting HTTP response including the 53 | * responseHttpCode, responseHeaders and responseBody. 54 | */ 55 | public function authenticatedRequest(Google_HttpRequest $request) { 56 | $request = Google_Client::$auth->sign($request); 57 | return $this->makeRequest($request); 58 | } 59 | 60 | /** 61 | * Execute a apiHttpRequest 62 | * 63 | * @param Google_HttpRequest $request the http request to be executed 64 | * @return Google_HttpRequest http request with the response http code, response 65 | * headers and response body filled in 66 | * @throws Google_IOException on curl or IO error 67 | */ 68 | public function makeRequest(Google_HttpRequest $request) { 69 | // First, check to see if we have a valid cached version. 70 | $cached = $this->getCachedRequest($request); 71 | if ($cached !== false) { 72 | if (Google_CacheParser::mustRevalidate($cached)) { 73 | $addHeaders = array(); 74 | if ($cached->getResponseHeader('etag')) { 75 | // [13.3.4] If an entity tag has been provided by the origin server, 76 | // we must use that entity tag in any cache-conditional request. 77 | $addHeaders['If-None-Match'] = $cached->getResponseHeader('etag'); 78 | } elseif ($cached->getResponseHeader('date')) { 79 | $addHeaders['If-Modified-Since'] = $cached->getResponseHeader('date'); 80 | } 81 | 82 | $request->setRequestHeaders($addHeaders); 83 | } else { 84 | // No need to revalidate the request, return it directly 85 | return $cached; 86 | } 87 | } 88 | 89 | if (array_key_exists($request->getRequestMethod(), 90 | self::$ENTITY_HTTP_METHODS)) { 91 | $request = $this->processEntityRequest($request); 92 | } 93 | 94 | $ch = curl_init(); 95 | curl_setopt_array($ch, $this->curlParams); 96 | curl_setopt($ch, CURLOPT_URL, $request->getUrl()); 97 | if ($request->getPostBody()) { 98 | curl_setopt($ch, CURLOPT_POSTFIELDS, $request->getPostBody()); 99 | } 100 | 101 | $requestHeaders = $request->getRequestHeaders(); 102 | if ($requestHeaders && is_array($requestHeaders)) { 103 | $parsed = array(); 104 | foreach ($requestHeaders as $k => $v) { 105 | $parsed[] = "$k: $v"; 106 | } 107 | curl_setopt($ch, CURLOPT_HTTPHEADER, $parsed); 108 | } 109 | 110 | curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $request->getRequestMethod()); 111 | curl_setopt($ch, CURLOPT_USERAGENT, $request->getUserAgent()); 112 | $respData = curl_exec($ch); 113 | 114 | // Retry if certificates are missing. 115 | if (curl_errno($ch) == CURLE_SSL_CACERT) { 116 | error_log('SSL certificate problem, verify that the CA cert is OK.' 117 | . ' Retrying with the CA cert bundle from google-api-php-client.'); 118 | curl_setopt($ch, CURLOPT_CAINFO, dirname(__FILE__) . '/cacerts.pem'); 119 | $respData = curl_exec($ch); 120 | } 121 | 122 | $respHeaderSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE); 123 | $respHttpCode = (int) curl_getinfo($ch, CURLINFO_HTTP_CODE); 124 | $curlErrorNum = curl_errno($ch); 125 | $curlError = curl_error($ch); 126 | curl_close($ch); 127 | if ($curlErrorNum != CURLE_OK) { 128 | throw new Google_IOException("HTTP Error: ($respHttpCode) $curlError"); 129 | } 130 | 131 | // Parse out the raw response into usable bits 132 | list($responseHeaders, $responseBody) = 133 | self::parseHttpResponse($respData, $respHeaderSize); 134 | 135 | if ($respHttpCode == 304 && $cached) { 136 | // If the server responded NOT_MODIFIED, return the cached request. 137 | if (isset($responseHeaders['connection'])) { 138 | $hopByHop = array_merge( 139 | self::$HOP_BY_HOP, 140 | explode(',', $responseHeaders['connection']) 141 | ); 142 | 143 | $endToEnd = array(); 144 | foreach($hopByHop as $key) { 145 | if (isset($responseHeaders[$key])) { 146 | $endToEnd[$key] = $responseHeaders[$key]; 147 | } 148 | } 149 | $cached->setResponseHeaders($endToEnd); 150 | } 151 | return $cached; 152 | } 153 | 154 | // Fill in the apiHttpRequest with the response values 155 | $request->setResponseHttpCode($respHttpCode); 156 | $request->setResponseHeaders($responseHeaders); 157 | $request->setResponseBody($responseBody); 158 | // Store the request in cache (the function checks to see if the request 159 | // can actually be cached) 160 | $this->setCachedRequest($request); 161 | // And finally return it 162 | return $request; 163 | } 164 | 165 | /** 166 | * @visible for testing. 167 | * Cache the response to an HTTP request if it is cacheable. 168 | * @param Google_HttpRequest $request 169 | * @return bool Returns true if the insertion was successful. 170 | * Otherwise, return false. 171 | */ 172 | public function setCachedRequest(Google_HttpRequest $request) { 173 | // Determine if the request is cacheable. 174 | if (Google_CacheParser::isResponseCacheable($request)) { 175 | Google_Client::$cache->set($request->getCacheKey(), $request); 176 | return true; 177 | } 178 | 179 | return false; 180 | } 181 | 182 | /** 183 | * @visible for testing. 184 | * @param Google_HttpRequest $request 185 | * @return Google_HttpRequest|bool Returns the cached object or 186 | * false if the operation was unsuccessful. 187 | */ 188 | public function getCachedRequest(Google_HttpRequest $request) { 189 | if (false == Google_CacheParser::isRequestCacheable($request)) { 190 | false; 191 | } 192 | 193 | return Google_Client::$cache->get($request->getCacheKey()); 194 | } 195 | 196 | /** 197 | * @param $respData 198 | * @param $headerSize 199 | * @return array 200 | */ 201 | public static function parseHttpResponse($respData, $headerSize) { 202 | if (stripos($respData, self::CONNECTION_ESTABLISHED) !== false) { 203 | $respData = str_ireplace(self::CONNECTION_ESTABLISHED, '', $respData); 204 | } 205 | 206 | if ($headerSize) { 207 | $responseBody = substr($respData, $headerSize); 208 | $responseHeaders = substr($respData, 0, $headerSize); 209 | } else { 210 | list($responseHeaders, $responseBody) = explode("\r\n\r\n", $respData, 2); 211 | } 212 | 213 | $responseHeaders = self::parseResponseHeaders($responseHeaders); 214 | return array($responseHeaders, $responseBody); 215 | } 216 | 217 | public static function parseResponseHeaders($rawHeaders) { 218 | $responseHeaders = array(); 219 | 220 | $responseHeaderLines = explode("\r\n", $rawHeaders); 221 | foreach ($responseHeaderLines as $headerLine) { 222 | if ($headerLine && strpos($headerLine, ':') !== false) { 223 | list($header, $value) = explode(': ', $headerLine, 2); 224 | $header = strtolower($header); 225 | if (isset($responseHeaders[$header])) { 226 | $responseHeaders[$header] .= "\n" . $value; 227 | } else { 228 | $responseHeaders[$header] = $value; 229 | } 230 | } 231 | } 232 | return $responseHeaders; 233 | } 234 | 235 | /** 236 | * @visible for testing 237 | * Process an http request that contains an enclosed entity. 238 | * @param Google_HttpRequest $request 239 | * @return Google_HttpRequest Processed request with the enclosed entity. 240 | */ 241 | public function processEntityRequest(Google_HttpRequest $request) { 242 | $postBody = $request->getPostBody(); 243 | $contentType = $request->getRequestHeader("content-type"); 244 | 245 | // Set the default content-type as application/x-www-form-urlencoded. 246 | if (false == $contentType) { 247 | $contentType = self::FORM_URLENCODED; 248 | $request->setRequestHeaders(array('content-type' => $contentType)); 249 | } 250 | 251 | // Force the payload to match the content-type asserted in the header. 252 | if ($contentType == self::FORM_URLENCODED && is_array($postBody)) { 253 | $postBody = http_build_query($postBody, '', '&'); 254 | $request->setPostBody($postBody); 255 | } 256 | 257 | // Make sure the content-length header is set. 258 | if (!$postBody || is_string($postBody)) { 259 | $postsLength = strlen($postBody); 260 | $request->setRequestHeaders(array('content-length' => $postsLength)); 261 | } 262 | 263 | return $request; 264 | } 265 | 266 | /** 267 | * Set options that update cURL's default behavior. 268 | * The list of accepted options are: 269 | * {@link http://php.net/manual/en/function.curl-setopt.php] 270 | * 271 | * @param array $optCurlParams Multiple options used by a cURL session. 272 | */ 273 | public function setOptions($optCurlParams) { 274 | foreach ($optCurlParams as $key => $val) { 275 | $this->curlParams[$key] = $val; 276 | } 277 | } 278 | } -------------------------------------------------------------------------------- /third_party/google-api-php-client/src/io/Google_HttpRequest.php: -------------------------------------------------------------------------------- 1 | 23 | * @author Chirag Shah 24 | * 25 | */ 26 | class Google_HttpRequest { 27 | const USER_AGENT_SUFFIX = "google-api-php-client/0.6.0"; 28 | private $batchHeaders = array( 29 | 'Content-Type' => 'application/http', 30 | 'Content-Transfer-Encoding' => 'binary', 31 | 'MIME-Version' => '1.0', 32 | 'Content-Length' => '' 33 | ); 34 | 35 | protected $url; 36 | protected $requestMethod; 37 | protected $requestHeaders; 38 | protected $postBody; 39 | protected $userAgent; 40 | 41 | protected $responseHttpCode; 42 | protected $responseHeaders; 43 | protected $responseBody; 44 | 45 | public $accessKey; 46 | 47 | public function __construct($url, $method = 'GET', $headers = array(), $postBody = null) { 48 | $this->setUrl($url); 49 | $this->setRequestMethod($method); 50 | $this->setRequestHeaders($headers); 51 | $this->setPostBody($postBody); 52 | 53 | global $apiConfig; 54 | if (empty($apiConfig['application_name'])) { 55 | $this->userAgent = self::USER_AGENT_SUFFIX; 56 | } else { 57 | $this->userAgent = $apiConfig['application_name'] . " " . self::USER_AGENT_SUFFIX; 58 | } 59 | } 60 | 61 | /** 62 | * Misc function that returns the base url component of the $url 63 | * used by the OAuth signing class to calculate the base string 64 | * @return string The base url component of the $url. 65 | * @see http://oauth.net/core/1.0a/#anchor13 66 | */ 67 | public function getBaseUrl() { 68 | if ($pos = strpos($this->url, '?')) { 69 | return substr($this->url, 0, $pos); 70 | } 71 | return $this->url; 72 | } 73 | 74 | /** 75 | * Misc function that returns an array of the query parameters of the current 76 | * url used by the OAuth signing class to calculate the signature 77 | * @return array Query parameters in the query string. 78 | */ 79 | public function getQueryParams() { 80 | if ($pos = strpos($this->url, '?')) { 81 | $queryStr = substr($this->url, $pos + 1); 82 | $params = array(); 83 | parse_str($queryStr, $params); 84 | return $params; 85 | } 86 | return array(); 87 | } 88 | 89 | /** 90 | * @return string HTTP Response Code. 91 | */ 92 | public function getResponseHttpCode() { 93 | return (int) $this->responseHttpCode; 94 | } 95 | 96 | /** 97 | * @param int $responseHttpCode HTTP Response Code. 98 | */ 99 | public function setResponseHttpCode($responseHttpCode) { 100 | $this->responseHttpCode = $responseHttpCode; 101 | } 102 | 103 | /** 104 | * @return $responseHeaders (array) HTTP Response Headers. 105 | */ 106 | public function getResponseHeaders() { 107 | return $this->responseHeaders; 108 | } 109 | 110 | /** 111 | * @return string HTTP Response Body 112 | */ 113 | public function getResponseBody() { 114 | return $this->responseBody; 115 | } 116 | 117 | /** 118 | * @param array $headers The HTTP response headers 119 | * to be normalized. 120 | */ 121 | public function setResponseHeaders($headers) { 122 | $headers = Google_Utils::normalize($headers); 123 | if ($this->responseHeaders) { 124 | $headers = array_merge($this->responseHeaders, $headers); 125 | } 126 | 127 | $this->responseHeaders = $headers; 128 | } 129 | 130 | /** 131 | * @param string $key 132 | * @return array|boolean Returns the requested HTTP header or 133 | * false if unavailable. 134 | */ 135 | public function getResponseHeader($key) { 136 | return isset($this->responseHeaders[$key]) 137 | ? $this->responseHeaders[$key] 138 | : false; 139 | } 140 | 141 | /** 142 | * @param string $responseBody The HTTP response body. 143 | */ 144 | public function setResponseBody($responseBody) { 145 | $this->responseBody = $responseBody; 146 | } 147 | 148 | /** 149 | * @return string $url The request URL. 150 | */ 151 | 152 | public function getUrl() { 153 | return $this->url; 154 | } 155 | 156 | /** 157 | * @return string $method HTTP Request Method. 158 | */ 159 | public function getRequestMethod() { 160 | return $this->requestMethod; 161 | } 162 | 163 | /** 164 | * @return array $headers HTTP Request Headers. 165 | */ 166 | public function getRequestHeaders() { 167 | return $this->requestHeaders; 168 | } 169 | 170 | /** 171 | * @param string $key 172 | * @return array|boolean Returns the requested HTTP header or 173 | * false if unavailable. 174 | */ 175 | public function getRequestHeader($key) { 176 | return isset($this->requestHeaders[$key]) 177 | ? $this->requestHeaders[$key] 178 | : false; 179 | } 180 | 181 | /** 182 | * @return string $postBody HTTP Request Body. 183 | */ 184 | public function getPostBody() { 185 | return $this->postBody; 186 | } 187 | 188 | /** 189 | * @param string $url the url to set 190 | */ 191 | public function setUrl($url) { 192 | if (substr($url, 0, 4) == 'http') { 193 | $this->url = $url; 194 | } else { 195 | // Force the path become relative. 196 | if (substr($url, 0, 1) !== '/') { 197 | $url = '/' . $url; 198 | } 199 | global $apiConfig; 200 | $this->url = $apiConfig['basePath'] . $url; 201 | } 202 | } 203 | 204 | /** 205 | * @param string $method Set he HTTP Method and normalize 206 | * it to upper-case, as required by HTTP. 207 | * 208 | */ 209 | public function setRequestMethod($method) { 210 | $this->requestMethod = strtoupper($method); 211 | } 212 | 213 | /** 214 | * @param array $headers The HTTP request headers 215 | * to be set and normalized. 216 | */ 217 | public function setRequestHeaders($headers) { 218 | $headers = Google_Utils::normalize($headers); 219 | if ($this->requestHeaders) { 220 | $headers = array_merge($this->requestHeaders, $headers); 221 | } 222 | $this->requestHeaders = $headers; 223 | } 224 | 225 | /** 226 | * @param string $postBody the postBody to set 227 | */ 228 | public function setPostBody($postBody) { 229 | $this->postBody = $postBody; 230 | } 231 | 232 | /** 233 | * Set the User-Agent Header. 234 | * @param string $userAgent The User-Agent. 235 | */ 236 | public function setUserAgent($userAgent) { 237 | $this->userAgent = $userAgent; 238 | } 239 | 240 | /** 241 | * @return string The User-Agent. 242 | */ 243 | public function getUserAgent() { 244 | return $this->userAgent; 245 | } 246 | 247 | /** 248 | * Returns a cache key depending on if this was an OAuth signed request 249 | * in which case it will use the non-signed url and access key to make this 250 | * cache key unique per authenticated user, else use the plain request url 251 | * @return string The md5 hash of the request cache key. 252 | */ 253 | public function getCacheKey() { 254 | $key = $this->getUrl(); 255 | 256 | if (isset($this->accessKey)) { 257 | $key .= $this->accessKey; 258 | } 259 | 260 | if (isset($this->requestHeaders['authorization'])) { 261 | $key .= $this->requestHeaders['authorization']; 262 | } 263 | 264 | return md5($key); 265 | } 266 | 267 | public function getParsedCacheControl() { 268 | $parsed = array(); 269 | $rawCacheControl = $this->getResponseHeader('cache-control'); 270 | if ($rawCacheControl) { 271 | $rawCacheControl = str_replace(', ', '&', $rawCacheControl); 272 | parse_str($rawCacheControl, $parsed); 273 | } 274 | 275 | return $parsed; 276 | } 277 | 278 | /** 279 | * @param string $id 280 | * @return string A string representation of the HTTP Request. 281 | */ 282 | public function toBatchString($id) { 283 | $str = ''; 284 | foreach($this->batchHeaders as $key => $val) { 285 | $str .= $key . ': ' . $val . "\n"; 286 | } 287 | 288 | $str .= "Content-ID: $id\n"; 289 | $str .= "\n"; 290 | 291 | $path = parse_url($this->getUrl(), PHP_URL_PATH); 292 | $str .= $this->getRequestMethod() . ' ' . $path . " HTTP/1.1\n"; 293 | foreach($this->getRequestHeaders() as $key => $val) { 294 | $str .= $key . ': ' . $val . "\n"; 295 | } 296 | 297 | if ($this->getPostBody()) { 298 | $str .= "\n"; 299 | $str .= $this->getPostBody(); 300 | } 301 | 302 | return $str; 303 | } 304 | } 305 | -------------------------------------------------------------------------------- /third_party/google-api-php-client/src/io/Google_IO.php: -------------------------------------------------------------------------------- 1 | 26 | */ 27 | interface Google_IO { 28 | /** 29 | * An utility function that first calls $this->auth->sign($request) and then executes makeRequest() 30 | * on that signed request. Used for when a request should be authenticated 31 | * @param Google_HttpRequest $request 32 | * @return Google_HttpRequest $request 33 | */ 34 | public function authenticatedRequest(Google_HttpRequest $request); 35 | 36 | /** 37 | * Executes a apIHttpRequest and returns the resulting populated httpRequest 38 | * @param Google_HttpRequest $request 39 | * @return Google_HttpRequest $request 40 | */ 41 | public function makeRequest(Google_HttpRequest $request); 42 | 43 | /** 44 | * Set options that update the transport implementation's behavior. 45 | * @param $options 46 | */ 47 | public function setOptions($options); 48 | 49 | } 50 | -------------------------------------------------------------------------------- /third_party/google-api-php-client/src/io/Google_REST.php: -------------------------------------------------------------------------------- 1 | 22 | * @author Chirag Shah 23 | */ 24 | class Google_REST { 25 | /** 26 | * Executes a apiServiceRequest using a RESTful call by transforming it into 27 | * an apiHttpRequest, and executed via apiIO::authenticatedRequest(). 28 | * 29 | * @param Google_HttpRequest $req 30 | * @return array decoded result 31 | * @throws Google_ServiceException on server side error (ie: not authenticated, 32 | * invalid or malformed post body, invalid url) 33 | */ 34 | static public function execute(Google_HttpRequest $req) { 35 | $httpRequest = Google_Client::$io->makeRequest($req); 36 | $decodedResponse = self::decodeHttpResponse($httpRequest); 37 | $ret = isset($decodedResponse['data']) 38 | ? $decodedResponse['data'] : $decodedResponse; 39 | return $ret; 40 | } 41 | 42 | 43 | /** 44 | * Decode an HTTP Response. 45 | * @static 46 | * @throws Google_ServiceException 47 | * @param Google_HttpRequest $response The http response to be decoded. 48 | * @return mixed|null 49 | */ 50 | public static function decodeHttpResponse($response) { 51 | $code = $response->getResponseHttpCode(); 52 | $body = $response->getResponseBody(); 53 | $decoded = null; 54 | 55 | if ($code != '200' && $code != '201' && $code != '204') { 56 | $decoded = json_decode($body, true); 57 | $err = 'Error calling ' . $response->getRequestMethod() . ' ' . $response->getUrl(); 58 | if ($decoded != null && isset($decoded['error']['message']) && isset($decoded['error']['code'])) { 59 | // if we're getting a json encoded error definition, use that instead of the raw response 60 | // body for improved readability 61 | $err .= ": ({$decoded['error']['code']}) {$decoded['error']['message']}"; 62 | } else { 63 | $err .= ": ($code) $body"; 64 | } 65 | 66 | throw new Google_ServiceException($err, $code, null, $decoded['error']['errors']); 67 | } 68 | 69 | // Only attempt to decode the response, if the response code wasn't (204) 'no content' 70 | if ($code != '204') { 71 | $decoded = json_decode($body, true); 72 | if ($decoded === null || $decoded === "") { 73 | throw new Google_ServiceException("Invalid json in service response: $body"); 74 | } 75 | } 76 | return $decoded; 77 | } 78 | 79 | /** 80 | * Parse/expand request parameters and create a fully qualified 81 | * request uri. 82 | * @static 83 | * @param string $servicePath 84 | * @param string $restPath 85 | * @param array $params 86 | * @return string $requestUrl 87 | */ 88 | static function createRequestUri($servicePath, $restPath, $params) { 89 | $requestUrl = $servicePath . $restPath; 90 | $uriTemplateVars = array(); 91 | $queryVars = array(); 92 | foreach ($params as $paramName => $paramSpec) { 93 | // Discovery v1.0 puts the canonical location under the 'location' field. 94 | if (! isset($paramSpec['location'])) { 95 | $paramSpec['location'] = $paramSpec['restParameterType']; 96 | } 97 | 98 | if ($paramSpec['type'] == 'boolean') { 99 | $paramSpec['value'] = ($paramSpec['value']) ? 'true' : 'false'; 100 | } 101 | if ($paramSpec['location'] == 'path') { 102 | $uriTemplateVars[$paramName] = $paramSpec['value']; 103 | } else { 104 | if (isset($paramSpec['repeated']) && is_array($paramSpec['value'])) { 105 | foreach ($paramSpec['value'] as $value) { 106 | $queryVars[] = $paramName . '=' . rawurlencode($value); 107 | } 108 | } else { 109 | $queryVars[] = $paramName . '=' . rawurlencode($paramSpec['value']); 110 | } 111 | } 112 | } 113 | 114 | if (count($uriTemplateVars)) { 115 | $uriTemplateParser = new URI_Template_Parser($requestUrl); 116 | $requestUrl = $uriTemplateParser->expand($uriTemplateVars); 117 | } 118 | //FIXME work around for the the uri template lib which url encodes 119 | // the @'s & confuses our servers. 120 | $requestUrl = str_replace('%40', '@', $requestUrl); 121 | 122 | if (count($queryVars)) { 123 | $requestUrl .= '?' . implode($queryVars, '&'); 124 | } 125 | 126 | return $requestUrl; 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /third_party/google-api-php-client/src/io/cacerts.pem: -------------------------------------------------------------------------------- 1 | # Certifcate Authority certificates for validating SSL connections. 2 | # 3 | # This file contains PEM format certificates generated from 4 | # http://mxr.mozilla.org/seamonkey/source/security/nss/lib/ckfw/builtins/certdata.txt 5 | # 6 | # ***** BEGIN LICENSE BLOCK ***** 7 | # Version: MPL 1.1/GPL 2.0/LGPL 2.1 8 | # 9 | # The contents of this file are subject to the Mozilla Public License Version 10 | # 1.1 (the "License"); you may not use this file except in compliance with 11 | # the License. You may obtain a copy of the License at 12 | # http://www.mozilla.org/MPL/ 13 | # 14 | # Software distributed under the License is distributed on an "AS IS" basis, 15 | # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 16 | # for the specific language governing rights and limitations under the 17 | # License. 18 | # 19 | # The Original Code is the Netscape security libraries. 20 | # 21 | # The Initial Developer of the Original Code is 22 | # Netscape Communications Corporation. 23 | # Portions created by the Initial Developer are Copyright (C) 1994-2000 24 | # the Initial Developer. All Rights Reserved. 25 | # 26 | # Contributor(s): 27 | # 28 | # Alternatively, the contents of this file may be used under the terms of 29 | # either the GNU General Public License Version 2 or later (the "GPL"), or 30 | # the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 31 | # in which case the provisions of the GPL or the LGPL are applicable instead 32 | # of those above. If you wish to allow use of your version of this file only 33 | # under the terms of either the GPL or the LGPL, and not to allow others to 34 | # use your version of this file under the terms of the MPL, indicate your 35 | # decision by deleting the provisions above and replace them with the notice 36 | # and other provisions required by the GPL or the LGPL. If you do not delete 37 | # the provisions above, a recipient may use your version of this file under 38 | # the terms of any one of the MPL, the GPL or the LGPL. 39 | # 40 | # ***** END LICENSE BLOCK ***** 41 | 42 | Verisign/RSA Secure Server CA 43 | ============================= 44 | 45 | -----BEGIN CERTIFICATE----- 46 | MIICNDCCAaECEAKtZn5ORf5eV288mBle3cAwDQYJKoZIhvcNAQECBQAwXzELMAkG 47 | A1UEBhMCVVMxIDAeBgNVBAoTF1JTQSBEYXRhIFNlY3VyaXR5LCBJbmMuMS4wLAYD 48 | VQQLEyVTZWN1cmUgU2VydmVyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk0 49 | MTEwOTAwMDAwMFoXDTEwMDEwNzIzNTk1OVowXzELMAkGA1UEBhMCVVMxIDAeBgNV 50 | BAoTF1JTQSBEYXRhIFNlY3VyaXR5LCBJbmMuMS4wLAYDVQQLEyVTZWN1cmUgU2Vy 51 | dmVyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGbMA0GCSqGSIb3DQEBAQUAA4GJ 52 | ADCBhQJ+AJLOesGugz5aqomDV6wlAXYMra6OLDfO6zV4ZFQD5YRAUcm/jwjiioII 53 | 0haGN1XpsSECrXZogZoFokvJSyVmIlZsiAeP94FZbYQHZXATcXY+m3dM41CJVphI 54 | uR2nKRoTLkoRWZweFdVJVCxzOmmCsZc5nG1wZ0jl3S3WyB57AgMBAAEwDQYJKoZI 55 | hvcNAQECBQADfgBl3X7hsuyw4jrg7HFGmhkRuNPHoLQDQCYCPgmc4RKz0Vr2N6W3 56 | YQO2WxZpO8ZECAyIUwxrl0nHPjXcbLm7qt9cuzovk2C2qUtN8iD3zV9/ZHuO3ABc 57 | 1/p3yjkWWW8O6tO1g39NTUJWdrTJXwT4OPjr0l91X817/OWOgHz8UA== 58 | -----END CERTIFICATE----- 59 | 60 | Thawte Personal Basic CA 61 | ======================== 62 | 63 | -----BEGIN CERTIFICATE----- 64 | MIIDITCCAoqgAwIBAgIBADANBgkqhkiG9w0BAQQFADCByzELMAkGA1UEBhMCWkEx 65 | FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMRowGAYD 66 | VQQKExFUaGF3dGUgQ29uc3VsdGluZzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBT 67 | ZXJ2aWNlcyBEaXZpc2lvbjEhMB8GA1UEAxMYVGhhd3RlIFBlcnNvbmFsIEJhc2lj 68 | IENBMSgwJgYJKoZIhvcNAQkBFhlwZXJzb25hbC1iYXNpY0B0aGF3dGUuY29tMB4X 69 | DTk2MDEwMTAwMDAwMFoXDTIwMTIzMTIzNTk1OVowgcsxCzAJBgNVBAYTAlpBMRUw 70 | EwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNVBAcTCUNhcGUgVG93bjEaMBgGA1UE 71 | ChMRVGhhd3RlIENvbnN1bHRpbmcxKDAmBgNVBAsTH0NlcnRpZmljYXRpb24gU2Vy 72 | dmljZXMgRGl2aXNpb24xITAfBgNVBAMTGFRoYXd0ZSBQZXJzb25hbCBCYXNpYyBD 73 | QTEoMCYGCSqGSIb3DQEJARYZcGVyc29uYWwtYmFzaWNAdGhhd3RlLmNvbTCBnzAN 74 | BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAvLyTU23AUE+CFeZIlDWmWr5vQvoPR+53 75 | dXLdjUmbllegeNTKP1GzaQuRdhciB5dqxFGTS+CN7zeVoQxN2jSQHReJl+A1OFdK 76 | wPQIcOk8RHtQfmGakOMj04gRRif1CwcOu93RfyAKiLlWCy4cgNrx454p7xS9CkT7 77 | G1sY0b8jkyECAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQQF 78 | AAOBgQAt4plrsD16iddZopQBHyvdEktTwq1/qqcAXJFAVyVKOKqEcLnZgA+le1z7 79 | c8a914phXAPjLSeoF+CEhULcXpvGt7Jtu3Sv5D/Lp7ew4F2+eIMllNLbgQ95B21P 80 | 9DkVWlIBe94y1k049hJcBlDfBVu9FEuh3ym6O0GN92NWod8isQ== 81 | -----END CERTIFICATE----- 82 | 83 | Thawte Personal Premium CA 84 | ========================== 85 | 86 | -----BEGIN CERTIFICATE----- 87 | MIIDKTCCApKgAwIBAgIBADANBgkqhkiG9w0BAQQFADCBzzELMAkGA1UEBhMCWkEx 88 | FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMRowGAYD 89 | VQQKExFUaGF3dGUgQ29uc3VsdGluZzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBT 90 | ZXJ2aWNlcyBEaXZpc2lvbjEjMCEGA1UEAxMaVGhhd3RlIFBlcnNvbmFsIFByZW1p 91 | dW0gQ0ExKjAoBgkqhkiG9w0BCQEWG3BlcnNvbmFsLXByZW1pdW1AdGhhd3RlLmNv 92 | bTAeFw05NjAxMDEwMDAwMDBaFw0yMDEyMzEyMzU5NTlaMIHPMQswCQYDVQQGEwJa 93 | QTEVMBMGA1UECBMMV2VzdGVybiBDYXBlMRIwEAYDVQQHEwlDYXBlIFRvd24xGjAY 94 | BgNVBAoTEVRoYXd0ZSBDb25zdWx0aW5nMSgwJgYDVQQLEx9DZXJ0aWZpY2F0aW9u 95 | IFNlcnZpY2VzIERpdmlzaW9uMSMwIQYDVQQDExpUaGF3dGUgUGVyc29uYWwgUHJl 96 | bWl1bSBDQTEqMCgGCSqGSIb3DQEJARYbcGVyc29uYWwtcHJlbWl1bUB0aGF3dGUu 97 | Y29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDJZtn4B0TPuYwu8KHvE0Vs 98 | Bd/eJxZRNkERbGw77f4QfRKe5ZtCmv5gMcNmt3M6SK5O0DI3lIi1DbbZ8/JE2dWI 99 | Et12TfIa/G8jHnrx2JhFTgcQ7xZC0EN1bUre4qrJMf8fAHB8Zs8QJQi6+u4A6UYD 100 | ZicRFTuqW/KY3TZCstqIdQIDAQABoxMwETAPBgNVHRMBAf8EBTADAQH/MA0GCSqG 101 | SIb3DQEBBAUAA4GBAGk2ifc0KjNyL2071CKyuG+axTZmDhs8obF1Wub9NdP4qPIH 102 | b4Vnjt4rueIXsDqg8A6iAJrf8xQVbrvIhVqYgPn/vnQdPfP+MCXRNzRn+qVxeTBh 103 | KXLA4CxM+1bkOqhv5TJZUtt1KFBZDPgLGeSs2a+WjS9Q2wfD6h+rM+D1KzGJ 104 | -----END CERTIFICATE----- 105 | 106 | Thawte Personal Freemail CA 107 | =========================== 108 | 109 | -----BEGIN CERTIFICATE----- 110 | MIIDLTCCApagAwIBAgIBADANBgkqhkiG9w0BAQQFADCB0TELMAkGA1UEBhMCWkEx 111 | FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMRowGAYD 112 | VQQKExFUaGF3dGUgQ29uc3VsdGluZzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBT 113 | ZXJ2aWNlcyBEaXZpc2lvbjEkMCIGA1UEAxMbVGhhd3RlIFBlcnNvbmFsIEZyZWVt 114 | YWlsIENBMSswKQYJKoZIhvcNAQkBFhxwZXJzb25hbC1mcmVlbWFpbEB0aGF3dGUu 115 | Y29tMB4XDTk2MDEwMTAwMDAwMFoXDTIwMTIzMTIzNTk1OVowgdExCzAJBgNVBAYT 116 | AlpBMRUwEwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNVBAcTCUNhcGUgVG93bjEa 117 | MBgGA1UEChMRVGhhd3RlIENvbnN1bHRpbmcxKDAmBgNVBAsTH0NlcnRpZmljYXRp 118 | b24gU2VydmljZXMgRGl2aXNpb24xJDAiBgNVBAMTG1RoYXd0ZSBQZXJzb25hbCBG 119 | cmVlbWFpbCBDQTErMCkGCSqGSIb3DQEJARYccGVyc29uYWwtZnJlZW1haWxAdGhh 120 | d3RlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1GnX1LCUZFtx6UfY 121 | DFG26nKRsIRefS0Nj3sS34UldSh0OkIsYyeflXtL734Zhx2G6qPduc6WZBrCFG5E 122 | rHzmj+hND3EfQDimAKOHePb5lIZererAXnbr2RSjXW56fAylS1V/Bhkpf56aJtVq 123 | uzgkCGqYx7Hao5iR/Xnb5VrEHLkCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zAN 124 | BgkqhkiG9w0BAQQFAAOBgQDH7JJ+Tvj1lqVnYiqk8E0RYNBvjWBYYawmu1I1XAjP 125 | MPuoSpaKH2JCI4wXD/S6ZJwXrEcp352YXtJsYHFcoqzceePnbgBHH7UNKOgCneSa 126 | /RP0ptl8sfjcXyMmCZGAc9AUG95DqYMl8uacLxXK/qarigd1iwzdUYRr5PjRznei 127 | gQ== 128 | -----END CERTIFICATE----- 129 | 130 | Thawte Server CA 131 | ================ 132 | 133 | -----BEGIN CERTIFICATE----- 134 | MIIDEzCCAnygAwIBAgIBATANBgkqhkiG9w0BAQQFADCBxDELMAkGA1UEBhMCWkEx 135 | FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYD 136 | VQQKExRUaGF3dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlv 137 | biBTZXJ2aWNlcyBEaXZpc2lvbjEZMBcGA1UEAxMQVGhhd3RlIFNlcnZlciBDQTEm 138 | MCQGCSqGSIb3DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0ZS5jb20wHhcNOTYwODAx 139 | MDAwMDAwWhcNMjAxMjMxMjM1OTU5WjCBxDELMAkGA1UEBhMCWkExFTATBgNVBAgT 140 | DFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYDVQQKExRUaGF3 141 | dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNl 142 | cyBEaXZpc2lvbjEZMBcGA1UEAxMQVGhhd3RlIFNlcnZlciBDQTEmMCQGCSqGSIb3 143 | DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0ZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQAD 144 | gY0AMIGJAoGBANOkUG7I/1Zr5s9dtuoMaHVHoqrC2oQl/Kj0R1HahbUgdJSGHg91 145 | yekIYfUGbTBuFRkC6VLAYttNmZ7iagxEOM3+vuNkCXDF/rFrKbYvScg71CcEJRCX 146 | L+eQbcAoQpnXTEPew/UhbVSfXcNY4cDk2VuwuNy0e982OsK1ZiIS1ocNAgMBAAGj 147 | EzARMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEEBQADgYEAB/pMaVz7lcxG 148 | 7oWDTSEwjsrZqG9JGubaUeNgcGyEYRGhGshIPllDfU+VPaGLtwtimHp1it2ITk6e 149 | QNuozDJ0uW8NxuOzRAvZim+aKZuZGCg70eNAKJpaPNW15yAbi8qkq43pUdniTCxZ 150 | qdq5snUb9kLy78fyGPmJvKP/iiMucEc= 151 | -----END CERTIFICATE----- 152 | 153 | Thawte Premium Server CA 154 | ======================== 155 | 156 | -----BEGIN CERTIFICATE----- 157 | MIIDJzCCApCgAwIBAgIBATANBgkqhkiG9w0BAQQFADCBzjELMAkGA1UEBhMCWkEx 158 | FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYD 159 | VQQKExRUaGF3dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlv 160 | biBTZXJ2aWNlcyBEaXZpc2lvbjEhMB8GA1UEAxMYVGhhd3RlIFByZW1pdW0gU2Vy 161 | dmVyIENBMSgwJgYJKoZIhvcNAQkBFhlwcmVtaXVtLXNlcnZlckB0aGF3dGUuY29t 162 | MB4XDTk2MDgwMTAwMDAwMFoXDTIwMTIzMTIzNTk1OVowgc4xCzAJBgNVBAYTAlpB 163 | MRUwEwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNVBAcTCUNhcGUgVG93bjEdMBsG 164 | A1UEChMUVGhhd3RlIENvbnN1bHRpbmcgY2MxKDAmBgNVBAsTH0NlcnRpZmljYXRp 165 | b24gU2VydmljZXMgRGl2aXNpb24xITAfBgNVBAMTGFRoYXd0ZSBQcmVtaXVtIFNl 166 | cnZlciBDQTEoMCYGCSqGSIb3DQEJARYZcHJlbWl1bS1zZXJ2ZXJAdGhhd3RlLmNv 167 | bTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0jY2aovXwlue2oFBYo847kkE 168 | VdbQ7xwblRZH7xhINTpS9CtqBo87L+pW46+GjZ4X9560ZXUCTe/LCaIhUdib0GfQ 169 | ug2SBhRz1JPLlyoAnFxODLz6FVL88kRu2hFKbgifLy3j+ao6hnO2RlNYyIkFvYMR 170 | uHM/qgeN9EJN50CdHDcCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG 171 | 9w0BAQQFAAOBgQAmSCwWwlj66BZ0DKqqX1Q/8tfJeGBeXm43YyJ3Nn6yF8Q0ufUI 172 | hfzJATj/Tb7yFkJD57taRvvBxhEf8UqwKEbJw8RCfbz6q1lu1bdRiBHjpIUZa4JM 173 | pAwSremkrj/xw0llmozFyD4lt5SZu5IycQfwhl7tUCemDaYj+bvLpgcUQg== 174 | -----END CERTIFICATE----- 175 | 176 | Equifax Secure CA 177 | ================= 178 | 179 | -----BEGIN CERTIFICATE----- 180 | MIIDIDCCAomgAwIBAgIENd70zzANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJV 181 | UzEQMA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2Vy 182 | dGlmaWNhdGUgQXV0aG9yaXR5MB4XDTk4MDgyMjE2NDE1MVoXDTE4MDgyMjE2NDE1 183 | MVowTjELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0VxdWlmYXgxLTArBgNVBAsTJEVx 184 | dWlmYXggU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eTCBnzANBgkqhkiG9w0B 185 | AQEFAAOBjQAwgYkCgYEAwV2xWGcIYu6gmi0fCG2RFGiYCh7+2gRvE4RiIcPRfM6f 186 | BeC4AfBONOziipUEZKzxa1NfBbPLZ4C/QgKO/t0BCezhABRP/PvwDN1Dulsr4R+A 187 | cJkVV5MW8Q+XarfCaCMczE1ZMKxRHjuvK9buY0V7xdlfUNLjUA86iOe/FP3gx7kC 188 | AwEAAaOCAQkwggEFMHAGA1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEQ 189 | MA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2VydGlm 190 | aWNhdGUgQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMBoGA1UdEAQTMBGBDzIwMTgw 191 | ODIyMTY0MTUxWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUSOZo+SvSspXXR9gj 192 | IBBPM5iQn9QwHQYDVR0OBBYEFEjmaPkr0rKV10fYIyAQTzOYkJ/UMAwGA1UdEwQF 193 | MAMBAf8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUA 194 | A4GBAFjOKer89961zgK5F7WF0bnj4JXMJTENAKaSbn+2kmOeUJXRmm/kEd5jhW6Y 195 | 7qj/WsjTVbJmcVfewCHrPSqnI0kBBIZCe/zuf6IWUrVnZ9NA2zsmWLIodz2uFHdh 196 | 1voqZiegDfqnc1zqcPGUIWVEX/r87yloqaKHee9570+sB3c4 197 | -----END CERTIFICATE----- 198 | 199 | Verisign Class 1 Public Primary Certification Authority 200 | ======================================================= 201 | 202 | -----BEGIN CERTIFICATE----- 203 | MIICPTCCAaYCEQDNun9W8N/kvFT+IqyzcqpVMA0GCSqGSIb3DQEBAgUAMF8xCzAJ 204 | BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE3MDUGA1UECxMuQ2xh 205 | c3MgMSBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw05 206 | NjAxMjkwMDAwMDBaFw0yODA4MDEyMzU5NTlaMF8xCzAJBgNVBAYTAlVTMRcwFQYD 207 | VQQKEw5WZXJpU2lnbiwgSW5jLjE3MDUGA1UECxMuQ2xhc3MgMSBQdWJsaWMgUHJp 208 | bWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCBnzANBgkqhkiG9w0BAQEFAAOB 209 | jQAwgYkCgYEA5Rm/baNWYS2ZSHH2Z965jeu3noaACpEO+jglr0aIguVzqKCbJF0N 210 | H8xlbgyw0FaEGIeaBpsQoXPftFg5a27B9hXVqKg/qhIGjTGsf7A01480Z4gJzRQR 211 | 4k5FVmkfeAKA2txHkSm7NsljXMXg1y2He6G3MrB7MLoqLzGq7qNn2tsCAwEAATAN 212 | BgkqhkiG9w0BAQIFAAOBgQBMP7iLxmjf7kMzDl3ppssHhE16M/+SG/Q2rdiVIjZo 213 | EWx8QszznC7EBz8UsA9P/5CSdvnivErpj82ggAr3xSnxgiJduLHdgSOjeyUVRjB5 214 | FvjqBUuUfx3CHMjjt/QQQDwTw18fU+hI5Ia0e6E1sHslurjTjqs/OJ0ANACY89Fx 215 | lA== 216 | -----END CERTIFICATE----- 217 | 218 | Verisign Class 2 Public Primary Certification Authority 219 | ======================================================= 220 | 221 | -----BEGIN CERTIFICATE----- 222 | MIICPDCCAaUCEC0b/EoXjaOR6+f/9YtFvgswDQYJKoZIhvcNAQECBQAwXzELMAkG 223 | A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz 224 | cyAyIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2 225 | MDEyOTAwMDAwMFoXDTI4MDgwMTIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV 226 | BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAyIFB1YmxpYyBQcmlt 227 | YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN 228 | ADCBiQKBgQC2WoujDWojg4BrzzmH9CETMwZMJaLtVRKXxaeAufqDwSCg+i8VDXyh 229 | YGt+eSz6Bg86rvYbb7HS/y8oUl+DfUvEerf4Zh+AVPy3wo5ZShRXRtGak75BkQO7 230 | FYCTXOvnzAhsPz6zSvz/S2wj1VCCJkQZjiPDceoZJEcEnnW/yKYAHwIDAQABMA0G 231 | CSqGSIb3DQEBAgUAA4GBAIobK/o5wXTXXtgZZKJYSi034DNHD6zt96rbHuSLBlxg 232 | J8pFUs4W7z8GZOeUaHxgMxURaa+dYo2jA1Rrpr7l7gUYYAS/QoD90KioHgE796Nc 233 | r6Pc5iaAIzy4RHT3Cq5Ji2F4zCS/iIqnDupzGUH9TQPwiNHleI2lKk/2lw0Xd8rY 234 | -----END CERTIFICATE----- 235 | 236 | Verisign Class 3 Public Primary Certification Authority 237 | ======================================================= 238 | 239 | -----BEGIN CERTIFICATE----- 240 | MIICPDCCAaUCEHC65B0Q2Sk0tjjKewPMur8wDQYJKoZIhvcNAQECBQAwXzELMAkG 241 | A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz 242 | cyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2 243 | MDEyOTAwMDAwMFoXDTI4MDgwMTIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV 244 | BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmlt 245 | YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN 246 | ADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhE 247 | BarsAx94f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/is 248 | I19wKTakyYbnsZogy1Olhec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0G 249 | CSqGSIb3DQEBAgUAA4GBALtMEivPLCYATxQT3ab7/AoRhIzzKBxnki98tsX63/Do 250 | lbwdj2wsqFHMc9ikwFPwTtYmwHYBV4GSXiHx0bH/59AhWM1pF+NEHJwZRDmJXNyc 251 | AA9WjQKZ7aKQRUzkuxCkPfAyAw7xzvjoyVGM5mKf5p/AfbdynMk2OmufTqj/ZA1k 252 | -----END CERTIFICATE----- 253 | 254 | Verisign Class 1 Public Primary Certification Authority - G2 255 | ============================================================ 256 | 257 | -----BEGIN CERTIFICATE----- 258 | MIIDAjCCAmsCEEzH6qqYPnHTkxD4PTqJkZIwDQYJKoZIhvcNAQEFBQAwgcExCzAJ 259 | BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xh 260 | c3MgMSBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcy 261 | MTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3Jp 262 | emVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMB4X 263 | DTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVowgcExCzAJBgNVBAYTAlVTMRcw 264 | FQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMSBQdWJsaWMg 265 | UHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEo 266 | YykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5 267 | MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEB 268 | AQUAA4GNADCBiQKBgQCq0Lq+Fi24g9TK0g+8djHKlNgdk4xWArzZbxpvUjZudVYK 269 | VdPfQ4chEWWKfo+9Id5rMj8bhDSVBZ1BNeuS65bdqlk/AVNtmU/t5eIqWpDBucSm 270 | Fc/IReumXY6cPvBkJHalzasab7bYe1FhbqZ/h8jit+U03EGI6glAvnOSPWvndQID 271 | AQABMA0GCSqGSIb3DQEBBQUAA4GBAKlPww3HZ74sy9mozS11534Vnjty637rXC0J 272 | h9ZrbWB85a7FkCMMXErQr7Fd88e2CtvgFZMN3QO8x3aKtd1Pw5sTdbgBwObJW2ul 273 | uIncrKTdcu1OofdPvAbT6shkdHvClUGcZXNY8ZCaPGqxmMnEh7zPRW1F4m4iP/68 274 | DzFc6PLZ 275 | -----END CERTIFICATE----- 276 | 277 | Verisign Class 2 Public Primary Certification Authority - G2 278 | ============================================================ 279 | 280 | -----BEGIN CERTIFICATE----- 281 | MIIDAzCCAmwCEQC5L2DMiJ+hekYJuFtwbIqvMA0GCSqGSIb3DQEBBQUAMIHBMQsw 282 | CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xPDA6BgNVBAsTM0Ns 283 | YXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBH 284 | MjE6MDgGA1UECxMxKGMpIDE5OTggVmVyaVNpZ24sIEluYy4gLSBGb3IgYXV0aG9y 285 | aXplZCB1c2Ugb25seTEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazAe 286 | Fw05ODA1MTgwMDAwMDBaFw0yODA4MDEyMzU5NTlaMIHBMQswCQYDVQQGEwJVUzEX 287 | MBUGA1UEChMOVmVyaVNpZ24sIEluYy4xPDA6BgNVBAsTM0NsYXNzIDIgUHVibGlj 288 | IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMjE6MDgGA1UECxMx 289 | KGMpIDE5OTggVmVyaVNpZ24sIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25s 290 | eTEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazCBnzANBgkqhkiG9w0B 291 | AQEFAAOBjQAwgYkCgYEAp4gBIXQs5xoD8JjhlzwPIQjxnNuX6Zr8wgQGE75fUsjM 292 | HiwSViy4AWkszJkfrbCWrnkE8hM5wXuYuggs6MKEEyyqaekJ9MepAqRCwiNPStjw 293 | DqL7MWzJ5m+ZJwf15vRMeJ5t60aG+rmGyVTyssSv1EYcWskVMP8NbPUtDm3Of3cC 294 | AwEAATANBgkqhkiG9w0BAQUFAAOBgQByLvl/0fFx+8Se9sVeUYpAmLho+Jscg9ji 295 | nb3/7aHmZuovCfTK1+qlK5X2JGCGTUQug6XELaDTrnhpb3LabK4I8GOSN+a7xDAX 296 | rXfMSTWqz9iP0b63GJZHc2pUIjRkLbYWm1lbtFFZOrMLFPQS32eg9K0yZF6xRnIn 297 | jBJ7xUS0rg== 298 | -----END CERTIFICATE----- 299 | 300 | Verisign Class 3 Public Primary Certification Authority - G2 301 | ============================================================ 302 | 303 | -----BEGIN CERTIFICATE----- 304 | MIIDAjCCAmsCEH3Z/gfPqB63EHln+6eJNMYwDQYJKoZIhvcNAQEFBQAwgcExCzAJ 305 | BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xh 306 | c3MgMyBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcy 307 | MTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3Jp 308 | emVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMB4X 309 | DTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVowgcExCzAJBgNVBAYTAlVTMRcw 310 | FQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMyBQdWJsaWMg 311 | UHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEo 312 | YykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5 313 | MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEB 314 | AQUAA4GNADCBiQKBgQDMXtERXVxp0KvTuWpMmR9ZmDCOFoUgRm1HP9SFIIThbbP4 315 | pO0M8RcPO/mn+SXXwc+EY/J8Y8+iR/LGWzOOZEAEaMGAuWQcRXfH2G71lSk8UOg0 316 | 13gfqLptQ5GVj0VXXn7F+8qkBOvqlzdUMG+7AUcyM83cV5tkaWH4mx0ciU9cZwID 317 | AQABMA0GCSqGSIb3DQEBBQUAA4GBAFFNzb5cy5gZnBWyATl4Lk0PZ3BwmcYQWpSk 318 | U01UbSuvDV1Ai2TT1+7eVmGSX6bEHRBhNtMsJzzoKQm5EWR0zLVznxxIqbxhAe7i 319 | F6YM40AIOw7n60RzKprxaZLvcRTDOaxxp5EJb+RxBrO6WVcmeQD2+A2iMzAo1KpY 320 | oJ2daZH9 321 | -----END CERTIFICATE----- 322 | 323 | Verisign Class 4 Public Primary Certification Authority - G2 324 | ============================================================ 325 | 326 | -----BEGIN CERTIFICATE----- 327 | MIIDAjCCAmsCEDKIjprS9esTR/h/xCA3JfgwDQYJKoZIhvcNAQEFBQAwgcExCzAJ 328 | BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xh 329 | c3MgNCBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcy 330 | MTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3Jp 331 | emVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMB4X 332 | DTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVowgcExCzAJBgNVBAYTAlVTMRcw 333 | FQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgNCBQdWJsaWMg 334 | UHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEo 335 | YykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5 336 | MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEB 337 | AQUAA4GNADCBiQKBgQC68OTP+cSuhVS5B1f5j8V/aBH4xBewRNzjMHPVKmIquNDM 338 | HO0oW369atyzkSTKQWI8/AIBvxwWMZQFl3Zuoq29YRdsTjCG8FE3KlDHqGKB3FtK 339 | qsGgtG7rL+VXxbErQHDbWk2hjh+9Ax/YA9SPTJlxvOKCzFjomDqG04Y48wApHwID 340 | AQABMA0GCSqGSIb3DQEBBQUAA4GBAIWMEsGnuVAVess+rLhDityq3RS6iYF+ATwj 341 | cSGIL4LcY/oCRaxFWdcqWERbt5+BO5JoPeI3JPV7bI92NZYJqFmduc4jq3TWg/0y 342 | cyfYaT5DdPauxYma51N86Xv2S/PBZYPejYqcPIiNOVn8qj8ijaHBZlCBckztImRP 343 | T8qAkbYp 344 | -----END CERTIFICATE----- 345 | 346 | Verisign Class 1 Public Primary Certification Authority - G3 347 | ============================================================ 348 | 349 | -----BEGIN CERTIFICATE----- 350 | MIIEGjCCAwICEQCLW3VWhFSFCwDPrzhIzrGkMA0GCSqGSIb3DQEBBQUAMIHKMQsw 351 | CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl 352 | cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu 353 | LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT 354 | aWduIENsYXNzIDEgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp 355 | dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD 356 | VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT 357 | aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ 358 | bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu 359 | IENsYXNzIDEgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg 360 | LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAN2E1Lm0+afY8wR4 361 | nN493GwTFtl63SRRZsDHJlkNrAYIwpTRMx/wgzUfbhvI3qpuFU5UJ+/EbRrsC+MO 362 | 8ESlV8dAWB6jRx9x7GD2bZTIGDnt/kIYVt/kTEkQeE4BdjVjEjbdZrwBBDajVWjV 363 | ojYJrKshJlQGrT/KFOCsyq0GHZXi+J3x4GD/wn91K0zM2v6HmSHquv4+VNfSWXjb 364 | PG7PoBMAGrgnoeS+Z5bKoMWznN3JdZ7rMJpfo83ZrngZPyPpXNspva1VyBtUjGP2 365 | 6KbqxzcSXKMpHgLZ2x87tNcPVkeBFQRKr4Mn0cVYiMHd9qqnoxjaaKptEVHhv2Vr 366 | n5Z20T0CAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAq2aN17O6x5q25lXQBfGfMY1a 367 | qtmqRiYPce2lrVNWYgFHKkTp/j90CxObufRNG7LRX7K20ohcs5/Ny9Sn2WCVhDr4 368 | wTcdYcrnsMXlkdpUpqwxga6X3s0IrLjAl4B/bnKk52kTlWUfxJM8/XmPBNQ+T+r3 369 | ns7NZ3xPZQL/kYVUc8f/NveGLezQXk//EZ9yBta4GvFMDSZl4kSAHsef493oCtrs 370 | pSCAaWihT37ha88HQfqDjrw43bAuEbFrskLMmrz5SCJ5ShkPshw+IHTZasO+8ih4 371 | E1Z5T21Q6huwtVexN2ZYI/PcD98Kh8TvhgXVOBRgmaNL3gaWcSzy27YfpO8/7g== 372 | -----END CERTIFICATE----- 373 | 374 | Verisign Class 2 Public Primary Certification Authority - G3 375 | ============================================================ 376 | 377 | -----BEGIN CERTIFICATE----- 378 | MIIEGTCCAwECEGFwy0mMX5hFKeewptlQW3owDQYJKoZIhvcNAQEFBQAwgcoxCzAJ 379 | BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVy 380 | aVNpZ24gVHJ1c3QgTmV0d29yazE6MDgGA1UECxMxKGMpIDE5OTkgVmVyaVNpZ24s 381 | IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTFFMEMGA1UEAxM8VmVyaVNp 382 | Z24gQ2xhc3MgMiBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0 383 | eSAtIEczMB4XDTk5MTAwMTAwMDAwMFoXDTM2MDcxNjIzNTk1OVowgcoxCzAJBgNV 384 | BAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVyaVNp 385 | Z24gVHJ1c3QgTmV0d29yazE6MDgGA1UECxMxKGMpIDE5OTkgVmVyaVNpZ24sIElu 386 | Yy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTFFMEMGA1UEAxM8VmVyaVNpZ24g 387 | Q2xhc3MgMiBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAt 388 | IEczMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArwoNwtUs22e5LeWU 389 | J92lvuCwTY+zYVY81nzD9M0+hsuiiOLh2KRpxbXiv8GmR1BeRjmL1Za6tW8UvxDO 390 | JxOeBUebMXoT2B/Z0wI3i60sR/COgQanDTAM6/c8DyAd3HJG7qUCyFvDyVZpTMUY 391 | wZF7C9UTAJu878NIPkZgIIUq1ZC2zYugzDLdt/1AVbJQHFauzI13TccgTacxdu9o 392 | koqQHgiBVrKtaaNS0MscxCM9H5n+TOgWY47GCI72MfbS+uV23bUckqNJzc0BzWjN 393 | qWm6o+sdDZykIKbBoMXRRkwXbdKsZj+WjOCE1Db/IlnF+RFgqF8EffIa9iVCYQ/E 394 | Srg+iQIDAQABMA0GCSqGSIb3DQEBBQUAA4IBAQA0JhU8wI1NQ0kdvekhktdmnLfe 395 | xbjQ5F1fdiLAJvmEOjr5jLX77GDx6M4EsMjdpwOPMPOY36TmpDHf0xwLRtxyID+u 396 | 7gU8pDM/CzmscHhzS5kr3zDCVLCoO1Wh/hYozUK9dG6A2ydEp85EXdQbkJgNHkKU 397 | sQAsBNB0owIFImNjzYO1+8FtYmtpdf1dcEG59b98377BMnMiIYtYgXsVkXq642RI 398 | sH/7NiXaldDxJBQX3RiAa0YjOVT1jmIJBB2UkKab5iXiQkWquJCtvgiPqQtCGJTP 399 | cjnhsUPgKM+351psE2tJs//jGHyJizNdrDPXp/naOlXJWBD5qu9ats9LS98q 400 | -----END CERTIFICATE----- 401 | 402 | Verisign Class 3 Public Primary Certification Authority - G3 403 | ============================================================ 404 | 405 | -----BEGIN CERTIFICATE----- 406 | MIIEGjCCAwICEQCbfgZJoz5iudXukEhxKe9XMA0GCSqGSIb3DQEBBQUAMIHKMQsw 407 | CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl 408 | cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu 409 | LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT 410 | aWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp 411 | dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD 412 | VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT 413 | aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ 414 | bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu 415 | IENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg 416 | LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMu6nFL8eB8aHm8b 417 | N3O9+MlrlBIwT/A2R/XQkQr1F8ilYcEWQE37imGQ5XYgwREGfassbqb1EUGO+i2t 418 | KmFZpGcmTNDovFJbcCAEWNF6yaRpvIMXZK0Fi7zQWM6NjPXr8EJJC52XJ2cybuGu 419 | kxUccLwgTS8Y3pKI6GyFVxEa6X7jJhFUokWWVYPKMIno3Nij7SqAP395ZVc+FSBm 420 | CC+Vk7+qRy+oRpfwEuL+wgorUeZ25rdGt+INpsyow0xZVYnm6FNcHOqd8GIWC6fJ 421 | Xwzw3sJ2zq/3avL6QaaiMxTJ5Xpj055iN9WFZZ4O5lMkdBteHRJTW8cs54NJOxWu 422 | imi5V5cCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAERSWwauSCPc/L8my/uRan2Te 423 | 2yFPhpk0djZX3dAVL8WtfxUfN2JzPtTnX84XA9s1+ivbrmAJXx5fj267Cz3qWhMe 424 | DGBvtcC1IyIuBwvLqXTLR7sdwdela8wv0kL9Sd2nic9TutoAWii/gt/4uhMdUIaC 425 | /Y4wjylGsB49Ndo4YhYYSq3mtlFs3q9i6wHQHiT+eo8SGhJouPtmmRQURVyu565p 426 | F4ErWjfJXir0xuKhXFSbplQAz/DxwceYMBo7Nhbbo27q/a2ywtrvAkcTisDxszGt 427 | TxzhT5yvDwyd93gN2PQ1VoDat20Xj50egWTh/sVFuq1ruQp6Tk9LhO5L8X3dEQ== 428 | -----END CERTIFICATE----- 429 | 430 | Verisign Class 4 Public Primary Certification Authority - G3 431 | ============================================================ 432 | 433 | -----BEGIN CERTIFICATE----- 434 | MIIEGjCCAwICEQDsoKeLbnVqAc/EfMwvlF7XMA0GCSqGSIb3DQEBBQUAMIHKMQsw 435 | CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl 436 | cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu 437 | LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT 438 | aWduIENsYXNzIDQgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp 439 | dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD 440 | VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT 441 | aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ 442 | bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu 443 | IENsYXNzIDQgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg 444 | LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK3LpRFpxlmr8Y+1 445 | GQ9Wzsy1HyDkniYlS+BzZYlZ3tCD5PUPtbut8XzoIfzk6AzufEUiGXaStBO3IFsJ 446 | +mGuqPKljYXCKtbeZjbSmwL0qJJgfJxptI8kHtCGUvYynEFYHiK9zUVilQhu0Gbd 447 | U6LM8BDcVHOLBKFGMzNcF0C5nk3T875Vg+ixiY5afJqWIpA7iCXy0lOIAgwLePLm 448 | NxdLMEYH5IBtptiWLugs+BGzOA1mppvqySNb247i8xOOGlktqgLw7KSHZtzBP/XY 449 | ufTsgsbSPZUd5cBPhMnZo0QoBmrXRazwa2rvTl/4EYIeOGM0ZlDUPpNz+jDDZq3/ 450 | ky2X7wMCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAj/ola09b5KROJ1WrIhVZPMq1 451 | CtRK26vdoV9TxaBXOcLORyu+OshWv8LZJxA6sQU8wHcxuzrTBXttmhwwjIDLk5Mq 452 | g6sFUYICABFna/OIYUdfA5PVWw3g8dShMjWFsjrbsIKr0csKvE+MW8VLADsfKoKm 453 | fjaF3H48ZwC15DtS4KjrXRX5xm3wrR0OhbepmnMUWluPQSjA1egtTaRezarZ7c7c 454 | 2NU8Qh0XwRJdRTjDOPP8hS6DRkiy1yBfkjaP53kPmF6Z6PDQpLv1U70qzlmwr25/ 455 | bLvSHgCwIe34QWKCudiyxLtGUPMxxY8BqHTr9Xgn2uf3ZkPznoM+IKrDNWCRzg== 456 | -----END CERTIFICATE----- 457 | 458 | Equifax Secure Global eBusiness CA 459 | ================================== 460 | 461 | -----BEGIN CERTIFICATE----- 462 | MIICkDCCAfmgAwIBAgIBATANBgkqhkiG9w0BAQQFADBaMQswCQYDVQQGEwJVUzEc 463 | MBoGA1UEChMTRXF1aWZheCBTZWN1cmUgSW5jLjEtMCsGA1UEAxMkRXF1aWZheCBT 464 | ZWN1cmUgR2xvYmFsIGVCdXNpbmVzcyBDQS0xMB4XDTk5MDYyMTA0MDAwMFoXDTIw 465 | MDYyMTA0MDAwMFowWjELMAkGA1UEBhMCVVMxHDAaBgNVBAoTE0VxdWlmYXggU2Vj 466 | dXJlIEluYy4xLTArBgNVBAMTJEVxdWlmYXggU2VjdXJlIEdsb2JhbCBlQnVzaW5l 467 | c3MgQ0EtMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAuucXkAJlsTRVPEnC 468 | UdXfp9E3j9HngXNBUmCbnaEXJnitx7HoJpQytd4zjTov2/KaelpzmKNc6fuKcxtc 469 | 58O/gGzNqfTWK8D3+ZmqY6KxRwIP1ORROhI8bIpaVIRw28HFkM9yRcuoWcDNM50/ 470 | o5brhTMhHD4ePmBudpxnhcXIw2ECAwEAAaNmMGQwEQYJYIZIAYb4QgEBBAQDAgAH 471 | MA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUvqigdHJQa0S3ySPY+6j/s1dr 472 | aGwwHQYDVR0OBBYEFL6ooHRyUGtEt8kj2Puo/7NXa2hsMA0GCSqGSIb3DQEBBAUA 473 | A4GBADDiAVGqx+pf2rnQZQ8w1j7aDRRJbpGTJxQx78T3LUX47Me/okENI7SS+RkA 474 | Z70Br83gcfxaz2TE4JaY0KNA4gGK7ycH8WUBikQtBmV1UsCGECAhX2xrD2yuCRyv 475 | 8qIYNMR1pHMc8Y3c7635s3a0kr/clRAevsvIO1qEYBlWlKlV 476 | -----END CERTIFICATE----- 477 | 478 | Equifax Secure eBusiness CA 1 479 | ============================= 480 | 481 | -----BEGIN CERTIFICATE----- 482 | MIICgjCCAeugAwIBAgIBBDANBgkqhkiG9w0BAQQFADBTMQswCQYDVQQGEwJVUzEc 483 | MBoGA1UEChMTRXF1aWZheCBTZWN1cmUgSW5jLjEmMCQGA1UEAxMdRXF1aWZheCBT 484 | ZWN1cmUgZUJ1c2luZXNzIENBLTEwHhcNOTkwNjIxMDQwMDAwWhcNMjAwNjIxMDQw 485 | MDAwWjBTMQswCQYDVQQGEwJVUzEcMBoGA1UEChMTRXF1aWZheCBTZWN1cmUgSW5j 486 | LjEmMCQGA1UEAxMdRXF1aWZheCBTZWN1cmUgZUJ1c2luZXNzIENBLTEwgZ8wDQYJ 487 | KoZIhvcNAQEBBQADgY0AMIGJAoGBAM4vGbwXt3fek6lfWg0XTzQaDJj0ItlZ1MRo 488 | RvC0NcWFAyDGr0WlIVFFQesWWDYyb+JQYmT5/VGcqiTZ9J2DKocKIdMSODRsjQBu 489 | WqDZQu4aIZX5UkxVWsUPOE9G+m34LjXWHXzr4vCwdYDIqROsvojvOm6rXyo4YgKw 490 | Env+j6YDAgMBAAGjZjBkMBEGCWCGSAGG+EIBAQQEAwIABzAPBgNVHRMBAf8EBTAD 491 | AQH/MB8GA1UdIwQYMBaAFEp4MlIR21kWNl7fwRQ2QGpHfEyhMB0GA1UdDgQWBBRK 492 | eDJSEdtZFjZe38EUNkBqR3xMoTANBgkqhkiG9w0BAQQFAAOBgQB1W6ibAxHm6VZM 493 | zfmpTMANmvPMZWnmJXbMWbfWVMMdzZmsGd20hdXgPfxiIKeES1hl8eL5lSE/9dR+ 494 | WB5Hh1Q+WKG1tfgq73HnvMP2sUlG4tega+VWeponmHxGYhTnyfxuAxJ5gDgdSIKN 495 | /Bf+KpYrtWKmpj29f5JZzVoqgrI3eQ== 496 | -----END CERTIFICATE----- 497 | 498 | Equifax Secure eBusiness CA 2 499 | ============================= 500 | 501 | -----BEGIN CERTIFICATE----- 502 | MIIDIDCCAomgAwIBAgIEN3DPtTANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJV 503 | UzEXMBUGA1UEChMORXF1aWZheCBTZWN1cmUxJjAkBgNVBAsTHUVxdWlmYXggU2Vj 504 | dXJlIGVCdXNpbmVzcyBDQS0yMB4XDTk5MDYyMzEyMTQ0NVoXDTE5MDYyMzEyMTQ0 505 | NVowTjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkVxdWlmYXggU2VjdXJlMSYwJAYD 506 | VQQLEx1FcXVpZmF4IFNlY3VyZSBlQnVzaW5lc3MgQ0EtMjCBnzANBgkqhkiG9w0B 507 | AQEFAAOBjQAwgYkCgYEA5Dk5kx5SBhsoNviyoynF7Y6yEb3+6+e0dMKP/wXn2Z0G 508 | vxLIPw7y1tEkshHe0XMJitSxLJgJDR5QRrKDpkWNYmi7hRsgcDKqQM2mll/EcTc/ 509 | BPO3QSQ5BxoeLmFYoBIL5aXfxavqN3HMHMg3OrmXUqesxWoklE6ce8/AatbfIb0C 510 | AwEAAaOCAQkwggEFMHAGA1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEX 511 | MBUGA1UEChMORXF1aWZheCBTZWN1cmUxJjAkBgNVBAsTHUVxdWlmYXggU2VjdXJl 512 | IGVCdXNpbmVzcyBDQS0yMQ0wCwYDVQQDEwRDUkwxMBoGA1UdEAQTMBGBDzIwMTkw 513 | NjIzMTIxNDQ1WjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUUJ4L6q9euSBIplBq 514 | y/3YIHqngnYwHQYDVR0OBBYEFFCeC+qvXrkgSKZQasv92CB6p4J2MAwGA1UdEwQF 515 | MAMBAf8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUA 516 | A4GBAAyGgq3oThr1jokn4jVYPSm0B482UJW/bsGe68SQsoWou7dC4A8HOd/7npCy 517 | 0cE+U58DRLB+S/Rv5Hwf5+Kx5Lia78O9zt4LMjTZ3ijtM2vE1Nc9ElirfQkty3D1 518 | E4qUoSek1nDFbZS1yX2doNLGCEnZZpum0/QL3MUmV+GRMOrN 519 | -----END CERTIFICATE----- 520 | 521 | Thawte Time Stamping CA 522 | ======================= 523 | 524 | -----BEGIN CERTIFICATE----- 525 | MIICoTCCAgqgAwIBAgIBADANBgkqhkiG9w0BAQQFADCBizELMAkGA1UEBhMCWkEx 526 | FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTEUMBIGA1UEBxMLRHVyYmFudmlsbGUxDzAN 527 | BgNVBAoTBlRoYXd0ZTEdMBsGA1UECxMUVGhhd3RlIENlcnRpZmljYXRpb24xHzAd 528 | BgNVBAMTFlRoYXd0ZSBUaW1lc3RhbXBpbmcgQ0EwHhcNOTcwMTAxMDAwMDAwWhcN 529 | MjAxMjMxMjM1OTU5WjCBizELMAkGA1UEBhMCWkExFTATBgNVBAgTDFdlc3Rlcm4g 530 | Q2FwZTEUMBIGA1UEBxMLRHVyYmFudmlsbGUxDzANBgNVBAoTBlRoYXd0ZTEdMBsG 531 | A1UECxMUVGhhd3RlIENlcnRpZmljYXRpb24xHzAdBgNVBAMTFlRoYXd0ZSBUaW1l 532 | c3RhbXBpbmcgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANYrWHhhRYZT 533 | 6jR7UZztsOYuGA7+4F+oJ9O0yeB8WU4WDnNUYMF/9p8u6TqFJBU820cEY8OexJQa 534 | Wt9MevPZQx08EHp5JduQ/vBR5zDWQQD9nyjfeb6Uu522FOMjhdepQeBMpHmwKxqL 535 | 8vg7ij5FrHGSALSQQZj7X+36ty6K+Ig3AgMBAAGjEzARMA8GA1UdEwEB/wQFMAMB 536 | Af8wDQYJKoZIhvcNAQEEBQADgYEAZ9viwuaHPUCDhjc1fR/OmsMMZiCouqoEiYbC 537 | 9RAIDb/LogWK0E02PvTX72nGXuSwlG9KuefeW4i2e9vjJ+V2w/A1wcu1J5szedyQ 538 | pgCed/r8zSeUQhac0xxo7L9c3eWpexAKMnRUEzGLhQOEkbdYATAUOK8oyvyxUBkZ 539 | CayJSdM= 540 | -----END CERTIFICATE----- 541 | 542 | thawte Primary Root CA 543 | ====================== 544 | 545 | -----BEGIN CERTIFICATE----- 546 | MIIEIDCCAwigAwIBAgIQNE7VVyDV7exJ9C/ON9srbTANBgkqhkiG9w0BAQUFADCB 547 | qTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMf 548 | Q2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIw 549 | MDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxHzAdBgNV 550 | BAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwHhcNMDYxMTE3MDAwMDAwWhcNMzYw 551 | NzE2MjM1OTU5WjCBqTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5j 552 | LjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYG 553 | A1UECxMvKGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl 554 | IG9ubHkxHzAdBgNVBAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwggEiMA0GCSqG 555 | SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCsoPD7gFnUnMekz52hWXMJEEUMDSxuaPFs 556 | W0hoSVk3/AszGcJ3f8wQLZU0HObrTQmnHNK4yZc2AreJ1CRfBsDMRJSUjQJib+ta 557 | 3RGNKJpchJAQeg29dGYvajig4tVUROsdB58Hum/u6f1OCyn1PoSgAfGcq/gcfomk 558 | 6KHYcWUNo1F77rzSImANuVud37r8UVsLr5iy6S7pBOhih94ryNdOwUxkHt3Ph1i6 559 | Sk/KaAcdHJ1KxtUvkcx8cXIcxcBn6zL9yZJclNqFwJu/U30rCfSMnZEfl2pSy94J 560 | NqR32HuHUETVPm4pafs5SSYeCaWAe0At6+gnhcn+Yf1+5nyXHdWdAgMBAAGjQjBA 561 | MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBR7W0XP 562 | r87Lev0xkhpqtvNG61dIUDANBgkqhkiG9w0BAQUFAAOCAQEAeRHAS7ORtvzw6WfU 563 | DW5FvlXok9LOAz/t2iWwHVfLHjp2oEzsUHboZHIMpKnxuIvW1oeEuzLlQRHAd9mz 564 | YJ3rG9XRbkREqaYB7FViHXe4XI5ISXycO1cRrK1zN44veFyQaEfZYGDm/Ac9IiAX 565 | xPcW6cTYcvnIc3zfFi8VqT79aie2oetaupgf1eNNZAqdE8hhuvU5HIe6uL17In/2 566 | /qxAeeWsEG89jxt5dovEN7MhGITlNgDrYyCZuen+MwS7QcjBAvlEYyCegc5C09Y/ 567 | LHbTY5xZ3Y+m4Q6gLkH3LpVHz7z9M/P2C2F+fpErgUfCJzDupxBdN49cOSvkBPB7 568 | jVaMaA== 569 | -----END CERTIFICATE----- 570 | 571 | VeriSign Class 3 Public Primary Certification Authority - G5 572 | ============================================================ 573 | 574 | -----BEGIN CERTIFICATE----- 575 | MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCB 576 | yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL 577 | ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJp 578 | U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxW 579 | ZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0 580 | aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCByjEL 581 | MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW 582 | ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2ln 583 | biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJp 584 | U2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9y 585 | aXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvJAgIKXo1 586 | nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKzj/i5Vbex 587 | t0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIz 588 | SdhDY2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQG 589 | BO+QueQA5N06tRn/Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+ 590 | rCpSx4/VBEnkjWNHiDxpg8v+R70rfk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/ 591 | NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8E 592 | BAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEwHzAH 593 | BgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy 594 | aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKv 595 | MzEzMA0GCSqGSIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzE 596 | p6B4Eq1iDkVwZMXnl2YtmAl+X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y 597 | 5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKEKQsTb47bDN0lAtukixlE0kF6BWlK 598 | WE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiCKm0oHw0LxOXnGiYZ 599 | 4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vEZV8N 600 | hnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq 601 | -----END CERTIFICATE----- 602 | 603 | Entrust.net Secure Server Certification Authority 604 | ================================================= 605 | 606 | -----BEGIN CERTIFICATE----- 607 | MIIE2DCCBEGgAwIBAgIEN0rSQzANBgkqhkiG9w0BAQUFADCBwzELMAkGA1UEBhMC 608 | VVMxFDASBgNVBAoTC0VudHJ1c3QubmV0MTswOQYDVQQLEzJ3d3cuZW50cnVzdC5u 609 | ZXQvQ1BTIGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMc 610 | KGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDE6MDgGA1UEAxMxRW50cnVzdC5u 611 | ZXQgU2VjdXJlIFNlcnZlciBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw05OTA1 612 | MjUxNjA5NDBaFw0xOTA1MjUxNjM5NDBaMIHDMQswCQYDVQQGEwJVUzEUMBIGA1UE 613 | ChMLRW50cnVzdC5uZXQxOzA5BgNVBAsTMnd3dy5lbnRydXN0Lm5ldC9DUFMgaW5j 614 | b3JwLiBieSByZWYuIChsaW1pdHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBF 615 | bnRydXN0Lm5ldCBMaW1pdGVkMTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUg 616 | U2VydmVyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGdMA0GCSqGSIb3DQEBAQUA 617 | A4GLADCBhwKBgQDNKIM0VBuJ8w+vN5Ex/68xYMmo6LIQaO2f55M28Qpku0f1BBc/ 618 | I0dNxScZgSYMVHINiC3ZH5oSn7yzcdOAGT9HZnuMNSjSuQrfJNqc1lB5gXpa0zf3 619 | wkrYKZImZNHkmGw6AIr1NJtl+O3jEP/9uElY3KDegjlrgbEWGWG5VLbmQwIBA6OC 620 | AdcwggHTMBEGCWCGSAGG+EIBAQQEAwIABzCCARkGA1UdHwSCARAwggEMMIHeoIHb 621 | oIHYpIHVMIHSMQswCQYDVQQGEwJVUzEUMBIGA1UEChMLRW50cnVzdC5uZXQxOzA5 622 | BgNVBAsTMnd3dy5lbnRydXN0Lm5ldC9DUFMgaW5jb3JwLiBieSByZWYuIChsaW1p 623 | dHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBFbnRydXN0Lm5ldCBMaW1pdGVk 624 | MTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUgU2VydmVyIENlcnRpZmljYXRp 625 | b24gQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMCmgJ6AlhiNodHRwOi8vd3d3LmVu 626 | dHJ1c3QubmV0L0NSTC9uZXQxLmNybDArBgNVHRAEJDAigA8xOTk5MDUyNTE2MDk0 627 | MFqBDzIwMTkwNTI1MTYwOTQwWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAU8Bdi 628 | E1U9s/8KAGv7UISX8+1i0BowHQYDVR0OBBYEFPAXYhNVPbP/CgBr+1CEl/PtYtAa 629 | MAwGA1UdEwQFMAMBAf8wGQYJKoZIhvZ9B0EABAwwChsEVjQuMAMCBJAwDQYJKoZI 630 | hvcNAQEFBQADgYEAkNwwAvpkdMKnCqV8IY00F6j7Rw7/JXyNEwr75Ji174z4xRAN 631 | 95K+8cPV1ZVqBLssziY2ZcgxxufuP+NXdYR6Ee9GTxj005i7qIcyunL2POI9n9cd 632 | 2cNgQ4xYDiKWL2KjLB+6rQXvqzJ4h6BUcxm1XAX5Uj5tLUUL9wqT6u0G+bI= 633 | -----END CERTIFICATE----- 634 | 635 | Go Daddy Certification Authority Root Certificate Bundle 636 | ======================================================== 637 | 638 | -----BEGIN CERTIFICATE----- 639 | MIIE3jCCA8agAwIBAgICAwEwDQYJKoZIhvcNAQEFBQAwYzELMAkGA1UEBhMCVVMx 640 | ITAfBgNVBAoTGFRoZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28g 641 | RGFkZHkgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjExMTYw 642 | MTU0MzdaFw0yNjExMTYwMTU0MzdaMIHKMQswCQYDVQQGEwJVUzEQMA4GA1UECBMH 643 | QXJpem9uYTETMBEGA1UEBxMKU2NvdHRzZGFsZTEaMBgGA1UEChMRR29EYWRkeS5j 644 | b20sIEluYy4xMzAxBgNVBAsTKmh0dHA6Ly9jZXJ0aWZpY2F0ZXMuZ29kYWRkeS5j 645 | b20vcmVwb3NpdG9yeTEwMC4GA1UEAxMnR28gRGFkZHkgU2VjdXJlIENlcnRpZmlj 646 | YXRpb24gQXV0aG9yaXR5MREwDwYDVQQFEwgwNzk2OTI4NzCCASIwDQYJKoZIhvcN 647 | AQEBBQADggEPADCCAQoCggEBAMQt1RWMnCZM7DI161+4WQFapmGBWTtwY6vj3D3H 648 | KrjJM9N55DrtPDAjhI6zMBS2sofDPZVUBJ7fmd0LJR4h3mUpfjWoqVTr9vcyOdQm 649 | VZWt7/v+WIbXnvQAjYwqDL1CBM6nPwT27oDyqu9SoWlm2r4arV3aLGbqGmu75RpR 650 | SgAvSMeYddi5Kcju+GZtCpyz8/x4fKL4o/K1w/O5epHBp+YlLpyo7RJlbmr2EkRT 651 | cDCVw5wrWCs9CHRK8r5RsL+H0EwnWGu1NcWdrxcx+AuP7q2BNgWJCJjPOq8lh8BJ 652 | 6qf9Z/dFjpfMFDniNoW1fho3/Rb2cRGadDAW/hOUoz+EDU8CAwEAAaOCATIwggEu 653 | MB0GA1UdDgQWBBT9rGEyk2xF1uLuhV+auud2mWjM5zAfBgNVHSMEGDAWgBTSxLDS 654 | kdRMEXGzYcs9of7dqGrU4zASBgNVHRMBAf8ECDAGAQH/AgEAMDMGCCsGAQUFBwEB 655 | BCcwJTAjBggrBgEFBQcwAYYXaHR0cDovL29jc3AuZ29kYWRkeS5jb20wRgYDVR0f 656 | BD8wPTA7oDmgN4Y1aHR0cDovL2NlcnRpZmljYXRlcy5nb2RhZGR5LmNvbS9yZXBv 657 | c2l0b3J5L2dkcm9vdC5jcmwwSwYDVR0gBEQwQjBABgRVHSAAMDgwNgYIKwYBBQUH 658 | AgEWKmh0dHA6Ly9jZXJ0aWZpY2F0ZXMuZ29kYWRkeS5jb20vcmVwb3NpdG9yeTAO 659 | BgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQEFBQADggEBANKGwOy9+aG2Z+5mC6IG 660 | OgRQjhVyrEp0lVPLN8tESe8HkGsz2ZbwlFalEzAFPIUyIXvJxwqoJKSQ3kbTJSMU 661 | A2fCENZvD117esyfxVgqwcSeIaha86ykRvOe5GPLL5CkKSkB2XIsKd83ASe8T+5o 662 | 0yGPwLPk9Qnt0hCqU7S+8MxZC9Y7lhyVJEnfzuz9p0iRFEUOOjZv2kWzRaJBydTX 663 | RE4+uXR21aITVSzGh6O1mawGhId/dQb8vxRMDsxuxN89txJx9OjxUUAiKEngHUuH 664 | qDTMBqLdElrRhjZkAzVvb3du6/KFUJheqwNTrZEjYx8WnM25sgVjOuH0aBsXBTWV 665 | U+4= 666 | -----END CERTIFICATE----- 667 | -----BEGIN CERTIFICATE----- 668 | MIIE+zCCBGSgAwIBAgICAQ0wDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1Zh 669 | bGlDZXJ0IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIElu 670 | Yy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIgUG9saWN5IFZhbGlkYXRpb24g 671 | QXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAe 672 | BgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTA0MDYyOTE3MDYyMFoX 673 | DTI0MDYyOTE3MDYyMFowYzELMAkGA1UEBhMCVVMxITAfBgNVBAoTGFRoZSBHbyBE 674 | YWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28gRGFkZHkgQ2xhc3MgMiBDZXJ0 675 | aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQADggENADCCAQgC 676 | ggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCAPVYYYwhv 677 | 2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6wwdhFJ2+q 678 | N1j3hybX2C32qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXiEqITLdiO 679 | r18SPaAIBQi2XKVlOARFmR6jYGB0xUGlcmIbYsUfb18aQr4CUWWoriMYavx4A6lN 680 | f4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmYvLEHZ6IVDd2gWMZEewo+YihfukEH 681 | U1jPEX44dMX4/7VpkI+EdOqXG68CAQOjggHhMIIB3TAdBgNVHQ4EFgQU0sSw0pHU 682 | TBFxs2HLPaH+3ahq1OMwgdIGA1UdIwSByjCBx6GBwaSBvjCBuzEkMCIGA1UEBxMb 683 | VmFsaUNlcnQgVmFsaWRhdGlvbiBOZXR3b3JrMRcwFQYDVQQKEw5WYWxpQ2VydCwg 684 | SW5jLjE1MDMGA1UECxMsVmFsaUNlcnQgQ2xhc3MgMiBQb2xpY3kgVmFsaWRhdGlv 685 | biBBdXRob3JpdHkxITAfBgNVBAMTGGh0dHA6Ly93d3cudmFsaWNlcnQuY29tLzEg 686 | MB4GCSqGSIb3DQEJARYRaW5mb0B2YWxpY2VydC5jb22CAQEwDwYDVR0TAQH/BAUw 687 | AwEB/zAzBggrBgEFBQcBAQQnMCUwIwYIKwYBBQUHMAGGF2h0dHA6Ly9vY3NwLmdv 688 | ZGFkZHkuY29tMEQGA1UdHwQ9MDswOaA3oDWGM2h0dHA6Ly9jZXJ0aWZpY2F0ZXMu 689 | Z29kYWRkeS5jb20vcmVwb3NpdG9yeS9yb290LmNybDBLBgNVHSAERDBCMEAGBFUd 690 | IAAwODA2BggrBgEFBQcCARYqaHR0cDovL2NlcnRpZmljYXRlcy5nb2RhZGR5LmNv 691 | bS9yZXBvc2l0b3J5MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOBgQC1 692 | QPmnHfbq/qQaQlpE9xXUhUaJwL6e4+PrxeNYiY+Sn1eocSxI0YGyeR+sBjUZsE4O 693 | WBsUs5iB0QQeyAfJg594RAoYC5jcdnplDQ1tgMQLARzLrUc+cb53S8wGd9D0Vmsf 694 | SxOaFIqII6hR8INMqzW/Rn453HWkrugp++85j09VZw== 695 | -----END CERTIFICATE----- 696 | -----BEGIN CERTIFICATE----- 697 | MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0 698 | IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAz 699 | BgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9y 700 | aXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG 701 | 9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAwMTk1NFoXDTE5MDYy 702 | NjAwMTk1NFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29y 703 | azEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs 704 | YXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw 705 | Oi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl 706 | cnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOOnHK5avIWZJV16vY 707 | dA757tn2VUdZZUcOBVXc65g2PFxTXdMwzzjsvUGJ7SVCCSRrCl6zfN1SLUzm1NZ9 708 | WlmpZdRJEy0kTRxQb7XBhVQ7/nHk01xC+YDgkRoKWzk2Z/M/VXwbP7RfZHM047QS 709 | v4dk+NoS/zcnwbNDu+97bi5p9wIDAQABMA0GCSqGSIb3DQEBBQUAA4GBADt/UG9v 710 | UJSZSWI4OB9L+KXIPqeCgfYrx+jFzug6EILLGACOTb2oWH+heQC1u+mNr0HZDzTu 711 | IYEZoDJJKPTEjlbVUjP9UNV+mWwD5MlM/Mtsq2azSiGM5bUMMj4QssxsodyamEwC 712 | W/POuZ6lcg5Ktz885hZo+L7tdEy8W9ViH0Pd 713 | -----END CERTIFICATE----- 714 | 715 | -------------------------------------------------------------------------------- /third_party/google-api-php-client/src/service/Google_BatchRequest.php: -------------------------------------------------------------------------------- 1 | 20 | */ 21 | class Google_BatchRequest { 22 | /** @var string Multipart Boundary. */ 23 | private $boundary; 24 | 25 | /** @var array service requests to be executed. */ 26 | private $requests = array(); 27 | 28 | public function __construct($boundary = false) { 29 | $boundary = (false == $boundary) ? mt_rand() : $boundary; 30 | $this->boundary = str_replace('"', '', $boundary); 31 | } 32 | 33 | public function add(Google_HttpRequest $request, $key = false) { 34 | if (false == $key) { 35 | $key = mt_rand(); 36 | } 37 | 38 | $this->requests[$key] = $request; 39 | } 40 | 41 | public function execute() { 42 | $body = ''; 43 | 44 | /** @var Google_HttpRequest $req */ 45 | foreach($this->requests as $key => $req) { 46 | $body .= "--{$this->boundary}\n"; 47 | $body .= $req->toBatchString($key) . "\n"; 48 | } 49 | 50 | $body = rtrim($body); 51 | $body .= "\n--{$this->boundary}--"; 52 | 53 | global $apiConfig; 54 | $url = $apiConfig['basePath'] . '/batch'; 55 | $httpRequest = new Google_HttpRequest($url, 'POST'); 56 | $httpRequest->setRequestHeaders(array( 57 | 'Content-Type' => 'multipart/mixed; boundary=' . $this->boundary)); 58 | 59 | $httpRequest->setPostBody($body); 60 | $response = Google_Client::$io->makeRequest($httpRequest); 61 | 62 | $response = $this->parseResponse($response); 63 | return $response; 64 | } 65 | 66 | public function parseResponse(Google_HttpRequest $response) { 67 | $contentType = $response->getResponseHeader('content-type'); 68 | $contentType = explode(';', $contentType); 69 | $boundary = false; 70 | foreach($contentType as $part) { 71 | $part = (explode('=', $part, 2)); 72 | if (isset($part[0]) && 'boundary' == trim($part[0])) { 73 | $boundary = $part[1]; 74 | } 75 | } 76 | 77 | $body = $response->getResponseBody(); 78 | if ($body) { 79 | $body = str_replace("--$boundary--", "--$boundary", $body); 80 | $parts = explode("--$boundary", $body); 81 | $responses = array(); 82 | 83 | foreach($parts as $part) { 84 | $part = trim($part); 85 | if (!empty($part)) { 86 | list($metaHeaders, $part) = explode("\r\n\r\n", $part, 2); 87 | $metaHeaders = Google_CurlIO::parseResponseHeaders($metaHeaders); 88 | 89 | $status = substr($part, 0, strpos($part, "\n")); 90 | $status = explode(" ", $status); 91 | $status = $status[1]; 92 | 93 | list($partHeaders, $partBody) = Google_CurlIO::parseHttpResponse($part, false); 94 | $response = new Google_HttpRequest(""); 95 | $response->setResponseHttpCode($status); 96 | $response->setResponseHeaders($partHeaders); 97 | $response->setResponseBody($partBody); 98 | $response = Google_REST::decodeHttpResponse($response); 99 | 100 | // Need content id. 101 | $responses[$metaHeaders['content-id']] = $response; 102 | } 103 | } 104 | 105 | return $responses; 106 | } 107 | 108 | return null; 109 | } 110 | } -------------------------------------------------------------------------------- /third_party/google-api-php-client/src/service/Google_MediaFileUpload.php: -------------------------------------------------------------------------------- 1 | 20 | * 21 | */ 22 | class Google_MediaFileUpload { 23 | const UPLOAD_MEDIA_TYPE = 'media'; 24 | const UPLOAD_MULTIPART_TYPE = 'multipart'; 25 | const UPLOAD_RESUMABLE_TYPE = 'resumable'; 26 | 27 | /** @var string $mimeType */ 28 | public $mimeType; 29 | 30 | /** @var string $data */ 31 | public $data; 32 | 33 | /** @var bool $resumable */ 34 | public $resumable; 35 | 36 | /** @var int $chunkSize */ 37 | public $chunkSize; 38 | 39 | /** @var int $size */ 40 | public $size; 41 | 42 | /** @var string $resumeUri */ 43 | public $resumeUri; 44 | 45 | /** @var int $progress */ 46 | public $progress; 47 | 48 | /** 49 | * @param $mimeType string 50 | * @param $data string The bytes you want to upload. 51 | * @param $resumable bool 52 | * @param bool $chunkSize File will be uploaded in chunks of this many bytes. 53 | * only used if resumable=True 54 | */ 55 | public function __construct($mimeType, $data, $resumable=false, $chunkSize=false) { 56 | $this->mimeType = $mimeType; 57 | $this->data = $data; 58 | $this->size = strlen($this->data); 59 | $this->resumable = $resumable; 60 | if(!$chunkSize) { 61 | $this->chunkSize = 256 * 1024; 62 | } 63 | 64 | $this->progress = 0; 65 | } 66 | 67 | /** 68 | * @static 69 | * @param $meta 70 | * @param $params 71 | * @return array|bool 72 | */ 73 | public static function process($meta, &$params) { 74 | $payload = array(); 75 | $meta = is_string($meta) ? json_decode($meta, true) : $meta; 76 | $uploadType = self::getUploadType($meta, $payload, $params); 77 | if (!$uploadType) { 78 | // Process as a normal API request. 79 | return false; 80 | } 81 | 82 | // Process as a media upload request. 83 | $params['uploadType'] = array( 84 | 'type' => 'string', 85 | 'location' => 'query', 86 | 'value' => $uploadType, 87 | ); 88 | 89 | if (isset($params['file'])) { 90 | // This is a standard file upload with curl. 91 | $file = $params['file']['value']; 92 | unset($params['file']); 93 | return self::processFileUpload($file); 94 | } 95 | 96 | $mimeType = isset($params['mimeType']) 97 | ? $params['mimeType']['value'] 98 | : false; 99 | unset($params['mimeType']); 100 | 101 | $data = isset($params['data']) 102 | ? $params['data']['value'] 103 | : false; 104 | unset($params['data']); 105 | 106 | if (self::UPLOAD_RESUMABLE_TYPE == $uploadType) { 107 | $payload['content-type'] = $mimeType; 108 | 109 | } elseif (self::UPLOAD_MEDIA_TYPE == $uploadType) { 110 | // This is a simple media upload. 111 | $payload['content-type'] = $mimeType; 112 | $payload['postBody'] = $data; 113 | } 114 | 115 | elseif (self::UPLOAD_MULTIPART_TYPE == $uploadType) { 116 | // This is a multipart/related upload. 117 | $boundary = isset($params['boundary']['value']) ? $params['boundary']['value'] : mt_rand(); 118 | $boundary = str_replace('"', '', $boundary); 119 | $payload['content-type'] = 'multipart/related; boundary=' . $boundary; 120 | $related = "--$boundary\r\n"; 121 | $related .= "Content-Type: application/json; charset=UTF-8\r\n"; 122 | $related .= "\r\n" . json_encode($meta) . "\r\n"; 123 | $related .= "--$boundary\r\n"; 124 | $related .= "Content-Type: $mimeType\r\n"; 125 | $related .= "Content-Transfer-Encoding: base64\r\n"; 126 | $related .= "\r\n" . base64_encode($data) . "\r\n"; 127 | $related .= "--$boundary--"; 128 | $payload['postBody'] = $related; 129 | } 130 | 131 | return $payload; 132 | } 133 | 134 | /** 135 | * Process standard file uploads. 136 | * @param $file 137 | * @internal param $fileName 138 | * @return array Inclues the processed file name. 139 | * @visible For testing. 140 | */ 141 | public static function processFileUpload($file) { 142 | if (!$file) return array(); 143 | if (substr($file, 0, 1) != '@') { 144 | $file = '@' . $file; 145 | } 146 | 147 | // This is a standard file upload with curl. 148 | return array('postBody' => array('file' => $file)); 149 | } 150 | 151 | /** 152 | * Valid upload types: 153 | * - resumable (UPLOAD_RESUMABLE_TYPE) 154 | * - media (UPLOAD_MEDIA_TYPE) 155 | * - multipart (UPLOAD_MULTIPART_TYPE) 156 | * - none (false) 157 | * @param $meta 158 | * @param $payload 159 | * @param $params 160 | * @return bool|string 161 | */ 162 | public static function getUploadType($meta, &$payload, &$params) { 163 | if (isset($params['mediaUpload']) 164 | && get_class($params['mediaUpload']['value']) == 'Google_MediaFileUpload') { 165 | $upload = $params['mediaUpload']['value']; 166 | unset($params['mediaUpload']); 167 | $payload['content-type'] = $upload->mimeType; 168 | if (isset($upload->resumable) && $upload->resumable) { 169 | return self::UPLOAD_RESUMABLE_TYPE; 170 | } 171 | } 172 | 173 | // Allow the developer to override the upload type. 174 | if (isset($params['uploadType'])) { 175 | return $params['uploadType']['value']; 176 | } 177 | 178 | $data = isset($params['data']['value']) 179 | ? $params['data']['value'] : false; 180 | 181 | if (false == $data && false == isset($params['file'])) { 182 | // No upload data available. 183 | return false; 184 | } 185 | 186 | if (isset($params['file'])) { 187 | return self::UPLOAD_MEDIA_TYPE; 188 | } 189 | 190 | if (false == $meta) { 191 | return self::UPLOAD_MEDIA_TYPE; 192 | } 193 | 194 | return self::UPLOAD_MULTIPART_TYPE; 195 | } 196 | 197 | 198 | public function nextChunk(Google_HttpRequest $req) { 199 | if (false == $this->resumeUri) { 200 | $this->resumeUri = $this->getResumeUri($req); 201 | } 202 | 203 | $data = substr($this->data, $this->progress, $this->chunkSize); 204 | $lastBytePos = $this->progress + strlen($data) - 1; 205 | $headers = array( 206 | 'content-range' => "bytes $this->progress-$lastBytePos/$this->size", 207 | 'content-type' => $req->getRequestHeader('content-type'), 208 | 'content-length' => $this->chunkSize, 209 | 'expect' => '', 210 | ); 211 | 212 | $httpRequest = new Google_HttpRequest($this->resumeUri, 'PUT', $headers, $data); 213 | $response = Google_Client::$io->authenticatedRequest($httpRequest); 214 | $code = $response->getResponseHttpCode(); 215 | if (308 == $code) { 216 | $range = explode('-', $response->getResponseHeader('range')); 217 | $this->progress = $range[1] + 1; 218 | return false; 219 | } else { 220 | return Google_REST::decodeHttpResponse($response); 221 | } 222 | } 223 | 224 | private function getResumeUri(Google_HttpRequest $httpRequest) { 225 | $result = null; 226 | $body = $httpRequest->getPostBody(); 227 | if ($body) { 228 | $httpRequest->setRequestHeaders(array( 229 | 'content-type' => 'application/json; charset=UTF-8', 230 | 'content-length' => Google_Utils::getStrLen($body), 231 | 'x-upload-content-type' => $this->mimeType, 232 | 'expect' => '', 233 | )); 234 | } 235 | 236 | $response = Google_Client::$io->makeRequest($httpRequest); 237 | $location = $response->getResponseHeader('location'); 238 | $code = $response->getResponseHttpCode(); 239 | if (200 == $code && true == $location) { 240 | return $location; 241 | } 242 | throw new Google_Exception("Failed to start the resumable upload"); 243 | } 244 | } -------------------------------------------------------------------------------- /third_party/google-api-php-client/src/service/Google_Model.php: -------------------------------------------------------------------------------- 1 | 23 | * 24 | */ 25 | class Google_Model { 26 | public function __construct( /* polymorphic */ ) { 27 | if (func_num_args() == 1 && is_array(func_get_arg(0))) { 28 | // Initialize the model with the array's contents. 29 | $array = func_get_arg(0); 30 | $this->mapTypes($array); 31 | } 32 | } 33 | 34 | /** 35 | * Initialize this object's properties from an array. 36 | * 37 | * @param array $array Used to seed this object's properties. 38 | * @return void 39 | */ 40 | protected function mapTypes($array) { 41 | foreach ($array as $key => $val) { 42 | $this->$key = $val; 43 | 44 | $keyTypeName = "__$key" . 'Type'; 45 | $keyDataType = "__$key" . 'DataType'; 46 | if ($this->useObjects() && property_exists($this, $keyTypeName)) { 47 | if ($this->isAssociativeArray($val)) { 48 | if (isset($this->$keyDataType) && 'map' == $this->$keyDataType) { 49 | foreach($val as $arrayKey => $arrayItem) { 50 | $val[$arrayKey] = $this->createObjectFromName($keyTypeName, $arrayItem); 51 | } 52 | $this->$key = $val; 53 | } else { 54 | $this->$key = $this->createObjectFromName($keyTypeName, $val); 55 | } 56 | } else if (is_array($val)) { 57 | $arrayObject = array(); 58 | foreach ($val as $arrayIndex => $arrayItem) { 59 | $arrayObject[$arrayIndex] = $this->createObjectFromName($keyTypeName, $arrayItem); 60 | } 61 | $this->$key = $arrayObject; 62 | } 63 | } 64 | } 65 | } 66 | 67 | /** 68 | * Returns true only if the array is associative. 69 | * @param array $array 70 | * @return bool True if the array is associative. 71 | */ 72 | protected function isAssociativeArray($array) { 73 | if (!is_array($array)) { 74 | return false; 75 | } 76 | $keys = array_keys($array); 77 | foreach($keys as $key) { 78 | if (is_string($key)) { 79 | return true; 80 | } 81 | } 82 | return false; 83 | } 84 | 85 | /** 86 | * Given a variable name, discover its type. 87 | * 88 | * @param $name 89 | * @param $item 90 | * @return object The object from the item. 91 | */ 92 | private function createObjectFromName($name, $item) { 93 | $type = $this->$name; 94 | return new $type($item); 95 | } 96 | 97 | protected function useObjects() { 98 | global $apiConfig; 99 | return (isset($apiConfig['use_objects']) && $apiConfig['use_objects']); 100 | } 101 | 102 | /** 103 | * Verify if $obj is an array. 104 | * @throws Google_Exception Thrown if $obj isn't an array. 105 | * @param array $obj Items that should be validated. 106 | * @param string $type Array items should be of this type. 107 | * @param string $method Method expecting an array as an argument. 108 | */ 109 | public function assertIsArray($obj, $type, $method) { 110 | if ($obj && !is_array($obj)) { 111 | throw new Google_Exception("Incorrect parameter type passed to $method(), expected an" 112 | . " array containing items of type $type."); 113 | } 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /third_party/google-api-php-client/src/service/Google_Service.php: -------------------------------------------------------------------------------- 1 | 24 | * @author Chirag Shah 25 | * 26 | */ 27 | class Google_ServiceResource { 28 | // Valid query parameters that work, but don't appear in discovery. 29 | private $stackParameters = array( 30 | 'alt' => array('type' => 'string', 'location' => 'query'), 31 | 'boundary' => array('type' => 'string', 'location' => 'query'), 32 | 'fields' => array('type' => 'string', 'location' => 'query'), 33 | 'trace' => array('type' => 'string', 'location' => 'query'), 34 | 'userIp' => array('type' => 'string', 'location' => 'query'), 35 | 'userip' => array('type' => 'string', 'location' => 'query'), 36 | 'file' => array('type' => 'complex', 'location' => 'body'), 37 | 'data' => array('type' => 'string', 'location' => 'body'), 38 | 'mimeType' => array('type' => 'string', 'location' => 'header'), 39 | 'uploadType' => array('type' => 'string', 'location' => 'query'), 40 | 'mediaUpload' => array('type' => 'complex', 'location' => 'query'), 41 | ); 42 | 43 | /** @var Google_Service $service */ 44 | private $service; 45 | 46 | /** @var string $serviceName */ 47 | private $serviceName; 48 | 49 | /** @var string $resourceName */ 50 | private $resourceName; 51 | 52 | /** @var array $methods */ 53 | private $methods; 54 | 55 | public function __construct($service, $serviceName, $resourceName, $resource) { 56 | $this->service = $service; 57 | $this->serviceName = $serviceName; 58 | $this->resourceName = $resourceName; 59 | $this->methods = isset($resource['methods']) ? $resource['methods'] : array($resourceName => $resource); 60 | } 61 | 62 | /** 63 | * @param $name 64 | * @param $arguments 65 | * @return Google_HttpRequest|array 66 | * @throws Google_Exception 67 | */ 68 | public function __call($name, $arguments) { 69 | if (! isset($this->methods[$name])) { 70 | throw new Google_Exception("Unknown function: {$this->serviceName}->{$this->resourceName}->{$name}()"); 71 | } 72 | $method = $this->methods[$name]; 73 | $parameters = $arguments[0]; 74 | 75 | // 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 76 | $postBody = null; 77 | if (isset($parameters['postBody'])) { 78 | if (is_object($parameters['postBody'])) { 79 | $this->stripNull($parameters['postBody']); 80 | } 81 | 82 | // Some APIs require the postBody to be set under the data key. 83 | if (is_array($parameters['postBody']) && 'latitude' == $this->serviceName) { 84 | if (!isset($parameters['postBody']['data'])) { 85 | $rawBody = $parameters['postBody']; 86 | unset($parameters['postBody']); 87 | $parameters['postBody']['data'] = $rawBody; 88 | } 89 | } 90 | 91 | $postBody = is_array($parameters['postBody']) || is_object($parameters['postBody']) 92 | ? json_encode($parameters['postBody']) 93 | : $parameters['postBody']; 94 | unset($parameters['postBody']); 95 | 96 | if (isset($parameters['optParams'])) { 97 | $optParams = $parameters['optParams']; 98 | unset($parameters['optParams']); 99 | $parameters = array_merge($parameters, $optParams); 100 | } 101 | } 102 | 103 | if (!isset($method['parameters'])) { 104 | $method['parameters'] = array(); 105 | } 106 | 107 | $method['parameters'] = array_merge($method['parameters'], $this->stackParameters); 108 | foreach ($parameters as $key => $val) { 109 | if ($key != 'postBody' && ! isset($method['parameters'][$key])) { 110 | throw new Google_Exception("($name) unknown parameter: '$key'"); 111 | } 112 | } 113 | if (isset($method['parameters'])) { 114 | foreach ($method['parameters'] as $paramName => $paramSpec) { 115 | if (isset($paramSpec['required']) && $paramSpec['required'] && ! isset($parameters[$paramName])) { 116 | throw new Google_Exception("($name) missing required param: '$paramName'"); 117 | } 118 | if (isset($parameters[$paramName])) { 119 | $value = $parameters[$paramName]; 120 | $parameters[$paramName] = $paramSpec; 121 | $parameters[$paramName]['value'] = $value; 122 | unset($parameters[$paramName]['required']); 123 | } else { 124 | unset($parameters[$paramName]); 125 | } 126 | } 127 | } 128 | 129 | // Discovery v1.0 puts the canonical method id under the 'id' field. 130 | if (! isset($method['id'])) { 131 | $method['id'] = $method['rpcMethod']; 132 | } 133 | 134 | // Discovery v1.0 puts the canonical path under the 'path' field. 135 | if (! isset($method['path'])) { 136 | $method['path'] = $method['restPath']; 137 | } 138 | 139 | $servicePath = $this->service->servicePath; 140 | 141 | // Process Media Request 142 | $contentType = false; 143 | if (isset($method['mediaUpload'])) { 144 | $media = Google_MediaFileUpload::process($postBody, $parameters); 145 | if ($media) { 146 | $contentType = isset($media['content-type']) ? $media['content-type']: null; 147 | $postBody = isset($media['postBody']) ? $media['postBody'] : null; 148 | $servicePath = $method['mediaUpload']['protocols']['simple']['path']; 149 | $method['path'] = ''; 150 | } 151 | } 152 | 153 | $url = Google_REST::createRequestUri($servicePath, $method['path'], $parameters); 154 | $httpRequest = new Google_HttpRequest($url, $method['httpMethod'], null, $postBody); 155 | if ($postBody) { 156 | $contentTypeHeader = array(); 157 | if (isset($contentType) && $contentType) { 158 | $contentTypeHeader['content-type'] = $contentType; 159 | } else { 160 | $contentTypeHeader['content-type'] = 'application/json; charset=UTF-8'; 161 | $contentTypeHeader['content-length'] = Google_Utils::getStrLen($postBody); 162 | } 163 | $httpRequest->setRequestHeaders($contentTypeHeader); 164 | } 165 | 166 | $httpRequest = Google_Client::$auth->sign($httpRequest); 167 | if (Google_Client::$useBatch) { 168 | return $httpRequest; 169 | } 170 | 171 | // Terminate immediatly if this is a resumable request. 172 | if (isset($parameters['uploadType']['value']) 173 | && 'resumable' == $parameters['uploadType']['value']) { 174 | return $httpRequest; 175 | } 176 | 177 | return Google_REST::execute($httpRequest); 178 | } 179 | 180 | public function useObjects() { 181 | global $apiConfig; 182 | return (isset($apiConfig['use_objects']) && $apiConfig['use_objects']); 183 | } 184 | 185 | protected function stripNull(&$o) { 186 | $o = (array) $o; 187 | foreach ($o as $k => $v) { 188 | if ($v === null || strstr($k, "\0*\0__")) { 189 | unset($o[$k]); 190 | } 191 | elseif (is_object($v) || is_array($v)) { 192 | $this->stripNull($o[$k]); 193 | } 194 | } 195 | } 196 | } 197 | -------------------------------------------------------------------------------- /third_party/google-api-php-client/src/service/Google_Utils.php: -------------------------------------------------------------------------------- 1 | 23 | */ 24 | class Google_Utils { 25 | public static function urlSafeB64Encode($data) { 26 | $b64 = base64_encode($data); 27 | $b64 = str_replace(array('+', '/', '\r', '\n', '='), 28 | array('-', '_'), 29 | $b64); 30 | return $b64; 31 | } 32 | 33 | public static function urlSafeB64Decode($b64) { 34 | $b64 = str_replace(array('-', '_'), 35 | array('+', '/'), 36 | $b64); 37 | return base64_decode($b64); 38 | } 39 | 40 | /** 41 | * Misc function used to count the number of bytes in a post body, in the world of multi-byte chars 42 | * and the unpredictability of strlen/mb_strlen/sizeof, this is the only way to do that in a sane 43 | * manner at the moment. 44 | * 45 | * This algorithm was originally developed for the 46 | * Solar Framework by Paul M. Jones 47 | * 48 | * @link http://solarphp.com/ 49 | * @link http://svn.solarphp.com/core/trunk/Solar/Json.php 50 | * @link http://framework.zend.com/svn/framework/standard/trunk/library/Zend/Json/Decoder.php 51 | * @param string $str 52 | * @return int The number of bytes in a string. 53 | */ 54 | static public function getStrLen($str) { 55 | $strlenVar = strlen($str); 56 | $d = $ret = 0; 57 | for ($count = 0; $count < $strlenVar; ++ $count) { 58 | $ordinalValue = ord($str{$ret}); 59 | switch (true) { 60 | case (($ordinalValue >= 0x20) && ($ordinalValue <= 0x7F)): 61 | // characters U-00000000 - U-0000007F (same as ASCII) 62 | $ret ++; 63 | break; 64 | 65 | case (($ordinalValue & 0xE0) == 0xC0): 66 | // characters U-00000080 - U-000007FF, mask 110XXXXX 67 | // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 68 | $ret += 2; 69 | break; 70 | 71 | case (($ordinalValue & 0xF0) == 0xE0): 72 | // characters U-00000800 - U-0000FFFF, mask 1110XXXX 73 | // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 74 | $ret += 3; 75 | break; 76 | 77 | case (($ordinalValue & 0xF8) == 0xF0): 78 | // characters U-00010000 - U-001FFFFF, mask 11110XXX 79 | // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 80 | $ret += 4; 81 | break; 82 | 83 | case (($ordinalValue & 0xFC) == 0xF8): 84 | // characters U-00200000 - U-03FFFFFF, mask 111110XX 85 | // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 86 | $ret += 5; 87 | break; 88 | 89 | case (($ordinalValue & 0xFE) == 0xFC): 90 | // characters U-04000000 - U-7FFFFFFF, mask 1111110X 91 | // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 92 | $ret += 6; 93 | break; 94 | default: 95 | $ret ++; 96 | } 97 | } 98 | return $ret; 99 | } 100 | 101 | /** 102 | * Normalize all keys in an array to lower-case. 103 | * @param array $arr 104 | * @return array Normalized array. 105 | */ 106 | public static function normalize($arr) { 107 | if (!is_array($arr)) { 108 | return array(); 109 | } 110 | 111 | $normalized = array(); 112 | foreach ($arr as $key => $val) { 113 | $normalized[strtolower($key)] = $val; 114 | } 115 | return $normalized; 116 | } 117 | } --------------------------------------------------------------------------------