Version Description
Better organized config pages.
Uses latest Google client library.
Option to link to wp-glogin.com from login page.
Download this release
Release Info
Developer | danlester |
Plugin | Google Apps Login |
Version | 2.3 |
Comparing to | |
See all releases |
Code changes from version 2.2 to 2.3
- googleclient/auth/Google_Auth.php → core/Google/Auth/Abstract.php +14 -9
- googleclient/auth/Google_AssertionCredentials.php → core/Google/Auth/AssertionCredentials.php +37 -7
- core/Google/Auth/Exception.php +22 -0
- googleclient/auth/Google_LoginTicket.php → core/Google/Auth/LoginTicket.php +13 -7
- core/Google/Auth/OAuth2.php +587 -0
- core/Google/Auth/Simple.php +92 -0
- core/Google/CONTRIBUTING.md +22 -0
- googleclient/cache/Google_Cache.php → core/Google/Cache/Abstract.php +7 -9
- core/Google/Cache/Apc.php +73 -0
- core/Google/Cache/Exception.php +21 -0
- core/Google/Cache/File.php +145 -0
- core/Google/Cache/Memcache.php +137 -0
- core/Google/Cache/Null.php +56 -0
- core/Google/Client.php +608 -0
- core/Google/Collection.php +94 -0
- core/Google/Config.php +315 -0
- googleclient/service/Google_Service.php → core/Google/Exception.php +3 -5
- googleclient/service/Google_BatchRequest.php → core/Google/Http/Batch.php +56 -23
- googleclient/io/Google_CacheParser.php → core/Google/Http/CacheParser.php +24 -13
- core/Google/Http/MediaFileUpload.php +292 -0
- googleclient/io/Google_REST.php → core/Google/Http/REST.php +43 -32
- core/Google/Http/Request.php +476 -0
- core/Google/IO/Abstract.php +312 -0
- core/Google/IO/Curl.php +135 -0
- core/Google/IO/Exception.php +22 -0
- core/Google/IO/Stream.php +182 -0
- core/Google/IO/cacerts.pem +2183 -0
- {googleclient → core/Google}/LICENSE +0 -0
- core/Google/Model.php +247 -0
- core/Google/README.md +59 -0
- core/Google/Service.php +39 -0
- core/Google/Service/AdExchangeBuyer.php +1288 -0
- core/Google/Service/AdExchangeSeller.php +1996 -0
- core/Google/Service/AdSense.php +3770 -0
- core/Google/Service/AdSenseHost.php +2281 -0
- core/Google/Service/Admin.php +207 -0
- core/Google/Service/Analytics.php +7769 -0
- core/Google/Service/AndroidPublisher.php +330 -0
- core/Google/Service/AppState.php +373 -0
- core/Google/Service/Audit.php +438 -0
- core/Google/Service/Bigquery.php +3368 -0
- core/Google/Service/Blogger.php +3315 -0
- core/Google/Service/Books.php +4082 -0
googleclient/auth/Google_Auth.php → core/Google/Auth/Abstract.php
RENAMED
@@ -14,23 +14,28 @@
|
|
14 |
* See the License for the specific language governing permissions and
|
15 |
* limitations under the License.
|
16 |
*/
|
17 |
-
|
18 |
-
require_once "Google_AuthNone.php";
|
19 |
-
require_once "Google_OAuth2.php";
|
20 |
|
21 |
/**
|
22 |
* Abstract class for the Authentication in the API client
|
23 |
* @author Chris Chabot <chabotc@google.com>
|
24 |
*
|
25 |
*/
|
26 |
-
abstract class
|
27 |
-
|
28 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
}
|
14 |
* See the License for the specific language governing permissions and
|
15 |
* limitations under the License.
|
16 |
*/
|
17 |
+
require_once "Google/Http/Request.php";
|
|
|
|
|
18 |
|
19 |
/**
|
20 |
* Abstract class for the Authentication in the API client
|
21 |
* @author Chris Chabot <chabotc@google.com>
|
22 |
*
|
23 |
*/
|
24 |
+
abstract class Google_Auth_Abstract
|
25 |
+
{
|
26 |
+
/**
|
27 |
+
* An utility function that first calls $this->auth->sign($request) and then
|
28 |
+
* executes makeRequest() on that signed request. Used for when a request
|
29 |
+
* should be authenticated
|
30 |
+
* @param Google_Http_Request $request
|
31 |
+
* @return Google_Http_Request $request
|
32 |
+
*/
|
33 |
+
abstract public function authenticatedRequest(Google_Http_Request $request);
|
34 |
+
|
35 |
+
abstract public function authenticate($code);
|
36 |
+
abstract public function sign(Google_Http_Request $request);
|
37 |
abstract public function createAuthUrl($scope);
|
38 |
|
|
|
|
|
|
|
39 |
abstract public function refreshToken($refreshToken);
|
40 |
abstract public function revokeToken();
|
41 |
}
|
googleclient/auth/Google_AssertionCredentials.php → core/Google/Auth/AssertionCredentials.php
RENAMED
@@ -15,12 +15,17 @@
|
|
15 |
* limitations under the License.
|
16 |
*/
|
17 |
|
|
|
|
|
|
|
|
|
18 |
/**
|
19 |
* Credentials object used for OAuth 2.0 Signed JWT assertion grants.
|
20 |
*
|
21 |
* @author Chirag Shah <chirags@google.com>
|
22 |
*/
|
23 |
-
class
|
|
|
24 |
const MAX_TOKEN_LIFETIME_SECS = 3600;
|
25 |
|
26 |
public $serviceAccountName;
|
@@ -34,6 +39,7 @@ class Google_AssertionCredentials {
|
|
34 |
* @link http://tools.ietf.org/html/draft-ietf-oauth-json-web-token-06
|
35 |
*/
|
36 |
public $prn;
|
|
|
37 |
|
38 |
/**
|
39 |
* @param $serviceAccountName
|
@@ -42,7 +48,9 @@ class Google_AssertionCredentials {
|
|
42 |
* @param string $privateKeyPassword
|
43 |
* @param string $assertionType
|
44 |
* @param bool|string $sub The email address of the user for which the
|
45 |
-
*
|
|
|
|
|
46 |
*/
|
47 |
public function __construct(
|
48 |
$serviceAccountName,
|
@@ -50,7 +58,9 @@ class Google_AssertionCredentials {
|
|
50 |
$privateKey,
|
51 |
$privateKeyPassword = 'notasecret',
|
52 |
$assertionType = 'http://oauth.net/grant_type/jwt/1.0/bearer',
|
53 |
-
$sub = false
|
|
|
|
|
54 |
$this->serviceAccountName = $serviceAccountName;
|
55 |
$this->scopes = is_string($scopes) ? $scopes : implode(' ', $scopes);
|
56 |
$this->privateKey = $privateKey;
|
@@ -58,13 +68,32 @@ class Google_AssertionCredentials {
|
|
58 |
$this->assertionType = $assertionType;
|
59 |
$this->sub = $sub;
|
60 |
$this->prn = $sub;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
61 |
}
|
62 |
|
63 |
-
public function generateAssertion()
|
|
|
64 |
$now = time();
|
65 |
|
66 |
$jwtParams = array(
|
67 |
-
'aud' =>
|
68 |
'scope' => $this->scopes,
|
69 |
'iat' => $now,
|
70 |
'exp' => $now + self::MAX_TOKEN_LIFETIME_SECS,
|
@@ -85,7 +114,8 @@ class Google_AssertionCredentials {
|
|
85 |
* @param array $payload
|
86 |
* @return string The signed JWT.
|
87 |
*/
|
88 |
-
private function makeSignedJwt($payload)
|
|
|
89 |
$header = array('typ' => 'JWT', 'alg' => 'RS256');
|
90 |
|
91 |
$segments = array(
|
@@ -94,7 +124,7 @@ class Google_AssertionCredentials {
|
|
94 |
);
|
95 |
|
96 |
$signingInput = implode('.', $segments);
|
97 |
-
$signer = new
|
98 |
$signature = $signer->sign($signingInput);
|
99 |
$segments[] = Google_Utils::urlSafeB64Encode($signature);
|
100 |
|
15 |
* limitations under the License.
|
16 |
*/
|
17 |
|
18 |
+
require_once "Google/Auth/OAuth2.php";
|
19 |
+
require_once "Google/Signer/P12.php";
|
20 |
+
require_once "Google/Utils.php";
|
21 |
+
|
22 |
/**
|
23 |
* Credentials object used for OAuth 2.0 Signed JWT assertion grants.
|
24 |
*
|
25 |
* @author Chirag Shah <chirags@google.com>
|
26 |
*/
|
27 |
+
class Google_Auth_AssertionCredentials
|
28 |
+
{
|
29 |
const MAX_TOKEN_LIFETIME_SECS = 3600;
|
30 |
|
31 |
public $serviceAccountName;
|
39 |
* @link http://tools.ietf.org/html/draft-ietf-oauth-json-web-token-06
|
40 |
*/
|
41 |
public $prn;
|
42 |
+
private $useCache;
|
43 |
|
44 |
/**
|
45 |
* @param $serviceAccountName
|
48 |
* @param string $privateKeyPassword
|
49 |
* @param string $assertionType
|
50 |
* @param bool|string $sub The email address of the user for which the
|
51 |
+
* application is requesting delegated access.
|
52 |
+
* @param bool useCache Whether to generate a cache key and allow
|
53 |
+
* automatic caching of the generated token.
|
54 |
*/
|
55 |
public function __construct(
|
56 |
$serviceAccountName,
|
58 |
$privateKey,
|
59 |
$privateKeyPassword = 'notasecret',
|
60 |
$assertionType = 'http://oauth.net/grant_type/jwt/1.0/bearer',
|
61 |
+
$sub = false,
|
62 |
+
$useCache = true
|
63 |
+
) {
|
64 |
$this->serviceAccountName = $serviceAccountName;
|
65 |
$this->scopes = is_string($scopes) ? $scopes : implode(' ', $scopes);
|
66 |
$this->privateKey = $privateKey;
|
68 |
$this->assertionType = $assertionType;
|
69 |
$this->sub = $sub;
|
70 |
$this->prn = $sub;
|
71 |
+
$this->useCache = $useCache;
|
72 |
+
}
|
73 |
+
|
74 |
+
/**
|
75 |
+
* Generate a unique key to represent this credential.
|
76 |
+
* @return string
|
77 |
+
*/
|
78 |
+
public function getCacheKey()
|
79 |
+
{
|
80 |
+
if (!$this->useCache) {
|
81 |
+
return false;
|
82 |
+
}
|
83 |
+
$h = $this->sub;
|
84 |
+
$h .= $this->assertionType;
|
85 |
+
$h .= $this->privateKey;
|
86 |
+
$h .= $this->scopes;
|
87 |
+
$h .= $this->serviceAccountName;
|
88 |
+
return md5($h);
|
89 |
}
|
90 |
|
91 |
+
public function generateAssertion()
|
92 |
+
{
|
93 |
$now = time();
|
94 |
|
95 |
$jwtParams = array(
|
96 |
+
'aud' => Google_Auth_OAuth2::OAUTH2_TOKEN_URI,
|
97 |
'scope' => $this->scopes,
|
98 |
'iat' => $now,
|
99 |
'exp' => $now + self::MAX_TOKEN_LIFETIME_SECS,
|
114 |
* @param array $payload
|
115 |
* @return string The signed JWT.
|
116 |
*/
|
117 |
+
private function makeSignedJwt($payload)
|
118 |
+
{
|
119 |
$header = array('typ' => 'JWT', 'alg' => 'RS256');
|
120 |
|
121 |
$segments = array(
|
124 |
);
|
125 |
|
126 |
$signingInput = implode('.', $segments);
|
127 |
+
$signer = new Google_Signer_P12($this->privateKey, $this->privateKeyPassword);
|
128 |
$signature = $signer->sign($signingInput);
|
129 |
$segments[] = Google_Utils::urlSafeB64Encode($signature);
|
130 |
|
core/Google/Auth/Exception.php
ADDED
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* Copyright 2013 Google Inc.
|
4 |
+
*
|
5 |
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
6 |
+
* you may not use this file except in compliance with the License.
|
7 |
+
* You may obtain a copy of the License at
|
8 |
+
*
|
9 |
+
* http://www.apache.org/licenses/LICENSE-2.0
|
10 |
+
*
|
11 |
+
* Unless required by applicable law or agreed to in writing, software
|
12 |
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
13 |
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14 |
+
* See the License for the specific language governing permissions and
|
15 |
+
* limitations under the License.
|
16 |
+
*/
|
17 |
+
|
18 |
+
require_once "Google/Exception.php";
|
19 |
+
|
20 |
+
class Google_Auth_Exception extends Google_Exception
|
21 |
+
{
|
22 |
+
}
|
googleclient/auth/Google_LoginTicket.php → core/Google/Auth/LoginTicket.php
RENAMED
@@ -15,13 +15,16 @@
|
|
15 |
* limitations under the License.
|
16 |
*/
|
17 |
|
|
|
|
|
18 |
/**
|
19 |
* Class to hold information about an authenticated login.
|
20 |
*
|
21 |
* @author Brian Eaton <beaton@google.com>
|
22 |
*/
|
23 |
-
class
|
24 |
-
|
|
|
25 |
|
26 |
// Information from id token envelope.
|
27 |
private $envelope;
|
@@ -35,21 +38,23 @@ class Google_LoginTicket {
|
|
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
|
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
|
53 |
}
|
54 |
|
55 |
/**
|
@@ -57,7 +62,8 @@ class Google_LoginTicket {
|
|
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 |
}
|
15 |
* limitations under the License.
|
16 |
*/
|
17 |
|
18 |
+
require_once "Google/Auth/Exception.php";
|
19 |
+
|
20 |
/**
|
21 |
* Class to hold information about an authenticated login.
|
22 |
*
|
23 |
* @author Brian Eaton <beaton@google.com>
|
24 |
*/
|
25 |
+
class Google_Auth_LoginTicket
|
26 |
+
{
|
27 |
+
const USER_ATTR = "sub";
|
28 |
|
29 |
// Information from id token envelope.
|
30 |
private $envelope;
|
38 |
* @param string $envelope Header from a verified authentication token.
|
39 |
* @param string $payload Information from a verified authentication token.
|
40 |
*/
|
41 |
+
public function __construct($envelope, $payload)
|
42 |
+
{
|
43 |
$this->envelope = $envelope;
|
44 |
$this->payload = $payload;
|
45 |
}
|
46 |
|
47 |
/**
|
48 |
* Returns the numeric identifier for the user.
|
49 |
+
* @throws Google_Auth_Exception
|
50 |
* @return
|
51 |
*/
|
52 |
+
public function getUserId()
|
53 |
+
{
|
54 |
if (array_key_exists(self::USER_ATTR, $this->payload)) {
|
55 |
return $this->payload[self::USER_ATTR];
|
56 |
}
|
57 |
+
throw new Google_Auth_Exception("No user_id in token");
|
58 |
}
|
59 |
|
60 |
/**
|
62 |
* various information about the user session.
|
63 |
* @return array
|
64 |
*/
|
65 |
+
public function getAttributes()
|
66 |
+
{
|
67 |
return array("envelope" => $this->envelope, "payload" => $this->payload);
|
68 |
}
|
69 |
}
|
core/Google/Auth/OAuth2.php
ADDED
@@ -0,0 +1,587 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* Copyright 2008 Google Inc.
|
4 |
+
*
|
5 |
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
6 |
+
* you may not use this file except in compliance with the License.
|
7 |
+
* You may obtain a copy of the License at
|
8 |
+
*
|
9 |
+
* http://www.apache.org/licenses/LICENSE-2.0
|
10 |
+
*
|
11 |
+
* Unless required by applicable law or agreed to in writing, software
|
12 |
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
13 |
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14 |
+
* See the License for the specific language governing permissions and
|
15 |
+
* limitations under the License.
|
16 |
+
*/
|
17 |
+
|
18 |
+
require_once "Google/Auth/Abstract.php";
|
19 |
+
require_once "Google/Auth/AssertionCredentials.php";
|
20 |
+
require_once "Google/Auth/Exception.php";
|
21 |
+
require_once "Google/Auth/LoginTicket.php";
|
22 |
+
require_once "Google/Client.php";
|
23 |
+
require_once "Google/Http/Request.php";
|
24 |
+
require_once "Google/Utils.php";
|
25 |
+
require_once "Google/Verifier/Pem.php";
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Authentication class that deals with the OAuth 2 web-server authentication flow
|
29 |
+
*
|
30 |
+
* @author Chris Chabot <chabotc@google.com>
|
31 |
+
* @author Chirag Shah <chirags@google.com>
|
32 |
+
*
|
33 |
+
*/
|
34 |
+
class Google_Auth_OAuth2 extends Google_Auth_Abstract
|
35 |
+
{
|
36 |
+
const OAUTH2_REVOKE_URI = 'https://accounts.google.com/o/oauth2/revoke';
|
37 |
+
const OAUTH2_TOKEN_URI = 'https://accounts.google.com/o/oauth2/token';
|
38 |
+
const OAUTH2_AUTH_URL = 'https://accounts.google.com/o/oauth2/auth';
|
39 |
+
const CLOCK_SKEW_SECS = 300; // five minutes in seconds
|
40 |
+
const AUTH_TOKEN_LIFETIME_SECS = 300; // five minutes in seconds
|
41 |
+
const MAX_TOKEN_LIFETIME_SECS = 86400; // one day in seconds
|
42 |
+
const OAUTH2_ISSUER = 'accounts.google.com';
|
43 |
+
|
44 |
+
/** @var Google_Auth_AssertionCredentials $assertionCredentials */
|
45 |
+
private $assertionCredentials;
|
46 |
+
|
47 |
+
/**
|
48 |
+
* @var string The state parameters for CSRF and other forgery protection.
|
49 |
+
*/
|
50 |
+
private $state;
|
51 |
+
|
52 |
+
/**
|
53 |
+
* @var array The token bundle.
|
54 |
+
*/
|
55 |
+
private $token = array();
|
56 |
+
|
57 |
+
/**
|
58 |
+
* @var Google_Client the base client
|
59 |
+
*/
|
60 |
+
private $client;
|
61 |
+
|
62 |
+
/**
|
63 |
+
* Instantiates the class, but does not initiate the login flow, leaving it
|
64 |
+
* to the discretion of the caller.
|
65 |
+
*/
|
66 |
+
public function __construct(Google_Client $client)
|
67 |
+
{
|
68 |
+
$this->client = $client;
|
69 |
+
}
|
70 |
+
|
71 |
+
/**
|
72 |
+
* Perform an authenticated / signed apiHttpRequest.
|
73 |
+
* This function takes the apiHttpRequest, calls apiAuth->sign on it
|
74 |
+
* (which can modify the request in what ever way fits the auth mechanism)
|
75 |
+
* and then calls apiCurlIO::makeRequest on the signed request
|
76 |
+
*
|
77 |
+
* @param Google_Http_Request $request
|
78 |
+
* @return Google_Http_Request The resulting HTTP response including the
|
79 |
+
* responseHttpCode, responseHeaders and responseBody.
|
80 |
+
*/
|
81 |
+
public function authenticatedRequest(Google_Http_Request $request)
|
82 |
+
{
|
83 |
+
$request = $this->sign($request);
|
84 |
+
return $this->client->getIo()->makeRequest($request);
|
85 |
+
}
|
86 |
+
|
87 |
+
/**
|
88 |
+
* @param string $code
|
89 |
+
* @throws Google_Auth_Exception
|
90 |
+
* @return string
|
91 |
+
*/
|
92 |
+
public function authenticate($code)
|
93 |
+
{
|
94 |
+
if (strlen($code) == 0) {
|
95 |
+
throw new Google_Auth_Exception("Invalid code");
|
96 |
+
}
|
97 |
+
|
98 |
+
// We got here from the redirect from a successful authorization grant,
|
99 |
+
// fetch the access token
|
100 |
+
$request = new Google_Http_Request(
|
101 |
+
self::OAUTH2_TOKEN_URI,
|
102 |
+
'POST',
|
103 |
+
array(),
|
104 |
+
array(
|
105 |
+
'code' => $code,
|
106 |
+
'grant_type' => 'authorization_code',
|
107 |
+
'redirect_uri' => $this->client->getClassConfig($this, 'redirect_uri'),
|
108 |
+
'client_id' => $this->client->getClassConfig($this, 'client_id'),
|
109 |
+
'client_secret' => $this->client->getClassConfig($this, 'client_secret')
|
110 |
+
)
|
111 |
+
);
|
112 |
+
$request->disableGzip();
|
113 |
+
$response = $this->client->getIo()->makeRequest($request);
|
114 |
+
|
115 |
+
if ($response->getResponseHttpCode() == 200) {
|
116 |
+
$this->setAccessToken($response->getResponseBody());
|
117 |
+
$this->token['created'] = time();
|
118 |
+
return $this->getAccessToken();
|
119 |
+
} else {
|
120 |
+
$decodedResponse = json_decode($response->getResponseBody(), true);
|
121 |
+
if ($decodedResponse != null && $decodedResponse['error']) {
|
122 |
+
$decodedResponse = $decodedResponse['error'];
|
123 |
+
}
|
124 |
+
throw new Google_Auth_Exception(
|
125 |
+
sprintf(
|
126 |
+
"Error fetching OAuth2 access token, message: '%s'",
|
127 |
+
$decodedResponse
|
128 |
+
),
|
129 |
+
$response->getResponseHttpCode()
|
130 |
+
);
|
131 |
+
}
|
132 |
+
}
|
133 |
+
|
134 |
+
/**
|
135 |
+
* Create a URL to obtain user authorization.
|
136 |
+
* The authorization endpoint allows the user to first
|
137 |
+
* authenticate, and then grant/deny the access request.
|
138 |
+
* @param string $scope The scope is expressed as a list of space-delimited strings.
|
139 |
+
* @return string
|
140 |
+
*/
|
141 |
+
public function createAuthUrl($scope)
|
142 |
+
{
|
143 |
+
$params = array(
|
144 |
+
'response_type' => 'code',
|
145 |
+
'redirect_uri' => $this->client->getClassConfig($this, 'redirect_uri'),
|
146 |
+
'client_id' => $this->client->getClassConfig($this, 'client_id'),
|
147 |
+
'scope' => $scope,
|
148 |
+
'access_type' => $this->client->getClassConfig($this, 'access_type'),
|
149 |
+
'approval_prompt' => $this->client->getClassConfig($this, 'approval_prompt'),
|
150 |
+
);
|
151 |
+
|
152 |
+
// If the list of scopes contains plus.login, add request_visible_actions
|
153 |
+
// to auth URL.
|
154 |
+
$rva = $this->client->getClassConfig($this, 'request_visible_actions');
|
155 |
+
if (strpos($scope, 'plus.login') && strlen($rva) > 0) {
|
156 |
+
$params['request_visible_actions'] = $rva;
|
157 |
+
}
|
158 |
+
|
159 |
+
if (isset($this->state)) {
|
160 |
+
$params['state'] = $this->state;
|
161 |
+
}
|
162 |
+
|
163 |
+
return self::OAUTH2_AUTH_URL . "?" . http_build_query($params, '', '&');
|
164 |
+
}
|
165 |
+
|
166 |
+
/**
|
167 |
+
* @param string $token
|
168 |
+
* @throws Google_Auth_Exception
|
169 |
+
*/
|
170 |
+
public function setAccessToken($token)
|
171 |
+
{
|
172 |
+
$token = json_decode($token, true);
|
173 |
+
if ($token == null) {
|
174 |
+
throw new Google_Auth_Exception('Could not json decode the token');
|
175 |
+
}
|
176 |
+
if (! isset($token['access_token'])) {
|
177 |
+
throw new Google_Auth_Exception("Invalid token format");
|
178 |
+
}
|
179 |
+
$this->token = $token;
|
180 |
+
}
|
181 |
+
|
182 |
+
public function getAccessToken()
|
183 |
+
{
|
184 |
+
return json_encode($this->token);
|
185 |
+
}
|
186 |
+
|
187 |
+
public function setState($state)
|
188 |
+
{
|
189 |
+
$this->state = $state;
|
190 |
+
}
|
191 |
+
|
192 |
+
public function setAssertionCredentials(Google_Auth_AssertionCredentials $creds)
|
193 |
+
{
|
194 |
+
$this->assertionCredentials = $creds;
|
195 |
+
}
|
196 |
+
|
197 |
+
/**
|
198 |
+
* Include an accessToken in a given apiHttpRequest.
|
199 |
+
* @param Google_Http_Request $request
|
200 |
+
* @return Google_Http_Request
|
201 |
+
* @throws Google_Auth_Exception
|
202 |
+
*/
|
203 |
+
public function sign(Google_Http_Request $request)
|
204 |
+
{
|
205 |
+
// add the developer key to the request before signing it
|
206 |
+
if ($this->client->getClassConfig($this, 'developer_key')) {
|
207 |
+
$request->setQueryParam('key', $this->client->getClassConfig($this, 'developer_key'));
|
208 |
+
}
|
209 |
+
|
210 |
+
// Cannot sign the request without an OAuth access token.
|
211 |
+
if (null == $this->token && null == $this->assertionCredentials) {
|
212 |
+
return $request;
|
213 |
+
}
|
214 |
+
|
215 |
+
// Check if the token is set to expire in the next 30 seconds
|
216 |
+
// (or has already expired).
|
217 |
+
if ($this->isAccessTokenExpired()) {
|
218 |
+
if ($this->assertionCredentials) {
|
219 |
+
$this->refreshTokenWithAssertion();
|
220 |
+
} else {
|
221 |
+
if (! array_key_exists('refresh_token', $this->token)) {
|
222 |
+
throw new Google_Auth_Exception(
|
223 |
+
"The OAuth 2.0 access token has expired,"
|
224 |
+
." and a refresh token is not available. Refresh tokens"
|
225 |
+
." are not returned for responses that were auto-approved."
|
226 |
+
);
|
227 |
+
}
|
228 |
+
$this->refreshToken($this->token['refresh_token']);
|
229 |
+
}
|
230 |
+
}
|
231 |
+
|
232 |
+
// Add the OAuth2 header to the request
|
233 |
+
$request->setRequestHeaders(
|
234 |
+
array('Authorization' => 'Bearer ' . $this->token['access_token'])
|
235 |
+
);
|
236 |
+
|
237 |
+
return $request;
|
238 |
+
}
|
239 |
+
|
240 |
+
/**
|
241 |
+
* Fetches a fresh access token with the given refresh token.
|
242 |
+
* @param string $refreshToken
|
243 |
+
* @return void
|
244 |
+
*/
|
245 |
+
public function refreshToken($refreshToken)
|
246 |
+
{
|
247 |
+
$this->refreshTokenRequest(
|
248 |
+
array(
|
249 |
+
'client_id' => $this->client->getClassConfig($this, 'client_id'),
|
250 |
+
'client_secret' => $this->client->getClassConfig($this, 'client_secret'),
|
251 |
+
'refresh_token' => $refreshToken,
|
252 |
+
'grant_type' => 'refresh_token'
|
253 |
+
)
|
254 |
+
);
|
255 |
+
}
|
256 |
+
|
257 |
+
/**
|
258 |
+
* Fetches a fresh access token with a given assertion token.
|
259 |
+
* @param Google_Auth_AssertionCredentials $assertionCredentials optional.
|
260 |
+
* @return void
|
261 |
+
*/
|
262 |
+
public function refreshTokenWithAssertion($assertionCredentials = null)
|
263 |
+
{
|
264 |
+
if (!$assertionCredentials) {
|
265 |
+
$assertionCredentials = $this->assertionCredentials;
|
266 |
+
}
|
267 |
+
|
268 |
+
$cacheKey = $assertionCredentials->getCacheKey();
|
269 |
+
|
270 |
+
if ($cacheKey) {
|
271 |
+
// We can check whether we have a token available in the
|
272 |
+
// cache. If it is expired, we can retrieve a new one from
|
273 |
+
// the assertion.
|
274 |
+
$token = $this->client->getCache()->get($cacheKey);
|
275 |
+
if ($token) {
|
276 |
+
$this->setAccessToken($token);
|
277 |
+
}
|
278 |
+
if (!$this->isAccessTokenExpired()) {
|
279 |
+
return;
|
280 |
+
}
|
281 |
+
}
|
282 |
+
|
283 |
+
$this->refreshTokenRequest(
|
284 |
+
array(
|
285 |
+
'grant_type' => 'assertion',
|
286 |
+
'assertion_type' => $assertionCredentials->assertionType,
|
287 |
+
'assertion' => $assertionCredentials->generateAssertion(),
|
288 |
+
)
|
289 |
+
);
|
290 |
+
|
291 |
+
if ($cacheKey) {
|
292 |
+
// Attempt to cache the token.
|
293 |
+
$this->client->getCache()->set(
|
294 |
+
$cacheKey,
|
295 |
+
$this->getAccessToken()
|
296 |
+
);
|
297 |
+
}
|
298 |
+
}
|
299 |
+
|
300 |
+
private function refreshTokenRequest($params)
|
301 |
+
{
|
302 |
+
$http = new Google_Http_Request(
|
303 |
+
self::OAUTH2_TOKEN_URI,
|
304 |
+
'POST',
|
305 |
+
array(),
|
306 |
+
$params
|
307 |
+
);
|
308 |
+
$http->disableGzip();
|
309 |
+
$request = $this->client->getIo()->makeRequest($http);
|
310 |
+
|
311 |
+
$code = $request->getResponseHttpCode();
|
312 |
+
$body = $request->getResponseBody();
|
313 |
+
if (200 == $code) {
|
314 |
+
$token = json_decode($body, true);
|
315 |
+
if ($token == null) {
|
316 |
+
throw new Google_Auth_Exception("Could not json decode the access token");
|
317 |
+
}
|
318 |
+
|
319 |
+
if (! isset($token['access_token']) || ! isset($token['expires_in'])) {
|
320 |
+
throw new Google_Auth_Exception("Invalid token format");
|
321 |
+
}
|
322 |
+
|
323 |
+
$this->token['access_token'] = $token['access_token'];
|
324 |
+
$this->token['expires_in'] = $token['expires_in'];
|
325 |
+
$this->token['created'] = time();
|
326 |
+
} else {
|
327 |
+
throw new Google_Auth_Exception("Error refreshing the OAuth2 token, message: '$body'", $code);
|
328 |
+
}
|
329 |
+
}
|
330 |
+
|
331 |
+
/**
|
332 |
+
* Revoke an OAuth2 access token or refresh token. This method will revoke the current access
|
333 |
+
* token, if a token isn't provided.
|
334 |
+
* @throws Google_Auth_Exception
|
335 |
+
* @param string|null $token The token (access token or a refresh token) that should be revoked.
|
336 |
+
* @return boolean Returns True if the revocation was successful, otherwise False.
|
337 |
+
*/
|
338 |
+
public function revokeToken($token = null)
|
339 |
+
{
|
340 |
+
if (!$token) {
|
341 |
+
if (!$this->token) {
|
342 |
+
// Not initialized, no token to actually revoke
|
343 |
+
return false;
|
344 |
+
} elseif (array_key_exists('refresh_token', $this->token)) {
|
345 |
+
$token = $this->token['refresh_token'];
|
346 |
+
} else {
|
347 |
+
$token = $this->token['access_token'];
|
348 |
+
}
|
349 |
+
}
|
350 |
+
$request = new Google_Http_Request(
|
351 |
+
self::OAUTH2_REVOKE_URI,
|
352 |
+
'POST',
|
353 |
+
array(),
|
354 |
+
"token=$token"
|
355 |
+
);
|
356 |
+
$request->disableGzip();
|
357 |
+
$response = $this->client->getIo()->makeRequest($request);
|
358 |
+
$code = $response->getResponseHttpCode();
|
359 |
+
if ($code == 200) {
|
360 |
+
$this->token = null;
|
361 |
+
return true;
|
362 |
+
}
|
363 |
+
|
364 |
+
return false;
|
365 |
+
}
|
366 |
+
|
367 |
+
/**
|
368 |
+
* Returns if the access_token is expired.
|
369 |
+
* @return bool Returns True if the access_token is expired.
|
370 |
+
*/
|
371 |
+
public function isAccessTokenExpired()
|
372 |
+
{
|
373 |
+
if (!$this->token) {
|
374 |
+
return true;
|
375 |
+
}
|
376 |
+
|
377 |
+
// If the token is set to expire in the next 30 seconds.
|
378 |
+
$expired = ($this->token['created']
|
379 |
+
+ ($this->token['expires_in'] - 30)) < time();
|
380 |
+
|
381 |
+
return $expired;
|
382 |
+
}
|
383 |
+
|
384 |
+
// Gets federated sign-on certificates to use for verifying identity tokens.
|
385 |
+
// Returns certs as array structure, where keys are key ids, and values
|
386 |
+
// are PEM encoded certificates.
|
387 |
+
private function getFederatedSignOnCerts()
|
388 |
+
{
|
389 |
+
return $this->retrieveCertsFromLocation(
|
390 |
+
$this->client->getClassConfig($this, 'federated_signon_certs_url')
|
391 |
+
);
|
392 |
+
}
|
393 |
+
|
394 |
+
/**
|
395 |
+
* Retrieve and cache a certificates file.
|
396 |
+
* @param $url location
|
397 |
+
* @return array certificates
|
398 |
+
*/
|
399 |
+
public function retrieveCertsFromLocation($url)
|
400 |
+
{
|
401 |
+
// If we're retrieving a local file, just grab it.
|
402 |
+
if ("http" != substr($url, 0, 4)) {
|
403 |
+
$file = file_get_contents($url);
|
404 |
+
if ($file) {
|
405 |
+
return json_decode($file, true);
|
406 |
+
} else {
|
407 |
+
throw new Google_Auth_Exception(
|
408 |
+
"Failed to retrieve verification certificates: '" .
|
409 |
+
$url . "'."
|
410 |
+
);
|
411 |
+
}
|
412 |
+
}
|
413 |
+
|
414 |
+
// This relies on makeRequest caching certificate responses.
|
415 |
+
$request = $this->client->getIo()->makeRequest(
|
416 |
+
new Google_Http_Request(
|
417 |
+
$url
|
418 |
+
)
|
419 |
+
);
|
420 |
+
if ($request->getResponseHttpCode() == 200) {
|
421 |
+
$certs = json_decode($request->getResponseBody(), true);
|
422 |
+
if ($certs) {
|
423 |
+
return $certs;
|
424 |
+
}
|
425 |
+
}
|
426 |
+
throw new Google_Auth_Exception(
|
427 |
+
"Failed to retrieve verification certificates: '" .
|
428 |
+
$request->getResponseBody() . "'.",
|
429 |
+
$request->getResponseHttpCode()
|
430 |
+
);
|
431 |
+
}
|
432 |
+
|
433 |
+
/**
|
434 |
+
* Verifies an id token and returns the authenticated apiLoginTicket.
|
435 |
+
* Throws an exception if the id token is not valid.
|
436 |
+
* The audience parameter can be used to control which id tokens are
|
437 |
+
* accepted. By default, the id token must have been issued to this OAuth2 client.
|
438 |
+
*
|
439 |
+
* @param $id_token
|
440 |
+
* @param $audience
|
441 |
+
* @return Google_Auth_LoginTicket
|
442 |
+
*/
|
443 |
+
public function verifyIdToken($id_token = null, $audience = null)
|
444 |
+
{
|
445 |
+
if (!$id_token) {
|
446 |
+
$id_token = $this->token['id_token'];
|
447 |
+
}
|
448 |
+
$certs = $this->getFederatedSignonCerts();
|
449 |
+
if (!$audience) {
|
450 |
+
$audience = $this->client->getClassConfig($this, 'client_id');
|
451 |
+
}
|
452 |
+
|
453 |
+
return $this->verifySignedJwtWithCerts($id_token, $certs, $audience, self::OAUTH2_ISSUER);
|
454 |
+
}
|
455 |
+
|
456 |
+
/**
|
457 |
+
* Verifies the id token, returns the verified token contents.
|
458 |
+
*
|
459 |
+
* @param $jwt the token
|
460 |
+
* @param $certs array of certificates
|
461 |
+
* @param $required_audience the expected consumer of the token
|
462 |
+
* @param [$issuer] the expected issues, defaults to Google
|
463 |
+
* @param [$max_expiry] the max lifetime of a token, defaults to MAX_TOKEN_LIFETIME_SECS
|
464 |
+
* @return token information if valid, false if not
|
465 |
+
*/
|
466 |
+
public function verifySignedJwtWithCerts(
|
467 |
+
$jwt,
|
468 |
+
$certs,
|
469 |
+
$required_audience,
|
470 |
+
$issuer = null,
|
471 |
+
$max_expiry = null
|
472 |
+
) {
|
473 |
+
if (!$max_expiry) {
|
474 |
+
// Set the maximum time we will accept a token for.
|
475 |
+
$max_expiry = self::MAX_TOKEN_LIFETIME_SECS;
|
476 |
+
}
|
477 |
+
|
478 |
+
$segments = explode(".", $jwt);
|
479 |
+
if (count($segments) != 3) {
|
480 |
+
throw new Google_Auth_Exception("Wrong number of segments in token: $jwt");
|
481 |
+
}
|
482 |
+
$signed = $segments[0] . "." . $segments[1];
|
483 |
+
$signature = Google_Utils::urlSafeB64Decode($segments[2]);
|
484 |
+
|
485 |
+
// Parse envelope.
|
486 |
+
$envelope = json_decode(Google_Utils::urlSafeB64Decode($segments[0]), true);
|
487 |
+
if (!$envelope) {
|
488 |
+
throw new Google_Auth_Exception("Can't parse token envelope: " . $segments[0]);
|
489 |
+
}
|
490 |
+
|
491 |
+
// Parse token
|
492 |
+
$json_body = Google_Utils::urlSafeB64Decode($segments[1]);
|
493 |
+
$payload = json_decode($json_body, true);
|
494 |
+
if (!$payload) {
|
495 |
+
throw new Google_Auth_Exception("Can't parse token payload: " . $segments[1]);
|
496 |
+
}
|
497 |
+
|
498 |
+
// Check signature
|
499 |
+
$verified = false;
|
500 |
+
foreach ($certs as $keyName => $pem) {
|
501 |
+
$public_key = new Google_Verifier_Pem($pem);
|
502 |
+
if ($public_key->verify($signed, $signature)) {
|
503 |
+
$verified = true;
|
504 |
+
break;
|
505 |
+
}
|
506 |
+
}
|
507 |
+
|
508 |
+
if (!$verified) {
|
509 |
+
throw new Google_Auth_Exception("Invalid token signature: $jwt");
|
510 |
+
}
|
511 |
+
|
512 |
+
// Check issued-at timestamp
|
513 |
+
$iat = 0;
|
514 |
+
if (array_key_exists("iat", $payload)) {
|
515 |
+
$iat = $payload["iat"];
|
516 |
+
}
|
517 |
+
if (!$iat) {
|
518 |
+
throw new Google_Auth_Exception("No issue time in token: $json_body");
|
519 |
+
}
|
520 |
+
$earliest = $iat - self::CLOCK_SKEW_SECS;
|
521 |
+
|
522 |
+
// Check expiration timestamp
|
523 |
+
$now = time();
|
524 |
+
$exp = 0;
|
525 |
+
if (array_key_exists("exp", $payload)) {
|
526 |
+
$exp = $payload["exp"];
|
527 |
+
}
|
528 |
+
if (!$exp) {
|
529 |
+
throw new Google_Auth_Exception("No expiration time in token: $json_body");
|
530 |
+
}
|
531 |
+
if ($exp >= $now + $max_expiry) {
|
532 |
+
throw new Google_Auth_Exception(
|
533 |
+
sprintf("Expiration time too far in future: %s", $json_body)
|
534 |
+
);
|
535 |
+
}
|
536 |
+
|
537 |
+
$latest = $exp + self::CLOCK_SKEW_SECS;
|
538 |
+
if ($now < $earliest) {
|
539 |
+
throw new Google_Auth_Exception(
|
540 |
+
sprintf(
|
541 |
+
"Token used too early, %s < %s: %s",
|
542 |
+
$now,
|
543 |
+
$earliest,
|
544 |
+
$json_body
|
545 |
+
)
|
546 |
+
);
|
547 |
+
}
|
548 |
+
if ($now > $latest) {
|
549 |
+
throw new Google_Auth_Exception(
|
550 |
+
sprintf(
|
551 |
+
"Token used too late, %s > %s: %s",
|
552 |
+
$now,
|
553 |
+
$latest,
|
554 |
+
$json_body
|
555 |
+
)
|
556 |
+
);
|
557 |
+
}
|
558 |
+
|
559 |
+
$iss = $payload['iss'];
|
560 |
+
if ($issuer && $iss != $issuer) {
|
561 |
+
throw new Google_Auth_Exception(
|
562 |
+
sprintf(
|
563 |
+
"Invalid issuer, %s != %s: %s",
|
564 |
+
$iss,
|
565 |
+
$issuer,
|
566 |
+
$json_body
|
567 |
+
)
|
568 |
+
);
|
569 |
+
}
|
570 |
+
|
571 |
+
// Check audience
|
572 |
+
$aud = $payload["aud"];
|
573 |
+
if ($aud != $required_audience) {
|
574 |
+
throw new Google_Auth_Exception(
|
575 |
+
sprintf(
|
576 |
+
"Wrong recipient, %s != %s:",
|
577 |
+
$aud,
|
578 |
+
$required_audience,
|
579 |
+
$json_body
|
580 |
+
)
|
581 |
+
);
|
582 |
+
}
|
583 |
+
|
584 |
+
// All good.
|
585 |
+
return new Google_Auth_LoginTicket($envelope, $payload);
|
586 |
+
}
|
587 |
+
}
|
core/Google/Auth/Simple.php
ADDED
@@ -0,0 +1,92 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* Copyright 2010 Google Inc.
|
4 |
+
*
|
5 |
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
6 |
+
* you may not use this file except in compliance with the License.
|
7 |
+
* You may obtain a copy of the License at
|
8 |
+
*
|
9 |
+
* http://www.apache.org/licenses/LICENSE-2.0
|
10 |
+
*
|
11 |
+
* Unless required by applicable law or agreed to in writing, software
|
12 |
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
13 |
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14 |
+
* See the License for the specific language governing permissions and
|
15 |
+
* limitations under the License.
|
16 |
+
*/
|
17 |
+
|
18 |
+
require_once "Google/Auth/Abstract.php";
|
19 |
+
require_once "Google/Http/Request.php";
|
20 |
+
|
21 |
+
/**
|
22 |
+
* Simple API access implementation. Can either be used to make requests
|
23 |
+
* completely unauthenticated, or by using a Simple API Access developer
|
24 |
+
* key.
|
25 |
+
* @author Chris Chabot <chabotc@google.com>
|
26 |
+
* @author Chirag Shah <chirags@google.com>
|
27 |
+
*/
|
28 |
+
class Google_Auth_Simple extends Google_Auth_Abstract
|
29 |
+
{
|
30 |
+
private $key = null;
|
31 |
+
private $client;
|
32 |
+
|
33 |
+
public function __construct(Google_Client $client, $config = null)
|
34 |
+
{
|
35 |
+
$this->client = $client;
|
36 |
+
}
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Perform an authenticated / signed apiHttpRequest.
|
40 |
+
* This function takes the apiHttpRequest, calls apiAuth->sign on it
|
41 |
+
* (which can modify the request in what ever way fits the auth mechanism)
|
42 |
+
* and then calls apiCurlIO::makeRequest on the signed request
|
43 |
+
*
|
44 |
+
* @param Google_Http_Request $request
|
45 |
+
* @return Google_Http_Request The resulting HTTP response including the
|
46 |
+
* responseHttpCode, responseHeaders and responseBody.
|
47 |
+
*/
|
48 |
+
public function authenticatedRequest(Google_Http_Request $request)
|
49 |
+
{
|
50 |
+
$request = $this->sign($request);
|
51 |
+
return $this->io->makeRequest($request);
|
52 |
+
}
|
53 |
+
|
54 |
+
public function authenticate($code)
|
55 |
+
{
|
56 |
+
throw new Google_Auth_Exception("Simple auth does not exchange tokens.");
|
57 |
+
}
|
58 |
+
|
59 |
+
public function setAccessToken($accessToken)
|
60 |
+
{
|
61 |
+
/* noop*/
|
62 |
+
}
|
63 |
+
|
64 |
+
public function getAccessToken()
|
65 |
+
{
|
66 |
+
return null;
|
67 |
+
}
|
68 |
+
|
69 |
+
public function createAuthUrl($scope)
|
70 |
+
{
|
71 |
+
return null;
|
72 |
+
}
|
73 |
+
|
74 |
+
public function refreshToken($refreshToken)
|
75 |
+
{
|
76 |
+
/* noop*/
|
77 |
+
}
|
78 |
+
|
79 |
+
public function revokeToken()
|
80 |
+
{
|
81 |
+
/* noop*/
|
82 |
+
}
|
83 |
+
|
84 |
+
public function sign(Google_Http_Request $request)
|
85 |
+
{
|
86 |
+
$key = $this->client->getClassConfig($this, 'developer_key');
|
87 |
+
if ($key) {
|
88 |
+
$request->setQueryParam('key', $key);
|
89 |
+
}
|
90 |
+
return $request;
|
91 |
+
}
|
92 |
+
}
|
core/Google/CONTRIBUTING.md
ADDED
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# How to become a contributor and submit your own code
|
2 |
+
|
3 |
+
## Contributor License Agreements
|
4 |
+
|
5 |
+
We'd love to accept your code patches! However, before we can take them, we have to jump a couple of legal hurdles.
|
6 |
+
|
7 |
+
Please fill out either the individual or corporate Contributor License Agreement (CLA).
|
8 |
+
|
9 |
+
* If you are an individual writing original source code and you're sure you own the intellectual property, then you'll need to sign an [individual CLA](http://code.google.com/legal/individual-cla-v1.0.html).
|
10 |
+
* If you work for a company that wants to allow you to contribute your work to this client library, then you'll need to sign a[corporate CLA](http://code.google.com/legal/corporate-cla-v1.0.html).
|
11 |
+
|
12 |
+
Follow either of the two links above to access the appropriate CLA and instructions for how to sign and return it. Once we receive it, we'll add you to the official list of contributors and be able to accept your patches.
|
13 |
+
|
14 |
+
## Submitting Patches
|
15 |
+
|
16 |
+
1. Fork the PHP client library on GitHub
|
17 |
+
1. Decide which code you want to submit. A submission should be a set of changes that addresses one issue in the issue tracker. Please file one change per issue, and address one issue per change. If you want to make a change that doesn't have a corresponding issue in the issue tracker, please file a new ticket!
|
18 |
+
1. Ensure that your code adheres to standard PHP conventions, as used in the rest of the library.
|
19 |
+
1. Ensure that there are unit tests for your code.
|
20 |
+
1. Sign a Contributor License Agreement (see above).
|
21 |
+
1. Submit a pull request with your patch on Github.
|
22 |
+
|
googleclient/cache/Google_Cache.php → core/Google/Cache/Abstract.php
RENAMED
@@ -15,15 +15,15 @@
|
|
15 |
* limitations under the License.
|
16 |
*/
|
17 |
|
18 |
-
require_once "Google_FileCache.php";
|
19 |
-
require_once "Google_MemcacheCache.php";
|
20 |
-
|
21 |
/**
|
22 |
* Abstract storage class
|
23 |
*
|
24 |
* @author Chris Chabot <chabotc@google.com>
|
25 |
*/
|
26 |
-
abstract class
|
|
|
|
|
|
|
27 |
|
28 |
/**
|
29 |
* Retrieves the data for the given key, or false if they
|
@@ -33,7 +33,7 @@ abstract class Google_Cache {
|
|
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
|
@@ -42,14 +42,12 @@ abstract class Google_Cache {
|
|
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 |
-
|
15 |
* limitations under the License.
|
16 |
*/
|
17 |
|
|
|
|
|
|
|
18 |
/**
|
19 |
* Abstract storage class
|
20 |
*
|
21 |
* @author Chris Chabot <chabotc@google.com>
|
22 |
*/
|
23 |
+
abstract class Google_Cache_Abstract
|
24 |
+
{
|
25 |
+
|
26 |
+
abstract public function __construct(Google_Client $client);
|
27 |
|
28 |
/**
|
29 |
* Retrieves the data for the given key, or false if they
|
33 |
* @param boolean|int $expiration Expiration time in seconds
|
34 |
*
|
35 |
*/
|
36 |
+
abstract public function get($key, $expiration = false);
|
37 |
|
38 |
/**
|
39 |
* Store the key => $value set. The $value is serialized
|
42 |
* @param string $key Key of the data
|
43 |
* @param string $value data
|
44 |
*/
|
45 |
+
abstract public function set($key, $value);
|
46 |
|
47 |
/**
|
48 |
* Removes the key/data pair for the given $key
|
49 |
*
|
50 |
* @param String $key
|
51 |
*/
|
52 |
+
abstract public function delete($key);
|
53 |
}
|
|
|
|
core/Google/Cache/Apc.php
ADDED
@@ -0,0 +1,73 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* Copyright 2010 Google Inc.
|
4 |
+
*
|
5 |
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
6 |
+
* you may not use this file except in compliance with the License.
|
7 |
+
* You may obtain a copy of the License at
|
8 |
+
*
|
9 |
+
* http://www.apache.org/licenses/LICENSE-2.0
|
10 |
+
*
|
11 |
+
* Unless required by applicable law or agreed to in writing, software
|
12 |
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
13 |
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14 |
+
* See the License for the specific language governing permissions and
|
15 |
+
* limitations under the License.
|
16 |
+
*/
|
17 |
+
|
18 |
+
require_once "Google/Cache/Abstract.php";
|
19 |
+
require_once "Google/Cache/Exception.php";
|
20 |
+
|
21 |
+
/**
|
22 |
+
* A persistent storage class based on the APC cache, which is not
|
23 |
+
* really very persistent, as soon as you restart your web server
|
24 |
+
* the storage will be wiped, however for debugging and/or speed
|
25 |
+
* it can be useful, and cache is a lot cheaper then storage.
|
26 |
+
*
|
27 |
+
* @author Chris Chabot <chabotc@google.com>
|
28 |
+
*/
|
29 |
+
class Google_Cache_Apc extends Google_Cache_Abstract
|
30 |
+
{
|
31 |
+
public function __construct(Google_Client $client)
|
32 |
+
{
|
33 |
+
if (! function_exists('apc_add') ) {
|
34 |
+
throw new Google_Cache_Exception("Apc functions not available");
|
35 |
+
}
|
36 |
+
}
|
37 |
+
|
38 |
+
/**
|
39 |
+
* @inheritDoc
|
40 |
+
*/
|
41 |
+
public function get($key, $expiration = false)
|
42 |
+
{
|
43 |
+
$ret = apc_fetch($key);
|
44 |
+
if ($ret === false) {
|
45 |
+
return false;
|
46 |
+
}
|
47 |
+
if (is_numeric($expiration) && (time() - $ret['time'] > $expiration)) {
|
48 |
+
$this->delete($key);
|
49 |
+
return false;
|
50 |
+
}
|
51 |
+
return $ret['data'];
|
52 |
+
}
|
53 |
+
|
54 |
+
/**
|
55 |
+
* @inheritDoc
|
56 |
+
*/
|
57 |
+
public function set($key, $value)
|
58 |
+
{
|
59 |
+
$rc = apc_store($key, array('time' => time(), 'data' => $value));
|
60 |
+
if ($rc == false) {
|
61 |
+
throw new Google_Cache_Exception("Couldn't store data");
|
62 |
+
}
|
63 |
+
}
|
64 |
+
|
65 |
+
/**
|
66 |
+
* @inheritDoc
|
67 |
+
* @param String $key
|
68 |
+
*/
|
69 |
+
public function delete($key)
|
70 |
+
{
|
71 |
+
apc_delete($key);
|
72 |
+
}
|
73 |
+
}
|
core/Google/Cache/Exception.php
ADDED
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* Copyright 2013 Google Inc.
|
4 |
+
*
|
5 |
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
6 |
+
* you may not use this file except in compliance with the License.
|
7 |
+
* You may obtain a copy of the License at
|
8 |
+
*
|
9 |
+
* http://www.apache.org/licenses/LICENSE-2.0
|
10 |
+
*
|
11 |
+
* Unless required by applicable law or agreed to in writing, software
|
12 |
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
13 |
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14 |
+
* See the License for the specific language governing permissions and
|
15 |
+
* limitations under the License.
|
16 |
+
*/
|
17 |
+
require_once "Google/Exception.php";
|
18 |
+
|
19 |
+
class Google_Cache_Exception extends Google_Exception
|
20 |
+
{
|
21 |
+
}
|
core/Google/Cache/File.php
ADDED
@@ -0,0 +1,145 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* Copyright 2008 Google Inc.
|
4 |
+
*
|
5 |
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
6 |
+
* you may not use this file except in compliance with the License.
|
7 |
+
* You may obtain a copy of the License at
|
8 |
+
*
|
9 |
+
* http://www.apache.org/licenses/LICENSE-2.0
|
10 |
+
*
|
11 |
+
* Unless required by applicable law or agreed to in writing, software
|
12 |
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
13 |
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14 |
+
* See the License for the specific language governing permissions and
|
15 |
+
* limitations under the License.
|
16 |
+
*/
|
17 |
+
|
18 |
+
require_once "Google/Cache/Abstract.php";
|
19 |
+
require_once "Google/Cache/Exception.php";
|
20 |
+
|
21 |
+
/*
|
22 |
+
* This class implements a basic on disk storage. While that does
|
23 |
+
* work quite well it's not the most elegant and scalable solution.
|
24 |
+
* It will also get you into a heap of trouble when you try to run
|
25 |
+
* this in a clustered environment.
|
26 |
+
*
|
27 |
+
* @author Chris Chabot <chabotc@google.com>
|
28 |
+
*/
|
29 |
+
class Google_Cache_File extends Google_Cache_Abstract
|
30 |
+
{
|
31 |
+
const MAX_LOCK_RETRIES = 10;
|
32 |
+
private $path;
|
33 |
+
private $fh;
|
34 |
+
|
35 |
+
public function __construct(Google_Client $client)
|
36 |
+
{
|
37 |
+
$this->path = $client->getClassConfig($this, 'directory');
|
38 |
+
}
|
39 |
+
|
40 |
+
public function get($key, $expiration = false)
|
41 |
+
{
|
42 |
+
$storageFile = $this->getCacheFile($key);
|
43 |
+
$data = false;
|
44 |
+
|
45 |
+
if (!file_exists($storageFile)) {
|
46 |
+
return false;
|
47 |
+
}
|
48 |
+
|
49 |
+
if ($expiration) {
|
50 |
+
$mtime = filemtime($storageFile);
|
51 |
+
if (($now - $mtime) >= $expiration) {
|
52 |
+
$this->delete($key);
|
53 |
+
return false;
|
54 |
+
}
|
55 |
+
}
|
56 |
+
|
57 |
+
if ($this->acquireReadLock($storageFile)) {
|
58 |
+
$data = fread($this->fh, filesize($storageFile));
|
59 |
+
$data = unserialize($data);
|
60 |
+
$this->unlock($storageFile);
|
61 |
+
}
|
62 |
+
|
63 |
+
return $data;
|
64 |
+
}
|
65 |
+
|
66 |
+
public function set($key, $value)
|
67 |
+
{
|
68 |
+
$storageFile = $this->getWriteableCacheFile($key);
|
69 |
+
if ($this->acquireWriteLock($storageFile)) {
|
70 |
+
// We serialize the whole request object, since we don't only want the
|
71 |
+
// responseContent but also the postBody used, headers, size, etc.
|
72 |
+
$data = serialize($value);
|
73 |
+
$result = fwrite($this->fh, $data);
|
74 |
+
$this->unlock($storageFile);
|
75 |
+
}
|
76 |
+
}
|
77 |
+
|
78 |
+
public function delete($key)
|
79 |
+
{
|
80 |
+
$file = $this->getCacheFile($key);
|
81 |
+
if (file_exists($file) && !unlink($file)) {
|
82 |
+
throw new Google_Cache_Exception("Cache file could not be deleted");
|
83 |
+
}
|
84 |
+
}
|
85 |
+
|
86 |
+
private function getWriteableCacheFile($file)
|
87 |
+
{
|
88 |
+
return $this->getCacheFile($file, true);
|
89 |
+
}
|
90 |
+
|
91 |
+
private function getCacheFile($file, $forWrite = false)
|
92 |
+
{
|
93 |
+
return $this->getCacheDir($file, $forWrite) . '/' . md5($file);
|
94 |
+
}
|
95 |
+
|
96 |
+
private function getCacheDir($file, $forWrite)
|
97 |
+
{
|
98 |
+
// use the first 2 characters of the hash as a directory prefix
|
99 |
+
// this should prevent slowdowns due to huge directory listings
|
100 |
+
// and thus give some basic amount of scalability
|
101 |
+
$storageDir = $this->path . '/' . substr(md5($file), 0, 2);
|
102 |
+
if ($forWrite && ! is_dir($storageDir)) {
|
103 |
+
if (! mkdir($storageDir, 0755, true)) {
|
104 |
+
throw new Google_Cache_Exception("Could not create storage directory: $storageDir");
|
105 |
+
}
|
106 |
+
}
|
107 |
+
return $storageDir;
|
108 |
+
}
|
109 |
+
|
110 |
+
private function acquireReadLock($storageFile)
|
111 |
+
{
|
112 |
+
return $this->acquireLock(LOCK_SH, $storageFile);
|
113 |
+
}
|
114 |
+
|
115 |
+
private function acquireWriteLock($storageFile)
|
116 |
+
{
|
117 |
+
$rc = $this->acquireLock(LOCK_EX, $storageFile);
|
118 |
+
if (!$rc) {
|
119 |
+
$this->delete($storageFile);
|
120 |
+
}
|
121 |
+
return $rc;
|
122 |
+
}
|
123 |
+
|
124 |
+
private function acquireLock($type, $storageFile)
|
125 |
+
{
|
126 |
+
$mode = $type == LOCK_EX ? "w" : "r";
|
127 |
+
$this->fh = fopen($storageFile, $mode);
|
128 |
+
$count = 0;
|
129 |
+
while (!flock($this->fh, $type | LOCK_NB)) {
|
130 |
+
// Sleep for 10ms.
|
131 |
+
usleep(10000);
|
132 |
+
if (++$count < self::MAX_LOCK_RETRIES) {
|
133 |
+
return false;
|
134 |
+
}
|
135 |
+
}
|
136 |
+
return true;
|
137 |
+
}
|
138 |
+
|
139 |
+
public function unlock($storageFile)
|
140 |
+
{
|
141 |
+
if ($this->fh) {
|
142 |
+
flock($this->fh, LOCK_UN);
|
143 |
+
}
|
144 |
+
}
|
145 |
+
}
|
core/Google/Cache/Memcache.php
ADDED
@@ -0,0 +1,137 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* Copyright 2008 Google Inc.
|
4 |
+
*
|
5 |
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
6 |
+
* you may not use this file except in compliance with the License.
|
7 |
+
* You may obtain a copy of the License at
|
8 |
+
*
|
9 |
+
* http://www.apache.org/licenses/LICENSE-2.0
|
10 |
+
*
|
11 |
+
* Unless required by applicable law or agreed to in writing, software
|
12 |
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
13 |
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14 |
+
* See the License for the specific language governing permissions and
|
15 |
+
* limitations under the License.
|
16 |
+
*/
|
17 |
+
|
18 |
+
require_once "Google/Cache/Abstract.php";
|
19 |
+
require_once "Google/Cache/Exception.php";
|
20 |
+
|
21 |
+
/**
|
22 |
+
* A persistent storage class based on the memcache, which is not
|
23 |
+
* really very persistent, as soon as you restart your memcache daemon
|
24 |
+
* the storage will be wiped.
|
25 |
+
*
|
26 |
+
* Will use either the memcache or memcached extensions, preferring
|
27 |
+
* memcached.
|
28 |
+
*
|
29 |
+
* @author Chris Chabot <chabotc@google.com>
|
30 |
+
*/
|
31 |
+
class Google_Cache_Memcache extends Google_Cache_Abstract
|
32 |
+
{
|
33 |
+
private $connection = false;
|
34 |
+
private $mc = false;
|
35 |
+
private $host;
|
36 |
+
private $port;
|
37 |
+
|
38 |
+
public function __construct(Google_Client $client)
|
39 |
+
{
|
40 |
+
if (!function_exists('memcache_connect') && !class_exists("Memcached")) {
|
41 |
+
throw new Google_Cache_Exception("Memcache functions not available");
|
42 |
+
}
|
43 |
+
if ($client->isAppEngine()) {
|
44 |
+
// No credentials needed for GAE.
|
45 |
+
$this->mc = new Memcached();
|
46 |
+
$this->connection = true;
|
47 |
+
} else {
|
48 |
+
$this->host = $client->getClassConfig($this, 'host');
|
49 |
+
$this->port = $client->getClassConfig($this, 'port');
|
50 |
+
if (empty($this->host) || empty($this->port)) {
|
51 |
+
throw new Google_Cache_Exception("You need to supply a valid memcache host and port");
|
52 |
+
}
|
53 |
+
}
|
54 |
+
}
|
55 |
+
|
56 |
+
/**
|
57 |
+
* @inheritDoc
|
58 |
+
*/
|
59 |
+
public function get($key, $expiration = false)
|
60 |
+
{
|
61 |
+
$this->connect();
|
62 |
+
$ret = false;
|
63 |
+
if ($this->mc) {
|
64 |
+
$ret = $this->mc->get($key);
|
65 |
+
} else {
|
66 |
+
$ret = memcache_get($this->connection, $key);
|
67 |
+
}
|
68 |
+
if ($ret === false) {
|
69 |
+
return false;
|
70 |
+
}
|
71 |
+
if (is_numeric($expiration) && (time() - $ret['time'] > $expiration)) {
|
72 |
+
$this->delete($key);
|
73 |
+
return false;
|
74 |
+
}
|
75 |
+
return $ret['data'];
|
76 |
+
}
|
77 |
+
|
78 |
+
/**
|
79 |
+
* @inheritDoc
|
80 |
+
* @param string $key
|
81 |
+
* @param string $value
|
82 |
+
* @throws Google_Cache_Exception
|
83 |
+
*/
|
84 |
+
public function set($key, $value)
|
85 |
+
{
|
86 |
+
$this->connect();
|
87 |
+
// we store it with the cache_time default expiration so objects will at
|
88 |
+
// least get cleaned eventually.
|
89 |
+
$data = array('time' => time(), 'data' => $value);
|
90 |
+
$rc = false;
|
91 |
+
if ($this->mc) {
|
92 |
+
$rc = $this->mc->set($key, $data);
|
93 |
+
} else {
|
94 |
+
$rc = memcache_set($this->connection, $key, $data, false);
|
95 |
+
}
|
96 |
+
if ($rc == false) {
|
97 |
+
throw new Google_Cache_Exception("Couldn't store data in cache");
|
98 |
+
}
|
99 |
+
}
|
100 |
+
|
101 |
+
/**
|
102 |
+
* @inheritDoc
|
103 |
+
* @param String $key
|
104 |
+
*/
|
105 |
+
public function delete($key)
|
106 |
+
{
|
107 |
+
$this->connect();
|
108 |
+
if ($this->mc) {
|
109 |
+
$this->mc->delete($key, 0);
|
110 |
+
} else {
|
111 |
+
memcache_delete($this->connection, $key, 0);
|
112 |
+
}
|
113 |
+
}
|
114 |
+
|
115 |
+
/**
|
116 |
+
* Lazy initialiser for memcache connection. Uses pconnect for to take
|
117 |
+
* advantage of the persistence pool where possible.
|
118 |
+
*/
|
119 |
+
private function connect()
|
120 |
+
{
|
121 |
+
if ($this->connection) {
|
122 |
+
return;
|
123 |
+
}
|
124 |
+
|
125 |
+
if (class_exists("Memcached")) {
|
126 |
+
$this->mc = new Memcached();
|
127 |
+
$this->mc->addServer($this->host, $this->port);
|
128 |
+
$this->connection = true;
|
129 |
+
} else {
|
130 |
+
$this->connection = memcache_pconnect($this->host, $this->port);
|
131 |
+
}
|
132 |
+
|
133 |
+
if (! $this->connection) {
|
134 |
+
throw new Google_Cache_Exception("Couldn't connect to memcache server");
|
135 |
+
}
|
136 |
+
}
|
137 |
+
}
|
core/Google/Cache/Null.php
ADDED
@@ -0,0 +1,56 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* Copyright 2014 Google Inc.
|
4 |
+
*
|
5 |
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
6 |
+
* you may not use this file except in compliance with the License.
|
7 |
+
* You may obtain a copy of the License at
|
8 |
+
*
|
9 |
+
* http://www.apache.org/licenses/LICENSE-2.0
|
10 |
+
*
|
11 |
+
* Unless required by applicable law or agreed to in writing, software
|
12 |
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
13 |
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14 |
+
* See the License for the specific language governing permissions and
|
15 |
+
* limitations under the License.
|
16 |
+
*/
|
17 |
+
|
18 |
+
require_once "Google/Cache/Abstract.php";
|
19 |
+
require_once "Google/Cache/Exception.php";
|
20 |
+
|
21 |
+
/**
|
22 |
+
* A blank storage class, for cases where caching is not
|
23 |
+
* required.
|
24 |
+
*/
|
25 |
+
class Google_Cache_Null extends Google_Cache_Abstract
|
26 |
+
{
|
27 |
+
public function __construct(Google_Client $client)
|
28 |
+
{
|
29 |
+
|
30 |
+
}
|
31 |
+
|
32 |
+
/**
|
33 |
+
* @inheritDoc
|
34 |
+
*/
|
35 |
+
public function get($key, $expiration = false)
|
36 |
+
{
|
37 |
+
return false;
|
38 |
+
}
|
39 |
+
|
40 |
+
/**
|
41 |
+
* @inheritDoc
|
42 |
+
*/
|
43 |
+
public function set($key, $value)
|
44 |
+
{
|
45 |
+
// Nop.
|
46 |
+
}
|
47 |
+
|
48 |
+
/**
|
49 |
+
* @inheritDoc
|
50 |
+
* @param String $key
|
51 |
+
*/
|
52 |
+
public function delete($key)
|
53 |
+
{
|
54 |
+
// Nop.
|
55 |
+
}
|
56 |
+
}
|
core/Google/Client.php
ADDED
@@ -0,0 +1,608 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|