Google Apps Login - Version 2.3

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 Icon 128x128 Google Apps Login
Version 2.3
Comparing to
See all releases

Code changes from version 2.2 to 2.3

Files changed (43) hide show
  1. googleclient/auth/Google_Auth.php → core/Google/Auth/Abstract.php +14 -9
  2. googleclient/auth/Google_AssertionCredentials.php → core/Google/Auth/AssertionCredentials.php +37 -7
  3. core/Google/Auth/Exception.php +22 -0
  4. googleclient/auth/Google_LoginTicket.php → core/Google/Auth/LoginTicket.php +13 -7
  5. core/Google/Auth/OAuth2.php +587 -0
  6. core/Google/Auth/Simple.php +92 -0
  7. core/Google/CONTRIBUTING.md +22 -0
  8. googleclient/cache/Google_Cache.php → core/Google/Cache/Abstract.php +7 -9
  9. core/Google/Cache/Apc.php +73 -0
  10. core/Google/Cache/Exception.php +21 -0
  11. core/Google/Cache/File.php +145 -0
  12. core/Google/Cache/Memcache.php +137 -0
  13. core/Google/Cache/Null.php +56 -0
  14. core/Google/Client.php +608 -0
  15. core/Google/Collection.php +94 -0
  16. core/Google/Config.php +315 -0
  17. googleclient/service/Google_Service.php → core/Google/Exception.php +3 -5
  18. googleclient/service/Google_BatchRequest.php → core/Google/Http/Batch.php +56 -23
  19. googleclient/io/Google_CacheParser.php → core/Google/Http/CacheParser.php +24 -13
  20. core/Google/Http/MediaFileUpload.php +292 -0
  21. googleclient/io/Google_REST.php → core/Google/Http/REST.php +43 -32
  22. core/Google/Http/Request.php +476 -0
  23. core/Google/IO/Abstract.php +312 -0
  24. core/Google/IO/Curl.php +135 -0
  25. core/Google/IO/Exception.php +22 -0
  26. core/Google/IO/Stream.php +182 -0
  27. core/Google/IO/cacerts.pem +2183 -0
  28. {googleclient → core/Google}/LICENSE +0 -0
  29. core/Google/Model.php +247 -0
  30. core/Google/README.md +59 -0
  31. core/Google/Service.php +39 -0
  32. core/Google/Service/AdExchangeBuyer.php +1288 -0
  33. core/Google/Service/AdExchangeSeller.php +1996 -0
  34. core/Google/Service/AdSense.php +3770 -0
  35. core/Google/Service/AdSenseHost.php +2281 -0
  36. core/Google/Service/Admin.php +207 -0
  37. core/Google/Service/Analytics.php +7769 -0
  38. core/Google/Service/AndroidPublisher.php +330 -0
  39. core/Google/Service/AppState.php +373 -0
  40. core/Google/Service/Audit.php +438 -0
  41. core/Google/Service/Bigquery.php +3368 -0
  42. core/Google/Service/Blogger.php +3315 -0
  43. 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 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
  }
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 Google_AssertionCredentials {
 
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
- * application is requesting delegated access.
 
 
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' => Google_OAuth2::OAUTH2_TOKEN_URI,
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 Google_P12Signer($this->privateKey, $this->privateKeyPassword);
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 Google_LoginTicket {
24
- const USER_ATTR = "id";
 
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 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
  /**
@@ -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 Google_Cache {
 
 
 
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 @@