MDL-47297 libraries: Update Google API to v1.0.5-beta
authorFrederic Massart <fred@moodle.com>
Tue, 30 Sep 2014 11:52:26 +0000 (19:52 +0800)
committerMarina Glancy <marina@moodle.com>
Wed, 8 Oct 2014 11:15:00 +0000 (19:15 +0800)
153 files changed:
lib/google/Google/Auth/Abstract.php [moved from lib/google/auth/Google_Auth.php with 57% similarity, mode: 0755]
lib/google/Google/Auth/AppIdentity.php [new file with mode: 0755]
lib/google/Google/Auth/AssertionCredentials.php [moved from lib/google/auth/Google_AssertionCredentials.php with 59% similarity, mode: 0755]
lib/google/Google/Auth/Exception.php [new file with mode: 0755]
lib/google/Google/Auth/LoginTicket.php [moved from lib/google/auth/Google_LoginTicket.php with 82% similarity, mode: 0755]
lib/google/Google/Auth/OAuth2.php [new file with mode: 0755]
lib/google/Google/Auth/Simple.php [new file with mode: 0755]
lib/google/Google/Cache/Abstract.php [moved from lib/google/cache/Google_Cache.php with 82% similarity, mode: 0755]
lib/google/Google/Cache/Apc.php [new file with mode: 0755]
lib/google/Google/Cache/Exception.php [new file with mode: 0755]
lib/google/Google/Cache/File.php [new file with mode: 0755]
lib/google/Google/Cache/Memcache.php [new file with mode: 0755]
lib/google/Google/Cache/Null.php [new file with mode: 0755]
lib/google/Google/Client.php [new file with mode: 0755]
lib/google/Google/Collection.php [new file with mode: 0755]
lib/google/Google/Config.php [new file with mode: 0755]
lib/google/Google/Exception.php [moved from lib/google/service/Google_Service.php with 83% similarity, mode: 0755]
lib/google/Google/Http/Batch.php [moved from lib/google/service/Google_BatchRequest.php with 52% similarity, mode: 0755]
lib/google/Google/Http/CacheParser.php [moved from lib/google/io/Google_CacheParser.php with 87% similarity, mode: 0755]
lib/google/Google/Http/MediaFileUpload.php [new file with mode: 0755]
lib/google/Google/Http/REST.php [moved from lib/google/io/Google_REST.php with 61% similarity, mode: 0755]
lib/google/Google/Http/Request.php [new file with mode: 0755]
lib/google/Google/IO/Abstract.php [new file with mode: 0755]
lib/google/Google/IO/Curl.php [new file with mode: 0755]
lib/google/Google/IO/Exception.php [new file with mode: 0755]
lib/google/Google/IO/Stream.php [new file with mode: 0755]
lib/google/Google/IO/cacerts.pem [new file with mode: 0755]
lib/google/Google/Model.php [new file with mode: 0755]
lib/google/Google/Service.php [new file with mode: 0755]
lib/google/Google/Service/AdExchangeBuyer.php [new file with mode: 0755]
lib/google/Google/Service/AdExchangeSeller.php [new file with mode: 0755]
lib/google/Google/Service/AdSense.php [new file with mode: 0755]
lib/google/Google/Service/AdSenseHost.php [new file with mode: 0755]
lib/google/Google/Service/Admin.php [new file with mode: 0755]
lib/google/Google/Service/Analytics.php [new file with mode: 0755]
lib/google/Google/Service/AndroidPublisher.php [new file with mode: 0755]
lib/google/Google/Service/AppState.php [new file with mode: 0755]
lib/google/Google/Service/Appsactivity.php [new file with mode: 0755]
lib/google/Google/Service/Audit.php [new file with mode: 0755]
lib/google/Google/Service/Autoscaler.php [new file with mode: 0755]
lib/google/Google/Service/Bigquery.php [new file with mode: 0755]
lib/google/Google/Service/Blogger.php [new file with mode: 0755]
lib/google/Google/Service/Books.php [new file with mode: 0755]
lib/google/Google/Service/Calendar.php [new file with mode: 0755]
lib/google/Google/Service/CivicInfo.php [new file with mode: 0755]
lib/google/Google/Service/CloudMonitoring.php [new file with mode: 0755]
lib/google/Google/Service/Compute.php [new file with mode: 0755]
lib/google/Google/Service/Coordinate.php [new file with mode: 0755]
lib/google/Google/Service/Customsearch.php [new file with mode: 0755]
lib/google/Google/Service/Datastore.php [new file with mode: 0755]
lib/google/Google/Service/Dfareporting.php [new file with mode: 0755]
lib/google/Google/Service/Directory.php [new file with mode: 0755]
lib/google/Google/Service/Dns.php [new file with mode: 0755]
lib/google/Google/Service/DoubleClickBidManager.php [new file with mode: 0755]
lib/google/Google/Service/Doubleclicksearch.php [new file with mode: 0755]
lib/google/Google/Service/Drive.php [new file with mode: 0755]
lib/google/Google/Service/Exception.php [new file with mode: 0755]
lib/google/Google/Service/Freebase.php [new file with mode: 0755]
lib/google/Google/Service/Fusiontables.php [new file with mode: 0755]
lib/google/Google/Service/Games.php [new file with mode: 0755]
lib/google/Google/Service/GamesManagement.php [new file with mode: 0755]
lib/google/Google/Service/Genomics.php [new file with mode: 0755]
lib/google/Google/Service/Gmail.php [new file with mode: 0755]
lib/google/Google/Service/GroupsMigration.php [new file with mode: 0755]
lib/google/Google/Service/Groupssettings.php [new file with mode: 0755]
lib/google/Google/Service/IdentityToolkit.php [new file with mode: 0755]
lib/google/Google/Service/Licensing.php [new file with mode: 0755]
lib/google/Google/Service/Manager.php [new file with mode: 0755]
lib/google/Google/Service/MapsEngine.php [new file with mode: 0755]
lib/google/Google/Service/Mirror.php [new file with mode: 0755]
lib/google/Google/Service/Oauth2.php [new file with mode: 0755]
lib/google/Google/Service/Orkut.php [new file with mode: 0755]
lib/google/Google/Service/Pagespeedonline.php [new file with mode: 0755]
lib/google/Google/Service/Plus.php [new file with mode: 0755]
lib/google/Google/Service/PlusDomains.php [new file with mode: 0755]
lib/google/Google/Service/Prediction.php [new file with mode: 0755]
lib/google/Google/Service/Pubsub.php [new file with mode: 0755]
lib/google/Google/Service/QPXExpress.php [new file with mode: 0755]
lib/google/Google/Service/Replicapool.php [new file with mode: 0755]
lib/google/Google/Service/Reports.php [new file with mode: 0755]
lib/google/Google/Service/Reseller.php [new file with mode: 0755]
lib/google/Google/Service/Resource.php [new file with mode: 0755]
lib/google/Google/Service/Resourceviews.php [new file with mode: 0755]
lib/google/Google/Service/SQLAdmin.php [new file with mode: 0755]
lib/google/Google/Service/ShoppingContent.php [new file with mode: 0755]
lib/google/Google/Service/SiteVerification.php [new file with mode: 0755]
lib/google/Google/Service/Spectrum.php [new file with mode: 0755]
lib/google/Google/Service/Storage.php [new file with mode: 0755]
lib/google/Google/Service/Taskqueue.php [new file with mode: 0755]
lib/google/Google/Service/Tasks.php [new file with mode: 0755]
lib/google/Google/Service/Translate.php [new file with mode: 0755]
lib/google/Google/Service/Urlshortener.php [new file with mode: 0755]
lib/google/Google/Service/Webfonts.php [new file with mode: 0755]
lib/google/Google/Service/YouTube.php [new file with mode: 0755]
lib/google/Google/Service/YouTubeAnalytics.php [new file with mode: 0755]
lib/google/Google/Signer/Abstract.php [moved from lib/google/auth/Google_Signer.php with 91% similarity, mode: 0755]
lib/google/Google/Signer/P12.php [new file with mode: 0755]
lib/google/Google/Utils.php [moved from lib/google/service/Google_Utils.php with 78% similarity, mode: 0755]
lib/google/Google/Utils/URITemplate.php [new file with mode: 0755]
lib/google/Google/Verifier/Abstract.php [moved from lib/google/auth/Google_Verifier.php with 91% similarity, mode: 0755]
lib/google/Google/Verifier/Pem.php [moved from lib/google/auth/Google_PemVerifier.php with 72% similarity, mode: 0755]
lib/google/NOTICE [deleted file]
lib/google/README [deleted file]
lib/google/README.md [new file with mode: 0644]
lib/google/auth/Google_AuthNone.php [deleted file]
lib/google/auth/Google_OAuth2.php [deleted file]
lib/google/auth/Google_P12Signer.php [deleted file]
lib/google/cache/Google_ApcCache.php [deleted file]
lib/google/cache/Google_FileCache.php [deleted file]
lib/google/cache/Google_MemcacheCache.php [deleted file]
lib/google/contrib/Google_AdexchangebuyerService.php [deleted file]
lib/google/contrib/Google_AdsenseService.php [deleted file]
lib/google/contrib/Google_AdsensehostService.php [deleted file]
lib/google/contrib/Google_AnalyticsService.php [deleted file]
lib/google/contrib/Google_BigqueryService.php [deleted file]
lib/google/contrib/Google_BloggerService.php [deleted file]
lib/google/contrib/Google_BooksService.php [deleted file]
lib/google/contrib/Google_CalendarService.php [deleted file]
lib/google/contrib/Google_ComputeService.php [deleted file]
lib/google/contrib/Google_CustomsearchService.php [deleted file]
lib/google/contrib/Google_DriveService.php [deleted file]
lib/google/contrib/Google_FreebaseService.php [deleted file]
lib/google/contrib/Google_FusiontablesService.php [deleted file]
lib/google/contrib/Google_GanService.php [deleted file]
lib/google/contrib/Google_LatitudeService.php [deleted file]
lib/google/contrib/Google_LicensingService.php [deleted file]
lib/google/contrib/Google_ModeratorService.php [deleted file]
lib/google/contrib/Google_Oauth2Service.php [deleted file]
lib/google/contrib/Google_OrkutService.php [deleted file]
lib/google/contrib/Google_PagespeedonlineService.php [deleted file]
lib/google/contrib/Google_PlusMomentsService.php [deleted file]
lib/google/contrib/Google_PlusService.php [deleted file]
lib/google/contrib/Google_PredictionService.php [deleted file]
lib/google/contrib/Google_ShoppingService.php [deleted file]
lib/google/contrib/Google_SiteVerificationService.php [deleted file]
lib/google/contrib/Google_StorageService.php [deleted file]
lib/google/contrib/Google_TaskqueueService.php [deleted file]
lib/google/contrib/Google_TasksService.php [deleted file]
lib/google/contrib/Google_TranslateService.php [deleted file]
lib/google/contrib/Google_UrlshortenerService.php [deleted file]
lib/google/contrib/Google_WebfontsService.php [deleted file]
lib/google/contrib/Google_YoutubeService.php [deleted file]
lib/google/curlio.php
lib/google/external/URITemplateParser.php [deleted file]
lib/google/io/Google_CurlIO.php [deleted file]
lib/google/io/Google_HttpRequest.php [deleted file]
lib/google/io/Google_IO.php [deleted file]
lib/google/io/cacerts.pem [deleted file]
lib/google/readme_moodle.txt
lib/google/service/Google_MediaFileUpload.php [deleted file]
lib/google/service/Google_Model.php [deleted file]
lib/google/service/Google_ServiceResource.php [deleted file]
lib/thirdpartylibs.xml

old mode 100644 (file)
new mode 100755 (executable)
similarity index 57%
rename from lib/google/auth/Google_Auth.php
rename to lib/google/Google/Auth/Abstract.php
index 010782d..0832df3
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
-require_once "Google_AuthNone.php";
-require_once "Google_OAuth2.php";
+require_once "Google/Http/Request.php";
 
 /**
  * Abstract class for the Authentication in the API client
  * @author Chris Chabot <chabotc@google.com>
  *
  */
-abstract class Google_Auth {
-  abstract public function authenticate($service);
-  abstract public function sign(Google_HttpRequest $request);
-  abstract public function createAuthUrl($scope);
-
-  abstract public function getAccessToken();
-  abstract public function setAccessToken($accessToken);
-  abstract public function setDeveloperKey($developerKey);
-  abstract public function refreshToken($refreshToken);
-  abstract public function revokeToken();
+abstract class Google_Auth_Abstract
+{
+  /**
+   * An utility function that first calls $this->auth->sign($request) and then
+   * executes makeRequest() on that signed request. Used for when a request
+   * should be authenticated
+   * @param Google_Http_Request $request
+   * @return Google_Http_Request $request
+   */
+  abstract public function authenticatedRequest(Google_Http_Request $request);
+  abstract public function sign(Google_Http_Request $request);
 }
diff --git a/lib/google/Google/Auth/AppIdentity.php b/lib/google/Google/Auth/AppIdentity.php
new file mode 100755 (executable)
index 0000000..0be5917
--- /dev/null
@@ -0,0 +1,100 @@
+<?php
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * WARNING - this class depends on the Google App Engine PHP library
+ * which is 5.3 and above only, so if you include this in a PHP 5.2
+ * setup or one without 5.3 things will blow up.
+ */
+use google\appengine\api\app_identity\AppIdentityService;
+
+require_once "Google/Auth/Abstract.php";
+require_once "Google/Http/Request.php";
+
+/**
+ * Authentication via the Google App Engine App Identity service.
+ */
+class Google_Auth_AppIdentity extends Google_Auth_Abstract
+{
+  const CACHE_PREFIX = "Google_Auth_AppIdentity::";
+  const CACHE_LIFETIME = 1500;
+  private $key = null;
+  private $client;
+  private $token = false;
+  private $tokenScopes = false;
+
+  public function __construct(Google_Client $client, $config = null)
+  {
+    $this->client = $client;
+  }
+
+  /**
+   * Retrieve an access token for the scopes supplied.
+   */
+  public function authenticateForScope($scopes)
+  {
+    if ($this->token && $this->tokenScopes == $scopes) {
+      return $this->token;
+    }
+    $memcache = new Memcached();
+    $this->token = $memcache->get(self::CACHE_PREFIX . $scopes);
+    if (!$this->token) {
+      $this->token = AppIdentityService::getAccessToken($scopes);
+      if ($this->token) {
+        $memcache_key = self::CACHE_PREFIX;
+        if (is_string($scopes)) {
+          $memcache_key .= $scopes;
+        } else if (is_array($scopes)) {
+          $memcache_key .= implode(":", $scopes);
+        }
+        $memcache->set($memcache_key, $this->token, self::CACHE_LIFETIME);
+      }
+    }
+    $this->tokenScopes = $scopes;
+    return $this->token;
+  }
+
+  /**
+   * Perform an authenticated / signed apiHttpRequest.
+   * This function takes the apiHttpRequest, calls apiAuth->sign on it
+   * (which can modify the request in what ever way fits the auth mechanism)
+   * and then calls apiCurlIO::makeRequest on the signed request
+   *
+   * @param Google_Http_Request $request
+   * @return Google_Http_Request The resulting HTTP response including the
+   * responseHttpCode, responseHeaders and responseBody.
+   */
+  public function authenticatedRequest(Google_Http_Request $request)
+  {
+    $request = $this->sign($request);
+    return $this->io->makeRequest($request);
+  }
+
+  public function sign(Google_Http_Request $request)
+  {
+    if (!$this->token) {
+      // No token, so nothing to do.
+      return $request;
+    }
+    // Add the OAuth2 header to the request
+    $request->setRequestHeaders(
+        array('Authorization' => 'Bearer ' . $this->token['access_token'])
+    );
+
+    return $request;
+  }
+}
old mode 100644 (file)
new mode 100755 (executable)
similarity index 59%
rename from lib/google/auth/Google_AssertionCredentials.php
rename to lib/google/Google/Auth/AssertionCredentials.php
index 0d7aeb3..3db0a77
  * limitations under the License.
  */
 
+require_once "Google/Auth/OAuth2.php";
+require_once "Google/Signer/P12.php";
+require_once "Google/Utils.php";
+
 /**
  * Credentials object used for OAuth 2.0 Signed JWT assertion grants.
  *
  * @author Chirag Shah <chirags@google.com>
  */
-class Google_AssertionCredentials {
+class Google_Auth_AssertionCredentials
+{
   const MAX_TOKEN_LIFETIME_SECS = 3600;
 
   public $serviceAccountName;
@@ -28,7 +33,13 @@ class Google_AssertionCredentials {
   public $privateKey;
   public $privateKeyPassword;
   public $assertionType;
+  public $sub;
+  /**
+   * @deprecated
+   * @link http://tools.ietf.org/html/draft-ietf-oauth-json-web-token-06
+   */
   public $prn;
+  private $useCache;
 
   /**
    * @param $serviceAccountName
@@ -36,8 +47,10 @@ class Google_AssertionCredentials {
    * @param $privateKey
    * @param string $privateKeyPassword
    * @param string $assertionType
-   * @param bool|string $prn The email address of the user for which the
-   *               application is requesting delegated access.
+   * @param bool|string $sub The email address of the user for which the
+   *              application is requesting delegated access.
+   * @param bool useCache Whether to generate a cache key and allow
+   *              automatic caching of the generated token.
    */
   public function __construct(
       $serviceAccountName,
@@ -45,27 +58,51 @@ class Google_AssertionCredentials {
       $privateKey,
       $privateKeyPassword = 'notasecret',
       $assertionType = 'http://oauth.net/grant_type/jwt/1.0/bearer',
-      $prn = false) {
+      $sub = false,
+      $useCache = true
+  ) {
     $this->serviceAccountName = $serviceAccountName;
     $this->scopes = is_string($scopes) ? $scopes : implode(' ', $scopes);
     $this->privateKey = $privateKey;
     $this->privateKeyPassword = $privateKeyPassword;
     $this->assertionType = $assertionType;
-    $this->prn = $prn;
+    $this->sub = $sub;
+    $this->prn = $sub;
+    $this->useCache = $useCache;
+  }
+  
+  /**
+   * Generate a unique key to represent this credential.
+   * @return string
+   */
+  public function getCacheKey()
+  {
+    if (!$this->useCache) {
+      return false;
+    }
+    $h = $this->sub;
+    $h .= $this->assertionType;
+    $h .= $this->privateKey;
+    $h .= $this->scopes;
+    $h .= $this->serviceAccountName;
+    return md5($h);
   }
 
-  public function generateAssertion() {
+  public function generateAssertion()
+  {
     $now = time();
 
     $jwtParams = array(
-          'aud' => Google_OAuth2::OAUTH2_TOKEN_URI,
+          'aud' => Google_Auth_OAuth2::OAUTH2_TOKEN_URI,
           'scope' => $this->scopes,
           'iat' => $now,
           'exp' => $now + self::MAX_TOKEN_LIFETIME_SECS,
           'iss' => $this->serviceAccountName,
     );
 
-    if ($this->prn !== false) {
+    if ($this->sub !== false) {
+      $jwtParams['sub'] = $this->sub;
+    } else if ($this->prn !== false) {
       $jwtParams['prn'] = $this->prn;
     }
 
@@ -77,16 +114,22 @@ class Google_AssertionCredentials {
    * @param array $payload
    * @return string The signed JWT.
    */
-  private function makeSignedJwt($payload) {
+  private function makeSignedJwt($payload)
+  {
     $header = array('typ' => 'JWT', 'alg' => 'RS256');
 
+    $payload = json_encode($payload);
+    // Handle some overzealous escaping in PHP json that seemed to cause some errors
+    // with claimsets.
+    $payload = str_replace('\/', '/', $payload);
+
     $segments = array(
       Google_Utils::urlSafeB64Encode(json_encode($header)),
-      Google_Utils::urlSafeB64Encode(json_encode($payload))
+      Google_Utils::urlSafeB64Encode($payload)
     );
 
     $signingInput = implode('.', $segments);
-    $signer = new Google_P12Signer($this->privateKey, $this->privateKeyPassword);
+    $signer = new Google_Signer_P12($this->privateKey, $this->privateKeyPassword);
     $signature = $signer->sign($signingInput);
     $segments[] = Google_Utils::urlSafeB64Encode($signature);
 
diff --git a/lib/google/Google/Auth/Exception.php b/lib/google/Google/Auth/Exception.php
new file mode 100755 (executable)
index 0000000..65067ee
--- /dev/null
@@ -0,0 +1,22 @@
+<?php
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+require_once "Google/Exception.php";
+
+class Google_Auth_Exception extends Google_Exception
+{
+}
old mode 100644 (file)
new mode 100755 (executable)
similarity index 82%
rename from lib/google/auth/Google_LoginTicket.php
rename to lib/google/Google/Auth/LoginTicket.php
index c0ce614..bcf798a
  * limitations under the License.
  */
 
+require_once "Google/Auth/Exception.php";
+
 /**
  * Class to hold information about an authenticated login.
  *
  * @author Brian Eaton <beaton@google.com>
  */
-class Google_LoginTicket {
-  const USER_ATTR = "id";
+class Google_Auth_LoginTicket
+{
+  const USER_ATTR = "sub";
 
   // Information from id token envelope.
   private $envelope;
@@ -35,21 +38,23 @@ class Google_LoginTicket {
    * @param string $envelope Header from a verified authentication token.
    * @param string $payload Information from a verified authentication token.
    */
-  public function __construct($envelope, $payload) {
+  public function __construct($envelope, $payload)
+  {
     $this->envelope = $envelope;
     $this->payload = $payload;
   }
 
   /**
    * Returns the numeric identifier for the user.
-   * @throws Google_AuthException
+   * @throws Google_Auth_Exception
    * @return
    */
-  public function getUserId() {
+  public function getUserId()
+  {
     if (array_key_exists(self::USER_ATTR, $this->payload)) {
       return $this->payload[self::USER_ATTR];
     }
-    throw new Google_AuthException("No user_id in token");
+    throw new Google_Auth_Exception("No user_id in token");
   }
 
   /**
@@ -57,7 +62,8 @@ class Google_LoginTicket {
    * various information about the user session.
    * @return array
    */
-  public function getAttributes() {
+  public function getAttributes()
+  {
     return array("envelope" => $this->envelope, "payload" => $this->payload);
   }
 }
diff --git a/lib/google/Google/Auth/OAuth2.php b/lib/google/Google/Auth/OAuth2.php
new file mode 100755 (executable)
index 0000000..e5b6031
--- /dev/null
@@ -0,0 +1,595 @@
+<?php
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+require_once "Google/Auth/Abstract.php";
+require_once "Google/Auth/AssertionCredentials.php";
+require_once "Google/Auth/Exception.php";
+require_once "Google/Auth/LoginTicket.php";
+require_once "Google/Client.php";
+require_once "Google/Http/Request.php";
+require_once "Google/Utils.php";
+require_once "Google/Verifier/Pem.php";
+
+/**
+ * Authentication class that deals with the OAuth 2 web-server authentication flow
+ *
+ * @author Chris Chabot <chabotc@google.com>
+ * @author Chirag Shah <chirags@google.com>
+ *
+ */
+class Google_Auth_OAuth2 extends Google_Auth_Abstract
+{
+  const OAUTH2_REVOKE_URI = 'https://accounts.google.com/o/oauth2/revoke';
+  const OAUTH2_TOKEN_URI = 'https://accounts.google.com/o/oauth2/token';
+  const OAUTH2_AUTH_URL = 'https://accounts.google.com/o/oauth2/auth';
+  const CLOCK_SKEW_SECS = 300; // five minutes in seconds
+  const AUTH_TOKEN_LIFETIME_SECS = 300; // five minutes in seconds
+  const MAX_TOKEN_LIFETIME_SECS = 86400; // one day in seconds
+  const OAUTH2_ISSUER = 'accounts.google.com';
+
+  /** @var Google_Auth_AssertionCredentials $assertionCredentials */
+  private $assertionCredentials;
+
+  /**
+   * @var string The state parameters for CSRF and other forgery protection.
+   */
+  private $state;
+
+  /**
+   * @var array The token bundle.
+   */
+  private $token = array();
+
+  /**
+   * @var Google_Client the base client
+   */
+  private $client;
+
+  /**
+   * Instantiates the class, but does not initiate the login flow, leaving it
+   * to the discretion of the caller.
+   */
+  public function __construct(Google_Client $client)
+  {
+    $this->client = $client;
+  }
+
+  /**
+   * Perform an authenticated / signed apiHttpRequest.
+   * This function takes the apiHttpRequest, calls apiAuth->sign on it
+   * (which can modify the request in what ever way fits the auth mechanism)
+   * and then calls apiCurlIO::makeRequest on the signed request
+   *
+   * @param Google_Http_Request $request
+   * @return Google_Http_Request The resulting HTTP response including the
+   * responseHttpCode, responseHeaders and responseBody.
+   */
+  public function authenticatedRequest(Google_Http_Request $request)
+  {
+    $request = $this->sign($request);
+    return $this->client->getIo()->makeRequest($request);
+  }
+
+  /**
+   * @param string $code
+   * @throws Google_Auth_Exception
+   * @return string
+   */
+  public function authenticate($code)
+  {
+    if (strlen($code) == 0) {
+      throw new Google_Auth_Exception("Invalid code");
+    }
+
+    // We got here from the redirect from a successful authorization grant,
+    // fetch the access token
+    $request = new Google_Http_Request(
+        self::OAUTH2_TOKEN_URI,
+        'POST',
+        array(),
+        array(
+          'code' => $code,
+          'grant_type' => 'authorization_code',
+          'redirect_uri' => $this->client->getClassConfig($this, 'redirect_uri'),
+          'client_id' => $this->client->getClassConfig($this, 'client_id'),
+          'client_secret' => $this->client->getClassConfig($this, 'client_secret')
+        )
+    );
+    $request->disableGzip();
+    $response = $this->client->getIo()->makeRequest($request);
+
+    if ($response->getResponseHttpCode() == 200) {
+      $this->setAccessToken($response->getResponseBody());
+      $this->token['created'] = time();
+      return $this->getAccessToken();
+    } else {
+      $decodedResponse = json_decode($response->getResponseBody(), true);
+      if ($decodedResponse != null && $decodedResponse['error']) {
+        $decodedResponse = $decodedResponse['error'];
+      }
+      throw new Google_Auth_Exception(
+          sprintf(
+              "Error fetching OAuth2 access token, message: '%s'",
+              $decodedResponse
+          ),
+          $response->getResponseHttpCode()
+      );
+    }
+  }
+
+  /**
+   * Create a URL to obtain user authorization.
+   * The authorization endpoint allows the user to first
+   * authenticate, and then grant/deny the access request.
+   * @param string $scope The scope is expressed as a list of space-delimited strings.
+   * @return string
+   */
+  public function createAuthUrl($scope)
+  {
+    $params = array(
+        'response_type' => 'code',
+        'redirect_uri' => $this->client->getClassConfig($this, 'redirect_uri'),
+        'client_id' => $this->client->getClassConfig($this, 'client_id'),
+        'scope' => $scope,
+        'access_type' => $this->client->getClassConfig($this, 'access_type'),
+        'approval_prompt' => $this->client->getClassConfig($this, 'approval_prompt'),
+    );
+
+    $login_hint = $this->client->getClassConfig($this, 'login_hint');
+    if ($login_hint != '') {
+      $params['login_hint'] = $login_hint;
+    }
+
+    // If the list of scopes contains plus.login, add request_visible_actions
+    // to auth URL.
+    $rva = $this->client->getClassConfig($this, 'request_visible_actions');
+    if (strpos($scope, 'plus.login') && strlen($rva) > 0) {
+        $params['request_visible_actions'] = $rva;
+    }
+
+    if (isset($this->state)) {
+      $params['state'] = $this->state;
+    }
+
+    return self::OAUTH2_AUTH_URL . "?" . http_build_query($params, '', '&');
+  }
+
+  /**
+   * @param string $token
+   * @throws Google_Auth_Exception
+   */
+  public function setAccessToken($token)
+  {
+    $token = json_decode($token, true);
+    if ($token == null) {
+      throw new Google_Auth_Exception('Could not json decode the token');
+    }
+    if (! isset($token['access_token'])) {
+      throw new Google_Auth_Exception("Invalid token format");
+    }
+    $this->token = $token;
+  }
+
+  public function getAccessToken()
+  {
+    return json_encode($this->token);
+  }
+
+  public function setState($state)
+  {
+    $this->state = $state;
+  }
+
+  public function setAssertionCredentials(Google_Auth_AssertionCredentials $creds)
+  {
+    $this->assertionCredentials = $creds;
+  }
+
+  /**
+   * Include an accessToken in a given apiHttpRequest.
+   * @param Google_Http_Request $request
+   * @return Google_Http_Request
+   * @throws Google_Auth_Exception
+   */
+  public function sign(Google_Http_Request $request)
+  {
+    // add the developer key to the request before signing it
+    if ($this->client->getClassConfig($this, 'developer_key')) {
+      $request->setQueryParam('key', $this->client->getClassConfig($this, 'developer_key'));
+    }
+
+    // Cannot sign the request without an OAuth access token.
+    if (null == $this->token && null == $this->assertionCredentials) {
+      return $request;
+    }
+
+    // Check if the token is set to expire in the next 30 seconds
+    // (or has already expired).
+    if ($this->isAccessTokenExpired()) {
+      if ($this->assertionCredentials) {
+        $this->refreshTokenWithAssertion();
+      } else {
+        if (! array_key_exists('refresh_token', $this->token)) {
+            throw new Google_Auth_Exception(
+                "The OAuth 2.0 access token has expired,"
+                ." and a refresh token is not available. Refresh tokens"
+                ." are not returned for responses that were auto-approved."
+            );
+        }
+        $this->refreshToken($this->token['refresh_token']);
+      }
+    }
+
+    // Add the OAuth2 header to the request
+    $request->setRequestHeaders(
+        array('Authorization' => 'Bearer ' . $this->token['access_token'])
+    );
+
+    return $request;
+  }
+
+  /**
+   * Fetches a fresh access token with the given refresh token.
+   * @param string $refreshToken
+   * @return void
+   */
+  public function refreshToken($refreshToken)
+  {
+    $this->refreshTokenRequest(
+        array(
+          'client_id' => $this->client->getClassConfig($this, 'client_id'),
+          'client_secret' => $this->client->getClassConfig($this, 'client_secret'),
+          'refresh_token' => $refreshToken,
+          'grant_type' => 'refresh_token'
+        )
+    );
+  }
+
+  /**
+   * Fetches a fresh access token with a given assertion token.
+   * @param Google_Auth_AssertionCredentials $assertionCredentials optional.
+   * @return void
+   */
+  public function refreshTokenWithAssertion($assertionCredentials = null)
+  {
+    if (!$assertionCredentials) {
+      $assertionCredentials = $this->assertionCredentials;
+    }
+
+    $cacheKey = $assertionCredentials->getCacheKey();
+
+    if ($cacheKey) {
+      // We can check whether we have a token available in the
+      // cache. If it is expired, we can retrieve a new one from
+      // the assertion.
+      $token = $this->client->getCache()->get($cacheKey);
+      if ($token) {
+        $this->setAccessToken($token);
+      }
+      if (!$this->isAccessTokenExpired()) {
+        return;
+      }
+    }
+
+    $this->refreshTokenRequest(
+        array(
+          'grant_type' => 'assertion',
+          'assertion_type' => $assertionCredentials->assertionType,
+          'assertion' => $assertionCredentials->generateAssertion(),
+        )
+    );
+
+    if ($cacheKey) {
+      // Attempt to cache the token.
+      $this->client->getCache()->set(
+          $cacheKey,
+          $this->getAccessToken()
+      );
+    }
+  }
+
+  private function refreshTokenRequest($params)
+  {
+    $http = new Google_Http_Request(
+        self::OAUTH2_TOKEN_URI,
+        'POST',
+        array(),
+        $params
+    );
+    $http->disableGzip();
+    $request = $this->client->getIo()->makeRequest($http);
+
+    $code = $request->getResponseHttpCode();
+    $body = $request->getResponseBody();
+    if (200 == $code) {
+      $token = json_decode($body, true);
+      if ($token == null) {
+        throw new Google_Auth_Exception("Could not json decode the access token");
+      }
+
+      if (! isset($token['access_token']) || ! isset($token['expires_in'])) {
+        throw new Google_Auth_Exception("Invalid token format");
+      }
+
+      if (isset($token['id_token'])) {
+        $this->token['id_token'] = $token['id_token'];
+      }
+      $this->token['access_token'] = $token['access_token'];
+      $this->token['expires_in'] = $token['expires_in'];
+      $this->token['created'] = time();
+    } else {
+      throw new Google_Auth_Exception("Error refreshing the OAuth2 token, message: '$body'", $code);
+    }
+  }
+
+  /**
+   * Revoke an OAuth2 access token or refresh token. This method will revoke the current access
+   * token, if a token isn't provided.
+   * @throws Google_Auth_Exception
+   * @param string|null $token The token (access token or a refresh token) that should be revoked.
+   * @return boolean Returns True if the revocation was successful, otherwise False.
+   */
+  public function revokeToken($token = null)
+  {
+    if (!$token) {
+      if (!$this->token) {
+        // Not initialized, no token to actually revoke
+        return false;
+      } elseif (array_key_exists('refresh_token', $this->token)) {
+        $token = $this->token['refresh_token'];
+      } else {
+        $token = $this->token['access_token'];
+      }
+    }
+    $request = new Google_Http_Request(
+        self::OAUTH2_REVOKE_URI,
+        'POST',
+        array(),
+        "token=$token"
+    );
+    $request->disableGzip();
+    $response = $this->client->getIo()->makeRequest($request);
+    $code = $response->getResponseHttpCode();
+    if ($code == 200) {
+      $this->token = null;
+      return true;
+    }
+
+    return false;
+  }
+
+  /**
+   * Returns if the access_token is expired.
+   * @return bool Returns True if the access_token is expired.
+   */
+  public function isAccessTokenExpired()
+  {
+    if (!$this->token || !isset($this->token['created'])) {
+      return true;
+    }
+
+    // If the token is set to expire in the next 30 seconds.
+    $expired = ($this->token['created']
+        + ($this->token['expires_in'] - 30)) < time();
+
+    return $expired;
+  }
+
+  // Gets federated sign-on certificates to use for verifying identity tokens.
+  // Returns certs as array structure, where keys are key ids, and values
+  // are PEM encoded certificates.
+  private function getFederatedSignOnCerts()
+  {
+    return $this->retrieveCertsFromLocation(
+        $this->client->getClassConfig($this, 'federated_signon_certs_url')
+    );
+  }
+
+  /**
+   * Retrieve and cache a certificates file.
+   * @param $url location
+   * @return array certificates
+   */
+  public function retrieveCertsFromLocation($url)
+  {
+    // If we're retrieving a local file, just grab it.
+    if ("http" != substr($url, 0, 4)) {
+      $file = file_get_contents($url);
+      if ($file) {
+        return json_decode($file, true);
+      } else {
+        throw new Google_Auth_Exception(
+            "Failed to retrieve verification certificates: '" .
+            $url . "'."
+        );
+      }
+    }
+
+    // This relies on makeRequest caching certificate responses.
+    $request = $this->client->getIo()->makeRequest(
+        new Google_Http_Request(
+            $url
+        )
+    );
+    if ($request->getResponseHttpCode() == 200) {
+      $certs = json_decode($request->getResponseBody(), true);
+      if ($certs) {
+        return $certs;
+      }
+    }
+    throw new Google_Auth_Exception(
+        "Failed to retrieve verification certificates: '" .
+        $request->getResponseBody() . "'.",
+        $request->getResponseHttpCode()
+    );
+  }
+
+  /**
+   * Verifies an id token and returns the authenticated apiLoginTicket.
+   * Throws an exception if the id token is not valid.
+   * The audience parameter can be used to control which id tokens are
+   * accepted.  By default, the id token must have been issued to this OAuth2 client.
+   *
+   * @param $id_token
+   * @param $audience
+   * @return Google_Auth_LoginTicket
+   */
+  public function verifyIdToken($id_token = null, $audience = null)
+  {
+    if (!$id_token) {
+      $id_token = $this->token['id_token'];
+    }
+    $certs = $this->getFederatedSignonCerts();
+    if (!$audience) {
+      $audience = $this->client->getClassConfig($this, 'client_id');
+    }
+
+    return $this->verifySignedJwtWithCerts($id_token, $certs, $audience, self::OAUTH2_ISSUER);
+  }
+
+  /**
+   * Verifies the id token, returns the verified token contents.
+   *
+   * @param $jwt the token
+   * @param $certs array of certificates
+   * @param $required_audience the expected consumer of the token
+   * @param [$issuer] the expected issues, defaults to Google
+   * @param [$max_expiry] the max lifetime of a token, defaults to MAX_TOKEN_LIFETIME_SECS
+   * @return token information if valid, false if not
+   */
+  public function verifySignedJwtWithCerts(
+      $jwt,
+      $certs,
+      $required_audience,
+      $issuer = null,
+      $max_expiry = null
+  ) {
+    if (!$max_expiry) {
+      // Set the maximum time we will accept a token for.
+      $max_expiry = self::MAX_TOKEN_LIFETIME_SECS;
+    }
+
+    $segments = explode(".", $jwt);
+    if (count($segments) != 3) {
+      throw new Google_Auth_Exception("Wrong number of segments in token: $jwt");
+    }
+    $signed = $segments[0] . "." . $segments[1];
+    $signature = Google_Utils::urlSafeB64Decode($segments[2]);
+
+    // Parse envelope.
+    $envelope = json_decode(Google_Utils::urlSafeB64Decode($segments[0]), true);
+    if (!$envelope) {
+      throw new Google_Auth_Exception("Can't parse token envelope: " . $segments[0]);
+    }
+
+    // Parse token
+    $json_body = Google_Utils::urlSafeB64Decode($segments[1]);
+    $payload = json_decode($json_body, true);
+    if (!$payload) {
+      throw new Google_Auth_Exception("Can't parse token payload: " . $segments[1]);
+    }
+
+    // Check signature
+    $verified = false;
+    foreach ($certs as $keyName => $pem) {
+      $public_key = new Google_Verifier_Pem($pem);
+      if ($public_key->verify($signed, $signature)) {
+        $verified = true;
+        break;
+      }
+    }
+
+    if (!$verified) {
+      throw new Google_Auth_Exception("Invalid token signature: $jwt");
+    }
+
+    // Check issued-at timestamp
+    $iat = 0;
+    if (array_key_exists("iat", $payload)) {
+      $iat = $payload["iat"];
+    }
+    if (!$iat) {
+      throw new Google_Auth_Exception("No issue time in token: $json_body");
+    }
+    $earliest = $iat - self::CLOCK_SKEW_SECS;
+
+    // Check expiration timestamp
+    $now = time();
+    $exp = 0;
+    if (array_key_exists("exp", $payload)) {
+      $exp = $payload["exp"];
+    }
+    if (!$exp) {
+      throw new Google_Auth_Exception("No expiration time in token: $json_body");
+    }
+    if ($exp >= $now + $max_expiry) {
+      throw new Google_Auth_Exception(
+          sprintf("Expiration time too far in future: %s", $json_body)
+      );
+    }
+
+    $latest = $exp + self::CLOCK_SKEW_SECS;
+    if ($now < $earliest) {
+      throw new Google_Auth_Exception(
+          sprintf(
+              "Token used too early, %s < %s: %s",
+              $now,
+              $earliest,
+              $json_body
+          )
+      );
+    }
+    if ($now > $latest) {
+      throw new Google_Auth_Exception(
+          sprintf(
+              "Token used too late, %s > %s: %s",
+              $now,
+              $latest,
+              $json_body
+          )
+      );
+    }
+
+    $iss = $payload['iss'];
+    if ($issuer && $iss != $issuer) {
+      throw new Google_Auth_Exception(
+          sprintf(
+              "Invalid issuer, %s != %s: %s",
+              $iss,
+              $issuer,
+              $json_body
+          )
+      );
+    }
+
+    // Check audience
+    $aud = $payload["aud"];
+    if ($aud != $required_audience) {
+      throw new Google_Auth_Exception(
+          sprintf(
+              "Wrong recipient, %s != %s:",
+              $aud,
+              $required_audience,
+              $json_body
+          )
+      );
+    }
+
+    // All good.
+    return new Google_Auth_LoginTicket($envelope, $payload);
+  }
+}
diff --git a/lib/google/Google/Auth/Simple.php b/lib/google/Google/Auth/Simple.php
new file mode 100755 (executable)
index 0000000..e83900f
--- /dev/null
@@ -0,0 +1,62 @@
+<?php
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+require_once "Google/Auth/Abstract.php";
+require_once "Google/Http/Request.php";
+
+/**
+ * Simple API access implementation. Can either be used to make requests
+ * completely unauthenticated, or by using a Simple API Access developer
+ * key.
+ * @author Chris Chabot <chabotc@google.com>
+ * @author Chirag Shah <chirags@google.com>
+ */
+class Google_Auth_Simple extends Google_Auth_Abstract
+{
+  private $key = null;
+  private $client;
+
+  public function __construct(Google_Client $client, $config = null)
+  {
+    $this->client = $client;
+  }
+
+  /**
+   * Perform an authenticated / signed apiHttpRequest.
+   * This function takes the apiHttpRequest, calls apiAuth->sign on it
+   * (which can modify the request in what ever way fits the auth mechanism)
+   * and then calls apiCurlIO::makeRequest on the signed request
+   *
+   * @param Google_Http_Request $request
+   * @return Google_Http_Request The resulting HTTP response including the
+   * responseHttpCode, responseHeaders and responseBody.
+   */
+  public function authenticatedRequest(Google_Http_Request $request)
+  {
+    $request = $this->sign($request);
+    return $this->io->makeRequest($request);
+  }
+
+  public function sign(Google_Http_Request $request)
+  {
+    $key = $this->client->getClassConfig($this, 'developer_key');
+    if ($key) {
+      $request->setQueryParam('key', $key);
+    }
+    return $request;
+  }
+}
old mode 100644 (file)
new mode 100755 (executable)
similarity index 82%
rename from lib/google/cache/Google_Cache.php
rename to lib/google/Google/Cache/Abstract.php
index 809c55e..ff19f36
  * limitations under the License.
  */
 
-require_once "Google_FileCache.php";
-require_once "Google_MemcacheCache.php";
-
 /**
  * Abstract storage class
  *
  * @author Chris Chabot <chabotc@google.com>
  */
-abstract class Google_Cache {
+abstract class Google_Cache_Abstract
+{
+  
+  abstract public function __construct(Google_Client $client);
 
   /**
    * Retrieves the data for the given key, or false if they
@@ -33,7 +33,7 @@ abstract class Google_Cache {
    * @param boolean|int $expiration Expiration time in seconds
    *
    */
-  abstract function get($key, $expiration = false);
+  abstract public function get($key, $expiration = false);
 
   /**
    * Store the key => $value set. The $value is serialized
@@ -42,14 +42,12 @@ abstract class Google_Cache {
    * @param string $key Key of the data
    * @param string $value data
    */
-  abstract function set($key, $value);
+  abstract public function set($key, $value);
 
   /**
    * Removes the key/data pair for the given $key
    *
    * @param String $key
    */
-  abstract function delete($key);
+  abstract public function delete($key);
 }
-
-
diff --git a/lib/google/Google/Cache/Apc.php b/lib/google/Google/Cache/Apc.php
new file mode 100755 (executable)
index 0000000..051b537
--- /dev/null
@@ -0,0 +1,73 @@
+<?php
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+require_once "Google/Cache/Abstract.php";
+require_once "Google/Cache/Exception.php";
+
+/**
+ * A persistent storage class based on the APC cache, which is not
+ * really very persistent, as soon as you restart your web server
+ * the storage will be wiped, however for debugging and/or speed
+ * it can be useful, and cache is a lot cheaper then storage.
+ *
+ * @author Chris Chabot <chabotc@google.com>
+ */
+class Google_Cache_Apc extends Google_Cache_Abstract
+{
+  public function __construct(Google_Client $client)
+  {
+    if (! function_exists('apc_add') ) {
+      throw new Google_Cache_Exception("Apc functions not available");
+    }
+  }
+
+   /**
+   * @inheritDoc
+   */
+  public function get($key, $expiration = false)
+  {
+    $ret = apc_fetch($key);
+    if ($ret === false) {
+      return false;
+    }
+    if (is_numeric($expiration) && (time() - $ret['time'] > $expiration)) {
+      $this->delete($key);
+      return false;
+    }
+    return $ret['data'];
+  }
+
+  /**
+   * @inheritDoc
+   */
+  public function set($key, $value)
+  {
+    $rc = apc_store($key, array('time' => time(), 'data' => $value));
+    if ($rc == false) {
+      throw new Google_Cache_Exception("Couldn't store data");
+    }
+  }
+
+  /**
+   * @inheritDoc
+   * @param String $key
+   */
+  public function delete($key)
+  {
+    apc_delete($key);
+  }
+}
diff --git a/lib/google/Google/Cache/Exception.php b/lib/google/Google/Cache/Exception.php
new file mode 100755 (executable)
index 0000000..23b6246
--- /dev/null
@@ -0,0 +1,21 @@
+<?php
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+require_once "Google/Exception.php";
+
+class Google_Cache_Exception extends Google_Exception
+{
+}
diff --git a/lib/google/Google/Cache/File.php b/lib/google/Google/Cache/File.php
new file mode 100755 (executable)
index 0000000..8d0d62f
--- /dev/null
@@ -0,0 +1,145 @@
+<?php
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+require_once "Google/Cache/Abstract.php";
+require_once "Google/Cache/Exception.php";
+
+/*
+ * This class implements a basic on disk storage. While that does
+ * work quite well it's not the most elegant and scalable solution.
+ * It will also get you into a heap of trouble when you try to run
+ * this in a clustered environment.
+ *
+ * @author Chris Chabot <chabotc@google.com>
+ */
+class Google_Cache_File extends Google_Cache_Abstract
+{
+  const MAX_LOCK_RETRIES = 10;
+  private $path;
+  private $fh;
+
+  public function __construct(Google_Client $client)
+  {
+    $this->path = $client->getClassConfig($this, 'directory');
+  }
+  
+  public function get($key, $expiration = false)
+  {
+    $storageFile = $this->getCacheFile($key);
+    $data = false;
+    
+    if (!file_exists($storageFile)) {
+      return false;
+    }
+
+    if ($expiration) {
+      $mtime = filemtime($storageFile);
+      if ((time() - $mtime) >= $expiration) {
+        $this->delete($key);
+        return false;
+      }
+    }
+
+    if ($this->acquireReadLock($storageFile)) {
+      $data = fread($this->fh, filesize($storageFile));
+      $data =  unserialize($data);
+      $this->unlock($storageFile);
+    }
+
+    return $data;
+  }
+
+  public function set($key, $value)
+  {
+    $storageFile = $this->getWriteableCacheFile($key);
+    if ($this->acquireWriteLock($storageFile)) {
+      // We serialize the whole request object, since we don't only want the
+      // responseContent but also the postBody used, headers, size, etc.
+      $data = serialize($value);
+      $result = fwrite($this->fh, $data);
+      $this->unlock($storageFile);
+    }
+  }
+
+  public function delete($key)
+  {
+    $file = $this->getCacheFile($key);
+    if (file_exists($file) && !unlink($file)) {
+      throw new Google_Cache_Exception("Cache file could not be deleted");
+    }
+  }
+  
+  private function getWriteableCacheFile($file)
+  {
+    return $this->getCacheFile($file, true);
+  }
+
+  private function getCacheFile($file, $forWrite = false)
+  {
+    return $this->getCacheDir($file, $forWrite) . '/' . md5($file);
+  }
+  
+  private function getCacheDir($file, $forWrite)
+  {
+    // use the first 2 characters of the hash as a directory prefix
+    // this should prevent slowdowns due to huge directory listings
+    // and thus give some basic amount of scalability
+    $storageDir = $this->path . '/' . substr(md5($file), 0, 2);
+    if ($forWrite && ! is_dir($storageDir)) {
+      if (! mkdir($storageDir, 0755, true)) {
+        throw new Google_Cache_Exception("Could not create storage directory: $storageDir");
+      }
+    }
+    return $storageDir;
+  }
+  
+  private function acquireReadLock($storageFile)
+  {
+    return $this->acquireLock(LOCK_SH, $storageFile);
+  }
+  
+  private function acquireWriteLock($storageFile)
+  {
+    $rc = $this->acquireLock(LOCK_EX, $storageFile);
+    if (!$rc) {
+      $this->delete($storageFile);
+    }
+    return $rc;
+  }
+  
+  private function acquireLock($type, $storageFile)
+  {
+    $mode = $type == LOCK_EX ? "w" : "r";
+    $this->fh = fopen($storageFile, $mode);
+    $count = 0;
+    while (!flock($this->fh, $type | LOCK_NB)) {
+      // Sleep for 10ms.
+      usleep(10000);
+      if (++$count < self::MAX_LOCK_RETRIES) {
+        return false;
+      }
+    }
+    return true;
+  }
+  
+  public function unlock($storageFile)
+  {
+    if ($this->fh) {
+      flock($this->fh, LOCK_UN);
+    }
+  }
+}
diff --git a/lib/google/Google/Cache/Memcache.php b/lib/google/Google/Cache/Memcache.php
new file mode 100755 (executable)
index 0000000..56676c2
--- /dev/null
@@ -0,0 +1,137 @@
+<?php
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+require_once "Google/Cache/Abstract.php";
+require_once "Google/Cache/Exception.php";
+
+/**
+ * A persistent storage class based on the memcache, which is not
+ * really very persistent, as soon as you restart your memcache daemon
+ * the storage will be wiped.
+ *
+ * Will use either the memcache or memcached extensions, preferring
+ * memcached.
+ *
+ * @author Chris Chabot <chabotc@google.com>
+ */
+class Google_Cache_Memcache extends Google_Cache_Abstract
+{
+  private $connection = false;
+  private $mc = false;
+  private $host;
+  private $port;
+
+  public function __construct(Google_Client $client)
+  {
+    if (!function_exists('memcache_connect') && !class_exists("Memcached")) {
+      throw new Google_Cache_Exception("Memcache functions not available");
+    }
+    if ($client->isAppEngine()) {
+      // No credentials needed for GAE.
+      $this->mc = new Memcached();
+      $this->connection = true;
+    } else {
+      $this->host = $client->getClassConfig($this, 'host');
+      $this->port = $client->getClassConfig($this, 'port');
+      if (empty($this->host) || empty($this->port)) {
+        throw new Google_Cache_Exception("You need to supply a valid memcache host and port");
+      }
+    }
+  }
+  
+  /**
+   * @inheritDoc
+   */
+  public function get($key, $expiration = false)
+  {
+    $this->connect();
+    $ret = false;
+    if ($this->mc) {
+      $ret = $this->mc->get($key);
+    } else {
+      $ret = memcache_get($this->connection, $key);
+    }
+    if ($ret === false) {
+      return false;
+    }
+    if (is_numeric($expiration) && (time() - $ret['time'] > $expiration)) {
+      $this->delete($key);
+      return false;
+    }
+    return $ret['data'];
+  }
+
+  /**
+   * @inheritDoc
+   * @param string $key
+   * @param string $value
+   * @throws Google_Cache_Exception
+   */
+  public function set($key, $value)
+  {
+    $this->connect();
+    // we store it with the cache_time default expiration so objects will at
+    // least get cleaned eventually.
+    $data = array('time' => time(), 'data' => $value);
+    $rc = false;
+    if ($this->mc) {
+      $rc = $this->mc->set($key, $data);
+    } else {
+      $rc = memcache_set($this->connection, $key, $data, false);
+    }
+    if ($rc == false) {
+      throw new Google_Cache_Exception("Couldn't store data in cache");
+    }
+  }
+
+  /**
+   * @inheritDoc
+   * @param String $key
+   */
+  public function delete($key)
+  {
+    $this->connect();
+    if ($this->mc) {
+      $this->mc->delete($key, 0);
+    } else {
+      memcache_delete($this->connection, $key, 0);
+    }
+  }
+
+  /**
+   * Lazy initialiser for memcache connection. Uses pconnect for to take 
+   * advantage of the persistence pool where possible. 
+   */
+  private function connect()
+  {
+    if ($this->connection) {
+      return;
+    }
+
+    if (class_exists("Memcached")) {
+      $this->mc = new Memcached();
+      $this->mc->addServer($this->host, $this->port);
+       $this->connection = true;
+    } else {
+      $this->connection = memcache_pconnect($this->host, $this->port);
+    }
+    
+    if (! $this->connection) {
+      throw new Google_Cache_Exception("Couldn't connect to memcache server");
+    }
+  }
+}
diff --git a/lib/google/Google/Cache/Null.php b/lib/google/Google/Cache/Null.php
new file mode 100755 (executable)
index 0000000..0e33631
--- /dev/null
@@ -0,0 +1,56 @@
+<?php
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+require_once "Google/Cache/Abstract.php";
+require_once "Google/Cache/Exception.php";
+
+/**
+ * A blank storage class, for cases where caching is not
+ * required.
+ */
+class Google_Cache_Null extends Google_Cache_Abstract
+{
+  public function __construct(Google_Client $client)
+  {
+
+  }
+
+   /**
+   * @inheritDoc
+   */
+  public function get($key, $expiration = false)
+  {
+    return false;
+  }
+
+  /**
+   * @inheritDoc
+   */
+  public function set($key, $value)
+  {
+    // Nop.
+  }
+
+  /**
+   * @inheritDoc
+   * @param String $key
+   */
+  public function delete($key)
+  {
+    // Nop.
+  }
+}
diff --git a/lib/google/Google/Client.php b/lib/google/Google/Client.php
new file mode 100755 (executable)
index 0000000..1ec2f32
--- /dev/null
@@ -0,0 +1,612 @@
+<?php
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+require_once 'Google/Auth/AssertionCredentials.php';
+require_once 'Google/Cache/File.php';
+require_once 'Google/Cache/Memcache.php';
+require_once 'Google/Config.php';
+require_once 'Google/Collection.php';
+require_once 'Google/Exception.php';
+require_once 'Google/IO/Curl.php';
+require_once 'Google/IO/Stream.php';
+require_once 'Google/Model.php';
+require_once 'Google/Service.php';
+require_once 'Google/Service/Resource.php';
+
+/**
+ * The Google API Client
+ * http://code.google.com/p/google-api-php-client/
+ *
+ * @author Chris Chabot <chabotc@google.com>
+ * @author Chirag Shah <chirags@google.com>
+ */
+class Google_Client
+{
+  const LIBVER = "1.0.5-beta";
+  const USER_AGENT_SUFFIX = "google-api-php-client/";
+  /**
+   * @var Google_Auth_Abstract $auth
+   */
+  private $auth;
+
+  /**
+   * @var Google_IO_Abstract $io
+   */
+  private $io;
+
+  /**
+   * @var Google_Cache_Abstract $cache
+   */
+  private $cache;
+
+  /**
+   * @var Google_Config $config
+   */
+  private $config;
+
+  /**
+   * @var boolean $deferExecution
+   */
+  private $deferExecution = false;
+
+  /** @var array $scopes */
+  // Scopes requested by the client
+  protected $requestedScopes = array();
+
+  // definitions of services that are discovered.
+  protected $services = array();
+
+  // Used to track authenticated state, can't discover services after doing authenticate()
+  private $authenticated = false;
+
+  /**
+   * Construct the Google Client.
+   *
+   * @param $config Google_Config or string for the ini file to load
+   */
+  public function __construct($config = null)
+  {
+    if (is_string($config) && strlen($config)) {
+      $config = new Google_Config($config);
+    } else if ( !($config instanceof Google_Config)) {
+      $config = new Google_Config();
+
+      if ($this->isAppEngine()) {
+        // Automatically use Memcache if we're in AppEngine.
+        $config->setCacheClass('Google_Cache_Memcache');
+      }
+
+      if (version_compare(phpversion(), "5.3.4", "<=") || $this->isAppEngine()) {
+        // Automatically disable compress.zlib, as currently unsupported.
+        $config->setClassConfig('Google_Http_Request', 'disable_gzip', true);
+      }
+    }
+
+    if ($config->getIoClass() == Google_Config::USE_AUTO_IO_SELECTION) {
+      if (function_exists('curl_version') && function_exists('curl_exec')) {
+        $config->setIoClass("Google_IO_Curl");
+      } else {
+        $config->setIoClass("Google_IO_Stream");
+      }
+    }
+
+    $this->config = $config;
+  }
+
+  /**
+   * Get a string containing the version of the library.
+   *
+   * @return string
+   */
+  public function getLibraryVersion()
+  {
+    return self::LIBVER;
+  }
+
+  /**
+   * Attempt to exchange a code for an valid authentication token.
+   * Helper wrapped around the OAuth 2.0 implementation.
+   *
+   * @param $code string code from accounts.google.com
+   * @return string token
+   */
+  public function authenticate($code)
+  {
+    $this->authenticated = true;
+    return $this->getAuth()->authenticate($code);
+  }
+
+  /**
+   * Set the auth config from the JSON string provided.
+   * This structure should match the file downloaded from
+   * the "Download JSON" button on in the Google Developer
+   * Console.
+   * @param string $json the configuration json
+   */
+  public function setAuthConfig($json)
+  {
+    $data = json_decode($json);
+    $key = isset($data->installed) ? 'installed' : 'web';
+    if (!isset($data->$key)) {
+      throw new Google_Exception("Invalid client secret JSON file.");
+    }
+    $this->setClientId($data->$key->client_id);
+    $this->setClientSecret($data->$key->client_secret);
+    if (isset($data->$key->redirect_uris)) {
+      $this->setRedirectUri($data->$key->redirect_uris[0]);
+    }
+  }
+
+  /**
+   * Set the auth config from the JSON file in the path
+   * provided. This should match the file downloaded from
+   * the "Download JSON" button on in the Google Developer
+   * Console.
+   * @param string $file the file location of the client json
+   */
+  public function setAuthConfigFile($file)
+  {
+    $this->setAuthConfig(file_get_contents($file));
+  }
+
+  /**
+   * @return array
+   * @visible For Testing
+   */
+  public function prepareScopes()
+  {
+    if (empty($this->requestedScopes)) {
+      throw new Google_Auth_Exception("No scopes specified");
+    }
+    $scopes = implode(' ', $this->requestedScopes);
+    return $scopes;
+  }
+
+  /**
+   * Set the OAuth 2.0 access token using the string that resulted from calling createAuthUrl()
+   * or Google_Client#getAccessToken().
+   * @param string $accessToken JSON encoded string containing in the following format:
+   * {"access_token":"TOKEN", "refresh_token":"TOKEN", "token_type":"Bearer",
+   *  "expires_in":3600, "id_token":"TOKEN", "created":1320790426}
+   */
+  public function setAccessToken($accessToken)
+  {
+    if ($accessToken == 'null') {
+      $accessToken = null;
+    }
+    $this->getAuth()->setAccessToken($accessToken);
+  }
+
+
+
+  /**
+   * Set the authenticator object
+   * @param Google_Auth_Abstract $auth
+   */
+  public function setAuth(Google_Auth_Abstract $auth)
+  {
+    $this->config->setAuthClass(get_class($auth));
+    $this->auth = $auth;
+  }
+
+  /**
+   * Set the IO object
+   * @param Google_Io_Abstract $auth
+   */
+  public function setIo(Google_Io_Abstract $io)
+  {
+    $this->config->setIoClass(get_class($io));
+    $this->io = $io;
+  }
+
+  /**
+   * Set the Cache object
+   * @param Google_Cache_Abstract $auth
+   */
+  public function setCache(Google_Cache_Abstract $cache)
+  {
+    $this->config->setCacheClass(get_class($cache));
+    $this->cache = $cache;
+  }
+
+  /**
+   * Construct the OAuth 2.0 authorization request URI.
+   * @return string
+   */
+  public function createAuthUrl()
+  {
+    $scopes = $this->prepareScopes();
+    return $this->getAuth()->createAuthUrl($scopes);
+  }
+
+  /**
+   * Get the OAuth 2.0 access token.
+   * @return string $accessToken JSON encoded string in the following format:
+   * {"access_token":"TOKEN", "refresh_token":"TOKEN", "token_type":"Bearer",
+   *  "expires_in":3600,"id_token":"TOKEN", "created":1320790426}
+   */
+  public function getAccessToken()
+  {
+    $token = $this->getAuth()->getAccessToken();
+    // The response is json encoded, so could be the string null.
+    // It is arguable whether this check should be here or lower
+    // in the library.
+    return (null == $token || 'null' == $token || '[]' == $token) ? null : $token;
+  }
+
+  /**
+   * Returns if the access_token is expired.
+   * @return bool Returns True if the access_token is expired.
+   */
+  public function isAccessTokenExpired()
+  {
+    return $this->getAuth()->isAccessTokenExpired();
+  }
+
+  /**
+   * Set OAuth 2.0 "state" parameter to achieve per-request customization.
+   * @see http://tools.ietf.org/html/draft-ietf-oauth-v2-22#section-3.1.2.2
+   * @param string $state
+   */
+  public function setState($state)
+  {
+    $this->getAuth()->setState($state);
+  }
+
+  /**
+   * @param string $accessType Possible values for access_type include:
+   *  {@code "offline"} to request offline access from the user.
+   *  {@code "online"} to request online access from the user.
+   */
+  public function setAccessType($accessType)
+  {
+    $this->config->setAccessType($accessType);
+  }
+
+  /**
+   * @param string $approvalPrompt Possible values for approval_prompt include:
+   *  {@code "force"} to force the approval UI to appear. (This is the default value)
+   *  {@code "auto"} to request auto-approval when possible.
+   */
+  public function setApprovalPrompt($approvalPrompt)
+  {
+    $this->config->setApprovalPrompt($approvalPrompt);
+  }
+
+  /**
+   * Set the login hint, email address or sub id.
+   * @param string $loginHint
+   */
+  public function setLoginHint($loginHint)
+  {
+      $this->config->setLoginHint($loginHint);
+  }
+
+  /**
+   * Set the application name, this is included in the User-Agent HTTP header.
+   * @param string $applicationName
+   */
+  public function setApplicationName($applicationName)
+  {
+    $this->config->setApplicationName($applicationName);
+  }
+
+  /**
+   * Set the OAuth 2.0 Client ID.
+   * @param string $clientId
+   */
+  public function setClientId($clientId)
+  {
+    $this->config->setClientId($clientId);
+  }
+
+  /**
+   * Set the OAuth 2.0 Client Secret.
+   * @param string $clientSecret
+   */
+  public function setClientSecret($clientSecret)
+  {
+    $this->config->setClientSecret($clientSecret);
+  }
+
+  /**
+   * Set the OAuth 2.0 Redirect URI.
+   * @param string $redirectUri
+   */
+  public function setRedirectUri($redirectUri)
+  {
+    $this->config->setRedirectUri($redirectUri);
+  }
+
+  /**
+   * If 'plus.login' is included in the list of requested scopes, you can use
+   * this method to define types of app activities that your app will write.
+   * You can find a list of available types here:
+   * @link https://developers.google.com/+/api/moment-types
+   *
+   * @param array $requestVisibleActions Array of app activity types
+   */
+  public function setRequestVisibleActions($requestVisibleActions)
+  {
+    if (is_array($requestVisibleActions)) {
+      $requestVisibleActions = join(" ", $requestVisibleActions);
+    }
+    $this->config->setRequestVisibleActions($requestVisibleActions);
+  }
+
+  /**
+   * Set the developer key to use, these are obtained through the API Console.
+   * @see http://code.google.com/apis/console-help/#generatingdevkeys
+   * @param string $developerKey
+   */
+  public function setDeveloperKey($developerKey)
+  {
+    $this->config->setDeveloperKey($developerKey);
+  }
+
+  /**
+   * Fetches a fresh OAuth 2.0 access token with the given refresh token.
+   * @param string $refreshToken
+   * @return void
+   */
+  public function refreshToken($refreshToken)
+  {
+    return $this->getAuth()->refreshToken($refreshToken);
+  }
+
+  /**
+   * Revoke an OAuth2 access token or refresh token. This method will revoke the current access
+   * token, if a token isn't provided.
+   * @throws Google_Auth_Exception
+   * @param string|null $token The token (access token or a refresh token) that should be revoked.
+   * @return boolean Returns True if the revocation was successful, otherwise False.
+   */
+  public function revokeToken($token = null)
+  {
+    return $this->getAuth()->revokeToken($token);
+  }
+
+  /**
+   * Verify an id_token. This method will verify the current id_token, if one
+   * isn't provided.
+   * @throws Google_Auth_Exception
+   * @param string|null $token The token (id_token) that should be verified.
+   * @return Google_Auth_LoginTicket Returns an apiLoginTicket if the verification was
+   * successful.
+   */
+  public function verifyIdToken($token = null)
+  {
+    return $this->getAuth()->verifyIdToken($token);
+  }
+
+  /**
+   * Verify a JWT that was signed with your own certificates.
+   *
+   * @param $jwt the token
+   * @param $certs array of certificates
+   * @param $required_audience the expected consumer of the token
+   * @param [$issuer] the expected issues, defaults to Google
+   * @param [$max_expiry] the max lifetime of a token, defaults to MAX_TOKEN_LIFETIME_SECS
+   * @return token information if valid, false if not
+   */
+  public function verifySignedJwt($id_token, $cert_location, $audience, $issuer, $max_expiry = null)
+  {
+    $auth = new Google_Auth_OAuth2($this);
+    $certs = $auth->retrieveCertsFromLocation($cert_location);
+    return $auth->verifySignedJwtWithCerts($id_token, $certs, $audience, $issuer, $max_expiry);
+  }
+
+  /**
+   * @param Google_Auth_AssertionCredentials $creds
+   * @return void
+   */
+  public function setAssertionCredentials(Google_Auth_AssertionCredentials $creds)
+  {
+    $this->getAuth()->setAssertionCredentials($creds);
+  }
+
+  /**
+   * Set the scopes to be requested. Must be called before createAuthUrl().
+   * Will remove any previously configured scopes.
+   * @param array $scopes, ie: array('https://www.googleapis.com/auth/plus.login',
+   * 'https://www.googleapis.com/auth/moderator')
+   */
+  public function setScopes($scopes)
+  {
+    $this->requestedScopes = array();
+    $this->addScope($scopes);
+  }
+
+  /**
+   * This functions adds a scope to be requested as part of the OAuth2.0 flow.
+   * Will append any scopes not previously requested to the scope parameter.
+   * A single string will be treated as a scope to request. An array of strings
+   * will each be appended.
+   * @param $scope_or_scopes string|array e.g. "profile"
+   */
+  public function addScope($scope_or_scopes)
+  {
+    if (is_string($scope_or_scopes) && !in_array($scope_or_scopes, $this->requestedScopes)) {
+      $this->requestedScopes[] = $scope_or_scopes;
+    } else if (is_array($scope_or_scopes)) {
+      foreach ($scope_or_scopes as $scope) {
+        $this->addScope($scope);
+      }
+    }
+  }
+
+  /**
+   * Returns the list of scopes requested by the client
+   * @return array the list of scopes
+   *
+   */
+  public function getScopes()
+  {
+     return $this->requestedScopes;
+  }
+
+  /**
+   * Declare whether batch calls should be used. This may increase throughput
+   * by making multiple requests in one connection.
+   *
+   * @param boolean $useBatch True if the batch support should
+   * be enabled. Defaults to False.
+   */
+  public function setUseBatch($useBatch)
+  {
+    // This is actually an alias for setDefer.
+    $this->setDefer($useBatch);
+  }
+
+  /**
+   * Declare whether making API calls should make the call immediately, or
+   * return a request which can be called with ->execute();
+   *
+   * @param boolean $defer True if calls should not be executed right away.
+   */
+  public function setDefer($defer)
+  {
+    $this->deferExecution = $defer;
+  }
+
+  /**
+   * Helper method to execute deferred HTTP requests.
+   *
+   * @returns object of the type of the expected class or array.
+   */
+  public function execute($request)
+  {
+    if ($request instanceof Google_Http_Request) {
+      $request->setUserAgent(
+          $this->getApplicationName()
+          . " " . self::USER_AGENT_SUFFIX
+          . $this->getLibraryVersion()
+      );
+      if (!$this->getClassConfig("Google_Http_Request", "disable_gzip")) {
+        $request->enableGzip();
+      }
+      $request->maybeMoveParametersToBody();
+      return Google_Http_REST::execute($this, $request);
+    } else if ($request instanceof Google_Http_Batch) {
+      return $request->execute();
+    } else {
+      throw new Google_Exception("Do not know how to execute this type of object.");
+    }
+  }
+
+  /**
+   * Whether or not to return raw requests
+   * @return boolean
+   */
+  public function shouldDefer()
+  {
+    return $this->deferExecution;
+  }
+
+  /**
+   * @return Google_Auth_Abstract Authentication implementation
+   */
+  public function getAuth()
+  {
+    if (!isset($this->auth)) {
+      $class = $this->config->getAuthClass();
+      $this->auth = new $class($this);
+    }
+    return $this->auth;
+  }
+
+  /**
+   * @return Google_IO_Abstract IO implementation
+   */
+  public function getIo()
+  {
+    if (!isset($this->io)) {
+      $class = $this->config->getIoClass();
+      $this->io = new $class($this);
+    }
+    return $this->io;
+  }
+
+  /**
+   * @return Google_Cache_Abstract Cache implementation
+   */
+  public function getCache()
+  {
+    if (!isset($this->cache)) {
+      $class = $this->config->getCacheClass();
+      $this->cache = new $class($this);
+    }
+    return $this->cache;
+  }
+
+  /**
+   * Retrieve custom configuration for a specific class.
+   * @param $class string|object - class or instance of class to retrieve
+   * @param $key string optional - key to retrieve
+   */
+  public function getClassConfig($class, $key = null)
+  {
+    if (!is_string($class)) {
+      $class = get_class($class);
+    }
+    return $this->config->getClassConfig($class, $key);
+  }
+
+  /**
+   * Set configuration specific to a given class.
+   * $config->setClassConfig('Google_Cache_File',
+   *   array('directory' => '/tmp/cache'));
+   * @param $class The class name for the configuration
+   * @param $config string key or an array of configuration values
+   * @param $value optional - if $config is a key, the value
+   *
+   */
+  public function setClassConfig($class, $config, $value = null)
+  {
+    if (!is_string($class)) {
+      $class = get_class($class);
+    }
+    return $this->config->setClassConfig($class, $config, $value);
+
+  }
+
+  /**
+   * @return string the base URL to use for calls to the APIs
+   */
+  public function getBasePath()
+  {
+    return $this->config->getBasePath();
+  }
+
+  /**
+   * @return string the name of the application
+   */
+  public function getApplicationName()
+  {
+    return $this->config->getApplicationName();
+  }
+
+  /**
+   * Are we running in Google AppEngine?
+   * return bool
+   */
+  public function isAppEngine()
+  {
+    return (isset($_SERVER['SERVER_SOFTWARE']) &&
+        strpos($_SERVER['SERVER_SOFTWARE'], 'Google App Engine') !== false);
+  }
+}
diff --git a/lib/google/Google/Collection.php b/lib/google/Google/Collection.php
new file mode 100755 (executable)
index 0000000..6e7bf9b
--- /dev/null
@@ -0,0 +1,96 @@
+<?php
+
+require_once "Google/Model.php";
+
+/**
+ * Extension to the regular Google_Model that automatically
+ * exposes the items array for iteration, so you can just
+ * iterate over the object rather than a reference inside.
+ */
+class Google_Collection extends Google_Model implements Iterator, Countable
+{
+  protected $collection_key = 'items';
+
+  public function rewind()
+  {
+    if (isset($this->modelData[$this->collection_key])
+        && is_array($this->modelData[$this->collection_key])) {
+      reset($this->modelData[$this->collection_key]);
+    }
+  }
+
+  public function current()
+  {
+    $this->coerceType($this->key());
+    if (is_array($this->modelData[$this->collection_key])) {
+      return current($this->modelData[$this->collection_key]);
+    }
+  }
+
+  public function key()
+  {
+    if (isset($this->modelData[$this->collection_key])
+        && is_array($this->modelData[$this->collection_key])) {
+      return key($this->modelData[$this->collection_key]);
+    }
+  }
+
+  public function next()
+  {
+    return next($this->modelData[$this->collection_key]);
+  }
+
+  public function valid()
+  {
+    $key = $this->key();
+    return $key !== null && $key !== false;
+  }
+
+  public function count()
+  {
+    return count($this->modelData[$this->collection_key]);
+  }
+
+  public function offsetExists ($offset)
+  {
+    if (!is_numeric($offset)) {
+      return parent::offsetExists($offset);
+    }
+    return isset($this->modelData[$this->collection_key][$offset]);
+  }
+
+  public function offsetGet($offset)
+  {
+    if (!is_numeric($offset)) {
+      return parent::offsetGet($offset);
+    }
+    $this->coerceType($offset);
+    return $this->modelData[$this->collection_key][$offset];
+  }
+
+  public function offsetSet($offset, $value)
+  {
+    if (!is_numeric($offset)) {
+      return parent::offsetSet($offset, $value);
+    }
+    $this->modelData[$this->collection_key][$offset] = $value;
+  }
+
+  public function offsetUnset($offset)
+  {
+    if (!is_numeric($offset)) {
+      return parent::offsetUnset($offset);
+    }
+    unset($this->modelData[$this->collection_key][$offset]);
+  }
+
+  private function coerceType($offset)
+  {
+    $typeKey = $this->keyType($this->collection_key);
+    if (isset($this->$typeKey) && !is_object($this->modelData[$this->collection_key][$offset])) {
+      $type = $this->$typeKey;
+      $this->modelData[$this->collection_key][$offset] =
+          new $type($this->modelData[$this->collection_key][$offset]);
+    }
+  }
+}
diff --git a/lib/google/Google/Config.php b/lib/google/Google/Config.php
new file mode 100755 (executable)
index 0000000..c45e2de
--- /dev/null
@@ -0,0 +1,325 @@
+<?php
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * A class to contain the library configuration for the Google API client.
+ */
+class Google_Config
+{
+  const GZIP_DISABLED = true;
+  const GZIP_ENABLED = false;
+  const GZIP_UPLOADS_ENABLED = true;
+  const GZIP_UPLOADS_DISABLED = false;
+  const USE_AUTO_IO_SELECTION = "auto";
+  private $configuration;
+
+  /**
+   * Create a new Google_Config. Can accept an ini file location with the
+   * local configuration. For example:
+   *     application_name: "My App";
+   *
+   * @param [$ini_file_location] - optional - The location of the ini file to load
+   */
+  public function __construct($ini_file_location = null)
+  {
+    $this->configuration = array(
+      // The application_name is included in the User-Agent HTTP header.
+      'application_name' => '',
+
+      // Which Authentication, Storage and HTTP IO classes to use.
+      'auth_class'    => 'Google_Auth_OAuth2',
+      'io_class'      => self::USE_AUTO_IO_SELECTION,
+      'cache_class'   => 'Google_Cache_File',
+
+      // Don't change these unless you're working against a special development
+      // or testing environment.
+      'base_path' => 'https://www.googleapis.com',
+
+      // Definition of class specific values, like file paths and so on.
+      'classes' => array(
+        'Google_IO_Abstract' => array(
+          'request_timeout_seconds' => 100,
+        ),
+        'Google_Http_Request' => array(
+          // Disable the use of gzip on calls if set to true. Defaults to false.
+          'disable_gzip' => self::GZIP_ENABLED,
+
+          // We default gzip to disabled on uploads even if gzip is otherwise
+          // enabled, due to some issues seen with small packet sizes for uploads.
+          // Please test with this option before enabling gzip for uploads in
+          // a production environment.
+          'enable_gzip_for_uploads' => self::GZIP_UPLOADS_DISABLED,
+        ),
+        // If you want to pass in OAuth 2.0 settings, they will need to be
+        // structured like this.
+        'Google_Auth_OAuth2' => array(
+          // Keys for OAuth 2.0 access, see the API console at
+          // https://developers.google.com/console
+          'client_id' => '',
+          'client_secret' => '',
+          'redirect_uri' => '',
+
+          // Simple API access key, also from the API console. Ensure you get
+          // a Server key, and not a Browser key.
+          'developer_key' => '',
+
+          // Other parameters.
+          'access_type' => 'online',
+          'approval_prompt' => 'auto',
+          'login_hint' => '',
+          'request_visible_actions' => '',
+          'federated_signon_certs_url' =>
+              'https://www.googleapis.com/oauth2/v1/certs',
+        ),
+        // Set a default directory for the file cache.
+        'Google_Cache_File' => array(
+          'directory' => sys_get_temp_dir() . '/Google_Client'
+        )
+      ),
+
+      // Definition of service specific values like scopes, oauth token URLs,
+      // etc. Example:
+      'services' => array(
+      ),
+    );
+    if ($ini_file_location) {
+      $ini = parse_ini_file($ini_file_location, true);
+      if (is_array($ini) && count($ini)) {
+        $this->configuration = array_merge($this->configuration, $ini);
+      }
+    }
+  }
+
+  /**
+   * Set configuration specific to a given class.
+   * $config->setClassConfig('Google_Cache_File',
+   *   array('directory' => '/tmp/cache'));
+   * @param $class The class name for the configuration
+   * @param $config string key or an array of configuration values
+   * @param $value optional - if $config is a key, the value
+   */
+  public function setClassConfig($class, $config, $value = null)
+  {
+    if (!is_array($config)) {
+      if (!isset($this->configuration['classes'][$class])) {
+        $this->configuration['classes'][$class] = array();
+      }
+      $this->configuration['classes'][$class][$config] = $value;
+    } else {
+      $this->configuration['classes'][$class] = $config;
+    }
+  }
+
+  public function getClassConfig($class, $key = null)
+  {
+    if (!isset($this->configuration['classes'][$class])) {
+      return null;
+    }
+    if ($key === null) {
+      return $this->configuration['classes'][$class];
+    } else {
+      return $this->configuration['classes'][$class][$key];
+    }
+  }
+
+  /**
+   * Return the configured cache class.
+   * @return string
+   */
+  public function getCacheClass()
+  {
+    return $this->configuration['cache_class'];
+  }
+
+  /**
+   * Return the configured Auth class.
+   * @return string
+   */
+  public function getAuthClass()
+  {
+    return $this->configuration['auth_class'];
+  }
+
+  /**
+   * Set the auth class.
+   *
+   * @param $class the class name to set
+   */
+  public function setAuthClass($class)
+  {
+    $prev = $this->configuration['auth_class'];
+    if (!isset($this->configuration['classes'][$class]) &&
+        isset($this->configuration['classes'][$prev])) {
+      $this->configuration['classes'][$class] =
+          $this->configuration['classes'][$prev];
+    }
+    $this->configuration['auth_class'] = $class;
+  }
+
+  /**
+   * Set the IO class.
+   *
+   * @param $class the class name to set
+   */
+  public function setIoClass($class)
+  {
+    $prev = $this->configuration['io_class'];
+    if (!isset($this->configuration['classes'][$class]) &&
+        isset($this->configuration['classes'][$prev])) {
+      $this->configuration['classes'][$class] =
+          $this->configuration['classes'][$prev];
+    }
+    $this->configuration['io_class'] = $class;
+  }
+
+  /**
+   * Set the cache class.
+   *
+   * @param $class the class name to set
+   */
+  public function setCacheClass($class)
+  {
+    $prev = $this->configuration['cache_class'];
+    if (!isset($this->configuration['classes'][$class]) &&
+        isset($this->configuration['classes'][$prev])) {
+      $this->configuration['classes'][$class] =
+          $this->configuration['classes'][$prev];
+    }
+    $this->configuration['cache_class'] = $class;
+  }
+
+  /**
+   * Return the configured IO class.
+   * @return string
+   */
+  public function getIoClass()
+  {
+    return $this->configuration['io_class'];
+  }
+
+  /**
+   * Set the application name, this is included in the User-Agent HTTP header.
+   * @param string $name
+   */
+  public function setApplicationName($name)
+  {
+    $this->configuration['application_name'] = $name;
+  }
+
+  /**
+   * @return string the name of the application
+   */
+  public function getApplicationName()
+  {
+    return $this->configuration['application_name'];
+  }
+
+  /**
+   * Set the client ID for the auth class.
+   * @param $key string - the API console client ID
+   */
+  public function setClientId($clientId)
+  {
+    $this->setAuthConfig('client_id', $clientId);
+  }
+
+  /**
+   * Set the client secret for the auth class.
+   * @param $key string - the API console client secret
+   */
+  public function setClientSecret($secret)
+  {
+    $this->setAuthConfig('client_secret', $secret);
+  }
+
+  /**
+   * Set the redirect uri for the auth class. Note that if using the
+   * Javascript based sign in flow, this should be the string 'postmessage'.
+   * @param $key string - the URI that users should be redirected to
+   */
+  public function setRedirectUri($uri)
+  {
+    $this->setAuthConfig('redirect_uri', $uri);
+  }
+
+  /**
+   * Set the app activities for the auth class.
+   * @param $rva string a space separated list of app activity types
+   */
+  public function setRequestVisibleActions($rva)
+  {
+    $this->setAuthConfig('request_visible_actions', $rva);
+  }
+
+  /**
+   * Set the the access type requested (offline or online.)
+   * @param $access string - the access type
+   */
+  public function setAccessType($access)
+  {
+    $this->setAuthConfig('access_type', $access);
+  }
+
+  /**
+   * Set when to show the approval prompt (auto or force)
+   * @param $approval string - the approval request
+   */
+  public function setApprovalPrompt($approval)
+  {
+    $this->setAuthConfig('approval_prompt', $approval);
+  }
+
+  /**
+   * Set the login hint (email address or sub identifier)
+   * @param $hint string
+   */
+  public function setLoginHint($hint)
+  {
+    $this->setAuthConfig('login_hint', $hint);
+  }
+
+  /**
+   * Set the developer key for the auth class. Note that this is separate value
+   * from the client ID - if it looks like a URL, its a client ID!
+   * @param $key string - the API console developer key
+   */
+  public function setDeveloperKey($key)
+  {
+    $this->setAuthConfig('developer_key', $key);
+  }
+
+  /**
+   * @return string the base URL to use for API calls
+   */
+  public function getBasePath()
+  {
+    return $this->configuration['base_path'];
+  }
+
+  /**
+   * Set the auth configuration for the current auth class.
+   * @param $key - the key to set
+   * @param $value - the parameter value
+   */
+  private function setAuthConfig($key, $value)
+  {
+    if (!isset($this->configuration['classes'][$this->getAuthClass()])) {
+      $this->configuration['classes'][$this->getAuthClass()] = array();
+    }
+    $this->configuration['classes'][$this->getAuthClass()][$key] = $value;
+  }
+}
old mode 100644 (file)
new mode 100755 (executable)
similarity index 83%
rename from lib/google/service/Google_Service.php
rename to lib/google/Google/Exception.php
index 1f4731f..af80269
@@ -1,6 +1,6 @@
 <?php
 /*
- * Copyright 2010 Google Inc.
+ * Copyright 2013 Google Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -15,8 +15,6 @@
  * limitations under the License.
  */
 
-class Google_Service {
-  public $version;
-  public $servicePath;
-  public $resource;
+class Google_Exception extends Exception
+{
 }
old mode 100644 (file)
new mode 100755 (executable)
similarity index 52%
rename from lib/google/service/Google_BatchRequest.php
rename to lib/google/Google/Http/Batch.php
index 3916b22..d851da5
  * limitations under the License.
  */
 
+require_once 'Google/Client.php';
+require_once 'Google/Http/Request.php';
+require_once 'Google/Http/REST.php';
+
 /**
  * @author Chirag Shah <chirags@google.com>
  */
-class Google_BatchRequest {
+class Google_Http_Batch
+{
   /** @var string Multipart Boundary. */
   private $boundary;
 
   /** @var array service requests to be executed. */
   private $requests = array();
 
-  public function __construct($boundary = false) {
+  /** @var Google_Client */
+  private $client;
+
+  private $expected_classes = array();
+
+  private $base_path;
+
+  public function __construct(Google_Client $client, $boundary = false)
+  {
+    $this->client = $client;
+    $this->base_path = $this->client->getBasePath();
+    $this->expected_classes = array();
     $boundary = (false == $boundary) ? mt_rand() : $boundary;
     $this->boundary = str_replace('"', '', $boundary);
   }
 
-  public function add(Google_HttpRequest $request, $key = false) {
+  public function add(Google_Http_Request $request, $key = false)
+  {
     if (false == $key) {
       $key = mt_rand();
     }
@@ -38,36 +55,38 @@ class Google_BatchRequest {
     $this->requests[$key] = $request;
   }
 
-  public function execute() {
+  public function execute()
+  {
     $body = '';
 
-    /** @var Google_HttpRequest $req */
-    foreach($this->requests as $key => $req) {
+    /** @var Google_Http_Request $req */
+    foreach ($this->requests as $key => $req) {
       $body .= "--{$this->boundary}\n";
       $body .= $req->toBatchString($key) . "\n";
+      $this->expected_classes["response-" . $key] = $req->getExpectedClass();
     }
 
     $body = rtrim($body);
     $body .= "\n--{$this->boundary}--";
 
-    global $apiConfig;
-    $url = $apiConfig['basePath'] . '/batch';
-    $httpRequest = new Google_HttpRequest($url, 'POST');
-    $httpRequest->setRequestHeaders(array(
-        'Content-Type' => 'multipart/mixed; boundary=' . $this->boundary));
+    $url = $this->base_path . '/batch';
+    $httpRequest = new Google_Http_Request($url, 'POST');
+    $httpRequest->setRequestHeaders(
+        array('Content-Type' => 'multipart/mixed; boundary=' . $this->boundary)
+    );
 
     $httpRequest->setPostBody($body);
-    $response = Google_Client::$io->makeRequest($httpRequest);
+    $response = $this->client->getIo()->makeRequest($httpRequest);
 
-    $response = $this->parseResponse($response);
-    return $response;
+    return $this->parseResponse($response);
   }
 
-  public function parseResponse(Google_HttpRequest $response) {
+  public function parseResponse(Google_Http_Request $response)
+  {
     $contentType = $response->getResponseHeader('content-type');
     $contentType = explode(';', $contentType);
     $boundary = false;
-    foreach($contentType as $part) {
+    foreach ($contentType as $part) {
       $part = (explode('=', $part, 2));
       if (isset($part[0]) && 'boundary' == trim($part[0])) {
         $boundary = $part[1];
@@ -80,25 +99,39 @@ class Google_BatchRequest {
       $parts = explode("--$boundary", $body);
       $responses = array();
 
-      foreach($parts as $part) {
+      foreach ($parts as $part) {
         $part = trim($part);
         if (!empty($part)) {
           list($metaHeaders, $part) = explode("\r\n\r\n", $part, 2);
-          $metaHeaders = Google_CurlIO::parseResponseHeaders($metaHeaders);
+          $metaHeaders = $this->client->getIo()->getHttpResponseHeaders($metaHeaders);
 
           $status = substr($part, 0, strpos($part, "\n"));
           $status = explode(" ", $status);
           $status = $status[1];
 
-          list($partHeaders, $partBody) = Google_CurlIO::parseHttpResponse($part, false);
-          $response = new Google_HttpRequest("");
+          list($partHeaders, $partBody) = $this->client->getIo()->ParseHttpResponse($part, false);
+          $response = new Google_Http_Request("");
           $response->setResponseHttpCode($status);
           $response->setResponseHeaders($partHeaders);
           $response->setResponseBody($partBody);
-          $response = Google_REST::decodeHttpResponse($response);
 
           // Need content id.
-          $responses[$metaHeaders['content-id']] = $response;
+          $key = $metaHeaders['content-id'];
+
+          if (isset($this->expected_classes[$key]) &&
+              strlen($this->expected_classes[$key]) > 0) {
+            $class = $this->expected_classes[$key];
+            $response->setExpectedClass($class);
+          }
+
+          try {
+            $response = Google_Http_REST::decodeHttpResponse($response);
+            $responses[$key] = $response;
+          } catch (Google_Service_Exception $e) {
+            // Store the exception as the response, so succesful responses
+            // can be processed.
+            $responses[$key] = $e;
+          }
         }
       }
 
@@ -107,4 +140,4 @@ class Google_BatchRequest {
 
     return null;
   }
-}
\ No newline at end of file
+}
old mode 100644 (file)
new mode 100755 (executable)
similarity index 87%
rename from lib/google/io/Google_CacheParser.php
rename to lib/google/Google/Http/CacheParser.php
index 7f5accf..83f1c8d
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
+require_once 'Google/Http/Request.php';
+
 /**
  * Implement the caching directives specified in rfc2616. This
  * implementation is guided by the guidance offered in rfc2616-sec13.
  * @author Chirag Shah <chirags@google.com>
  */
-class Google_CacheParser {
+class Google_Http_CacheParser
+{
   public static $CACHEABLE_HTTP_METHODS = array('GET', 'HEAD');
   public static $CACHEABLE_STATUS_CODES = array('200', '203', '300', '301');
 
-  private function __construct() {}
-
   /**
    * Check if an HTTP request can be cached by a private local cache.
    *
    * @static
-   * @param Google_HttpRequest $resp
+   * @param Google_Http_Request $resp
    * @return bool True if the request is cacheable.
    * False if the request is uncacheable.
    */
-  public static function isRequestCacheable (Google_HttpRequest $resp) {
+  public static function isRequestCacheable(Google_Http_Request $resp)
+  {
     $method = $resp->getRequestMethod();
     if (! in_array($method, self::$CACHEABLE_HTTP_METHODS)) {
       return false;
@@ -54,11 +57,12 @@ class Google_CacheParser {
    * Check if an HTTP response can be cached by a private local cache.
    *
    * @static
-   * @param Google_HttpRequest $resp
+   * @param Google_Http_Request $resp
    * @return bool True if the response is cacheable.
    * False if the response is un-cacheable.
    */
-  public static function isResponseCacheable (Google_HttpRequest $resp) {
+  public static function isResponseCacheable(Google_Http_Request $resp)
+  {
     // First, check if the HTTP request was cacheable before inspecting the
     // HTTP response.
     if (false == self::isRequestCacheable($resp)) {
@@ -105,15 +109,17 @@ class Google_CacheParser {
 
   /**
    * @static
-   * @param Google_HttpRequest $resp
+   * @param Google_Http_Request $resp
    * @return bool True if the HTTP response is considered to be expired.
    * False if it is considered to be fresh.
    */
-  public static function isExpired(Google_HttpRequest $resp) {
+  public static function isExpired(Google_Http_Request $resp)
+  {
     // HTTP/1.1 clients and caches MUST treat other invalid date formats,
     // especially including the value “0”, as in the past.
     $parsedExpires = false;
     $responseHeaders = $resp->getResponseHeaders();
+
     if (isset($responseHeaders['expires'])) {
       $rawExpires = $responseHeaders['expires'];
       // Check for a malformed expires header first.
@@ -139,8 +145,12 @@ class Google_CacheParser {
     $parsedDate = strtotime($rawDate);
 
     if (empty($rawDate) || false == $parsedDate) {
-      $parsedDate = time();
+      // We can't default this to now, as that means future cache reads
+      // will always pass with the logic below, so we will require a
+      // date be injected if not supplied.
+      throw new Google_Exception("All cacheable requests must have creation dates.");
     }
+
     if (false == $freshnessLifetime && isset($responseHeaders['expires'])) {
       $freshnessLifetime = $parsedExpires - $parsedDate;
     }
@@ -161,13 +171,14 @@ class Google_CacheParser {
   /**
    * Determine if a cache entry should be revalidated with by the origin.
    *
-   * @param Google_HttpRequest $response
+   * @param Google_Http_Request $response
    * @return bool True if the entry is expired, else return false.
    */
-  public static function mustRevalidate(Google_HttpRequest $response) {
+  public static function mustRevalidate(Google_Http_Request $response)
+  {
     // [13.3] When a cache has a stale entry that it would like to use as a
     // response to a client's request, it first has to check with the origin
     // server to see if its cached entry is still usable.
     return self::isExpired($response);
   }
-}
\ No newline at end of file
+}
diff --git a/lib/google/Google/Http/MediaFileUpload.php b/lib/google/Google/Http/MediaFileUpload.php
new file mode 100755 (executable)
index 0000000..a934f56
--- /dev/null
@@ -0,0 +1,292 @@
+<?php
+/**
+ * Copyright 2012 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+require_once 'Google/Client.php';
+require_once 'Google/Exception.php';
+require_once 'Google/Http/Request.php';
+require_once 'Google/Http/REST.php';
+require_once 'Google/Utils.php';
+
+/**
+ * @author Chirag Shah <chirags@google.com>
+ *
+ */
+class Google_Http_MediaFileUpload
+{
+  const UPLOAD_MEDIA_TYPE = 'media';
+  const UPLOAD_MULTIPART_TYPE = 'multipart';
+  const UPLOAD_RESUMABLE_TYPE = 'resumable';
+
+  /** @var string $mimeType */
+  private $mimeType;
+
+  /** @var string $data */
+  private $data;
+
+  /** @var bool $resumable */
+  private $resumable;
+
+  /** @var int $chunkSize */
+  private $chunkSize;
+
+  /** @var int $size */
+  private $size;
+
+  /** @var string $resumeUri */
+  private $resumeUri;
+
+  /** @var int $progress */
+  private $progress;
+
+  /** @var Google_Client */
+  private $client;
+
+  /** @var Google_Http_Request */
+  private $request;
+
+  /** @var string */
+  private $boundary;
+
+  /**
+   * Result code from last HTTP call
+   * @var int
+   */
+  private $httpResultCode;
+
+  /**
+   * @param $mimeType string
+   * @param $data string The bytes you want to upload.
+   * @param $resumable bool
+   * @param bool $chunkSize File will be uploaded in chunks of this many bytes.
+   * only used if resumable=True
+   */
+  public function __construct(
+      Google_Client $client,
+      Google_Http_Request $request,
+      $mimeType,
+      $data,
+      $resumable = false,
+      $chunkSize = false,
+      $boundary = false
+  ) {
+    $this->client = $client;
+    $this->request = $request;
+    $this->mimeType = $mimeType;
+    $this->data = $data;
+    $this->size = strlen($this->data);
+    $this->resumable = $resumable;
+    if (!$chunkSize) {
+      $chunkSize = 256 * 1024;
+    }
+    $this->chunkSize = $chunkSize;
+    $this->progress = 0;
+    $this->boundary = $boundary;
+
+    // Process Media Request
+    $this->process();
+  }
+
+  /**
+   * Set the size of the file that is being uploaded.
+   * @param $size - int file size in bytes
+   */
+  public function setFileSize($size)
+  {
+    $this->size = $size;
+  }
+
+  /**
+   * Return the progress on the upload
+   * @return int progress in bytes uploaded.
+   */
+  public function getProgress()
+  {
+    return $this->progress;
+  }
+
+  /**
+   * Return the HTTP result code from the last call made.
+   * @return int code
+   */
+  public function getHttpResultCode()
+  {
+    return $this->httpResultCode;
+  }
+
+  /**
+   * Send the next part of the file to upload.
+   * @param [$chunk] the next set of bytes to send. If false will used $data passed
+   * at construct time.
+   */
+  public function nextChunk($chunk = false)
+  {
+    if (false == $this->resumeUri) {
+      $this->resumeUri = $this->getResumeUri();
+    }
+
+    if (false == $chunk) {
+      $chunk = substr($this->data, $this->progress, $this->chunkSize);
+    }
+
+    $lastBytePos = $this->progress + strlen($chunk) - 1;
+    $headers = array(
+      'content-range' => "bytes $this->progress-$lastBytePos/$this->size",
+      'content-type' => $this->request->getRequestHeader('content-type'),
+      'content-length' => $this->chunkSize,
+      'expect' => '',
+    );
+
+    $httpRequest = new Google_Http_Request(
+        $this->resumeUri,
+        'PUT',
+        $headers,
+        $chunk
+    );
+
+    if ($this->client->getClassConfig("Google_Http_Request", "enable_gzip_for_uploads")) {
+      $httpRequest->enableGzip();
+    } else {
+      $httpRequest->disableGzip();
+    }
+
+    $response = $this->client->getIo()->makeRequest($httpRequest);
+    $response->setExpectedClass($this->request->getExpectedClass());
+    $code = $response->getResponseHttpCode();
+    $this->httpResultCode = $code;
+
+    if (308 == $code) {
+      // Track the amount uploaded.
+      $range = explode('-', $response->getResponseHeader('range'));
+      $this->progress = $range[1] + 1;
+
+      // Allow for changing upload URLs.
+      $location = $response->getResponseHeader('location');
+      if ($location) {
+        $this->resumeUri = $location;
+      }
+
+      // No problems, but upload not complete.
+      return false;
+    } else {
+      return Google_Http_REST::decodeHttpResponse($response);
+    }
+  }
+
+  /**
+   * @param $meta
+   * @param $params
+   * @return array|bool
+   * @visible for testing
+   */
+  private function process()
+  {
+    $postBody = false;
+    $contentType = false;
+
+    $meta = $this->request->getPostBody();
+    $meta = is_string($meta) ? json_decode($meta, true) : $meta;
+
+    $uploadType = $this->getUploadType($meta);
+    $this->request->setQueryParam('uploadType', $uploadType);
+    $this->transformToUploadUrl();
+    $mimeType = $this->mimeType ?
+        $this->mimeType :
+        $this->request->getRequestHeader('content-type');
+
+    if (self::UPLOAD_RESUMABLE_TYPE == $uploadType) {
+      $contentType = $mimeType;
+      $postBody = is_string($meta) ? $meta : json_encode($meta);
+    } else if (self::UPLOAD_MEDIA_TYPE == $uploadType) {
+      $contentType = $mimeType;
+      $postBody = $this->data;
+    } else if (self::UPLOAD_MULTIPART_TYPE == $uploadType) {
+      // This is a multipart/related upload.
+      $boundary = $this->boundary ? $this->boundary : mt_rand();
+      $boundary = str_replace('"', '', $boundary);
+      $contentType = 'multipart/related; boundary=' . $boundary;
+      $related = "--$boundary\r\n";
+      $related .= "Content-Type: application/json; charset=UTF-8\r\n";
+      $related .= "\r\n" . json_encode($meta) . "\r\n";
+      $related .= "--$boundary\r\n";
+      $related .= "Content-Type: $mimeType\r\n";
+      $related .= "Content-Transfer-Encoding: base64\r\n";
+      $related .= "\r\n" . base64_encode($this->data) . "\r\n";
+      $related .= "--$boundary--";
+      $postBody = $related;
+    }
+
+    $this->request->setPostBody($postBody);
+
+    if (isset($contentType) && $contentType) {
+      $contentTypeHeader['content-type'] = $contentType;
+      $this->request->setRequestHeaders($contentTypeHeader);
+    }
+  }
+
+  private function transformToUploadUrl()
+  {
+    $base = $this->request->getBaseComponent();
+    $this->request->setBaseComponent($base . '/upload');
+  }
+
+  /**
+   * Valid upload types:
+   * - resumable (UPLOAD_RESUMABLE_TYPE)
+   * - media (UPLOAD_MEDIA_TYPE)
+   * - multipart (UPLOAD_MULTIPART_TYPE)
+   * @param $meta
+   * @return string
+   * @visible for testing
+   */
+  public function getUploadType($meta)
+  {
+    if ($this->resumable) {
+      return self::UPLOAD_RESUMABLE_TYPE;
+    }
+
+    if (false == $meta && $this->data) {
+      return self::UPLOAD_MEDIA_TYPE;
+    }
+
+    return self::UPLOAD_MULTIPART_TYPE;
+  }
+
+  private function getResumeUri()
+  {
+    $result = null;
+    $body = $this->request->getPostBody();
+    if ($body) {
+      $headers = array(
+        'content-type' => 'application/json; charset=UTF-8',
+        'content-length' => Google_Utils::getStrLen($body),
+        'x-upload-content-type' => $this->mimeType,
+        'x-upload-content-length' => $this->size,
+        'expect' => '',
+      );
+      $this->request->setRequestHeaders($headers);
+    }
+
+    $response = $this->client->getIo()->makeRequest($this->request);
+    $location = $response->getResponseHeader('location');
+    $code = $response->getResponseHttpCode();
+
+    if (200 == $code && true == $location) {
+      return $location;
+    }
+    throw new Google_Exception("Failed to start the resumable upload");
+  }
+}
old mode 100644 (file)
new mode 100755 (executable)
similarity index 61%
rename from lib/google/io/Google_REST.php
rename to lib/google/Google/Http/REST.php
index a53055a..3c318e4
  * limitations under the License.
  */
 
+require_once 'Google/Client.php';
+require_once 'Google/Http/Request.php';
+require_once 'Google/Service/Exception.php';
+require_once 'Google/Utils/URITemplate.php';
+
 /**
  * This class implements the RESTful transport of apiServiceRequest()'s
  *
  * @author Chris Chabot <chabotc@google.com>
  * @author Chirag Shah <chirags@google.com>
  */
-class Google_REST {
+class Google_Http_REST
+{
   /**
-   * Executes a apiServiceRequest using a RESTful call by transforming it into
-   * an apiHttpRequest, and executed via apiIO::authenticatedRequest().
+   * Executes a Google_Http_Request
    *
-   * @param Google_HttpRequest $req
+   * @param Google_Client $client
+   * @param Google_Http_Request $req
    * @return array decoded result
-   * @throws Google_ServiceException on server side error (ie: not authenticated,
+   * @throws Google_Service_Exception on server side error (ie: not authenticated,
    *  invalid or malformed post body, invalid url)
    */
-  static public function execute(Google_HttpRequest $req) {
-    $httpRequest = Google_Client::$io->makeRequest($req);
-    $decodedResponse = self::decodeHttpResponse($httpRequest);
-    $ret = isset($decodedResponse['data'])
-        ? $decodedResponse['data'] : $decodedResponse;
-    return $ret;
+  public static function execute(Google_Client $client, Google_Http_Request $req)
+  {
+    $httpRequest = $client->getIo()->makeRequest($req);
+    $httpRequest->setExpectedClass($req->getExpectedClass());
+    return self::decodeHttpResponse($httpRequest);
   }
 
-  
   /**
    * Decode an HTTP Response.
    * @static
-   * @throws Google_ServiceException
-   * @param Google_HttpRequest $response The http response to be decoded.
+   * @throws Google_Service_Exception
+   * @param Google_Http_Request $response The http response to be decoded.
    * @return mixed|null
    */
-  public static function decodeHttpResponse($response) {
+  public static function decodeHttpResponse($response)
+  {
     $code = $response->getResponseHttpCode();
     $body = $response->getResponseBody();
     $decoded = null;
-    
-    if ($code != '200' && $code != '201' && $code != '204') {
+
+    if ((intVal($code)) >= 300) {
       $decoded = json_decode($body, true);
       $err = 'Error calling ' . $response->getRequestMethod() . ' ' . $response->getUrl();
-      if ($decoded != null && isset($decoded['error']['message'])  && isset($decoded['error']['code'])) {
+      if (isset($decoded['error']) &&
+          isset($decoded['error']['message'])  &&
+          isset($decoded['error']['code'])) {
         // if we're getting a json encoded error definition, use that instead of the raw response
         // body for improved readability
         $err .= ": ({$decoded['error']['code']}) {$decoded['error']['message']}";
@@ -63,14 +70,25 @@ class Google_REST {
         $err .= ": ($code) $body";
       }
 
-      throw new Google_ServiceException($err, $code, null, $decoded['error']['errors']);
+      $errors = null;
+      // Specific check for APIs which don't return error details, such as Blogger.
+      if (isset($decoded['error']) && isset($decoded['error']['errors'])) {
+        $errors = $decoded['error']['errors'];
+      }
+
+      throw new Google_Service_Exception($err, $code, null, $errors);
     }
-    
+
     // Only attempt to decode the response, if the response code wasn't (204) 'no content'
     if ($code != '204') {
       $decoded = json_decode($body, true);
       if ($decoded === null || $decoded === "") {
-        throw new Google_ServiceException("Invalid json in service response: $body");
+        throw new Google_Service_Exception("Invalid json in service response: $body");
+      }
+
+      if ($response->getExpectedClass()) {
+        $class = $response->getExpectedClass();
+        $decoded = new $class($decoded);
       }
     }
     return $decoded;
@@ -85,22 +103,18 @@ class Google_REST {
    * @param array $params
    * @return string $requestUrl
    */
-  static function createRequestUri($servicePath, $restPath, $params) {
+  public static function createRequestUri($servicePath, $restPath, $params)
+  {
     $requestUrl = $servicePath . $restPath;
     $uriTemplateVars = array();
     $queryVars = array();
     foreach ($params as $paramName => $paramSpec) {
-      // Discovery v1.0 puts the canonical location under the 'location' field.
-      if (! isset($paramSpec['location'])) {
-        $paramSpec['location'] = $paramSpec['restParameterType'];
-      }
-
       if ($paramSpec['type'] == 'boolean') {
         $paramSpec['value'] = ($paramSpec['value']) ? 'true' : 'false';
       }
       if ($paramSpec['location'] == 'path') {
         $uriTemplateVars[$paramName] = $paramSpec['value'];
-      } else {
+      } else if ($paramSpec['location'] == 'query') {
         if (isset($paramSpec['repeated']) && is_array($paramSpec['value'])) {
           foreach ($paramSpec['value'] as $value) {
             $queryVars[] = $paramName . '=' . rawurlencode($value);
@@ -112,12 +126,9 @@ class Google_REST {
     }
 
     if (count($uriTemplateVars)) {
-      $uriTemplateParser = new URI_Template_Parser($requestUrl);
-      $requestUrl = $uriTemplateParser->expand($uriTemplateVars);
+      $uriTemplateParser = new Google_Utils_URITemplate();
+      $requestUrl = $uriTemplateParser->parse($requestUrl, $uriTemplateVars);
     }
-    //FIXME work around for the the uri template lib which url encodes
-    // the @'s & confuses our servers.
-    $requestUrl = str_replace('%40', '@', $requestUrl);
 
     if (count($queryVars)) {
       $requestUrl .= '?' . implode($queryVars, '&');
diff --git a/lib/google/Google/Http/Request.php b/lib/google/Google/Http/Request.php
new file mode 100755 (executable)
index 0000000..8643694
--- /dev/null
@@ -0,0 +1,476 @@
+<?php
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+require_once 'Google/Utils.php';
+
+/**
+ * HTTP Request to be executed by IO classes. Upon execution, the
+ * responseHttpCode, responseHeaders and responseBody will be filled in.
+ *
+ * @author Chris Chabot <chabotc@google.com>
+ * @author Chirag Shah <chirags@google.com>
+ *
+ */
+class Google_Http_Request
+{
+  const GZIP_UA = " (gzip)";
+
+  private $batchHeaders = array(
+    'Content-Type' => 'application/http',
+    'Content-Transfer-Encoding' => 'binary',
+    'MIME-Version' => '1.0',
+  );
+
+  protected $queryParams;
+  protected $requestMethod;
+  protected $requestHeaders;
+  protected $baseComponent = null;
+  protected $path;
+  protected $postBody;
+  protected $userAgent;
+  protected $canGzip = null;
+
+  protected $responseHttpCode;
+  protected $responseHeaders;
+  protected $responseBody;
+  
+  protected $expectedClass;
+
+  public $accessKey;
+
+  public function __construct(
+      $url,
+      $method = 'GET',
+      $headers = array(),
+      $postBody = null
+  ) {
+    $this->setUrl($url);
+    $this->setRequestMethod($method);
+    $this->setRequestHeaders($headers);
+    $this->setPostBody($postBody);
+  }
+
+  /**
+   * Misc function that returns the base url component of the $url
+   * used by the OAuth signing class to calculate the base string
+   * @return string The base url component of the $url.
+   */
+  public function getBaseComponent()
+  {
+    return $this->baseComponent;
+  }
+  
+  /**
+   * Set the base URL that path and query parameters will be added to.
+   * @param $baseComponent string
+   */
+  public function setBaseComponent($baseComponent)
+  {
+    $this->baseComponent = $baseComponent;
+  }
+  
+  /**
+   * Enable support for gzipped responses with this request.
+   */
+  public function enableGzip()
+  {
+    $this->setRequestHeaders(array("Accept-Encoding" => "gzip"));
+    $this->canGzip = true;
+    $this->setUserAgent($this->userAgent);
+  }
+  
+  /**
+   * Disable support for gzip responses with this request.
+   */
+  public function disableGzip()
+  {
+    if (
+        isset($this->requestHeaders['accept-encoding']) &&
+        $this->requestHeaders['accept-encoding'] == "gzip"
+    ) {
+      unset($this->requestHeaders['accept-encoding']);
+    }
+    $this->canGzip = false;
+    $this->userAgent = str_replace(self::GZIP_UA, "", $this->userAgent);
+  }
+  
+  /**
+   * Can this request accept a gzip response?
+   * @return bool
+   */
+  public function canGzip()
+  {
+    return $this->canGzip;
+  }
+
+  /**
+   * Misc function that returns an array of the query parameters of the current
+   * url used by the OAuth signing class to calculate the signature
+   * @return array Query parameters in the query string.
+   */
+  public function getQueryParams()
+  {
+    return $this->queryParams;
+  }
+
+  /** 
+   * Set a new query parameter.
+   * @param $key - string to set, does not need to be URL encoded
+   * @param $value - string to set, does not need to be URL encoded
+   */
+  public function setQueryParam($key, $value)
+  {
+    $this->queryParams[$key] = $value;
+  }
+
+  /**
+   * @return string HTTP Response Code.
+   */
+  public function getResponseHttpCode()
+  {
+    return (int) $this->responseHttpCode;
+  }
+
+  /**
+   * @param int $responseHttpCode HTTP Response Code.
+   */
+  public function setResponseHttpCode($responseHttpCode)
+  {
+    $this->responseHttpCode = $responseHttpCode;
+  }
+
+  /**
+   * @return $responseHeaders (array) HTTP Response Headers.
+   */
+  public function getResponseHeaders()
+  {
+    return $this->responseHeaders;
+  }
+
+  /**
+   * @return string HTTP Response Body
+   */
+  public function getResponseBody()
+  {
+    return $this->responseBody;
+  }
+  
+  /**
+   * Set the class the response to this request should expect.
+   *
+   * @param $class string the class name
+   */
+  public function setExpectedClass($class)
+  {
+    $this->expectedClass = $class;
+  }
+  
+  /**
+   * Retrieve the expected class the response should expect.
+   * @return string class name
+   */
+  public function getExpectedClass()
+  {
+    return $this->expectedClass;
+  }
+
+  /**
+   * @param array $headers The HTTP response headers
+   * to be normalized.
+   */
+  public function setResponseHeaders($headers)
+  {
+    $headers = Google_Utils::normalize($headers);
+    if ($this->responseHeaders) {
+      $headers = array_merge($this->responseHeaders, $headers);
+    }
+
+    $this->responseHeaders = $headers;
+  }
+
+  /**
+   * @param string $key
+   * @return array|boolean Returns the requested HTTP header or
+   * false if unavailable.
+   */
+  public function getResponseHeader($key)
+  {
+    return isset($this->responseHeaders[$key])
+        ? $this->responseHeaders[$key]
+        : false;
+  }
+
+  /**
+   * @param string $responseBody The HTTP response body.
+   */
+  public function setResponseBody($responseBody)
+  {
+    $this->responseBody = $responseBody;
+  }
+
+  /**
+   * @return string $url The request URL.
+   */
+  public function getUrl()
+  {
+    return $this->baseComponent . $this->path .
+        (count($this->queryParams) ?
+            "?" . $this->buildQuery($this->queryParams) :
+            '');
+  }
+
+  /**
+   * @return string $method HTTP Request Method.
+   */
+  public function getRequestMethod()
+  {
+    return $this->requestMethod;
+  }
+
+  /**
+   * @return array $headers HTTP Request Headers.
+   */
+  public function getRequestHeaders()
+  {
+    return $this->requestHeaders;
+  }
+
+  /**
+   * @param string $key
+   * @return array|boolean Returns the requested HTTP header or
+   * false if unavailable.
+   */
+  public function getRequestHeader($key)
+  {
+    return isset($this->requestHeaders[$key])
+        ? $this->requestHeaders[$key]
+        : false;
+  }
+
+  /**
+   * @return string $postBody HTTP Request Body.
+   */
+  public function getPostBody()
+  {
+    return $this->postBody;
+  }
+
+  /**
+   * @param string $url the url to set
+   */
+  public function setUrl($url)
+  {
+    if (substr($url, 0, 4) != 'http') {
+      // Force the path become relative.
+      if (substr($url, 0, 1) !== '/') {
+        $url = '/' . $url;
+      }
+    }
+    $parts = parse_url($url);
+    if (isset($parts['host'])) {
+      $this->baseComponent = sprintf(
+          "%s%s%s",
+          isset($parts['scheme']) ? $parts['scheme'] . "://" : '',
+          isset($parts['host']) ? $parts['host'] : '',
+          isset($parts['port']) ? ":" . $parts['port'] : ''
+      );
+    }
+    $this->path = isset($parts['path']) ? $parts['path'] : '';
+    $this->queryParams = array();
+    if (isset($parts['query'])) {
+      $this->queryParams = $this->parseQuery($parts['query']);
+    }
+  }
+
+  /**
+   * @param string $method Set he HTTP Method and normalize
+   * it to upper-case, as required by HTTP.
+   *
+   */
+  public function setRequestMethod($method)
+  {
+    $this->requestMethod = strtoupper($method);
+  }
+
+  /**
+   * @param array $headers The HTTP request headers
+   * to be set and normalized.
+   */
+  public function setRequestHeaders($headers)
+  {
+    $headers = Google_Utils::normalize($headers);
+    if ($this->requestHeaders) {
+      $headers = array_merge($this->requestHeaders, $headers);
+    }
+    $this->requestHeaders = $headers;
+  }
+
+  /**
+   * @param string $postBody the postBody to set
+   */
+  public function setPostBody($postBody)
+  {
+    $this->postBody = $postBody;
+  }
+
+  /**
+   * Set the User-Agent Header.
+   * @param string $userAgent The User-Agent.
+   */
+  public function setUserAgent($userAgent)
+  {
+    $this->userAgent = $userAgent;
+    if ($this->canGzip) {
+      $this->userAgent = $userAgent . self::GZIP_UA;
+    }
+  }
+
+  /**
+   * @return string The User-Agent.
+   */
+  public function getUserAgent()
+  {
+    return $this->userAgent;
+  }
+
+  /**
+   * Returns a cache key depending on if this was an OAuth signed request
+   * in which case it will use the non-signed url and access key to make this
+   * cache key unique per authenticated user, else use the plain request url
+   * @return string The md5 hash of the request cache key.
+   */
+  public function getCacheKey()
+  {
+    $key = $this->getUrl();
+
+    if (isset($this->accessKey)) {
+      $key .= $this->accessKey;
+    }
+
+    if (isset($this->requestHeaders['authorization'])) {
+      $key .= $this->requestHeaders['authorization'];
+    }
+
+    return md5($key);
+  }
+
+  public function getParsedCacheControl()
+  {
+    $parsed = array();
+    $rawCacheControl = $this->getResponseHeader('cache-control');
+    if ($rawCacheControl) {
+      $rawCacheControl = str_replace(', ', '&', $rawCacheControl);
+      parse_str($rawCacheControl, $parsed);
+    }
+
+    return $parsed;
+  }
+
+  /**
+   * @param string $id
+   * @return string A string representation of the HTTP Request.
+   */
+  public function toBatchString($id)
+  {
+    $str = '';
+    $path = parse_url($this->getUrl(), PHP_URL_PATH) . "?" .
+        http_build_query($this->queryParams);
+    $str .= $this->getRequestMethod() . ' ' . $path . " HTTP/1.1\n";
+
+    foreach ($this->getRequestHeaders() as $key => $val) {
+      $str .= $key . ': ' . $val . "\n";
+    }
+
+    if ($this->getPostBody()) {
+      $str .= "\n";
+      $str .= $this->getPostBody();
+    }
+    
+    $headers = '';
+    foreach ($this->batchHeaders as $key => $val) {
+      $headers .= $key . ': ' . $val . "\n";
+    }
+
+    $headers .= "Content-ID: $id\n";
+    $str = $headers . "\n" . $str;
+
+    return $str;
+  }
+  
+  /**
+   * Our own version of parse_str that allows for multiple variables
+   * with the same name. 
+   * @param $string - the query string to parse
+   */
+  private function parseQuery($string)
+  {
+    $return = array();
+    $parts = explode("&", $string);
+    foreach ($parts as $part) {
+      list($key, $value) = explode('=', $part, 2);
+      $value = urldecode($value);
+      if (isset($return[$key])) {
+        if (!is_array($return[$key])) {
+          $return[$key] = array($return[$key]);
+        }
+        $return[$key][] = $value;
+      } else {
+        $return[$key] = $value;
+      }
+    }
+    return $return;
+  }
+  
+  /**
+   * A version of build query that allows for multiple
+   * duplicate keys. 
+   * @param $parts array of key value pairs
+   */
+  private function buildQuery($parts)
+  {
+    $return = array();
+    foreach ($parts as $key => $value) {
+      if (is_array($value)) {
+        foreach ($value as $v) {
+          $return[] = urlencode($key) . "=" . urlencode($v);
+        }
+      } else {
+        $return[] = urlencode($key) . "=" . urlencode($value);
+      }
+    }
+    return implode('&', $return);
+  }
+  
+  /** 
+   * If we're POSTing and have no body to send, we can send the query
+   * parameters in there, which avoids length issues with longer query
+   * params.
+   */
+  public function maybeMoveParametersToBody()
+  {
+    if ($this->getRequestMethod() == "POST" && empty($this->postBody)) {
+      $this->setRequestHeaders(
+          array(
+            "content-type" =>
+                "application/x-www-form-urlencoded; charset=UTF-8"
+          )
+      );
+      $this->setPostBody($this->buildQuery($this->queryParams));
+      $this->queryParams = array();
+    }
+  }
+}
diff --git a/lib/google/Google/IO/Abstract.php b/lib/google/Google/IO/Abstract.php
new file mode 100755 (executable)
index 0000000..4f11342
--- /dev/null
@@ -0,0 +1,329 @@
+<?php
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Abstract IO base class
+ */
+
+require_once 'Google/Client.php';
+require_once 'Google/IO/Exception.php';
+require_once 'Google/Http/CacheParser.php';
+require_once 'Google/Http/Request.php';
+
+abstract class Google_IO_Abstract
+{
+  const UNKNOWN_CODE = 0;
+  const FORM_URLENCODED = 'application/x-www-form-urlencoded';
+  private static $CONNECTION_ESTABLISHED_HEADERS = array(
+    "HTTP/1.0 200 Connection established\r\n\r\n",
+    "HTTP/1.1 200 Connection established\r\n\r\n",
+  );
+  private static $ENTITY_HTTP_METHODS = array("POST" => null, "PUT" => null);
+
+  /** @var Google_Client */
+  protected $client;
+
+  public function __construct(Google_Client $client)
+  {
+    $this->client = $client;
+    $timeout = $client->getClassConfig('Google_IO_Abstract', 'request_timeout_seconds');
+    if ($timeout > 0) {
+      $this->setTimeout($timeout);
+    }
+  }
+
+  /**
+   * Executes a Google_Http_Request and returns the resulting populated Google_Http_Request
+   * @param Google_Http_Request $request
+   * @return Google_Http_Request $request
+   */
+  abstract public function executeRequest(Google_Http_Request $request);
+
+  /**
+   * Set options that update the transport implementation's behavior.
+   * @param $options
+   */
+  abstract public function setOptions($options);
+  
+  /**
+   * Set the maximum request time in seconds.
+   * @param $timeout in seconds
+   */
+  abstract public function setTimeout($timeout);
+  
+  /**
+   * Get the maximum request time in seconds.
+   * @return timeout in seconds
+   */
+  abstract public function getTimeout();
+
+  /**
+   * Test for the presence of a cURL header processing bug
+   *
+   * The cURL bug was present in versions prior to 7.30.0 and caused the header
+   * length to be miscalculated when a "Connection established" header added by
+   * some proxies was present.
+   *
+   * @return boolean
+   */
+  abstract protected function needsQuirk();
+
+  /**
+   * @visible for testing.
+   * Cache the response to an HTTP request if it is cacheable.
+   * @param Google_Http_Request $request
+   * @return bool Returns true if the insertion was successful.
+   * Otherwise, return false.
+   */
+  public function setCachedRequest(Google_Http_Request $request)
+  {
+    // Determine if the request is cacheable.
+    if (Google_Http_CacheParser::isResponseCacheable($request)) {
+      $this->client->getCache()->set($request->getCacheKey(), $request);
+      return true;
+    }
+
+    return false;
+  }
+  
+  /**
+   * Execute an HTTP Request
+   *
+   * @param Google_HttpRequest $request the http request to be executed
+   * @return Google_HttpRequest http request with the response http code,
+   * response headers and response body filled in
+   * @throws Google_IO_Exception on curl or IO error
+   */
+  public function makeRequest(Google_Http_Request $request)
+  {
+    // First, check to see if we have a valid cached version.
+    $cached = $this->getCachedRequest($request);
+    if ($cached !== false && $cached instanceof Google_Http_Request) {
+      if (!$this->checkMustRevalidateCachedRequest($cached, $request)) {
+        return $cached;
+      }
+    }
+
+    if (array_key_exists($request->getRequestMethod(), self::$ENTITY_HTTP_METHODS)) {
+      $request = $this->processEntityRequest($request);
+    }
+
+    list($responseData, $responseHeaders, $respHttpCode) = $this->executeRequest($request);
+
+    if ($respHttpCode == 304 && $cached) {
+      // If the server responded NOT_MODIFIED, return the cached request.
+      $this->updateCachedRequest($cached, $responseHeaders);
+      return $cached;
+    }
+
+    if (!isset($responseHeaders['Date']) && !isset($responseHeaders['date'])) {
+      $responseHeaders['Date'] = date("r");
+    }
+
+    $request->setResponseHttpCode($respHttpCode);
+    $request->setResponseHeaders($responseHeaders);
+    $request->setResponseBody($responseData);
+    // Store the request in cache (the function checks to see if the request
+    // can actually be cached)
+    $this->setCachedRequest($request);
+    return $request;
+  }
+
+  /**
+   * @visible for testing.
+   * @param Google_Http_Request $request
+   * @return Google_Http_Request|bool Returns the cached object or
+   * false if the operation was unsuccessful.
+   */
+  public function getCachedRequest(Google_Http_Request $request)
+  {
+    if (false === Google_Http_CacheParser::isRequestCacheable($request)) {
+      return false;
+    }
+
+    return $this->client->getCache()->get($request->getCacheKey());
+  }
+
+  /**
+   * @visible for testing
+   * Process an http request that contains an enclosed entity.
+   * @param Google_Http_Request $request
+   * @return Google_Http_Request Processed request with the enclosed entity.
+   */
+  public function processEntityRequest(Google_Http_Request $request)
+  {
+    $postBody = $request->getPostBody();
+    $contentType = $request->getRequestHeader("content-type");
+
+    // Set the default content-type as application/x-www-form-urlencoded.
+    if (false == $contentType) {
+      $contentType = self::FORM_URLENCODED;
+      $request->setRequestHeaders(array('content-type' => $contentType));
+    }
+
+    // Force the payload to match the content-type asserted in the header.
+    if ($contentType == self::FORM_URLENCODED && is_array($postBody)) {
+      $postBody = http_build_query($postBody, '', '&');
+      $request->setPostBody($postBody);
+    }
+
+    // Make sure the content-length header is set.
+    if (!$postBody || is_string($postBody)) {
+      $postsLength = strlen($postBody);
+      $request->setRequestHeaders(array('content-length' => $postsLength));
+    }
+
+    return $request;
+  }
+
+  /**
+   * Check if an already cached request must be revalidated, and if so update
+   * the request with the correct ETag headers.
+   * @param Google_Http_Request $cached A previously cached response.
+   * @param Google_Http_Request $request The outbound request.
+   * return bool If the cached object needs to be revalidated, false if it is
+   * still current and can be re-used.
+   */
+  protected function checkMustRevalidateCachedRequest($cached, $request)
+  {
+    if (Google_Http_CacheParser::mustRevalidate($cached)) {
+      $addHeaders = array();
+      if ($cached->getResponseHeader('etag')) {
+        // [13.3.4] If an entity tag has been provided by the origin server,
+        // we must use that entity tag in any cache-conditional request.
+        $addHeaders['If-None-Match'] = $cached->getResponseHeader('etag');
+      } elseif ($cached->getResponseHeader('date')) {
+        $addHeaders['If-Modified-Since'] = $cached->getResponseHeader('date');
+      }
+
+      $request->setRequestHeaders($addHeaders);
+      return true;
+    } else {
+      return false;
+    }
+  }
+
+  /**
+   * Update a cached request, using the headers from the last response.
+   * @param Google_HttpRequest $cached A previously cached response.
+   * @param mixed Associative array of response headers from the last request.
+   */
+  protected function updateCachedRequest($cached, $responseHeaders)
+  {
+    if (isset($responseHeaders['connection'])) {
+      $hopByHop = array_merge(
+          self::$HOP_BY_HOP,
+          explode(
+              ',',
+              $responseHeaders['connection']
+          )
+      );
+
+      $endToEnd = array();
+      foreach ($hopByHop as $key) {
+        if (isset($responseHeaders[$key])) {
+          $endToEnd[$key] = $responseHeaders[$key];
+        }
+      }
+      $cached->setResponseHeaders($endToEnd);
+    }
+  }
+
+  /**
+   * Used by the IO lib and also the batch processing.
+   *
+   * @param $respData
+   * @param $headerSize
+   * @return array
+   */
+  public function parseHttpResponse($respData, $headerSize)
+  {
+    // check proxy header
+    foreach (self::$CONNECTION_ESTABLISHED_HEADERS as $established_header) {
+      if (stripos($respData, $established_header) !== false) {
+        // existed, remove it
+        $respData = str_ireplace($established_header, '', $respData);
+        // Subtract the proxy header size unless the cURL bug prior to 7.30.0
+        // is present which prevented the proxy header size from being taken into
+        // account.
+        if (!$this->needsQuirk()) {
+          $headerSize -= strlen($established_header);
+        }
+        break;
+      }
+    }
+
+    if ($headerSize) {
+      $responseBody = substr($respData, $headerSize);
+      $responseHeaders = substr($respData, 0, $headerSize);
+    } else {
+      list($responseHeaders, $responseBody) = explode("\r\n\r\n", $respData, 2);
+    }
+
+    $responseHeaders = $this->getHttpResponseHeaders($responseHeaders);
+    return array($responseHeaders, $responseBody);
+  }
+
+  /**
+   * Parse out headers from raw headers
+   * @param rawHeaders array or string
+   * @return array
+   */
+  public function getHttpResponseHeaders($rawHeaders)
+  {
+    if (is_array($rawHeaders)) {
+      return $this->parseArrayHeaders($rawHeaders);
+    } else {
+      return $this->parseStringHeaders($rawHeaders);
+    }
+  }
+
+  private function parseStringHeaders($rawHeaders)
+  {
+    $headers = array();
+    $responseHeaderLines = explode("\r\n", $rawHeaders);
+    foreach ($responseHeaderLines as $headerLine) {
+      if ($headerLine && strpos($headerLine, ':') !== false) {
+        list($header, $value) = explode(': ', $headerLine, 2);
+        $header = strtolower($header);
+        if (isset($headers[$header])) {
+          $headers[$header] .= "\n" . $value;
+        } else {
+          $headers[$header] = $value;
+        }
+      }
+    }
+    return $headers;
+  }
+
+  private function parseArrayHeaders($rawHeaders)
+  {
+    $header_count = count($rawHeaders);
+    $headers = array();
+
+    for ($i = 0; $i < $header_count; $i++) {
+      $header = $rawHeaders[$i];
+      // Times will have colons in - so we just want the first match.
+      $header_parts = explode(': ', $header, 2);
+      if (count($header_parts) == 2) {
+        $headers[$header_parts[0]] = $header_parts[1];
+      }
+    }
+
+    return $headers;
+  }
+}
diff --git a/lib/google/Google/IO/Curl.php b/lib/google/Google/IO/Curl.php
new file mode 100755 (executable)
index 0000000..57a0571
--- /dev/null
@@ -0,0 +1,137 @@
+<?php
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Curl based implementation of Google_IO.
+ *
+ * @author Stuart Langley <slangley@google.com>
+ */
+
+require_once 'Google/IO/Abstract.php';
+
+class Google_IO_Curl extends Google_IO_Abstract
+{
+  // cURL hex representation of version 7.30.0
+  const NO_QUIRK_VERSION = 0x071E00;
+
+  private $options = array();
+  /**
+   * Execute an HTTP Request
+   *
+   * @param Google_HttpRequest $request the http request to be executed
+   * @return Google_HttpRequest http request with the response http code,
+   * response headers and response body filled in
+   * @throws Google_IO_Exception on curl or IO error
+   */
+  public function executeRequest(Google_Http_Request $request)
+  {
+    $curl = curl_init();
+
+    if ($request->getPostBody()) {
+      curl_setopt($curl, CURLOPT_POSTFIELDS, $request->getPostBody());
+    }
+
+    $requestHeaders = $request->getRequestHeaders();
+    if ($requestHeaders && is_array($requestHeaders)) {
+      $curlHeaders = array();
+      foreach ($requestHeaders as $k => $v) {
+        $curlHeaders[] = "$k: $v";
+      }
+      curl_setopt($curl, CURLOPT_HTTPHEADER, $curlHeaders);
+    }
+
+    curl_setopt($curl, CURLOPT_URL, $request->getUrl());
+    
+    curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $request->getRequestMethod());
+    curl_setopt($curl, CURLOPT_USERAGENT, $request->getUserAgent());
+
+    curl_setopt($curl, CURLOPT_FOLLOWLOCATION, false);
+    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true);
+    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
+    curl_setopt($curl, CURLOPT_HEADER, true);
+
+    if ($request->canGzip()) {
+      curl_setopt($curl, CURLOPT_ENCODING, 'gzip,deflate');
+    }
+
+    foreach ($this->options as $key => $var) {
+      curl_setopt($curl, $key, $var);
+    }
+
+    if (!isset($this->options[CURLOPT_CAINFO])) {
+      curl_setopt($curl, CURLOPT_CAINFO, dirname(__FILE__) . '/cacerts.pem');
+    }
+
+    $response = curl_exec($curl);
+    if ($response === false) {
+      throw new Google_IO_Exception(curl_error($curl));
+    }
+    $headerSize = curl_getinfo($curl, CURLINFO_HEADER_SIZE);
+
+    list($responseHeaders, $responseBody) = $this->parseHttpResponse($response, $headerSize);
+
+    $responseCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
+
+    return array($responseBody, $responseHeaders, $responseCode);
+  }
+
+  /**
+   * Set options that update the transport implementation's behavior.
+   * @param $options
+   */
+  public function setOptions($options)
+  {
+    $this->options = $options + $this->options;
+  }
+
+  /**
+   * Set the maximum request time in seconds.
+   * @param $timeout in seconds
+   */
+  public function setTimeout($timeout)
+  {
+    // Since this timeout is really for putting a bound on the time
+    // we'll set them both to the same. If you need to specify a longer
+    // CURLOPT_TIMEOUT, or a tigher CONNECTTIMEOUT, the best thing to
+    // do is use the setOptions method for the values individually.
+    $this->options[CURLOPT_CONNECTTIMEOUT] = $timeout;
+    $this->options[CURLOPT_TIMEOUT] = $timeout;
+  }
+
+  /**
+   * Get the maximum request time in seconds.
+   * @return timeout in seconds
+   */
+  public function getTimeout()
+  {
+    return $this->options[CURLOPT_TIMEOUT];
+  }
+
+  /**
+   * Test for the presence of a cURL header processing bug
+   *
+   * {@inheritDoc}
+   *
+   * @return boolean
+   */
+  protected function needsQuirk()
+  {
+    $ver = curl_version();
+    $versionNum = $ver['version_number'];
+    return $versionNum < Google_IO_Curl::NO_QUIRK_VERSION;
+  }
+}
diff --git a/lib/google/Google/IO/Exception.php b/lib/google/Google/IO/Exception.php
new file mode 100755 (executable)
index 0000000..28c2d8c
--- /dev/null
@@ -0,0 +1,22 @@
+<?php
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+require_once 'Google/Exception.php';
+
+class Google_IO_Exception extends Google_Exception
+{
+}
diff --git a/lib/google/Google/IO/Stream.php b/lib/google/Google/IO/Stream.php
new file mode 100755 (executable)
index 0000000..917578d
--- /dev/null
@@ -0,0 +1,211 @@
+<?php
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Http Streams based implementation of Google_IO.
+ *
+ * @author Stuart Langley <slangley@google.com>
+ */
+
+require_once 'Google/IO/Abstract.php';
+
+class Google_IO_Stream extends Google_IO_Abstract
+{
+  const TIMEOUT = "timeout";
+  const ZLIB = "compress.zlib://";
+  private $options = array();
+  private $trappedErrorNumber;
+  private $trappedErrorString;
+
+  private static $DEFAULT_HTTP_CONTEXT = array(
+    "follow_location" => 0,
+    "ignore_errors" => 1,
+  );
+
+  private static $DEFAULT_SSL_CONTEXT = array(
+    "verify_peer" => true,
+  );
+
+  /**
+   * Execute an HTTP Request
+   *
+   * @param Google_HttpRequest $request the http request to be executed
+   * @return Google_HttpRequest http request with the response http code,
+   * response headers and response body filled in
+   * @throws Google_IO_Exception on curl or IO error
+   */
+  public function executeRequest(Google_Http_Request $request)
+  {
+    $default_options = stream_context_get_options(stream_context_get_default());
+
+    $requestHttpContext = array_key_exists('http', $default_options) ?
+        $default_options['http'] : array();
+
+    if ($request->getPostBody()) {
+      $requestHttpContext["content"] = $request->getPostBody();
+    }
+
+    $requestHeaders = $request->getRequestHeaders();
+    if ($requestHeaders && is_array($requestHeaders)) {
+      $headers = "";
+      foreach ($requestHeaders as $k => $v) {
+        $headers .= "$k: $v\r\n";
+      }
+      $requestHttpContext["header"] = $headers;
+    }
+
+    $requestHttpContext["method"] = $request->getRequestMethod();
+    $requestHttpContext["user_agent"] = $request->getUserAgent();
+
+    $requestSslContext = array_key_exists('ssl', $default_options) ?
+        $default_options['ssl'] : array();
+
+    if (!array_key_exists("cafile", $requestSslContext)) {
+      $requestSslContext["cafile"] = dirname(__FILE__) . '/cacerts.pem';
+    }
+
+    $options = array(
+        "http" => array_merge(
+            self::$DEFAULT_HTTP_CONTEXT,
+            $requestHttpContext
+        ),
+        "ssl" => array_merge(
+            self::$DEFAULT_SSL_CONTEXT,
+            $requestSslContext
+        )
+    );
+
+    $context = stream_context_create($options);
+
+    $url = $request->getUrl();
+
+    if ($request->canGzip()) {
+      $url = self::ZLIB . $url;
+    }
+
+    // We are trapping any thrown errors in this method only and
+    // throwing an exception.
+    $this->trappedErrorNumber = null;
+    $this->trappedErrorString = null;
+
+    // START - error trap.
+    set_error_handler(array($this, 'trapError'));
+    $fh = fopen($url, 'r', false, $context);
+    restore_error_handler();
+    // END - error trap.
+
+    if ($this->trappedErrorNumber) {
+      throw new Google_IO_Exception(
+          sprintf(
+              "HTTP Error: Unable to connect: '%s'",
+              $this->trappedErrorString
+          ),
+          $this->trappedErrorNumber
+      );
+    }
+
+    $response_data = false;
+    $respHttpCode = self::UNKNOWN_CODE;
+    if ($fh) {
+      if (isset($this->options[self::TIMEOUT])) {
+        stream_set_timeout($fh, $this->options[self::TIMEOUT]);
+      }
+
+      $response_data = stream_get_contents($fh);
+      fclose($fh);
+
+      $respHttpCode = $this->getHttpResponseCode($http_response_header);
+    }
+
+    if (false === $response_data) {
+      throw new Google_IO_Exception(
+          sprintf(
+              "HTTP Error: Unable to connect: '%s'",
+              $respHttpCode
+          ),
+          $respHttpCode
+      );
+    }
+
+    $responseHeaders = $this->getHttpResponseHeaders($http_response_header);
+
+    return array($response_data, $responseHeaders, $respHttpCode);
+  }
+
+  /**
+   * Set options that update the transport implementation's behavior.
+   * @param $options
+   */
+  public function setOptions($options)
+  {
+    $this->options = $options + $this->options;
+  }
+
+  /**
+   * Method to handle errors, used for error handling around
+   * stream connection methods.
+   */
+  public function trapError($errno, $errstr)
+  {
+    $this->trappedErrorNumber = $errno;
+    $this->trappedErrorString = $errstr;
+  }
+
+  /**
+   * Set the maximum request time in seconds.
+   * @param $timeout in seconds
+   */
+  public function setTimeout($timeout)
+  {
+    $this->options[self::TIMEOUT] = $timeout;
+  }
+
+  /**
+   * Get the maximum request time in seconds.
+   * @return timeout in seconds
+   */
+  public function getTimeout()
+  {
+    return $this->options[self::TIMEOUT];
+  }
+
+  /**
+   * Test for the presence of a cURL header processing bug
+   *
+   * {@inheritDoc}
+   *
+   * @return boolean
+   */
+  protected function needsQuirk()
+  {
+    return false;
+  }
+
+  protected function getHttpResponseCode($response_headers)
+  {
+    $header_count = count($response_headers);
+
+    for ($i = 0; $i < $header_count; $i++) {
+      $header = $response_headers[$i];
+      if (strncasecmp("HTTP", $header, strlen("HTTP")) == 0) {
+        $response = explode(' ', $header);
+        return $response[1];
+      }
+    }
+    return self::UNKNOWN_CODE;
+  }
+}
diff --git a/lib/google/Google/IO/cacerts.pem b/lib/google/Google/IO/cacerts.pem
new file mode 100755 (executable)
index 0000000..70990f1
--- /dev/null
@@ -0,0 +1,2183 @@
+# Issuer: CN=GTE CyberTrust Global Root O=GTE Corporation OU=GTE CyberTrust Solutions, Inc.
+# Subject: CN=GTE CyberTrust Global Root O=GTE Corporation OU=GTE CyberTrust Solutions, Inc.
+# Label: "GTE CyberTrust Global Root"
+# Serial: 421
+# MD5 Fingerprint: ca:3d:d3:68:f1:03:5c:d0:32:fa:b8:2b:59:e8:5a:db
+# SHA1 Fingerprint: 97:81:79:50:d8:1c:96:70:cc:34:d8:09:cf:79:44:31:36:7e:f4:74
+# SHA256 Fingerprint: a5:31:25:18:8d:21:10:aa:96:4b:02:c7:b7:c6:da:32:03:17:08:94:e5:fb:71:ff:fb:66:67:d5:e6:81:0a:36
+-----BEGIN CERTIFICATE-----
+MIICWjCCAcMCAgGlMA0GCSqGSIb3DQEBBAUAMHUxCzAJBgNVBAYTAlVTMRgwFgYD
+VQQKEw9HVEUgQ29ycG9yYXRpb24xJzAlBgNVBAsTHkdURSBDeWJlclRydXN0IFNv
+bHV0aW9ucywgSW5jLjEjMCEGA1UEAxMaR1RFIEN5YmVyVHJ1c3QgR2xvYmFsIFJv
+b3QwHhcNOTgwODEzMDAyOTAwWhcNMTgwODEzMjM1OTAwWjB1MQswCQYDVQQGEwJV
+UzEYMBYGA1UEChMPR1RFIENvcnBvcmF0aW9uMScwJQYDVQQLEx5HVEUgQ3liZXJU
+cnVzdCBTb2x1dGlvbnMsIEluYy4xIzAhBgNVBAMTGkdURSBDeWJlclRydXN0IEds
+b2JhbCBSb290MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVD6C28FCc6HrH
+iM3dFw4usJTQGz0O9pTAipTHBsiQl8i4ZBp6fmw8U+E3KHNgf7KXUwefU/ltWJTS
+r41tiGeA5u2ylc9yMcqlHHK6XALnZELn+aks1joNrI1CqiQBOeacPwGFVw1Yh0X4
+04Wqk2kmhXBIgD8SFcd5tB8FLztimQIDAQABMA0GCSqGSIb3DQEBBAUAA4GBAG3r
+GwnpXtlR22ciYaQqPEh346B8pt5zohQDhT37qw4wxYMWM4ETCJ57NE7fQMh017l9
+3PR2VX2bY1QY6fDq81yx2YtCHrnAlU66+tXifPVoYb+O7AWXX1uw16OFNMQkpw0P
+lZPvy5TYnh+dXIVtx6quTx8itc2VrbqnzPmrC3p/
+-----END CERTIFICATE-----
+
+# Issuer: CN=Thawte Server CA O=Thawte Consulting cc OU=Certification Services Division
+# Subject: CN=Thawte Server CA O=Thawte Consulting cc OU=Certification Services Division
+# Label: "Thawte Server CA"
+# Serial: 1
+# MD5 Fingerprint: c5:70:c4:a2:ed:53:78:0c:c8:10:53:81:64:cb:d0:1d
+# SHA1 Fingerprint: 23:e5:94:94:51:95:f2:41:48:03:b4:d5:64:d2:a3:a3:f5:d8:8b:8c
+# SHA256 Fingerprint: b4:41:0b:73:e2:e6:ea:ca:47:fb:c4:2f:8f:a4:01:8a:f4:38:1d:c5:4c:fa:a8:44:50:46:1e:ed:09:45:4d:e9
+-----BEGIN CERTIFICATE-----
+MIIDEzCCAnygAwIBAgIBATANBgkqhkiG9w0BAQQFADCBxDELMAkGA1UEBhMCWkEx
+FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYD
+VQQKExRUaGF3dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlv
+biBTZXJ2aWNlcyBEaXZpc2lvbjEZMBcGA1UEAxMQVGhhd3RlIFNlcnZlciBDQTEm
+MCQGCSqGSIb3DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0ZS5jb20wHhcNOTYwODAx
+MDAwMDAwWhcNMjAxMjMxMjM1OTU5WjCBxDELMAkGA1UEBhMCWkExFTATBgNVBAgT
+DFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYDVQQKExRUaGF3
+dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNl
+cyBEaXZpc2lvbjEZMBcGA1UEAxMQVGhhd3RlIFNlcnZlciBDQTEmMCQGCSqGSIb3
+DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0ZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQAD
+gY0AMIGJAoGBANOkUG7I/1Zr5s9dtuoMaHVHoqrC2oQl/Kj0R1HahbUgdJSGHg91
+yekIYfUGbTBuFRkC6VLAYttNmZ7iagxEOM3+vuNkCXDF/rFrKbYvScg71CcEJRCX
+L+eQbcAoQpnXTEPew/UhbVSfXcNY4cDk2VuwuNy0e982OsK1ZiIS1ocNAgMBAAGj
+EzARMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEEBQADgYEAB/pMaVz7lcxG
+7oWDTSEwjsrZqG9JGubaUeNgcGyEYRGhGshIPllDfU+VPaGLtwtimHp1it2ITk6e
+QNuozDJ0uW8NxuOzRAvZim+aKZuZGCg70eNAKJpaPNW15yAbi8qkq43pUdniTCxZ
+qdq5snUb9kLy78fyGPmJvKP/iiMucEc=
+-----END CERTIFICATE-----
+
+# Issuer: CN=Thawte Premium Server CA O=Thawte Consulting cc OU=Certification Services Division
+# Subject: CN=Thawte Premium Server CA O=Thawte Consulting cc OU=Certification Services Division
+# Label: "Thawte Premium Server CA"
+# Serial: 1
+# MD5 Fingerprint: 06:9f:69:79:16:66:90:02:1b:8c:8c:a2:c3:07:6f:3a
+# SHA1 Fingerprint: 62:7f:8d:78:27:65:63:99:d2:7d:7f:90:44:c9:fe:b3:f3:3e:fa:9a
+# SHA256 Fingerprint: ab:70:36:36:5c:71:54:aa:29:c2:c2:9f:5d:41:91:16:3b:16:2a:22:25:01:13:57:d5:6d:07:ff:a7:bc:1f:72
+-----BEGIN CERTIFICATE-----
+MIIDJzCCApCgAwIBAgIBATANBgkqhkiG9w0BAQQFADCBzjELMAkGA1UEBhMCWkEx
+FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYD
+VQQKExRUaGF3dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlv
+biBTZXJ2aWNlcyBEaXZpc2lvbjEhMB8GA1UEAxMYVGhhd3RlIFByZW1pdW0gU2Vy
+dmVyIENBMSgwJgYJKoZIhvcNAQkBFhlwcmVtaXVtLXNlcnZlckB0aGF3dGUuY29t
+MB4XDTk2MDgwMTAwMDAwMFoXDTIwMTIzMTIzNTk1OVowgc4xCzAJBgNVBAYTAlpB
+MRUwEwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNVBAcTCUNhcGUgVG93bjEdMBsG
+A1UEChMUVGhhd3RlIENvbnN1bHRpbmcgY2MxKDAmBgNVBAsTH0NlcnRpZmljYXRp
+b24gU2VydmljZXMgRGl2aXNpb24xITAfBgNVBAMTGFRoYXd0ZSBQcmVtaXVtIFNl
+cnZlciBDQTEoMCYGCSqGSIb3DQEJARYZcHJlbWl1bS1zZXJ2ZXJAdGhhd3RlLmNv
+bTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0jY2aovXwlue2oFBYo847kkE
+VdbQ7xwblRZH7xhINTpS9CtqBo87L+pW46+GjZ4X9560ZXUCTe/LCaIhUdib0GfQ
+ug2SBhRz1JPLlyoAnFxODLz6FVL88kRu2hFKbgifLy3j+ao6hnO2RlNYyIkFvYMR
+uHM/qgeN9EJN50CdHDcCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG
+9w0BAQQFAAOBgQAmSCwWwlj66BZ0DKqqX1Q/8tfJeGBeXm43YyJ3Nn6yF8Q0ufUI
+hfzJATj/Tb7yFkJD57taRvvBxhEf8UqwKEbJw8RCfbz6q1lu1bdRiBHjpIUZa4JM
+pAwSremkrj/xw0llmozFyD4lt5SZu5IycQfwhl7tUCemDaYj+bvLpgcUQg==
+-----END CERTIFICATE-----
+
+# Issuer: O=Equifax OU=Equifax Secure Certificate Authority
+# Subject: O=Equifax OU=Equifax Secure Certificate Authority
+# Label: "Equifax Secure CA"
+# Serial: 903804111
+# MD5 Fingerprint: 67:cb:9d:c0:13:24:8a:82:9b:b2:17:1e:d1:1b:ec:d4
+# SHA1 Fingerprint: d2:32:09:ad:23:d3:14:23:21:74:e4:0d:7f:9d:62:13:97:86:63:3a
+# SHA256 Fingerprint: 08:29:7a:40:47:db:a2:36:80:c7:31:db:6e:31:76:53:ca:78:48:e1:be:bd:3a:0b:01:79:a7:07:f9:2c:f1:78
+-----BEGIN CERTIFICATE-----
+MIIDIDCCAomgAwIBAgIENd70zzANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJV
+UzEQMA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2Vy
+dGlmaWNhdGUgQXV0aG9yaXR5MB4XDTk4MDgyMjE2NDE1MVoXDTE4MDgyMjE2NDE1
+MVowTjELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0VxdWlmYXgxLTArBgNVBAsTJEVx
+dWlmYXggU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eTCBnzANBgkqhkiG9w0B
+AQEFAAOBjQAwgYkCgYEAwV2xWGcIYu6gmi0fCG2RFGiYCh7+2gRvE4RiIcPRfM6f
+BeC4AfBONOziipUEZKzxa1NfBbPLZ4C/QgKO/t0BCezhABRP/PvwDN1Dulsr4R+A
+cJkVV5MW8Q+XarfCaCMczE1ZMKxRHjuvK9buY0V7xdlfUNLjUA86iOe/FP3gx7kC
+AwEAAaOCAQkwggEFMHAGA1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEQ
+MA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2VydGlm
+aWNhdGUgQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMBoGA1UdEAQTMBGBDzIwMTgw
+ODIyMTY0MTUxWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUSOZo+SvSspXXR9gj
+IBBPM5iQn9QwHQYDVR0OBBYEFEjmaPkr0rKV10fYIyAQTzOYkJ/UMAwGA1UdEwQF
+MAMBAf8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUA
+A4GBAFjOKer89961zgK5F7WF0bnj4JXMJTENAKaSbn+2kmOeUJXRmm/kEd5jhW6Y
+7qj/WsjTVbJmcVfewCHrPSqnI0kBBIZCe/zuf6IWUrVnZ9NA2zsmWLIodz2uFHdh
+1voqZiegDfqnc1zqcPGUIWVEX/r87yloqaKHee9570+sB3c4
+-----END CERTIFICATE-----
+
+# Issuer: O=VeriSign, Inc. OU=Class 3 Public Primary Certification Authority
+# Subject: O=VeriSign, Inc. OU=Class 3 Public Primary Certification Authority
+# Label: "Verisign Class 3 Public Primary Certification Authority"
+# Serial: 149843929435818692848040365716851702463
+# MD5 Fingerprint: 10:fc:63:5d:f6:26:3e:0d:f3:25:be:5f:79:cd:67:67
+# SHA1 Fingerprint: 74:2c:31:92:e6:07:e4:24:eb:45:49:54:2b:e1:bb:c5:3e:61:74:e2
+# SHA256 Fingerprint: e7:68:56:34:ef:ac:f6:9a:ce:93:9a:6b:25:5b:7b:4f:ab:ef:42:93:5b:50:a2:65:ac:b5:cb:60:27:e4:4e:70
+-----BEGIN CERTIFICATE-----
+MIICPDCCAaUCEHC65B0Q2Sk0tjjKewPMur8wDQYJKoZIhvcNAQECBQAwXzELMAkG
+A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz
+cyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2
+MDEyOTAwMDAwMFoXDTI4MDgwMTIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV
+BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmlt
+YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN
+ADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhE
+BarsAx94f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/is
+I19wKTakyYbnsZogy1Olhec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0G
+CSqGSIb3DQEBAgUAA4GBALtMEivPLCYATxQT3ab7/AoRhIzzKBxnki98tsX63/Do
+lbwdj2wsqFHMc9ikwFPwTtYmwHYBV4GSXiHx0bH/59AhWM1pF+NEHJwZRDmJXNyc
+AA9WjQKZ7aKQRUzkuxCkPfAyAw7xzvjoyVGM5mKf5p/AfbdynMk2OmufTqj/ZA1k
+-----END CERTIFICATE-----
+
+# Issuer: O=VeriSign, Inc. OU=Class 3 Public Primary Certification Authority - G2/(c) 1998 VeriSign, Inc. - For authorized use only/VeriSign Trust Network
+# Subject: O=VeriSign, Inc. OU=Class 3 Public Primary Certification Authority - G2/(c) 1998 VeriSign, Inc. - For authorized use only/VeriSign Trust Network
+# Label: "Verisign Class 3 Public Primary Certification Authority - G2"
+# Serial: 167285380242319648451154478808036881606
+# MD5 Fingerprint: a2:33:9b:4c:74:78:73:d4:6c:e7:c1:f3:8d:cb:5c:e9
+# SHA1 Fingerprint: 85:37:1c:a6:e5:50:14:3d:ce:28:03:47:1b:de:3a:09:e8:f8:77:0f
+# SHA256 Fingerprint: 83:ce:3c:12:29:68:8a:59:3d:48:5f:81:97:3c:0f:91:95:43:1e:da:37:cc:5e:36:43:0e:79:c7:a8:88:63:8b
+-----BEGIN CERTIFICATE-----
+MIIDAjCCAmsCEH3Z/gfPqB63EHln+6eJNMYwDQYJKoZIhvcNAQEFBQAwgcExCzAJ
+BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xh
+c3MgMyBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcy
+MTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3Jp
+emVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMB4X
+DTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVowgcExCzAJBgNVBAYTAlVTMRcw
+FQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMyBQdWJsaWMg
+UHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEo
+YykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5
+MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEB
+AQUAA4GNADCBiQKBgQDMXtERXVxp0KvTuWpMmR9ZmDCOFoUgRm1HP9SFIIThbbP4
+pO0M8RcPO/mn+SXXwc+EY/J8Y8+iR/LGWzOOZEAEaMGAuWQcRXfH2G71lSk8UOg0
+13gfqLptQ5GVj0VXXn7F+8qkBOvqlzdUMG+7AUcyM83cV5tkaWH4mx0ciU9cZwID
+AQABMA0GCSqGSIb3DQEBBQUAA4GBAFFNzb5cy5gZnBWyATl4Lk0PZ3BwmcYQWpSk
+U01UbSuvDV1Ai2TT1+7eVmGSX6bEHRBhNtMsJzzoKQm5EWR0zLVznxxIqbxhAe7i
+F6YM40AIOw7n60RzKprxaZLvcRTDOaxxp5EJb+RxBrO6WVcmeQD2+A2iMzAo1KpY
+oJ2daZH9
+-----END CERTIFICATE-----
+
+# Issuer: CN=GlobalSign Root CA O=GlobalSign nv-sa OU=Root CA
+# Subject: CN=GlobalSign Root CA O=GlobalSign nv-sa OU=Root CA
+# Label: "GlobalSign Root CA"
+# Serial: 4835703278459707669005204
+# MD5 Fingerprint: 3e:45:52:15:09:51:92:e1:b7:5d:37:9f:b1:87:29:8a
+# SHA1 Fingerprint: b1:bc:96:8b:d4:f4:9d:62:2a:a8:9a:81:f2:15:01:52:a4:1d:82:9c
+# SHA256 Fingerprint: eb:d4:10:40:e4:bb:3e:c7:42:c9:e3:81:d3:1e:f2:a4:1a:48:b6:68:5c:96:e7:ce:f3:c1:df:6c:d4:33:1c:99
+-----BEGIN CERTIFICATE-----
+MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG
+A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv
+b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw
+MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i
+YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT
+aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ
+jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp
+xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp
+1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG
+snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ
+U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8
+9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E
+BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B
+AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz
+yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE
+38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP
+AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad
+DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME
+HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A==
+-----END CERTIFICATE-----
+
+# Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R2
+# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R2
+# Label: "GlobalSign Root CA - R2"
+# Serial: 4835703278459682885658125
+# MD5 Fingerprint: 94:14:77:7e:3e:5e:fd:8f:30:bd:41:b0:cf:e7:d0:30
+# SHA1 Fingerprint: 75:e0:ab:b6:13:85:12:27:1c:04:f8:5f:dd:de:38:e4:b7:24:2e:fe
+# SHA256 Fingerprint: ca:42:dd:41:74:5f:d0:b8:1e:b9:02:36:2c:f9:d8:bf:71:9d:a1:bd:1b:1e:fc:94:6f:5b:4c:99:f4:2c:1b:9e
+-----BEGIN CERTIFICATE-----
+MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4G
+A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNp
+Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1
+MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMjETMBEG
+A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6ErPL
+v4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8
+eoLrvozps6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklq
+tTleiDTsvHgMCJiEbKjNS7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzd
+C9XZzPnqJworc5HGnRusyMvo4KD0L5CLTfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pa
+zq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6CygPCm48CAwEAAaOBnDCB
+mTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUm+IH
+V2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5n
+bG9iYWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG
+3lm0mi3f3BmGLjANBgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4Gs
+J0/WwbgcQ3izDJr86iw8bmEbTUsp9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO
+291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu01yiPqFbQfXf5WRDLenVOavS
+ot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG79G+dwfCMNYxd
+AfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7
+TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg==
+-----END CERTIFICATE-----
+
+# Issuer: CN=http://www.valicert.com/ O=ValiCert, Inc. OU=ValiCert Class 1 Policy Validation Authority
+# Subject: CN=http://www.valicert.com/ O=ValiCert, Inc. OU=ValiCert Class 1 Policy Validation Authority
+# Label: "ValiCert Class 1 VA"
+# Serial: 1
+# MD5 Fingerprint: 65:58:ab:15:ad:57:6c:1e:a8:a7:b5:69:ac:bf:ff:eb
+# SHA1 Fingerprint: e5:df:74:3c:b6:01:c4:9b:98:43:dc:ab:8c:e8:6a:81:10:9f:e4:8e
+# SHA256 Fingerprint: f4:c1:49:55:1a:30:13:a3:5b:c7:bf:fe:17:a7:f3:44:9b:c1:ab:5b:5a:0a:e7:4b:06:c2:3b:90:00:4c:01:04
+-----BEGIN CERTIFICATE-----
+MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0
+IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAz
+BgNVBAsTLFZhbGlDZXJ0IENsYXNzIDEgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9y
+aXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG
+9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNTIyMjM0OFoXDTE5MDYy
+NTIyMjM0OFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29y
+azEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs
+YXNzIDEgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw
+Oi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl
+cnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDYWYJ6ibiWuqYvaG9Y
+LqdUHAZu9OqNSLwxlBfw8068srg1knaw0KWlAdcAAxIiGQj4/xEjm84H9b9pGib+
+TunRf50sQB1ZaG6m+FiwnRqP0z/x3BkGgagO4DrdyFNFCQbmD3DD+kCmDuJWBQ8Y
+TfwggtFzVXSNdnKgHZ0dwN0/cQIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAFBoPUn0
+LBwGlN+VYH+Wexf+T3GtZMjdd9LvWVXoP+iOBSoh8gfStadS/pyxtuJbdxdA6nLW
+I8sogTLDAHkY7FkXicnGah5xyf23dKUlRWnFSKsZ4UWKJWsZ7uW7EvV/96aNUcPw
+nXS3qT6gpf+2SQMT2iLM7XGCK5nPOrf1LXLI
+-----END CERTIFICATE-----
+
+# Issuer: CN=http://www.valicert.com/ O=ValiCert, Inc. OU=ValiCert Class 2 Policy Validation Authority
+# Subject: CN=http://www.valicert.com/ O=ValiCert, Inc. OU=ValiCert Class 2 Policy Validation Authority
+# Label: "ValiCert Class 2 VA"
+# Serial: 1
+# MD5 Fingerprint: a9:23:75:9b:ba:49:36:6e:31:c2:db:f2:e7:66:ba:87
+# SHA1 Fingerprint: 31:7a:2a:d0:7f:2b:33:5e:f5:a1:c3:4e:4b:57:e8:b7:d8:f1:fc:a6
+# SHA256 Fingerprint: 58:d0:17:27:9c:d4:dc:63:ab:dd:b1:96:a6:c9:90:6c:30:c4:e0:87:83:ea:e8:c1:60:99:54:d6:93:55:59:6b
+-----BEGIN CERTIFICATE-----
+MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0
+IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAz
+BgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9y
+aXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG
+9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAwMTk1NFoXDTE5MDYy
+NjAwMTk1NFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29y
+azEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs
+YXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw
+Oi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl
+cnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOOnHK5avIWZJV16vY
+dA757tn2VUdZZUcOBVXc65g2PFxTXdMwzzjsvUGJ7SVCCSRrCl6zfN1SLUzm1NZ9
+WlmpZdRJEy0kTRxQb7XBhVQ7/nHk01xC+YDgkRoKWzk2Z/M/VXwbP7RfZHM047QS
+v4dk+NoS/zcnwbNDu+97bi5p9wIDAQABMA0GCSqGSIb3DQEBBQUAA4GBADt/UG9v
+UJSZSWI4OB9L+KXIPqeCgfYrx+jFzug6EILLGACOTb2oWH+heQC1u+mNr0HZDzTu
+IYEZoDJJKPTEjlbVUjP9UNV+mWwD5MlM/Mtsq2azSiGM5bUMMj4QssxsodyamEwC
+W/POuZ6lcg5Ktz885hZo+L7tdEy8W9ViH0Pd
+-----END CERTIFICATE-----
+
+# Issuer: CN=http://www.valicert.com/ O=ValiCert, Inc. OU=ValiCert Class 3 Policy Validation Authority
+# Subject: CN=http://www.valicert.com/ O=ValiCert, Inc. OU=ValiCert Class 3 Policy Validation Authority
+# Label: "RSA Root Certificate 1"
+# Serial: 1
+# MD5 Fingerprint: a2:6f:53:b7:ee:40:db:4a:68:e7:fa:18:d9:10:4b:72
+# SHA1 Fingerprint: 69:bd:8c:f4:9c:d3:00:fb:59:2e:17:93:ca:55:6a:f3:ec:aa:35:fb
+# SHA256 Fingerprint: bc:23:f9:8a:31:3c:b9:2d:e3:bb:fc:3a:5a:9f:44:61:ac:39:49:4c:4a:e1:5a:9e:9d:f1:31:e9:9b:73:01:9a
+-----BEGIN CERTIFICATE-----
+MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0
+IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAz
+BgNVBAsTLFZhbGlDZXJ0IENsYXNzIDMgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9y
+aXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG
+9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAwMjIzM1oXDTE5MDYy
+NjAwMjIzM1owgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29y
+azEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs
+YXNzIDMgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw
+Oi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl
+cnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDjmFGWHOjVsQaBalfD
+cnWTq8+epvzzFlLWLU2fNUSoLgRNB0mKOCn1dzfnt6td3zZxFJmP3MKS8edgkpfs
+2Ejcv8ECIMYkpChMMFp2bbFc893enhBxoYjHW5tBbcqwuI4V7q0zK89HBFx1cQqY
+JJgpp0lZpd34t0NiYfPT4tBVPwIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAFa7AliE
+Zwgs3x/be0kz9dNnnfS0ChCzycUs4pJqcXgn8nCDQtM+z6lU9PHYkhaM0QTLS6vJ
+n0WuPIqpsHEzXcjFV9+vqDWzf4mH6eglkrh/hXqu1rweN1gqZ8mRzyqBPu3GOd/A
+PhmcGcwTTYJBtYze4D1gCCAPRX5ron+jjBXu
+-----END CERTIFICATE-----
+
+# Issuer: CN=VeriSign Class 3 Public Primary Certification Authority - G3 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 1999 VeriSign, Inc. - For authorized use only
+# Subject: CN=VeriSign Class 3 Public Primary Certification Authority - G3 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 1999 VeriSign, Inc. - For authorized use only
+# Label: "Verisign Class 3 Public Primary Certification Authority - G3"
+# Serial: 206684696279472310254277870180966723415
+# MD5 Fingerprint: cd:68:b6:a7:c7:c4:ce:75:e0:1d:4f:57:44:61:92:09
+# SHA1 Fingerprint: 13:2d:0d:45:53:4b:69:97:cd:b2:d5:c3:39:e2:55:76:60:9b:5c:c6
+# SHA256 Fingerprint: eb:04:cf:5e:b1:f3:9a:fa:76:2f:2b:b1:20:f2:96:cb:a5:20:c1:b9:7d:b1:58:95:65:b8:1c:b9:a1:7b:72:44
+-----BEGIN CERTIFICATE-----
+MIIEGjCCAwICEQCbfgZJoz5iudXukEhxKe9XMA0GCSqGSIb3DQEBBQUAMIHKMQsw
+CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl
+cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu
+LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT
+aWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp
+dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD
+VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT
+aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ
+bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu
+IENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg
+LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMu6nFL8eB8aHm8b
+N3O9+MlrlBIwT/A2R/XQkQr1F8ilYcEWQE37imGQ5XYgwREGfassbqb1EUGO+i2t
+KmFZpGcmTNDovFJbcCAEWNF6yaRpvIMXZK0Fi7zQWM6NjPXr8EJJC52XJ2cybuGu
+kxUccLwgTS8Y3pKI6GyFVxEa6X7jJhFUokWWVYPKMIno3Nij7SqAP395ZVc+FSBm
+CC+Vk7+qRy+oRpfwEuL+wgorUeZ25rdGt+INpsyow0xZVYnm6FNcHOqd8GIWC6fJ
+Xwzw3sJ2zq/3avL6QaaiMxTJ5Xpj055iN9WFZZ4O5lMkdBteHRJTW8cs54NJOxWu
+imi5V5cCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAERSWwauSCPc/L8my/uRan2Te
+2yFPhpk0djZX3dAVL8WtfxUfN2JzPtTnX84XA9s1+ivbrmAJXx5fj267Cz3qWhMe
+DGBvtcC1IyIuBwvLqXTLR7sdwdela8wv0kL9Sd2nic9TutoAWii/gt/4uhMdUIaC
+/Y4wjylGsB49Ndo4YhYYSq3mtlFs3q9i6wHQHiT+eo8SGhJouPtmmRQURVyu565p
+F4ErWjfJXir0xuKhXFSbplQAz/DxwceYMBo7Nhbbo27q/a2ywtrvAkcTisDxszGt
+TxzhT5yvDwyd93gN2PQ1VoDat20Xj50egWTh/sVFuq1ruQp6Tk9LhO5L8X3dEQ==
+-----END CERTIFICATE-----
+
+# Issuer: CN=VeriSign Class 4 Public Primary Certification Authority - G3 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 1999 VeriSign, Inc. - For authorized use only
+# Subject: CN=VeriSign Class 4 Public Primary Certification Authority - G3 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 1999 VeriSign, Inc. - For authorized use only
+# Label: "Verisign Class 4 Public Primary Certification Authority - G3"
+# Serial: 314531972711909413743075096039378935511
+# MD5 Fingerprint: db:c8:f2:27:2e:b1:ea:6a:29:23:5d:fe:56:3e:33:df
+# SHA1 Fingerprint: c8:ec:8c:87:92:69:cb:4b:ab:39:e9:8d:7e:57:67:f3:14:95:73:9d
+# SHA256 Fingerprint: e3:89:36:0d:0f:db:ae:b3:d2:50:58:4b:47:30:31:4e:22:2f:39:c1:56:a0:20:14:4e:8d:96:05:61:79:15:06
+-----BEGIN CERTIFICATE-----
+MIIEGjCCAwICEQDsoKeLbnVqAc/EfMwvlF7XMA0GCSqGSIb3DQEBBQUAMIHKMQsw
+CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl
+cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu
+LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT
+aWduIENsYXNzIDQgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp
+dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD
+VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT
+aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ
+bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu
+IENsYXNzIDQgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg
+LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK3LpRFpxlmr8Y+1
+GQ9Wzsy1HyDkniYlS+BzZYlZ3tCD5PUPtbut8XzoIfzk6AzufEUiGXaStBO3IFsJ
++mGuqPKljYXCKtbeZjbSmwL0qJJgfJxptI8kHtCGUvYynEFYHiK9zUVilQhu0Gbd
+U6LM8BDcVHOLBKFGMzNcF0C5nk3T875Vg+ixiY5afJqWIpA7iCXy0lOIAgwLePLm
+NxdLMEYH5IBtptiWLugs+BGzOA1mppvqySNb247i8xOOGlktqgLw7KSHZtzBP/XY
+ufTsgsbSPZUd5cBPhMnZo0QoBmrXRazwa2rvTl/4EYIeOGM0ZlDUPpNz+jDDZq3/
+ky2X7wMCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAj/ola09b5KROJ1WrIhVZPMq1
+CtRK26vdoV9TxaBXOcLORyu+OshWv8LZJxA6sQU8wHcxuzrTBXttmhwwjIDLk5Mq
+g6sFUYICABFna/OIYUdfA5PVWw3g8dShMjWFsjrbsIKr0csKvE+MW8VLADsfKoKm
+fjaF3H48ZwC15DtS4KjrXRX5xm3wrR0OhbepmnMUWluPQSjA1egtTaRezarZ7c7c
+2NU8Qh0XwRJdRTjDOPP8hS6DRkiy1yBfkjaP53kPmF6Z6PDQpLv1U70qzlmwr25/
+bLvSHgCwIe34QWKCudiyxLtGUPMxxY8BqHTr9Xgn2uf3ZkPznoM+IKrDNWCRzg==
+-----END CERTIFICATE-----
+
+# Issuer: CN=Entrust.net Secure Server Certification Authority O=Entrust.net OU=www.entrust.net/CPS incorp. by ref. (limits liab.)/(c) 1999 Entrust.net Limited
+# Subject: CN=Entrust.net Secure Server Certification Authority O=Entrust.net OU=www.entrust.net/CPS incorp. by ref. (limits liab.)/(c) 1999 Entrust.net Limited
+# Label: "Entrust.net Secure Server CA"
+# Serial: 927650371
+# MD5 Fingerprint: df:f2:80:73:cc:f1:e6:61:73:fc:f5:42:e9:c5:7c:ee
+# SHA1 Fingerprint: 99:a6:9b:e6:1a:fe:88:6b:4d:2b:82:00:7c:b8:54:fc:31:7e:15:39
+# SHA256 Fingerprint: 62:f2:40:27:8c:56:4c:4d:d8:bf:7d:9d:4f:6f:36:6e:a8:94:d2:2f:5f:34:d9:89:a9:83:ac:ec:2f:ff:ed:50
+-----BEGIN CERTIFICATE-----
+MIIE2DCCBEGgAwIBAgIEN0rSQzANBgkqhkiG9w0BAQUFADCBwzELMAkGA1UEBhMC
+VVMxFDASBgNVBAoTC0VudHJ1c3QubmV0MTswOQYDVQQLEzJ3d3cuZW50cnVzdC5u
+ZXQvQ1BTIGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMc
+KGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDE6MDgGA1UEAxMxRW50cnVzdC5u
+ZXQgU2VjdXJlIFNlcnZlciBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw05OTA1
+MjUxNjA5NDBaFw0xOTA1MjUxNjM5NDBaMIHDMQswCQYDVQQGEwJVUzEUMBIGA1UE
+ChMLRW50cnVzdC5uZXQxOzA5BgNVBAsTMnd3dy5lbnRydXN0Lm5ldC9DUFMgaW5j
+b3JwLiBieSByZWYuIChsaW1pdHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBF
+bnRydXN0Lm5ldCBMaW1pdGVkMTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUg
+U2VydmVyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGdMA0GCSqGSIb3DQEBAQUA
+A4GLADCBhwKBgQDNKIM0VBuJ8w+vN5Ex/68xYMmo6LIQaO2f55M28Qpku0f1BBc/
+I0dNxScZgSYMVHINiC3ZH5oSn7yzcdOAGT9HZnuMNSjSuQrfJNqc1lB5gXpa0zf3
+wkrYKZImZNHkmGw6AIr1NJtl+O3jEP/9uElY3KDegjlrgbEWGWG5VLbmQwIBA6OC
+AdcwggHTMBEGCWCGSAGG+EIBAQQEAwIABzCCARkGA1UdHwSCARAwggEMMIHeoIHb
+oIHYpIHVMIHSMQswCQYDVQQGEwJVUzEUMBIGA1UEChMLRW50cnVzdC5uZXQxOzA5
+BgNVBAsTMnd3dy5lbnRydXN0Lm5ldC9DUFMgaW5jb3JwLiBieSByZWYuIChsaW1p
+dHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBFbnRydXN0Lm5ldCBMaW1pdGVk
+MTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUgU2VydmVyIENlcnRpZmljYXRp
+b24gQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMCmgJ6AlhiNodHRwOi8vd3d3LmVu
+dHJ1c3QubmV0L0NSTC9uZXQxLmNybDArBgNVHRAEJDAigA8xOTk5MDUyNTE2MDk0
+MFqBDzIwMTkwNTI1MTYwOTQwWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAU8Bdi
+E1U9s/8KAGv7UISX8+1i0BowHQYDVR0OBBYEFPAXYhNVPbP/CgBr+1CEl/PtYtAa
+MAwGA1UdEwQFMAMBAf8wGQYJKoZIhvZ9B0EABAwwChsEVjQuMAMCBJAwDQYJKoZI
+hvcNAQEFBQADgYEAkNwwAvpkdMKnCqV8IY00F6j7Rw7/JXyNEwr75Ji174z4xRAN
+95K+8cPV1ZVqBLssziY2ZcgxxufuP+NXdYR6Ee9GTxj005i7qIcyunL2POI9n9cd
+2cNgQ4xYDiKWL2KjLB+6rQXvqzJ4h6BUcxm1XAX5Uj5tLUUL9wqT6u0G+bI=
+-----END CERTIFICATE-----
+
+# Issuer: CN=Entrust.net Certification Authority (2048) O=Entrust.net OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.)/(c) 1999 Entrust.net Limited
+# Subject: CN=Entrust.net Certification Authority (2048) O=Entrust.net OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.)/(c) 1999 Entrust.net Limited
+# Label: "Entrust.net Premium 2048 Secure Server CA"
+# Serial: 946059622
+# MD5 Fingerprint: ba:21:ea:20:d6:dd:db:8f:c1:57:8b:40:ad:a1:fc:fc
+# SHA1 Fingerprint: 80:1d:62:d0:7b:44:9d:5c:5c:03:5c:98:ea:61:fa:44:3c:2a:58:fe
+# SHA256 Fingerprint: d1:c3:39:ea:27:84:eb:87:0f:93:4f:c5:63:4e:4a:a9:ad:55:05:01:64:01:f2:64:65:d3:7a:57:46:63:35:9f
+-----BEGIN CERTIFICATE-----
+MIIEXDCCA0SgAwIBAgIEOGO5ZjANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChML
+RW50cnVzdC5uZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBp
+bmNvcnAuIGJ5IHJlZi4gKGxpbWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5
+IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNVBAMTKkVudHJ1c3QubmV0IENlcnRp
+ZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQxNzUwNTFaFw0xOTEy
+MjQxODIwNTFaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3d3d3
+LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxp
+YWIuKTElMCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEG
+A1UEAxMqRW50cnVzdC5uZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgp
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArU1LqRKGsuqjIAcVFmQq
+K0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOLGp18EzoOH1u3Hs/lJBQe
+sYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSrhRSGlVuX
+MlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVT
+XTzWnLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/
+HoZdenoVve8AjhUiVBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH
+4QIDAQABo3QwcjARBglghkgBhvhCAQEEBAMCAAcwHwYDVR0jBBgwFoAUVeSB0RGA
+vtiJuQijMfmhJAkWuXAwHQYDVR0OBBYEFFXkgdERgL7YibkIozH5oSQJFrlwMB0G
+CSqGSIb2fQdBAAQQMA4bCFY1LjA6NC4wAwIEkDANBgkqhkiG9w0BAQUFAAOCAQEA
+WUesIYSKF8mciVMeuoCFGsY8Tj6xnLZ8xpJdGGQC49MGCBFhfGPjK50xA3B20qMo
+oPS7mmNz7W3lKtvtFKkrxjYR0CvrB4ul2p5cGZ1WEvVUKcgF7bISKo30Axv/55IQ
+h7A6tcOdBTcSo8f0FbnVpDkWm1M6I5HxqIKiaohowXkCIryqptau37AUX7iH0N18
+f3v/rxzP5tsHrV7bhZ3QKw0z2wTR5klAEyt2+z7pnIkPFc4YsIV4IU9rTw76NmfN
+B/L/CNDi3tm/Kq+4h4YhPATKt5Rof8886ZjXOP/swNlQ8C5LWK5Gb9Auw2DaclVy
+vUxFnmG6v4SBkgPR0ml8xQ==
+-----END CERTIFICATE-----
+
+# Issuer: CN=Baltimore CyberTrust Root O=Baltimore OU=CyberTrust
+# Subject: CN=Baltimore CyberTrust Root O=Baltimore OU=CyberTrust
+# Label: "Baltimore CyberTrust Root"
+# Serial: 33554617
+# MD5 Fingerprint: ac:b6:94:a5:9c:17:e0:d7:91:52:9b:b1:97:06:a6:e4
+# SHA1 Fingerprint: d4:de:20:d0:5e:66:fc:53:fe:1a:50:88:2c:78:db:28:52:ca:e4:74
+# SHA256 Fingerprint: 16:af:57:a9:f6:76:b0:ab:12:60:95:aa:5e:ba:de:f2:2a:b3:11:19:d6:44:ac:95:cd:4b:93:db:f3:f2:6a:eb
+-----BEGIN CERTIFICATE-----
+MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ
+RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD
+VQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoX
+DTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9y
+ZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFsdGltb3JlIEN5YmVy
+VHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKMEuyKr
+mD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjr
+IZ3AQSsBUnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeK
+mpYcqWe4PwzV9/lSEy/CG9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSu
+XmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9XbIGevOF6uvUA65ehD5f/xXtabz5OTZy
+dc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v/ye
+jl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1
+BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3
+DQEBBQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT92
+9hkTI7gQCvlYpNRhcL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3Wgx
+jkzSswF07r51XgdIGn9w/xZchMB5hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0
+Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h+3zvDyny67G7fyUIhz
+ksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLS
+R9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp
+-----END CERTIFICATE-----
+
+# Issuer: CN=Equifax Secure Global eBusiness CA-1 O=Equifax Secure Inc.
+# Subject: CN=Equifax Secure Global eBusiness CA-1 O=Equifax Secure Inc.
+# Label: "Equifax Secure Global eBusiness CA"
+# Serial: 1
+# MD5 Fingerprint: 8f:5d:77:06:27:c4:98:3c:5b:93:78:e7:d7:7d:9b:cc
+# SHA1 Fingerprint: 7e:78:4a:10:1c:82:65:cc:2d:e1:f1:6d:47:b4:40:ca:d9:0a:19:45
+# SHA256 Fingerprint: 5f:0b:62:ea:b5:e3:53:ea:65:21:65:16:58:fb:b6:53:59:f4:43:28:0a:4a:fb:d1:04:d7:7d:10:f9:f0:4c:07
+-----BEGIN CERTIFICATE-----
+MIICkDCCAfmgAwIBAgIBATANBgkqhkiG9w0BAQQFADBaMQswCQYDVQQGEwJVUzEc
+MBoGA1UEChMTRXF1aWZheCBTZWN1cmUgSW5jLjEtMCsGA1UEAxMkRXF1aWZheCBT
+ZWN1cmUgR2xvYmFsIGVCdXNpbmVzcyBDQS0xMB4XDTk5MDYyMTA0MDAwMFoXDTIw
+MDYyMTA0MDAwMFowWjELMAkGA1UEBhMCVVMxHDAaBgNVBAoTE0VxdWlmYXggU2Vj
+dXJlIEluYy4xLTArBgNVBAMTJEVxdWlmYXggU2VjdXJlIEdsb2JhbCBlQnVzaW5l
+c3MgQ0EtMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAuucXkAJlsTRVPEnC
+UdXfp9E3j9HngXNBUmCbnaEXJnitx7HoJpQytd4zjTov2/KaelpzmKNc6fuKcxtc
+58O/gGzNqfTWK8D3+ZmqY6KxRwIP1ORROhI8bIpaVIRw28HFkM9yRcuoWcDNM50/
+o5brhTMhHD4ePmBudpxnhcXIw2ECAwEAAaNmMGQwEQYJYIZIAYb4QgEBBAQDAgAH
+MA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUvqigdHJQa0S3ySPY+6j/s1dr
+aGwwHQYDVR0OBBYEFL6ooHRyUGtEt8kj2Puo/7NXa2hsMA0GCSqGSIb3DQEBBAUA
+A4GBADDiAVGqx+pf2rnQZQ8w1j7aDRRJbpGTJxQx78T3LUX47Me/okENI7SS+RkA
+Z70Br83gcfxaz2TE4JaY0KNA4gGK7ycH8WUBikQtBmV1UsCGECAhX2xrD2yuCRyv
+8qIYNMR1pHMc8Y3c7635s3a0kr/clRAevsvIO1qEYBlWlKlV
+-----END CERTIFICATE-----
+
+# Issuer: CN=Equifax Secure eBusiness CA-1 O=Equifax Secure Inc.
+# Subject: CN=Equifax Secure eBusiness CA-1 O=Equifax Secure Inc.
+# Label: "Equifax Secure eBusiness CA 1"
+# Serial: 4
+# MD5 Fingerprint: 64:9c:ef:2e:44:fc:c6:8f:52:07:d0:51:73:8f:cb:3d
+# SHA1 Fingerprint: da:40:18:8b:91:89:a3:ed:ee:ae:da:97:fe:2f:9d:f5:b7:d1:8a:41
+# SHA256 Fingerprint: cf:56:ff:46:a4:a1:86:10:9d:d9:65:84:b5:ee:b5:8a:51:0c:42:75:b0:e5:f9:4f:40:bb:ae:86:5e:19:f6:73
+-----BEGIN CERTIFICATE-----
+MIICgjCCAeugAwIBAgIBBDANBgkqhkiG9w0BAQQFADBTMQswCQYDVQQGEwJVUzEc
+MBoGA1UEChMTRXF1aWZheCBTZWN1cmUgSW5jLjEmMCQGA1UEAxMdRXF1aWZheCBT
+ZWN1cmUgZUJ1c2luZXNzIENBLTEwHhcNOTkwNjIxMDQwMDAwWhcNMjAwNjIxMDQw
+MDAwWjBTMQswCQYDVQQGEwJVUzEcMBoGA1UEChMTRXF1aWZheCBTZWN1cmUgSW5j
+LjEmMCQGA1UEAxMdRXF1aWZheCBTZWN1cmUgZUJ1c2luZXNzIENBLTEwgZ8wDQYJ
+KoZIhvcNAQEBBQADgY0AMIGJAoGBAM4vGbwXt3fek6lfWg0XTzQaDJj0ItlZ1MRo
+RvC0NcWFAyDGr0WlIVFFQesWWDYyb+JQYmT5/VGcqiTZ9J2DKocKIdMSODRsjQBu
+WqDZQu4aIZX5UkxVWsUPOE9G+m34LjXWHXzr4vCwdYDIqROsvojvOm6rXyo4YgKw
+Env+j6YDAgMBAAGjZjBkMBEGCWCGSAGG+EIBAQQEAwIABzAPBgNVHRMBAf8EBTAD
+AQH/MB8GA1UdIwQYMBaAFEp4MlIR21kWNl7fwRQ2QGpHfEyhMB0GA1UdDgQWBBRK
+eDJSEdtZFjZe38EUNkBqR3xMoTANBgkqhkiG9w0BAQQFAAOBgQB1W6ibAxHm6VZM
+zfmpTMANmvPMZWnmJXbMWbfWVMMdzZmsGd20hdXgPfxiIKeES1hl8eL5lSE/9dR+
+WB5Hh1Q+WKG1tfgq73HnvMP2sUlG4tega+VWeponmHxGYhTnyfxuAxJ5gDgdSIKN
+/Bf+KpYrtWKmpj29f5JZzVoqgrI3eQ==
+-----END CERTIFICATE-----
+
+# Issuer: O=Equifax Secure OU=Equifax Secure eBusiness CA-2
+# Subject: O=Equifax Secure OU=Equifax Secure eBusiness CA-2
+# Label: "Equifax Secure eBusiness CA 2"
+# Serial: 930140085
+# MD5 Fingerprint: aa:bf:bf:64:97:da:98:1d:6f:c6:08:3a:95:70:33:ca
+# SHA1 Fingerprint: 39:4f:f6:85:0b:06:be:52:e5:18:56:cc:10:e1:80:e8:82:b3:85:cc
+# SHA256 Fingerprint: 2f:27:4e:48:ab:a4:ac:7b:76:59:33:10:17:75:50:6d:c3:0e:e3:8e:f6:ac:d5:c0:49:32:cf:e0:41:23:42:20
+-----BEGIN CERTIFICATE-----
+MIIDIDCCAomgAwIBAgIEN3DPtTANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJV
+UzEXMBUGA1UEChMORXF1aWZheCBTZWN1cmUxJjAkBgNVBAsTHUVxdWlmYXggU2Vj
+dXJlIGVCdXNpbmVzcyBDQS0yMB4XDTk5MDYyMzEyMTQ0NVoXDTE5MDYyMzEyMTQ0
+NVowTjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkVxdWlmYXggU2VjdXJlMSYwJAYD
+VQQLEx1FcXVpZmF4IFNlY3VyZSBlQnVzaW5lc3MgQ0EtMjCBnzANBgkqhkiG9w0B
+AQEFAAOBjQAwgYkCgYEA5Dk5kx5SBhsoNviyoynF7Y6yEb3+6+e0dMKP/wXn2Z0G
+vxLIPw7y1tEkshHe0XMJitSxLJgJDR5QRrKDpkWNYmi7hRsgcDKqQM2mll/EcTc/
+BPO3QSQ5BxoeLmFYoBIL5aXfxavqN3HMHMg3OrmXUqesxWoklE6ce8/AatbfIb0C
+AwEAAaOCAQkwggEFMHAGA1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEX
+MBUGA1UEChMORXF1aWZheCBTZWN1cmUxJjAkBgNVBAsTHUVxdWlmYXggU2VjdXJl
+IGVCdXNpbmVzcyBDQS0yMQ0wCwYDVQQDEwRDUkwxMBoGA1UdEAQTMBGBDzIwMTkw
+NjIzMTIxNDQ1WjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUUJ4L6q9euSBIplBq
+y/3YIHqngnYwHQYDVR0OBBYEFFCeC+qvXrkgSKZQasv92CB6p4J2MAwGA1UdEwQF
+MAMBAf8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUA
+A4GBAAyGgq3oThr1jokn4jVYPSm0B482UJW/bsGe68SQsoWou7dC4A8HOd/7npCy
+0cE+U58DRLB+S/Rv5Hwf5+Kx5Lia78O9zt4LMjTZ3ijtM2vE1Nc9ElirfQkty3D1
+E4qUoSek1nDFbZS1yX2doNLGCEnZZpum0/QL3MUmV+GRMOrN
+-----END CERTIFICATE-----
+
+# Issuer: CN=AddTrust Class 1 CA Root O=AddTrust AB OU=AddTrust TTP Network
+# Subject: CN=AddTrust Class 1 CA Root O=AddTrust AB OU=AddTrust TTP Network
+# Label: "AddTrust Low-Value Services Root"
+# Serial: 1
+# MD5 Fingerprint: 1e:42:95:02:33:92:6b:b9:5f:c0:7f:da:d6:b2:4b:fc
+# SHA1 Fingerprint: cc:ab:0e:a0:4c:23:01:d6:69:7b:dd:37:9f:cd:12:eb:24:e3:94:9d
+# SHA256 Fingerprint: 8c:72:09:27:9a:c0:4e:27:5e:16:d0:7f:d3:b7:75:e8:01:54:b5:96:80:46:e3:1f:52:dd:25:76:63:24:e9:a7
+-----BEGIN CERTIFICATE-----
+MIIEGDCCAwCgAwIBAgIBATANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQGEwJTRTEU
+MBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3
+b3JrMSEwHwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3QwHhcNMDAwNTMw
+MTAzODMxWhcNMjAwNTMwMTAzODMxWjBlMQswCQYDVQQGEwJTRTEUMBIGA1UEChML
+QWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSEwHwYD
+VQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3QwggEiMA0GCSqGSIb3DQEBAQUA
+A4IBDwAwggEKAoIBAQCWltQhSWDia+hBBwzexODcEyPNwTXH+9ZOEQpnXvUGW2ul
+CDtbKRY654eyNAbFvAWlA3yCyykQruGIgb3WntP+LVbBFc7jJp0VLhD7Bo8wBN6n
+tGO0/7Gcrjyvd7ZWxbWroulpOj0OM3kyP3CCkplhbY0wCI9xP6ZIVxn4JdxLZlyl
+dI+Yrsj5wAYi56xz36Uu+1LcsRVlIPo1Zmne3yzxbrww2ywkEtvrNTVokMsAsJch
+PXQhI2U0K7t4WaPW4XY5mqRJjox0r26kmqPZm9I4XJuiGMx1I4S+6+JNM3GOGvDC
++Mcdoq0Dlyz4zyXG9rgkMbFjXZJ/Y/AlyVMuH79NAgMBAAGjgdIwgc8wHQYDVR0O
+BBYEFJWxtPCUtr3H2tERCSG+wa9J/RB7MAsGA1UdDwQEAwIBBjAPBgNVHRMBAf8E
+BTADAQH/MIGPBgNVHSMEgYcwgYSAFJWxtPCUtr3H2tERCSG+wa9J/RB7oWmkZzBl
+MQswCQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFk
+ZFRydXN0IFRUUCBOZXR3b3JrMSEwHwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENB
+IFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBACxtZBsfzQ3duQH6lmM0MkhHma6X
+7f1yFqZzR1r0693p9db7RcwpiURdv0Y5PejuvE1Uhh4dbOMXJ0PhiVYrqW9yTkkz
+43J8KiOavD7/KCrto/8cI7pDVwlnTUtiBi34/2ydYB7YHEt9tTEv2dB8Xfjea4MY
+eDdXL+gzB2ffHsdrKpV2ro9Xo/D0UrSpUwjP4E/TelOL/bscVjby/rK25Xa71SJl
+pz/+0WatC7xrmYbvP33zGDLKe8bjq2RGlfgmadlVg3sslgf/WSxEo8bl6ancoWOA
+WiFeIc9TVPC6b4nbqKqVz4vjccweGyBECMB6tkD9xOQ14R0WHNC8K47Wcdk=
+-----END CERTIFICATE-----
+
+# Issuer: CN=AddTrust External CA Root O=AddTrust AB OU=AddTrust External TTP Network
+# Subject: CN=AddTrust External CA Root O=AddTrust AB OU=AddTrust External TTP Network
+# Label: "AddTrust External Root"
+# Serial: 1
+# MD5 Fingerprint: 1d:35:54:04:85:78:b0:3f:42:42:4d:bf:20:73:0a:3f
+# SHA1 Fingerprint: 02:fa:f3:e2:91:43:54:68:60:78:57:69:4d:f5:e4:5b:68:85:18:68
+# SHA256 Fingerprint: 68:7f:a4:51:38:22:78:ff:f0:c8:b1:1f:8d:43:d5:76:67:1c:6e:b2:bc:ea:b4:13:fb:83:d9:65:d0:6d:2f:f2
+-----BEGIN CERTIFICATE-----
+MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEU
+MBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFs
+IFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290
+MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEwNDgzOFowbzELMAkGA1UEBhMCU0Ux
+FDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRUcnVzdCBFeHRlcm5h
+bCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0EgUm9v
+dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvt
+H7xsD821+iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9
+uMq/NzgtHj6RQa1wVsfwTz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzX
+mk6vBbOmcZSccbNQYArHE504B4YCqOmoaSYYkKtMsE8jqzpPhNjfzp/haW+710LX
+a0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy2xSoRcRdKn23tNbE7qzN
+E0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv77+ldU9U0
+WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYD
+VR0PBAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0
+Jvf6xCZU7wO94CTLVBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRU
+cnVzdCBBQjEmMCQGA1UECxMdQWRkVHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsx
+IjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENBIFJvb3SCAQEwDQYJKoZIhvcN
+AQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZlj7DYd7usQWxH
+YINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5
+6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvC
+Nr4TDea9Y355e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEX
+c4g/VhsxOBi0cQ+azcgOno4uG+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5a
+mnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ=
+-----END CERTIFICATE-----
+
+# Issuer: CN=AddTrust Public CA Root O=AddTrust AB OU=AddTrust TTP Network
+# Subject: CN=AddTrust Public CA Root O=AddTrust AB OU=AddTrust TTP Network
+# Label: "AddTrust Public Services Root"
+# Serial: 1
+# MD5 Fingerprint: c1:62:3e:23:c5:82:73:9c:03:59:4b:2b:e9:77:49:7f
+# SHA1 Fingerprint: 2a:b6:28:48:5e:78:fb:f3:ad:9e:79:10:dd:6b:df:99:72:2c:96:e5
+# SHA256 Fingerprint: 07:91:ca:07:49:b2:07:82:aa:d3:c7:d7:bd:0c:df:c9:48:58:35:84:3e:b2:d7:99:60:09:ce:43:ab:6c:69:27
+-----BEGIN CERTIFICATE-----
+MIIEFTCCAv2gAwIBAgIBATANBgkqhkiG9w0BAQUFADBkMQswCQYDVQQGEwJTRTEU
+MBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3
+b3JrMSAwHgYDVQQDExdBZGRUcnVzdCBQdWJsaWMgQ0EgUm9vdDAeFw0wMDA1MzAx
+MDQxNTBaFw0yMDA1MzAxMDQxNTBaMGQxCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtB
+ZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3QgVFRQIE5ldHdvcmsxIDAeBgNV
+BAMTF0FkZFRydXN0IFB1YmxpYyBDQSBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOC
+AQ8AMIIBCgKCAQEA6Rowj4OIFMEg2Dybjxt+A3S72mnTRqX4jsIMEZBRpS9mVEBV
+6tsfSlbunyNu9DnLoblv8n75XYcmYZ4c+OLspoH4IcUkzBEMP9smcnrHAZcHF/nX
+GCwwfQ56HmIexkvA/X1id9NEHif2P0tEs7c42TkfYNVRknMDtABp4/MUTu7R3AnP
+dzRGULD4EfL+OHn3Bzn+UZKXC1sIXzSGAa2Il+tmzV7R/9x98oTaunet3IAIx6eH
+1lWfl2royBFkuucZKT8Rs3iQhCBSWxHveNCD9tVIkNAwHM+A+WD+eeSI8t0A65RF
+62WUaUC6wNW0uLp9BBGo6zEFlpROWCGOn9Bg/QIDAQABo4HRMIHOMB0GA1UdDgQW
+BBSBPjfYkrAfd59ctKtzquf2NGAv+jALBgNVHQ8EBAMCAQYwDwYDVR0TAQH/BAUw
+AwEB/zCBjgYDVR0jBIGGMIGDgBSBPjfYkrAfd59ctKtzquf2NGAv+qFopGYwZDEL
+MAkGA1UEBhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQLExRBZGRU
+cnVzdCBUVFAgTmV0d29yazEgMB4GA1UEAxMXQWRkVHJ1c3QgUHVibGljIENBIFJv
+b3SCAQEwDQYJKoZIhvcNAQEFBQADggEBAAP3FUr4JNojVhaTdt02KLmuG7jD8WS6
+IBh4lSknVwW8fCr0uVFV2ocC3g8WFzH4qnkuCRO7r7IgGRLlk/lL+YPoRNWyQSW/
+iHVv/xD8SlTQX/D67zZzfRs2RcYhbbQVuE7PnFylPVoAjgbjPGsye/Kf8Lb93/Ao
+GEjwxrzQvzSAlsJKsW2Ox5BF3i9nrEUEo3rcVZLJR2bYGozH7ZxOmuASu7VqTITh
+4SINhwBk/ox9Yjllpu9CtoAlEmEBqCQTcAARJl/6NVDFSMwGR+gn2HCNX2TmoUQm
+XiLsks3/QppEIW1cxeMiHV9HEufOX1362KqxMy3ZdvJOOjMMK7MtkAY=
+-----END CERTIFICATE-----
+
+# Issuer: CN=AddTrust Qualified CA Root O=AddTrust AB OU=AddTrust TTP Network
+# Subject: CN=AddTrust Qualified CA Root O=AddTrust AB OU=AddTrust TTP Network
+# Label: "AddTrust Qualified Certificates Root"
+# Serial: 1
+# MD5 Fingerprint: 27:ec:39:47:cd:da:5a:af:e2:9a:01:65:21:a9:4c:bb
+# SHA1 Fingerprint: 4d:23:78:ec:91:95:39:b5:00:7f:75:8f:03:3b:21:1e:c5:4d:8b:cf
+# SHA256 Fingerprint: 80:95:21:08:05:db:4b:bc:35:5e:44:28:d8:fd:6e:c2:cd:e3:ab:5f:b9:7a:99:42:98:8e:b8:f4:dc:d0:60:16
+-----BEGIN CERTIFICATE-----
+MIIEHjCCAwagAwIBAgIBATANBgkqhkiG9w0BAQUFADBnMQswCQYDVQQGEwJTRTEU
+MBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3
+b3JrMSMwIQYDVQQDExpBZGRUcnVzdCBRdWFsaWZpZWQgQ0EgUm9vdDAeFw0wMDA1
+MzAxMDQ0NTBaFw0yMDA1MzAxMDQ0NTBaMGcxCzAJBgNVBAYTAlNFMRQwEgYDVQQK
+EwtBZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3QgVFRQIE5ldHdvcmsxIzAh
+BgNVBAMTGkFkZFRydXN0IFF1YWxpZmllZCBDQSBSb290MIIBIjANBgkqhkiG9w0B
+AQEFAAOCAQ8AMIIBCgKCAQEA5B6a/twJWoekn0e+EV+vhDTbYjx5eLfpMLXsDBwq
+xBb/4Oxx64r1EW7tTw2R0hIYLUkVAcKkIhPHEWT/IhKauY5cLwjPcWqzZwFZ8V1G
+87B4pfYOQnrjfxvM0PC3KP0q6p6zsLkEqv32x7SxuCqg+1jxGaBvcCV+PmlKfw8i
+2O+tCBGaKZnhqkRFmhJePp1tUvznoD1oL/BLcHwTOK28FSXx1s6rosAx1i+f4P8U
+WfyEk9mHfExUE+uf0S0R+Bg6Ot4l2ffTQO2kBhLEO+GRwVY18BTcZTYJbqukB8c1
+0cIDMzZbdSZtQvESa0NvS3GU+jQd7RNuyoB/mC9suWXY6QIDAQABo4HUMIHRMB0G
+A1UdDgQWBBQ5lYtii1zJ1IC6WA+XPxUIQ8yYpzALBgNVHQ8EBAMCAQYwDwYDVR0T
+AQH/BAUwAwEB/zCBkQYDVR0jBIGJMIGGgBQ5lYtii1zJ1IC6WA+XPxUIQ8yYp6Fr
+pGkwZzELMAkGA1UEBhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQL
+ExRBZGRUcnVzdCBUVFAgTmV0d29yazEjMCEGA1UEAxMaQWRkVHJ1c3QgUXVhbGlm
+aWVkIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBABmrder4i2VhlRO6aQTv
+hsoToMeqT2QbPxj2qC0sVY8FtzDqQmodwCVRLae/DLPt7wh/bDxGGuoYQ992zPlm
+hpwsaPXpF/gxsxjE1kh9I0xowX67ARRvxdlu3rsEQmr49lx95dr6h+sNNVJn0J6X
+dgWTP5XHAeZpVTh/EGGZyeNfpso+gmNIquIISD6q8rKFYqa0p9m9N5xotS1WfbC3
+P6CxB9bpT9zeRXEwMn8bLgn5v1Kh7sKAPgZcLlVAwRv1cEWw3F369nJad9Jjzc9Y
+iQBCYz95OdBEsIJuQRno3eDBiFrRHnGTHyQwdOUeqN48Jzd/g66ed8/wMLH/S5no
+xqE=
+-----END CERTIFICATE-----
+
+# Issuer: CN=Entrust Root Certification Authority O=Entrust, Inc. OU=www.entrust.net/CPS is incorporated by reference/(c) 2006 Entrust, Inc.
+# Subject: CN=Entrust Root Certification Authority O=Entrust, Inc. OU=www.entrust.net/CPS is incorporated by reference/(c) 2006 Entrust, Inc.
+# Label: "Entrust Root Certification Authority"
+# Serial: 1164660820
+# MD5 Fingerprint: d6:a5:c3:ed:5d:dd:3e:00:c1:3d:87:92:1f:1d:3f:e4
+# SHA1 Fingerprint: b3:1e:b1:b7:40:e3:6c:84:02:da:dc:37:d4:4d:f5:d4:67:49:52:f9
+# SHA256 Fingerprint: 73:c1:76:43:4f:1b:c6:d5:ad:f4:5b:0e:76:e7:27:28:7c:8d:e5:76:16:c1:e6:e6:14:1a:2b:2c:bc:7d:8e:4c
+-----BEGIN CERTIFICATE-----
+MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMC
+VVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0
+Lm5ldC9DUFMgaXMgaW5jb3Jwb3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMW
+KGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsGA1UEAxMkRW50cnVzdCBSb290IENl
+cnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0MloXDTI2MTEyNzIw
+NTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMTkw
+NwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSBy
+ZWZlcmVuY2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNV
+BAMTJEVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJ
+KoZIhvcNAQEBBQADggEPADCCAQoCggEBALaVtkNC+sZtKm9I35RMOVcF7sN5EUFo
+Nu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYszA9u3g3s+IIRe7bJWKKf4
+4LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOwwCj0Yzfv9
+KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGI
+rb68j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi
+94DkZfs0Nw4pgHBNrziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOB
+sDCBrTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAi
+gA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1MzQyWjAfBgNVHSMEGDAWgBRo
+kORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DHhmak8fdLQ/uE
+vW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA
+A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9t
+O1KzKtvn1ISMY/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6Zua
+AGAT/3B+XxFNSRuzFVJ7yVTav52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP
+9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTSW3iDVuycNsMm4hH2Z0kdkquM++v/
+eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0tHuu2guQOHXvgR1m
+0vdXcDazv/wor3ElhVsT/h5/WrQ8
+-----END CERTIFICATE-----
+
+# Issuer: CN=GeoTrust Global CA O=GeoTrust Inc.
+# Subject: CN=GeoTrust Global CA O=GeoTrust Inc.
+# Label: "GeoTrust Global CA"
+# Serial: 144470
+# MD5 Fingerprint: f7:75:ab:29:fb:51:4e:b7:77:5e:ff:05:3c:99:8e:f5
+# SHA1 Fingerprint: de:28:f4:a4:ff:e5:b9:2f:a3:c5:03:d1:a3:49:a7:f9:96:2a:82:12
+# SHA256 Fingerprint: ff:85:6a:2d:25:1d:cd:88:d3:66:56:f4:50:12:67:98:cf:ab:aa:de:40:79:9c:72:2d:e4:d2:b5:db:36:a7:3a
+-----BEGIN CERTIFICATE-----
+MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT
+MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i
+YWwgQ0EwHhcNMDIwNTIxMDQwMDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQG
+EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UEAxMSR2VvVHJ1c3Qg
+R2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2swYYzD9
+9BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjoBbdq
+fnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDv
+iS2Aelet8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU
+1XupGc1V3sjs0l44U+VcT4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+
+bw8HHa8sHo9gOeL6NlMTOdReJivbPagUvTLrGAMoUgRx5aszPeE4uwc2hGKceeoW
+MPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTA
+ephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVkDBF9qn1l
+uMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKIn
+Z57QzxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfS
+tQWVYrmm3ok9Nns4d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcF
+PseKUgzbFbS9bZvlxrFUaKnjaZC2mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Un
+hw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6pXE0zX5IJL4hmXXeXxx12E6nV
+5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvmMw==
+-----END CERTIFICATE-----
+
+# Issuer: CN=GeoTrust Global CA 2 O=GeoTrust Inc.
+# Subject: CN=GeoTrust Global CA 2 O=GeoTrust Inc.
+# Label: "GeoTrust Global CA 2"
+# Serial: 1
+# MD5 Fingerprint: 0e:40:a7:6c:de:03:5d:8f:d1:0f:e4:d1:8d:f9:6c:a9
+# SHA1 Fingerprint: a9:e9:78:08:14:37:58:88:f2:05:19:b0:6d:2b:0d:2b:60:16:90:7d
+# SHA256 Fingerprint: ca:2d:82:a0:86:77:07:2f:8a:b6:76:4f:f0:35:67:6c:fe:3e:5e:32:5e:01:21:72:df:3f:92:09:6d:b7:9b:85
+-----BEGIN CERTIFICATE-----
+MIIDZjCCAk6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBEMQswCQYDVQQGEwJVUzEW
+MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEdMBsGA1UEAxMUR2VvVHJ1c3QgR2xvYmFs
+IENBIDIwHhcNMDQwMzA0MDUwMDAwWhcNMTkwMzA0MDUwMDAwWjBEMQswCQYDVQQG
+EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEdMBsGA1UEAxMUR2VvVHJ1c3Qg
+R2xvYmFsIENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDvPE1A
+PRDfO1MA4Wf+lGAVPoWI8YkNkMgoI5kF6CsgncbzYEbYwbLVjDHZ3CB5JIG/NTL8
+Y2nbsSpr7iFY8gjpeMtvy/wWUsiRxP89c96xPqfCfWbB9X5SJBri1WeR0IIQ13hL
+TytCOb1kLUCgsBDTOEhGiKEMuzozKmKY+wCdE1l/bztyqu6mD4b5BWHqZ38MN5aL
+5mkWRxHCJ1kDs6ZgwiFAVvqgx306E+PsV8ez1q6diYD3Aecs9pYrEw15LNnA5IZ7
+S4wMcoKK+xfNAGw6EzywhIdLFnopsk/bHdQL82Y3vdj2V7teJHq4PIu5+pIaGoSe
+2HSPqht/XvT+RSIhAgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE
+FHE4NvICMVNHK266ZUapEBVYIAUJMB8GA1UdIwQYMBaAFHE4NvICMVNHK266ZUap
+EBVYIAUJMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQUFAAOCAQEAA/e1K6td
+EPx7srJerJsOflN4WT5CBP51o62sgU7XAotexC3IUnbHLB/8gTKY0UvGkpMzNTEv
+/NgdRN3ggX+d6YvhZJFiCzkIjKx0nVnZellSlxG5FntvRdOW2TF9AjYPnDtuzywN
+A0ZF66D0f0hExghAzN4bcLUprbqLOzRldRtxIR0sFAqwlpW41uryZfspuk/qkZN0
+abby/+Ea0AzRdoXLiiW9l14sbxWZJue2Kf8i7MkCx1YAzUm5s2x7UwQa4qjJqhIF
+I8LO57sEAszAR6LkxCkvW0VXiVHuPOtSCP8HNR6fNWpHSlaY0VqFH4z1Ir+rzoPz
+4iIprn2DQKi6bA==
+-----END CERTIFICATE-----
+
+# Issuer: CN=GeoTrust Universal CA O=GeoTrust Inc.
+# Subject: CN=GeoTrust Universal CA O=GeoTrust Inc.
+# Label: "GeoTrust Universal CA"
+# Serial: 1
+# MD5 Fingerprint: 92:65:58:8b:a2:1a:31:72:73:68:5c:b4:a5:7a:07:48
+# SHA1 Fingerprint: e6:21:f3:35:43:79:05:9a:4b:68:30:9d:8a:2f:74:22:15:87:ec:79
+# SHA256 Fingerprint: a0:45:9b:9f:63:b2:25:59:f5:fa:5d:4c:6d:b3:f9:f7:2f:f1:93:42:03:35:78:f0:73:bf:1d:1b:46:cb:b9:12
+-----BEGIN CERTIFICATE-----
+MIIFaDCCA1CgAwIBAgIBATANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJVUzEW
+MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEeMBwGA1UEAxMVR2VvVHJ1c3QgVW5pdmVy
+c2FsIENBMB4XDTA0MDMwNDA1MDAwMFoXDTI5MDMwNDA1MDAwMFowRTELMAkGA1UE
+BhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xHjAcBgNVBAMTFUdlb1RydXN0
+IFVuaXZlcnNhbCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKYV
+VaCjxuAfjJ0hUNfBvitbtaSeodlyWL0AG0y/YckUHUWCq8YdgNY96xCcOq9tJPi8
+cQGeBvV8Xx7BDlXKg5pZMK4ZyzBIle0iN430SppyZj6tlcDgFgDgEB8rMQ7XlFTT
+QjOgNB0eRXbdT8oYN+yFFXoZCPzVx5zw8qkuEKmS5j1YPakWaDwvdSEYfyh3peFh
+F7em6fgemdtzbvQKoiFs7tqqhZJmr/Z6a4LauiIINQ/PQvE1+mrufislzDoR5G2v
+c7J2Ha3QsnhnGqQ5HFELZ1aD/ThdDc7d8Lsrlh/eezJS/R27tQahsiFepdaVaH/w
+mZ7cRQg+59IJDTWU3YBOU5fXtQlEIGQWFwMCTFMNaN7VqnJNk22CDtucvc+081xd
+VHppCZbW2xHBjXWotM85yM48vCR85mLK4b19p71XZQvk/iXttmkQ3CgaRr0BHdCX
+teGYO8A3ZNY9lO4L4fUorgtWv3GLIylBjobFS1J72HGrH4oVpjuDWtdYAVHGTEHZ
+f9hBZ3KiKN9gg6meyHv8U3NyWfWTehd2Ds735VzZC1U0oqpbtWpU5xPKV+yXbfRe
+Bi9Fi1jUIxaS5BZuKGNZMN9QAZxjiRqf2xeUgnA3wySemkfWWspOqGmJch+RbNt+
+nhutxx9z3SxPGWX9f5NAEC7S8O08ni4oPmkmM8V7AgMBAAGjYzBhMA8GA1UdEwEB
+/wQFMAMBAf8wHQYDVR0OBBYEFNq7LqqwDLiIJlF0XG0D08DYj3rWMB8GA1UdIwQY
+MBaAFNq7LqqwDLiIJlF0XG0D08DYj3rWMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG
+9w0BAQUFAAOCAgEAMXjmx7XfuJRAyXHEqDXsRh3ChfMoWIawC/yOsjmPRFWrZIRc
+aanQmjg8+uUfNeVE44B5lGiku8SfPeE0zTBGi1QrlaXv9z+ZhP015s8xxtxqv6fX
+IwjhmF7DWgh2qaavdy+3YL1ERmrvl/9zlcGO6JP7/TG37FcREUWbMPEaiDnBTzyn
+ANXH/KttgCJwpQzgXQQpAvvLoJHRfNbDflDVnVi+QTjruXU8FdmbyUqDWcDaU/0z
+uzYYm4UPFd3uLax2k7nZAY1IEKj79TiG8dsKxr2EoyNB3tZ3b4XUhRxQ4K5RirqN
+Pnbiucon8l+f725ZDQbYKxek0nxru18UGkiPGkzns0ccjkxFKyDuSN/n3QmOGKja
+QI2SJhFTYXNd673nxE0pN2HrrDktZy4W1vUAg4WhzH92xH3kt0tm7wNFYGm2DFKW
+koRepqO1pD4r2czYG0eq8kTaT/kD6PAUyz/zg97QwVTjt+gKN02LIFkDMBmhLMi9
+ER/frslKxfMnZmaGrGiR/9nmUxwPi1xpZQomyB40w11Re9epnAahNt3ViZS82eQt
+DF4JbAiXfKM9fJP/P6EUp8+1Xevb2xzEdt+Iub1FBZUbrvxGakyvSOPOrg/Sfuvm
+bJxPgWp6ZKy7PtXny3YuxadIwVyQD8vIP/rmMuGNG2+k5o7Y+SlIis5z/iw=
+-----END CERTIFICATE-----
+
+# Issuer: CN=GeoTrust Universal CA 2 O=GeoTrust Inc.
+# Subject: CN=GeoTrust Universal CA 2 O=GeoTrust Inc.
+# Label: "GeoTrust Universal CA 2"
+# Serial: 1
+# MD5 Fingerprint: 34:fc:b8:d0:36:db:9e:14:b3:c2:f2:db:8f:e4:94:c7
+# SHA1 Fingerprint: 37:9a:19:7b:41:85:45:35:0c:a6:03:69:f3:3c:2e:af:47:4f:20:79
+# SHA256 Fingerprint: a0:23:4f:3b:c8:52:7c:a5:62:8e:ec:81:ad:5d:69:89:5d:a5:68:0d:c9:1d:1c:b8:47:7f:33:f8:78:b9:5b:0b
+-----BEGIN CERTIFICATE-----
+MIIFbDCCA1SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzEW
+MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVy
+c2FsIENBIDIwHhcNMDQwMzA0MDUwMDAwWhcNMjkwMzA0MDUwMDAwWjBHMQswCQYD
+VQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1
+c3QgVW5pdmVyc2FsIENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC
+AQCzVFLByT7y2dyxUxpZKeexw0Uo5dfR7cXFS6GqdHtXr0om/Nj1XqduGdt0DE81
+WzILAePb63p3NeqqWuDW6KFXlPCQo3RWlEQwAx5cTiuFJnSCegx2oG9NzkEtoBUG
+FF+3Qs17j1hhNNwqCPkuwwGmIkQcTAeC5lvO0Ep8BNMZcyfwqph/Lq9O64ceJHdq
+XbboW0W63MOhBW9Wjo8QJqVJwy7XQYci4E+GymC16qFjwAGXEHm9ADwSbSsVsaxL
+se4YuU6W3Nx2/zu+z18DwPw76L5GG//aQMJS9/7jOvdqdzXQ2o3rXhhqMcceujwb
+KNZrVMaqW9eiLBsZzKIC9ptZvTdrhrVtgrrY6slWvKk2WP0+GfPtDCapkzj4T8Fd
+IgbQl+rhrcZV4IErKIM6+vR7IVEAvlI4zs1meaj0gVbi0IMJR1FbUGrP20gaXT73
+y/Zl92zxlfgCOzJWgjl6W70viRu/obTo/3+NjN8D8WBOWBFM66M/ECuDmgFz2ZRt
+hAAnZqzwcEAJQpKtT5MNYQlRJNiS1QuUYbKHsu3/mjX/hVTK7URDrBs8FmtISgoc
+QIgfksILAAX/8sgCSqSqqcyZlpwvWOB94b67B9xfBHJcMTTD7F8t4D1kkCLm0ey4
+Lt1ZrtmhN79UNdxzMk+MBB4zsslG8dhcyFVQyWi9qLo2CQIDAQABo2MwYTAPBgNV
+HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAfBgNV
+HSMEGDAWgBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAOBgNVHQ8BAf8EBAMCAYYwDQYJ
+KoZIhvcNAQEFBQADggIBAGbBxiPz2eAubl/oz66wsCVNK/g7WJtAJDday6sWSf+z
+dXkzoS9tcBc0kf5nfo/sm+VegqlVHy/c1FEHEv6sFj4sNcZj/NwQ6w2jqtB8zNHQ
+L1EuxBRa3ugZ4T7GzKQp5y6EqgYweHZUcyiYWTjgAA1i00J9IZ+uPTqM1fp3DRgr
+Fg5fNuH8KrUwJM/gYwx7WBr+mbpCErGR9Hxo4sjoryzqyX6uuyo9DRXcNJW2GHSo
+ag/HtPQTxORb7QrSpJdMKu0vbBKJPfEncKpqA1Ihn0CoZ1Dy81of398j9tx4TuaY
+T1U6U+Pv8vSfx3zYWK8pIpe44L2RLrB27FcRz+8pRPPphXpgY+RdM4kX2TGq2tbz
+GDVyz4crL2MjhF2EjD9XoIj8mZEoJmmZ1I+XRL6O1UixpCgp8RW04eWe3fiPpm8m
+1wk8OhwRDqZsN/etRIcsKMfYdIKz0G9KV7s1KSegi+ghp4dkNl3M2Basx7InQJJV
+OCiNUW7dFGdTbHFcJoRNdVq2fmBWqU2t+5sel/MN2dKXVHfaPRK34B7vCAas+YWH
+6aLcr34YEoP9VhdBLtUpgn2Z9DH2canPLAEnpQW5qrJITirvn5NSUZU8UnOOVkwX
+QMAJKOSLakhT2+zNVVXxxvjpoixMptEmX36vWkzaH6byHCx+rgIW0lbQL1dTR+iS
+-----END CERTIFICATE-----
+
+# Issuer: CN=America Online Root Certification Authority 1 O=America Online Inc.
+# Subject: CN=America Online Root Certification Authority 1 O=America Online Inc.
+# Label: "America Online Root Certification Authority 1"
+# Serial: 1
+# MD5 Fingerprint: 14:f1:08:ad:9d:fa:64:e2:89:e7:1c:cf:a8:ad:7d:5e
+# SHA1 Fingerprint: 39:21:c1:15:c1:5d:0e:ca:5c:cb:5b:c4:f0:7d:21:d8:05:0b:56:6a
+# SHA256 Fingerprint: 77:40:73:12:c6:3a:15:3d:5b:c0:0b:4e:51:75:9c:df:da:c2:37:dc:2a:33:b6:79:46:e9:8e:9b:fa:68:0a:e3
+-----BEGIN CERTIFICATE-----
+MIIDpDCCAoygAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEc
+MBoGA1UEChMTQW1lcmljYSBPbmxpbmUgSW5jLjE2MDQGA1UEAxMtQW1lcmljYSBP
+bmxpbmUgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAxMB4XDTAyMDUyODA2
+MDAwMFoXDTM3MTExOTIwNDMwMFowYzELMAkGA1UEBhMCVVMxHDAaBgNVBAoTE0Ft
+ZXJpY2EgT25saW5lIEluYy4xNjA0BgNVBAMTLUFtZXJpY2EgT25saW5lIFJvb3Qg
+Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgMTCCASIwDQYJKoZIhvcNAQEBBQADggEP
+ADCCAQoCggEBAKgv6KRpBgNHw+kqmP8ZonCaxlCyfqXfaE0bfA+2l2h9LaaLl+lk
+hsmj76CGv2BlnEtUiMJIxUo5vxTjWVXlGbR0yLQFOVwWpeKVBeASrlmLojNoWBym
+1BW32J/X3HGrfpq/m44zDyL9Hy7nBzbvYjnF3cu6JRQj3gzGPTzOggjmZj7aUTsW
+OqMFf6Dch9Wc/HKpoH145LcxVR5lu9RhsCFg7RAycsWSJR74kEoYeEfffjA3PlAb
+2xzTa5qGUwew76wGePiEmf4hjUyAtgyC9mZweRrTT6PP8c9GsEsPPt2IYriMqQko
+O3rHl+Ee5fSfwMCuJKDIodkP1nsmgmkyPacCAwEAAaNjMGEwDwYDVR0TAQH/BAUw
+AwEB/zAdBgNVHQ4EFgQUAK3Zo/Z59m50qX8zPYEX10zPM94wHwYDVR0jBBgwFoAU
+AK3Zo/Z59m50qX8zPYEX10zPM94wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEB
+BQUAA4IBAQB8itEfGDeC4Liwo+1WlchiYZwFos3CYiZhzRAW18y0ZTTQEYqtqKkF
+Zu90821fnZmv9ov761KyBZiibyrFVL0lvV+uyIbqRizBs73B6UlwGBaXCBOMIOAb
+LjpHyx7kADCVW/RFo8AasAFOq73AI25jP4BKxQft3OJvx8Fi8eNy1gTIdGcL+oir
+oQHIb/AUr9KZzVGTfu0uOMe9zkZQPXLjeSWdm4grECDdpbgyn43gKd8hdIaC2y+C
+MMbHNYaz+ZZfRtsMRf3zUMNvxsNIrUam4SdHCh0Om7bCd39j8uB9Gr784N/Xx6ds
+sPmuujz9dLQR6FgNgLzTqIA6me11zEZ7
+-----END CERTIFICATE-----
+
+# Issuer: CN=America Online Root Certification Authority 2 O=America Online Inc.
+# Subject: CN=America Online Root Certification Authority 2 O=America Online Inc.
+# Label: "America Online Root Certification Authority 2"
+# Serial: 1
+# MD5 Fingerprint: d6:ed:3c:ca:e2:66:0f:af:10:43:0d:77:9b:04:09:bf
+# SHA1 Fingerprint: 85:b5:ff:67:9b:0c:79:96:1f:c8:6e:44:22:00:46:13:db:17:92:84
+# SHA256 Fingerprint: 7d:3b:46:5a:60:14:e5:26:c0:af:fc:ee:21:27:d2:31:17:27:ad:81:1c:26:84:2d:00:6a:f3:73:06:cc:80:bd
+-----BEGIN CERTIFICATE-----
+MIIFpDCCA4ygAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEc
+MBoGA1UEChMTQW1lcmljYSBPbmxpbmUgSW5jLjE2MDQGA1UEAxMtQW1lcmljYSBP
+bmxpbmUgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAyMB4XDTAyMDUyODA2
+MDAwMFoXDTM3MDkyOTE0MDgwMFowYzELMAkGA1UEBhMCVVMxHDAaBgNVBAoTE0Ft
+ZXJpY2EgT25saW5lIEluYy4xNjA0BgNVBAMTLUFtZXJpY2EgT25saW5lIFJvb3Qg
+Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIP
+ADCCAgoCggIBAMxBRR3pPU0Q9oyxQcngXssNt79Hc9PwVU3dxgz6sWYFas14tNwC
+206B89enfHG8dWOgXeMHDEjsJcQDIPT/DjsS/5uN4cbVG7RtIuOx238hZK+GvFci
+KtZHgVdEglZTvYYUAQv8f3SkWq7xuhG1m1hagLQ3eAkzfDJHA1zEpYNI9FdWboE2
+JxhP7JsowtS013wMPgwr38oE18aO6lhOqKSlGBxsRZijQdEt0sdtjRnxrXm3gT+9
+BoInLRBYBbV4Bbkv2wxrkJB+FFk4u5QkE+XRnRTf04JNRvCAOVIyD+OEsnpD8l7e
+Xz8d3eOyG6ChKiMDbi4BFYdcpnV1x5dhvt6G3NRI270qv0pV2uh9UPu0gBe4lL8B
+PeraunzgWGcXuVjgiIZGZ2ydEEdYMtA1fHkqkKJaEBEjNa0vzORKW6fIJ/KD3l67
+Xnfn6KVuY8INXWHQjNJsWiEOyiijzirplcdIz5ZvHZIlyMbGwcEMBawmxNJ10uEq
+Z8A9W6Wa6897GqidFEXlD6CaZd4vKL3Ob5Rmg0gp2OpljK+T2WSfVVcmv2/LNzGZ
+o2C7HK2JNDJiuEMhBnIMoVxtRsX6Kc8w3onccVvdtjc+31D1uAclJuW8tf48ArO3
++L5DwYcRlJ4jbBeKuIonDFRH8KmzwICMoCfrHRnjB453cMor9H124HhnAgMBAAGj
+YzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFE1FwWg4u3OpaaEg5+31IqEj
+FNeeMB8GA1UdIwQYMBaAFE1FwWg4u3OpaaEg5+31IqEjFNeeMA4GA1UdDwEB/wQE
+AwIBhjANBgkqhkiG9w0BAQUFAAOCAgEAZ2sGuV9FOypLM7PmG2tZTiLMubekJcmn
+xPBUlgtk87FYT15R/LKXeydlwuXK5w0MJXti4/qftIe3RUavg6WXSIylvfEWK5t2
+LHo1YGwRgJfMqZJS5ivmae2p+DYtLHe/YUjRYwu5W1LtGLBDQiKmsXeu3mnFzccc
+obGlHBD7GL4acN3Bkku+KVqdPzW+5X1R+FXgJXUjhx5c3LqdsKyzadsXg8n33gy8
+CNyRnqjQ1xU3c6U1uPx+xURABsPr+CKAXEfOAuMRn0T//ZoyzH1kUQ7rVyZ2OuMe
+IjzCpjbdGe+n/BLzJsBZMYVMnNjP36TMzCmT/5RtdlwTCJfy7aULTd3oyWgOZtMA
+DjMSW7yV5TKQqLPGbIOtd+6Lfn6xqavT4fG2wLHqiMDn05DpKJKUe2h7lyoKZy2F
+AjgQ5ANh1NolNscIWC2hp1GvMApJ9aZphwctREZ2jirlmjvXGKL8nDgQzMY70rUX
+Om/9riW99XJZZLF0KjhfGEzfz3EEWjbUvy+ZnOjZurGV5gJLIaFb1cFPj65pbVPb
+AZO1XB4Y3WRayhgoPmMEEf0cjQAPuDffZ4qdZqkCapH/E8ovXYO8h5Ns3CRRFgQl
+Zvqz2cK6Kb6aSDiCmfS/O0oxGfm/jiEzFMpPVF/7zvuPcX/9XhmgD0uRuMRUvAaw
+RY8mkaKO/qk=
+-----END CERTIFICATE-----
+
+# Issuer: CN=AAA Certificate Services O=Comodo CA Limited
+# Subject: CN=AAA Certificate Services O=Comodo CA Limited
+# Label: "Comodo AAA Services root"
+# Serial: 1
+# MD5 Fingerprint: 49:79:04:b0:eb:87:19:ac:47:b0:bc:11:51:9b:74:d0
+# SHA1 Fingerprint: d1:eb:23:a4:6d:17:d6:8f:d9:25:64:c2:f1:f1:60:17:64:d8:e3:49
+# SHA256 Fingerprint: d7:a7:a0:fb:5d:7e:27:31:d7:71:e9:48:4e:bc:de:f7:1d:5f:0c:3e:0a:29:48:78:2b:c8:3e:e0:ea:69:9e:f4
+-----BEGIN CERTIFICATE-----
+MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEb
+MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow
+GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmlj
+YXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAwMFoXDTI4MTIzMTIzNTk1OVowezEL
+MAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE
+BwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNVBAMM
+GEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEP
+ADCCAQoCggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQua
+BtDFcCLNSS1UY8y2bmhGC1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe
+3M/vg4aijJRPn2jymJBGhCfHdr/jzDUsi14HZGWCwEiwqJH5YZ92IFCokcdmtet4
+YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszWY19zjNoFmag4qMsXeDZR
+rOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjHYpy+g8cm
+ez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQU
+oBEKIz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF
+MAMBAf8wewYDVR0fBHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20v
+QUFBQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29t
+b2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2VzLmNybDANBgkqhkiG9w0BAQUF
+AAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm7l3sAg9g1o1Q
+GE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz
+Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2
+G9w84FoVxp7Z8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsi
+l2D4kF501KKaU73yqWjgom7C12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3
+smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg==
+-----END CERTIFICATE-----
+
+# Issuer: CN=Secure Certificate Services O=Comodo CA Limited
+# Subject: CN=Secure Certificate Services O=Comodo CA Limited
+# Label: "Comodo Secure Services root"
+# Serial: 1
+# MD5 Fingerprint: d3:d9:bd:ae:9f:ac:67:24:b3:c8:1b:52:e1:b9:a9:bd
+# SHA1 Fingerprint: 4a:65:d5:f4:1d:ef:39:b8:b8:90:4a:4a:d3:64:81:33:cf:c7:a1:d1
+# SHA256 Fingerprint: bd:81:ce:3b:4f:65:91:d1:1a:67:b5:fc:7a:47:fd:ef:25:52:1b:f9:aa:4e:18:b9:e3:df:2e:34:a7:80:3b:e8
+-----BEGIN CERTIFICATE-----
+MIIEPzCCAyegAwIBAgIBATANBgkqhkiG9w0BAQUFADB+MQswCQYDVQQGEwJHQjEb
+MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow
+GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEkMCIGA1UEAwwbU2VjdXJlIENlcnRp
+ZmljYXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAwMFoXDTI4MTIzMTIzNTk1OVow
+fjELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
+A1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxJDAiBgNV
+BAMMG1NlY3VyZSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEB
+BQADggEPADCCAQoCggEBAMBxM4KK0HDrc4eCQNUd5MvJDkKQ+d40uaG6EfQlhfPM
+cm3ye5drswfxdySRXyWP9nQ95IDC+DwN879A6vfIUtFyb+/Iq0G4bi4XKpVpDM3S
+HpR7LZQdqnXXs5jLrLxkU0C8j6ysNstcrbvd4JQX7NFc0L/vpZXJkMWwrPsbQ996
+CF23uPJAGysnnlDOXmWCiIxe004MeuoIkbY2qitC++rCoznl2yY4rYsK7hljxxwk
+3wN42ubqwUcaCwtGCd0C/N7Lh1/XMGNooa7cMqG6vv5Eq2i2pRcV/b3Vp6ea5EQz
+6YiO/O1R65NxTq0B50SOqy3LqP4BSUjwwN3HaNiS/j0CAwEAAaOBxzCBxDAdBgNV
+HQ4EFgQUPNiTiMLAggnMAZkGkyDpnnAJY08wDgYDVR0PAQH/BAQDAgEGMA8GA1Ud
+EwEB/wQFMAMBAf8wgYEGA1UdHwR6MHgwO6A5oDeGNWh0dHA6Ly9jcmwuY29tb2Rv
+Y2EuY29tL1NlY3VyZUNlcnRpZmljYXRlU2VydmljZXMuY3JsMDmgN6A1hjNodHRw
+Oi8vY3JsLmNvbW9kby5uZXQvU2VjdXJlQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmww
+DQYJKoZIhvcNAQEFBQADggEBAIcBbSMdflsXfcFhMs+P5/OKlFlm4J4oqF7Tt/Q0
+5qo5spcWxYJvMqTpjOev/e/C6LlLqqP05tqNZSH7uoDrJiiFGv45jN5bBAS0VPmj
+Z55B+glSzAVIqMk/IQQezkhr/IXownuvf7fM+F86/TXGDe+X3EyrEeFryzHRbPtI
+gKvcnDe4IRRLDXE97IMzbtFuMhbsmMcWi1mmNKsFVy2T96oTy9IT4rcuO81rUBcJ
+aD61JlfutuC23bkpgHl9j6PwpCikFcSF9CfUa7/lXORlAnZUtOM3ZiTTGWHIUhDl
+izeauan5Hb/qmZJhlv8BzaFfDbxxvA6sCx1HRR3B7Hzs/Sk=
+-----END CERTIFICATE-----
+
+# Issuer: CN=Trusted Certificate Services O=Comodo CA Limited
+# Subject: CN=Trusted Certificate Services O=Comodo CA Limited
+# Label: "Comodo Trusted Services root"
+# Serial: 1
+# MD5 Fingerprint: 91:1b:3f:6e:cd:9e:ab:ee:07:fe:1f:71:d2:b3:61:27
+# SHA1 Fingerprint: e1:9f:e3:0e:8b:84:60:9e:80:9b:17:0d:72:a8:c5:ba:6e:14:09:bd
+# SHA256 Fingerprint: 3f:06:e5:56:81:d4:96:f5:be:16:9e:b5:38:9f:9f:2b:8f:f6:1e:17:08:df:68:81:72:48:49:cd:5d:27:cb:69
+-----BEGIN CERTIFICATE-----
+MIIEQzCCAyugAwIBAgIBATANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJHQjEb
+MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow
+GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDElMCMGA1UEAwwcVHJ1c3RlZCBDZXJ0
+aWZpY2F0ZSBTZXJ2aWNlczAeFw0wNDAxMDEwMDAwMDBaFw0yODEyMzEyMzU5NTla
+MH8xCzAJBgNVBAYTAkdCMRswGQYDVQQIDBJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAO
+BgNVBAcMB1NhbGZvcmQxGjAYBgNVBAoMEUNvbW9kbyBDQSBMaW1pdGVkMSUwIwYD
+VQQDDBxUcnVzdGVkIENlcnRpZmljYXRlIFNlcnZpY2VzMIIBIjANBgkqhkiG9w0B
+AQEFAAOCAQ8AMIIBCgKCAQEA33FvNlhTWvI2VFeAxHQIIO0Yfyod5jWaHiWsnOWW
+fnJSoBVC21ndZHoa0Lh73TkVvFVIxO06AOoxEbrycXQaZ7jPM8yoMa+j49d/vzMt
+TGo87IvDktJTdyR0nAducPy9C1t2ul/y/9c3S0pgePfw+spwtOpZqqPOSC+pw7IL
+fhdyFgymBwwbOM/JYrc/oJOlh0Hyt3BAd9i+FHzjqMB6juljatEPmsbS9Is6FARW
+1O24zG71++IsWL1/T2sr92AkWCTOJu80kTrV44HQsvAEAtdbtz6SrGsSivnkBbA7
+kUlcsutT6vifR4buv5XAwAaf0lteERv0xwQ1KdJVXOTt6wIDAQABo4HJMIHGMB0G
+A1UdDgQWBBTFe1i97doladL3WRaoszLAeydb9DAOBgNVHQ8BAf8EBAMCAQYwDwYD
+VR0TAQH/BAUwAwEB/zCBgwYDVR0fBHwwejA8oDqgOIY2aHR0cDovL2NybC5jb21v
+ZG9jYS5jb20vVHJ1c3RlZENlcnRpZmljYXRlU2VydmljZXMuY3JsMDqgOKA2hjRo
+dHRwOi8vY3JsLmNvbW9kby5uZXQvVHJ1c3RlZENlcnRpZmljYXRlU2VydmljZXMu
+Y3JsMA0GCSqGSIb3DQEBBQUAA4IBAQDIk4E7ibSvuIQSTI3S8NtwuleGFTQQuS9/
+HrCoiWChisJ3DFBKmwCL2Iv0QeLQg4pKHBQGsKNoBXAxMKdTmw7pSqBYaWcOrp32
+pSxBvzwGa+RZzG0Q8ZZvH9/0BAKkn0U+yNj6NkZEUD+Cl5EfKNsYEYwq5GWDVxIS
+jBc/lDb+XbDABHcTuPQV1T84zJQ6VdCsmPW6AF/ghhmBeC8owH7TzEIK9a5QoNE+
+xqFx7D+gIIxmOom0jtTYsU0lR+4viMi14QVFwL4Ucd56/Y57fU0IlqUSc/Atyjcn
+dBInTMu2l+nZrghtWjlA3QVHdWpaIbOjGM9O9y5Xt5hwXsjEeLBi
+-----END CERTIFICATE-----
+
+# Issuer: CN=UTN - DATACorp SGC O=The USERTRUST Network OU=http://www.usertrust.com
+# Subject: CN=UTN - DATACorp SGC O=The USERTRUST Network OU=http://www.usertrust.com
+# Label: "UTN DATACorp SGC Root CA"
+# Serial: 91374294542884689855167577680241077609
+# MD5 Fingerprint: b3:a5:3e:77:21:6d:ac:4a:c0:c9:fb:d5:41:3d:ca:06
+# SHA1 Fingerprint: 58:11:9f:0e:12:82:87:ea:50:fd:d9:87:45:6f:4f:78:dc:fa:d6:d4
+# SHA256 Fingerprint: 85:fb:2f:91:dd:12:27:5a:01:45:b6:36:53:4f:84:02:4a:d6:8b:69:b8:ee:88:68:4f:f7:11:37:58:05:b3:48
+-----BEGIN CERTIFICATE-----
+MIIEXjCCA0agAwIBAgIQRL4Mi1AAIbQR0ypoBqmtaTANBgkqhkiG9w0BAQUFADCB
+kzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug
+Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho
+dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xGzAZBgNVBAMTElVUTiAtIERBVEFDb3Jw
+IFNHQzAeFw05OTA2MjQxODU3MjFaFw0xOTA2MjQxOTA2MzBaMIGTMQswCQYDVQQG
+EwJVUzELMAkGA1UECBMCVVQxFzAVBgNVBAcTDlNhbHQgTGFrZSBDaXR5MR4wHAYD
+VQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxITAfBgNVBAsTGGh0dHA6Ly93d3cu
+dXNlcnRydXN0LmNvbTEbMBkGA1UEAxMSVVROIC0gREFUQUNvcnAgU0dDMIIBIjAN
+BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3+5YEKIrblXEjr8uRgnn4AgPLit6
+E5Qbvfa2gI5lBZMAHryv4g+OGQ0SR+ysraP6LnD43m77VkIVni5c7yPeIbkFdicZ
+D0/Ww5y0vpQZY/KmEQrrU0icvvIpOxboGqBMpsn0GFlowHDyUwDAXlCCpVZvNvlK
+4ESGoE1O1kduSUrLZ9emxAW5jh70/P/N5zbgnAVssjMiFdC04MwXwLLA9P4yPykq
+lXvY8qdOD1R8oQ2AswkDwf9c3V6aPryuvEeKaq5xyh+xKrhfQgUL7EYw0XILyulW
+bfXv33i+Ybqypa4ETLyorGkVl73v67SMvzX41MPRKA5cOp9wGDMgd8SirwIDAQAB
+o4GrMIGoMAsGA1UdDwQEAwIBxjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRT
+MtGzz3/64PGgXYVOktKeRR20TzA9BgNVHR8ENjA0MDKgMKAuhixodHRwOi8vY3Js
+LnVzZXJ0cnVzdC5jb20vVVROLURBVEFDb3JwU0dDLmNybDAqBgNVHSUEIzAhBggr
+BgEFBQcDAQYKKwYBBAGCNwoDAwYJYIZIAYb4QgQBMA0GCSqGSIb3DQEBBQUAA4IB
+AQAnNZcAiosovcYzMB4p/OL31ZjUQLtgyr+rFywJNn9Q+kHcrpY6CiM+iVnJowft
+Gzet/Hy+UUla3joKVAgWRcKZsYfNjGjgaQPpxE6YsjuMFrMOoAyYUJuTqXAJyCyj
+j98C5OBxOvG0I3KgqgHf35g+FFCgMSa9KOlaMCZ1+XtgHI3zzVAmbQQnmt/VDUVH
+KWss5nbZqSl9Mt3JNjy9rjXxEZ4du5A/EkdOjtd+D2JzHVImOBwYSf0wdJrE5SIv
+2MCN7ZF6TACPcn9d2t0bi0Vr591pl6jFVkwPDPafepE39peC4N1xaf92P2BNPM/3
+mfnGV/TJVTl4uix5yaaIK/QI
+-----END CERTIFICATE-----
+
+# Issuer: CN=UTN-USERFirst-Hardware O=The USERTRUST Network OU=http://www.usertrust.com
+# Subject: CN=UTN-USERFirst-Hardware O=The USERTRUST Network OU=http://www.usertrust.com
+# Label: "UTN USERFirst Hardware Root CA"
+# Serial: 91374294542884704022267039221184531197
+# MD5 Fingerprint: 4c:56:41:e5:0d:bb:2b:e8:ca:a3:ed:18:08:ad:43:39
+# SHA1 Fingerprint: 04:83:ed:33:99:ac:36:08:05:87:22:ed:bc:5e:46:00:e3:be:f9:d7
+# SHA256 Fingerprint: 6e:a5:47:41:d0:04:66:7e:ed:1b:48:16:63:4a:a3:a7:9e:6e:4b:96:95:0f:82:79:da:fc:8d:9b:d8:81:21:37
+-----BEGIN CERTIFICATE-----
+MIIEdDCCA1ygAwIBAgIQRL4Mi1AAJLQR0zYq/mUK/TANBgkqhkiG9w0BAQUFADCB
+lzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug
+Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho
+dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3Qt
+SGFyZHdhcmUwHhcNOTkwNzA5MTgxMDQyWhcNMTkwNzA5MTgxOTIyWjCBlzELMAkG
+A1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEe
+MBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8v
+d3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3QtSGFyZHdh
+cmUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCx98M4P7Sof885glFn
+0G2f0v9Y8+efK+wNiVSZuTiZFvfgIXlIwrthdBKWHTxqctU8EGc6Oe0rE81m65UJ
+M6Rsl7HoxuzBdXmcRl6Nq9Bq/bkqVRcQVLMZ8Jr28bFdtqdt++BxF2uiiPsA3/4a
+MXcMmgF6sTLjKwEHOG7DpV4jvEWbe1DByTCP2+UretNb+zNAHqDVmBe8i4fDidNd
+oI6yqqr2jmmIBsX6iSHzCJ1pLgkzmykNRg+MzEk0sGlRvfkGzWitZky8PqxhvQqI
+DsjfPe58BEydCl5rkdbux+0ojatNh4lz0G6k0B4WixThdkQDf2Os5M1JnMWS9Ksy
+oUhbAgMBAAGjgbkwgbYwCwYDVR0PBAQDAgHGMA8GA1UdEwEB/wQFMAMBAf8wHQYD
+VR0OBBYEFKFyXyYbKJhDlV0HN9WFlp1L0sNFMEQGA1UdHwQ9MDswOaA3oDWGM2h0
+dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9VVE4tVVNFUkZpcnN0LUhhcmR3YXJlLmNy
+bDAxBgNVHSUEKjAoBggrBgEFBQcDAQYIKwYBBQUHAwUGCCsGAQUFBwMGBggrBgEF
+BQcDBzANBgkqhkiG9w0BAQUFAAOCAQEARxkP3nTGmZev/K0oXnWO6y1n7k57K9cM
+//bey1WiCuFMVGWTYGufEpytXoMs61quwOQt9ABjHbjAbPLPSbtNk28Gpgoiskli
+CE7/yMgUsogWXecB5BKV5UU0s4tpvc+0hY91UZ59Ojg6FEgSxvunOxqNDYJAB+gE
+CJChicsZUN/KHAG8HQQZexB2lzvukJDKxA4fFm517zP4029bHpbj4HR3dHuKom4t
+3XbWOTCC8KucUvIqx69JXn7HaOWCgchqJ/kniCrVWFCVH/A7HFe7fRQ5YiuayZSS
+KqMiDP+JJn1fIytH1xUdqWqeUQ0qUZ6B+dQ7XnASfxAynB67nfhmqA==
+-----END CERTIFICATE-----
+
+# Issuer: CN=XRamp Global Certification Authority O=XRamp Security Services Inc OU=www.xrampsecurity.com
+# Subject: CN=XRamp Global Certification Authority O=XRamp Security Services Inc OU=www.xrampsecurity.com
+# Label: "XRamp Global CA Root"
+# Serial: 107108908803651509692980124233745014957
+# MD5 Fingerprint: a1:0b:44:b3:ca:10:d8:00:6e:9d:0f:d8:0f:92:0a:d1
+# SHA1 Fingerprint: b8:01:86:d1:eb:9c:86:a5:41:04:cf:30:54:f3:4c:52:b7:e5:58:c6
+# SHA256 Fingerprint: ce:cd:dc:90:50:99:d8:da:df:c5:b1:d2:09:b7:37:cb:e2:c1:8c:fb:2c:10:c0:ff:0b:cf:0d:32:86:fc:1a:a2
+-----BEGIN CERTIFICATE-----
+MIIEMDCCAxigAwIBAgIQUJRs7Bjq1ZxN1ZfvdY+grTANBgkqhkiG9w0BAQUFADCB
+gjELMAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEk
+MCIGA1UEChMbWFJhbXAgU2VjdXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRY
+UmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQxMTAxMTcx
+NDA0WhcNMzUwMTAxMDUzNzE5WjCBgjELMAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3
+dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2VjdXJpdHkgU2Vy
+dmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBB
+dXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCYJB69FbS6
+38eMpSe2OAtp87ZOqCwuIR1cRN8hXX4jdP5efrRKt6atH67gBhbim1vZZ3RrXYCP
+KZ2GG9mcDZhtdhAoWORlsH9KmHmf4MMxfoArtYzAQDsRhtDLooY2YKTVMIJt2W7Q
+DxIEM5dfT2Fa8OT5kavnHTu86M/0ay00fOJIYRyO82FEzG+gSqmUsE3a56k0enI4
+qEHMPJQRfevIpoy3hsvKMzvZPTeL+3o+hiznc9cKV6xkmxnr9A8ECIqsAxcZZPRa
+JSKNNCyy9mgdEm3Tih4U2sSPpuIjhdV6Db1q4Ons7Be7QhtnqiXtRYMh/MHJfNVi
+PvryxS3T/dRlAgMBAAGjgZ8wgZwwEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0P
+BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFMZPoj0GY4QJnM5i5ASs
+jVy16bYbMDYGA1UdHwQvMC0wK6ApoCeGJWh0dHA6Ly9jcmwueHJhbXBzZWN1cml0
+eS5jb20vWEdDQS5jcmwwEAYJKwYBBAGCNxUBBAMCAQEwDQYJKoZIhvcNAQEFBQAD
+ggEBAJEVOQMBG2f7Shz5CmBbodpNl2L5JFMn14JkTpAuw0kbK5rc/Kh4ZzXxHfAR
+vbdI4xD2Dd8/0sm2qlWkSLoC295ZLhVbO50WfUfXN+pfTXYSNrsf16GBBEYgoyxt
+qZ4Bfj8pzgCT3/3JknOJiWSe5yvkHJEs0rnOfc5vMZnT5r7SHpDwCRR5XCOrTdLa
+IR9NmXmd4c8nnxCbHIgNsIpkQTG4DmyQJKSbXHGPurt+HBvbaoAPIbzp26a3QPSy
+i6mx5O+aGtA9aZnuqCij4Tyz8LIRnM98QObd50N9otg6tamN8jSZxNQQ4Qb9CYQQ
+O+7ETPTsJ3xCwnR8gooJybQDJbw=
+-----END CERTIFICATE-----
+
+# Issuer: O=The Go Daddy Group, Inc. OU=Go Daddy Class 2 Certification Authority
+# Subject: O=The Go Daddy Group, Inc. OU=Go Daddy Class 2 Certification Authority
+# Label: "Go Daddy Class 2 CA"
+# Serial: 0
+# MD5 Fingerprint: 91:de:06:25:ab:da:fd:32:17:0c:bb:25:17:2a:84:67
+# SHA1 Fingerprint: 27:96:ba:e6:3f:18:01:e2:77:26:1b:a0:d7:77:70:02:8f:20:ee:e4
+# SHA256 Fingerprint: c3:84:6b:f2:4b:9e:93:ca:64:27:4c:0e:c6:7c:1e:cc:5e:02:4f:fc:ac:d2:d7:40:19:35:0e:81:fe:54:6a:e4
+-----BEGIN CERTIFICATE-----
+MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEh
+MB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBE
+YWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3
+MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkGA1UEBhMCVVMxITAfBgNVBAoTGFRo
+ZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28gRGFkZHkgQ2xhc3Mg
+MiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQADggEN
+ADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCA
+PVYYYwhv2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6w
+wdhFJ2+qN1j3hybX2C32qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXi
+EqITLdiOr18SPaAIBQi2XKVlOARFmR6jYGB0xUGlcmIbYsUfb18aQr4CUWWoriMY
+avx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmYvLEHZ6IVDd2gWMZEewo+
+YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0OBBYEFNLE
+sNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h
+/t2oatTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5
+IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmlj
+YXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQAD
+ggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wimPQoZ+YeAEW5p5JYXMP80kWNy
+OO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKtI3lpjbi2Tc7P
+TMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ
+HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mER
+dEr/VxqHD3VILs9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5Cuf
+ReYNnyicsbkqWletNw+vHX/bvZ8=
+-----END CERTIFICATE-----
+
+# Issuer: O=Starfield Technologies, Inc. OU=Starfield Class 2 Certification Authority
+# Subject: O=Starfield Technologies, Inc. OU=Starfield Class 2 Certification Authority
+# Label: "Starfield Class 2 CA"
+# Serial: 0
+# MD5 Fingerprint: 32:4a:4b:bb:c8:63:69:9b:be:74:9a:c6:dd:1d:46:24
+# SHA1 Fingerprint: ad:7e:1c:28:b0:64:ef:8f:60:03:40:20:14:c3:d0:e3:37:0e:b5:8a
+# SHA256 Fingerprint: 14:65:fa:20:53:97:b8:76:fa:a6:f0:a9:95:8e:55:90:e4:0f:cc:7f:aa:4f:b7:c2:c8:67:75:21:fb:5f:b6:58
+-----BEGIN CERTIFICATE-----
+MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzEl
+MCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMp
+U3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQw
+NjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBoMQswCQYDVQQGEwJVUzElMCMGA1UE
+ChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZp
+ZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqGSIb3
+DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf
+8MOh2tTYbitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN
++lq2cwQlZut3f+dZxkqZJRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0
+X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVmepsZGD3/cVE8MC5fvj13c7JdBmzDI1aa
+K4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSNF4Azbl5KXZnJHoe0nRrA
+1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HFMIHCMB0G
+A1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fR
+zt0fhvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0
+YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBD
+bGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8w
+DQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGsafPzWdqbAYcaT1epoXkJKtv3
+L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLMPUxA2IGvd56D
+eruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl
+xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynp
+VSJYACPq4xJDKVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEY
+WQPJIrSPnNVeKtelttQKbfi3QBFGmh95DmK/D5fs4C8fF5Q=
+-----END CERTIFICATE-----
+
+# Issuer: CN=StartCom Certification Authority O=StartCom Ltd. OU=Secure Digital Certificate Signing
+# Subject: CN=StartCom Certification Authority O=StartCom Ltd. OU=Secure Digital Certificate Signing
+# Label: "StartCom Certification Authority"
+# Serial: 1
+# MD5 Fingerprint: 22:4d:8f:8a:fc:f7:35:c2:bb:57:34:90:7b:8b:22:16
+# SHA1 Fingerprint: 3e:2b:f7:f2:03:1b:96:f3:8c:e6:c4:d8:a8:5d:3e:2d:58:47:6a:0f
+# SHA256 Fingerprint: c7:66:a9:be:f2:d4:07:1c:86:3a:31:aa:49:20:e8:13:b2:d1:98:60:8c:b7:b7:cf:e2:11:43:b8:36:df:09:ea
+-----BEGIN CERTIFICATE-----
+MIIHyTCCBbGgAwIBAgIBATANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJJTDEW
+MBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwg
+Q2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNh
+dGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0NjM2WhcNMzYwOTE3MTk0NjM2WjB9
+MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMi
+U2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3Rh
+cnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUA
+A4ICDwAwggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZk
+pMyONvg45iPwbm2xPN1yo4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rf
+OQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/C
+Ji/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/deMotHweXMAEtcnn6RtYT
+Kqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt2PZE4XNi
+HzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMM
+Av+Z6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w
++2OqqGwaVLRcJXrJosmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+
+Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3
+Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVcUjyJthkqcwEKDwOzEmDyei+B
+26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT37uMdBNSSwID
+AQABo4ICUjCCAk4wDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCAa4wHQYDVR0OBBYE
+FE4L7xqkQFulF2mHMMo0aEPQQa7yMGQGA1UdHwRdMFswLKAqoCiGJmh0dHA6Ly9j
+ZXJ0LnN0YXJ0Y29tLm9yZy9zZnNjYS1jcmwuY3JsMCugKaAnhiVodHRwOi8vY3Js
+LnN0YXJ0Y29tLm9yZy9zZnNjYS1jcmwuY3JsMIIBXQYDVR0gBIIBVDCCAVAwggFM
+BgsrBgEEAYG1NwEBATCCATswLwYIKwYBBQUHAgEWI2h0dHA6Ly9jZXJ0LnN0YXJ0
+Y29tLm9yZy9wb2xpY3kucGRmMDUGCCsGAQUFBwIBFilodHRwOi8vY2VydC5zdGFy
+dGNvbS5vcmcvaW50ZXJtZWRpYXRlLnBkZjCB0AYIKwYBBQUHAgIwgcMwJxYgU3Rh
+cnQgQ29tbWVyY2lhbCAoU3RhcnRDb20pIEx0ZC4wAwIBARqBl0xpbWl0ZWQgTGlh
+YmlsaXR5LCByZWFkIHRoZSBzZWN0aW9uICpMZWdhbCBMaW1pdGF0aW9ucyogb2Yg
+dGhlIFN0YXJ0Q29tIENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFBvbGljeSBhdmFp
+bGFibGUgYXQgaHR0cDovL2NlcnQuc3RhcnRjb20ub3JnL3BvbGljeS5wZGYwEQYJ
+YIZIAYb4QgEBBAQDAgAHMDgGCWCGSAGG+EIBDQQrFilTdGFydENvbSBGcmVlIFNT
+TCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTANBgkqhkiG9w0BAQUFAAOCAgEAFmyZ
+9GYMNPXQhV59CuzaEE44HF7fpiUFS5Eyweg78T3dRAlbB0mKKctmArexmvclmAk8
+jhvh3TaHK0u7aNM5Zj2gJsfyOZEdUauCe37Vzlrk4gNXcGmXCPleWKYK34wGmkUW
+FjgKXlf2Ysd6AgXmvB618p70qSmD+LIU424oh0TDkBreOKk8rENNZEXO3SipXPJz
+ewT4F+irsfMuXGRuczE6Eri8sxHkfY+BUZo7jYn0TZNmezwD7dOaHZrzZVD1oNB1
+ny+v8OqCQ5j4aZyJecRDjkZy42Q2Eq/3JR44iZB3fsNrarnDy0RLrHiQi+fHLB5L
+EUTINFInzQpdn4XBidUaePKVEFMy3YCEZnXZtWgo+2EuvoSoOMCZEoalHmdkrQYu
+L6lwhceWD3yJZfWOQ1QOq92lgDmUYMA0yZZwLKMS9R9Ie70cfmu3nZD0Ijuu+Pwq
+yvqCUqDvr0tVk+vBtfAii6w0TiYiBKGHLHVKt+V9E9e4DGTANtLJL4YSjCMJwRuC
+O3NJo2pXh5Tl1njFmUNj403gdy3hZZlyaQQaRwnmDwFWJPsfvw55qVguucQJAX6V
+um0ABj6y6koQOdjQK/W/7HW/lwLFCRsI3FU34oH7N4RDYiDK51ZLZer+bMEkkySh
+NOsF/5oirpt9P/FlUQqmMGqz9IgcgA38corog14=
+-----END CERTIFICATE-----
+
+# Issuer: CN=DigiCert Assured ID Root CA O=DigiCert Inc OU=www.digicert.com
+# Subject: CN=DigiCert Assured ID Root CA O=DigiCert Inc OU=www.digicert.com
+# Label: "DigiCert Assured ID Root CA"
+# Serial: 17154717934120587862167794914071425081
+# MD5 Fingerprint: 87:ce:0b:7b:2a:0e:49:00:e1:58:71:9b:37:a8:93:72
+# SHA1 Fingerprint: 05:63:b8:63:0d:62:d7:5a:bb:c8:ab:1e:4b:df:b5:a8:99:b2:4d:43
+# SHA256 Fingerprint: 3e:90:99:b5:01:5e:8f:48:6c:00:bc:ea:9d:11:1e:e7:21:fa:ba:35:5a:89:bc:f1:df:69:56:1e:3d:c6:32:5c
+-----BEGIN CERTIFICATE-----
+MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBl
+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
+d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv
+b3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzExMTEwMDAwMDAwWjBlMQswCQYDVQQG
+EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl
+cnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwggEi
+MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7c
+JpSIqvTO9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYP
+mDI2dsze3Tyoou9q+yHyUmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+
+wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW/lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4
+VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpyoeb6pNnVFzF1roV9Iq4/
+AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whfGHdPAgMB
+AAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW
+BBRF66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYun
+pyGd823IDzANBgkqhkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRC
+dWKuh+vy1dneVrOfzM4UKLkNl2BcEkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTf
+fwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38FnSbNd67IJKusm7Xi+fT8r87cm
+NW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i8b5QZ7dsvfPx
+H2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe
++o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g==
+-----END CERTIFICATE-----
+
+# Issuer: CN=DigiCert Global Root CA O=DigiCert Inc OU=www.digicert.com
+# Subject: CN=DigiCert Global Root CA O=DigiCert Inc OU=www.digicert.com
+# Label: "DigiCert Global Root CA"
+# Serial: 10944719598952040374951832963794454346
+# MD5 Fingerprint: 79:e4:a9:84:0d:7d:3a:96:d7:c0:4f:e2:43:4c:89:2e
+# SHA1 Fingerprint: a8:98:5d:3a:65:e5:e5:c4:b2:d7:d6:6d:40:c6:dd:2f:b1:9c:54:36
+# SHA256 Fingerprint: 43:48:a0:e9:44:4c:78:cb:26:5e:05:8d:5e:89:44:b4:d8:4f:96:62:bd:26:db:25:7f:89:34:a4:43:c7:01:61
+-----BEGIN CERTIFICATE-----
+MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh
+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
+d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD
+QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT
+MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
+b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG
+9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB
+CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97
+nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt
+43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P
+T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4
+gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO
+BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR
+TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw
+DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr
+hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg
+06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF
+PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls
+YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk
+CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=
+-----END CERTIFICATE-----
+
+# Issuer: CN=DigiCert High Assurance EV Root CA O=DigiCert Inc OU=www.digicert.com
+# Subject: CN=DigiCert High Assurance EV Root CA O=DigiCert Inc OU=www.digicert.com
+# Label: "DigiCert High Assurance EV Root CA"
+# Serial: 3553400076410547919724730734378100087
+# MD5 Fingerprint: d4:74:de:57:5c:39:b2:d3:9c:85:83:c5:c0:65:49:8a
+# SHA1 Fingerprint: 5f:b7:ee:06:33:e2:59:db:ad:0c:4c:9a:e6:d3:8f:1a:61:c7:dc:25
+# SHA256 Fingerprint: 74:31:e5:f4:c3:c1:ce:46:90:77:4f:0b:61:e0:54:40:88:3b:a9:a0:1e:d0:0b:a6:ab:d7:80:6e:d3:b1:18:cf
+-----BEGIN CERTIFICATE-----
+MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs
+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
+d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j
+ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL
+MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3
+LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug
+RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm
++9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW
+PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM
+xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB
+Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3
+hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg
+EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF
+MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA
+FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec
+nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z
+eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF
+hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2
+Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe
+vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep
++OkuE6N36B9K
+-----END CERTIFICATE-----
+
+# Issuer: CN=GeoTrust Primary Certification Authority O=GeoTrust Inc.
+# Subject: CN=GeoTrust Primary Certification Authority O=GeoTrust Inc.
+# Label: "GeoTrust Primary Certification Authority"
+# Serial: 32798226551256963324313806436981982369
+# MD5 Fingerprint: 02:26:c3:01:5e:08:30:37:43:a9:d0:7d:cf:37:e6:bf
+# SHA1 Fingerprint: 32:3c:11:8e:1b:f7:b8:b6:52:54:e2:e2:10:0d:d6:02:90:37:f0:96
+# SHA256 Fingerprint: 37:d5:10:06:c5:12:ea:ab:62:64:21:f1:ec:8c:92:01:3f:c5:f8:2a:e9:8e:e5:33:eb:46:19:b8:de:b4:d0:6c
+-----BEGIN CERTIFICATE-----
+MIIDfDCCAmSgAwIBAgIQGKy1av1pthU6Y2yv2vrEoTANBgkqhkiG9w0BAQUFADBY
+MQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjExMC8GA1UEAxMo
+R2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEx
+MjcwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMFgxCzAJBgNVBAYTAlVTMRYwFAYDVQQK
+Ew1HZW9UcnVzdCBJbmMuMTEwLwYDVQQDEyhHZW9UcnVzdCBQcmltYXJ5IENlcnRp
+ZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
+AQEAvrgVe//UfH1nrYNke8hCUy3f9oQIIGHWAVlqnEQRr+92/ZV+zmEwu3qDXwK9
+AWbK7hWNb6EwnL2hhZ6UOvNWiAAxz9juapYC2e0DjPt1befquFUWBRaa9OBesYjA
+ZIVcFU2Ix7e64HXprQU9nceJSOC7KMgD4TCTZF5SwFlwIjVXiIrxlQqD17wxcwE0
+7e9GceBrAqg1cmuXm2bgyxx5X9gaBGgeRwLmnWDiNpcB3841kt++Z8dtd1k7j53W
+kBWUvEI0EME5+bEnPn7WinXFsq+W06Lem+SYvn3h6YGttm/81w7a4DSwDRp35+MI
+mO9Y+pyEtzavwt+s0vQQBnBxNQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4G
+A1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQULNVQQZcVi/CPNmFbSvtr2ZnJM5IwDQYJ
+KoZIhvcNAQEFBQADggEBAFpwfyzdtzRP9YZRqSa+S7iq8XEN3GHHoOo0Hnp3DwQ1
+6CePbJC/kRYkRj5KTs4rFtULUh38H2eiAkUxT87z+gOneZ1TatnaYzr4gNfTmeGl
+4b7UVXGYNTq+k+qurUKykG/g/CFNNWMziUnWm07Kx+dOCQD32sfvmWKZd7aVIl6K
+oKv0uHiYyjgZmclynnjNS6yvGaBzEi38wkG6gZHaFloxt/m0cYASSJlyc1pZU8Fj
+UjPtp8nSOQJw+uCxQmYpqptR7TBUIhRf2asdweSU8Pj1K/fqynhG1riR/aYNKxoU
+AT6A8EKglQdebc3MS6RFjasS6LPeWuWgfOgPIh1a6Vk=
+-----END CERTIFICATE-----
+
+# Issuer: CN=thawte Primary Root CA O=thawte, Inc. OU=Certification Services Division/(c) 2006 thawte, Inc. - For authorized use only
+# Subject: CN=thawte Primary Root CA O=thawte, Inc. OU=Certification Services Division/(c) 2006 thawte, Inc. - For authorized use only
+# Label: "thawte Primary Root CA"
+# Serial: 69529181992039203566298953787712940909
+# MD5 Fingerprint: 8c:ca:dc:0b:22:ce:f5:be:72:ac:41:1a:11:a8:d8:12
+# SHA1 Fingerprint: 91:c6:d6:ee:3e:8a:c8:63:84:e5:48:c2:99:29:5c:75:6c:81:7b:81
+# SHA256 Fingerprint: 8d:72:2f:81:a9:c1:13:c0:79:1d:f1:36:a2:96:6d:b2:6c:95:0a:97:1d:b4:6b:41:99:f4:ea:54:b7:8b:fb:9f
+-----BEGIN CERTIFICATE-----
+MIIEIDCCAwigAwIBAgIQNE7VVyDV7exJ9C/ON9srbTANBgkqhkiG9w0BAQUFADCB
+qTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMf
+Q2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIw
+MDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxHzAdBgNV
+BAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwHhcNMDYxMTE3MDAwMDAwWhcNMzYw
+NzE2MjM1OTU5WjCBqTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5j
+LjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYG
+A1UECxMvKGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl
+IG9ubHkxHzAdBgNVBAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwggEiMA0GCSqG
+SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCsoPD7gFnUnMekz52hWXMJEEUMDSxuaPFs
+W0hoSVk3/AszGcJ3f8wQLZU0HObrTQmnHNK4yZc2AreJ1CRfBsDMRJSUjQJib+ta
+3RGNKJpchJAQeg29dGYvajig4tVUROsdB58Hum/u6f1OCyn1PoSgAfGcq/gcfomk
+6KHYcWUNo1F77rzSImANuVud37r8UVsLr5iy6S7pBOhih94ryNdOwUxkHt3Ph1i6
+Sk/KaAcdHJ1KxtUvkcx8cXIcxcBn6zL9yZJclNqFwJu/U30rCfSMnZEfl2pSy94J
+NqR32HuHUETVPm4pafs5SSYeCaWAe0At6+gnhcn+Yf1+5nyXHdWdAgMBAAGjQjBA
+MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBR7W0XP
+r87Lev0xkhpqtvNG61dIUDANBgkqhkiG9w0BAQUFAAOCAQEAeRHAS7ORtvzw6WfU
+DW5FvlXok9LOAz/t2iWwHVfLHjp2oEzsUHboZHIMpKnxuIvW1oeEuzLlQRHAd9mz
+YJ3rG9XRbkREqaYB7FViHXe4XI5ISXycO1cRrK1zN44veFyQaEfZYGDm/Ac9IiAX
+xPcW6cTYcvnIc3zfFi8VqT79aie2oetaupgf1eNNZAqdE8hhuvU5HIe6uL17In/2
+/qxAeeWsEG89jxt5dovEN7MhGITlNgDrYyCZuen+MwS7QcjBAvlEYyCegc5C09Y/
+LHbTY5xZ3Y+m4Q6gLkH3LpVHz7z9M/P2C2F+fpErgUfCJzDupxBdN49cOSvkBPB7
+jVaMaA==
+-----END CERTIFICATE-----
+
+# Issuer: CN=VeriSign Class 3 Public Primary Certification Authority - G5 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2006 VeriSign, Inc. - For authorized use only
+# Subject: CN=VeriSign Class 3 Public Primary Certification Authority - G5 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2006 VeriSign, Inc. - For authorized use only
+# Label: "VeriSign Class 3 Public Primary Certification Authority - G5"
+# Serial: 33037644167568058970164719475676101450
+# MD5 Fingerprint: cb:17:e4:31:67:3e:e2:09:fe:45:57:93:f3:0a:fa:1c
+# SHA1 Fingerprint: 4e:b6:d5:78:49:9b:1c:cf:5f:58:1e:ad:56:be:3d:9b:67:44:a5:e5
+# SHA256 Fingerprint: 9a:cf:ab:7e:43:c8:d8:80:d0:6b:26:2a:94:de:ee:e4:b4:65:99:89:c3:d0:ca:f1:9b:af:64:05:e4:1a:b7:df
+-----BEGIN CERTIFICATE-----
+MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCB
+yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL
+ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJp
+U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxW
+ZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0
+aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCByjEL
+MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW
+ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2ln
+biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJp
+U2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9y
+aXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvJAgIKXo1
+nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKzj/i5Vbex
+t0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIz
+SdhDY2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQG
+BO+QueQA5N06tRn/Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+
+rCpSx4/VBEnkjWNHiDxpg8v+R70rfk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/
+NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8E
+BAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEwHzAH
+BgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy
+aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKv
+MzEzMA0GCSqGSIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzE
+p6B4Eq1iDkVwZMXnl2YtmAl+X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y
+5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKEKQsTb47bDN0lAtukixlE0kF6BWlK
+WE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiCKm0oHw0LxOXnGiYZ
+4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vEZV8N
+hnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq
+-----END CERTIFICATE-----
+
+# Issuer: CN=COMODO Certification Authority O=COMODO CA Limited
+# Subject: CN=COMODO Certification Authority O=COMODO CA Limited
+# Label: "COMODO Certification Authority"
+# Serial: 104350513648249232941998508985834464573
+# MD5 Fingerprint: 5c:48:dc:f7:42:72:ec:56:94:6d:1c:cc:71:35:80:75
+# SHA1 Fingerprint: 66:31:bf:9e:f7:4f:9e:b6:c9:d5:a6:0c:ba:6a:be:d1:f7:bd:ef:7b
+# SHA256 Fingerprint: 0c:2c:d6:3d:f7:80:6f:a3:99:ed:e8:09:11:6b:57:5b:f8:79:89:f0:65:18:f9:80:8c:86:05:03:17:8b:af:66
+-----BEGIN CERTIFICATE-----
+MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCB
+gTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
+A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNV
+BAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEyMDEwMDAw
+MDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3Jl
+YXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01P
+RE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0
+aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3
+UcEbVASY06m/weaKXTuH+7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI
+2GqGd0S7WWaXUF601CxwRM/aN5VCaTwwxHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8
+Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV4EajcNxo2f8ESIl33rXp
++2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA1KGzqSX+
+DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5O
+nKVIrLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW
+/zAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6g
+PKA6hjhodHRwOi8vY3JsLmNvbW9kb2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9u
+QXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOCAQEAPpiem/Yb6dc5t3iuHXIY
+SdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CPOGEIqB6BCsAv
+IC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/
+RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4
+zJVSk/BwJVmcIGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5dd
+BA6+C4OmF4O5MBKgxTMVBbkN+8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IB
+ZQ==
+-----END CERTIFICATE-----
+
+# Issuer: CN=Network Solutions Certificate Authority O=Network Solutions L.L.C.
+# Subject: CN=Network Solutions Certificate Authority O=Network Solutions L.L.C.
+# Label: "Network Solutions Certificate Authority"
+# Serial: 116697915152937497490437556386812487904
+# MD5 Fingerprint: d3:f3:a6:16:c0:fa:6b:1d:59:b1:2d:96:4d:0e:11:2e
+# SHA1 Fingerprint: 74:f8:a3:c3:ef:e7:b3:90:06:4b:83:90:3c:21:64:60:20:e5:df:ce
+# SHA256 Fingerprint: 15:f0:ba:00:a3:ac:7a:f3:ac:88:4c:07:2b:10:11:a0:77:bd:77:c0:97:f4:01:64:b2:f8:59:8a:bd:83:86:0c
+-----BEGIN CERTIFICATE-----
+MIID5jCCAs6gAwIBAgIQV8szb8JcFuZHFhfjkDFo4DANBgkqhkiG9w0BAQUFADBi
+MQswCQYDVQQGEwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMu
+MTAwLgYDVQQDEydOZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3Jp
+dHkwHhcNMDYxMjAxMDAwMDAwWhcNMjkxMjMxMjM1OTU5WjBiMQswCQYDVQQGEwJV
+UzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMuMTAwLgYDVQQDEydO
+ZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0GCSqG
+SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDkvH6SMG3G2I4rC7xGzuAnlt7e+foS0zwz
+c7MEL7xxjOWftiJgPl9dzgn/ggwbmlFQGiaJ3dVhXRncEg8tCqJDXRfQNJIg6nPP
+OCwGJgl6cvf6UDL4wpPTaaIjzkGxzOTVHzbRijr4jGPiFFlp7Q3Tf2vouAPlT2rl
+mGNpSAW+Lv8ztumXWWn4Zxmuk2GWRBXTcrA/vGp97Eh/jcOrqnErU2lBUzS1sLnF
+BgrEsEX1QV1uiUV7PTsmjHTC5dLRfbIR1PtYMiKagMnc/Qzpf14Dl847ABSHJ3A4
+qY5usyd2mFHgBeMhqxrVhSI8KbWaFsWAqPS7azCPL0YCorEMIuDTAgMBAAGjgZcw
+gZQwHQYDVR0OBBYEFCEwyfsA106Y2oeqKtCnLrFAMadMMA4GA1UdDwEB/wQEAwIB
+BjAPBgNVHRMBAf8EBTADAQH/MFIGA1UdHwRLMEkwR6BFoEOGQWh0dHA6Ly9jcmwu
+bmV0c29sc3NsLmNvbS9OZXR3b3JrU29sdXRpb25zQ2VydGlmaWNhdGVBdXRob3Jp
+dHkuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQC7rkvnt1frf6ott3NHhWrB5KUd5Oc8
+6fRZZXe1eltajSU24HqXLjjAV2CDmAaDn7l2em5Q4LqILPxFzBiwmZVRDuwduIj/
+h1AcgsLj4DKAv6ALR8jDMe+ZZzKATxcheQxpXN5eNK4CtSbqUN9/GGUsyfJj4akH
+/nxxH2szJGoeBfcFaMBqEssuXmHLrijTfsK0ZpEmXzwuJF/LWA/rKOyvEZbz3Htv
+wKeI8lN3s2Berq4o2jUsbzRF0ybh3uxbTydrFny9RAQYgrOJeRcQcT16ohZO9QHN
+pGxlaKFJdlxDydi8NmdspZS11My5vWo1ViHe2MPr+8ukYEywVaCge1ey
+-----END CERTIFICATE-----
+
+# Issuer: CN=COMODO ECC Certification Authority O=COMODO CA Limited
+# Subject: CN=COMODO ECC Certification Authority O=COMODO CA Limited
+# Label: "COMODO ECC Certification Authority"
+# Serial: 41578283867086692638256921589707938090
+# MD5 Fingerprint: 7c:62:ff:74:9d:31:53:5e:68:4a:d5:78:aa:1e:bf:23
+# SHA1 Fingerprint: 9f:74:4e:9f:2b:4d:ba:ec:0f:31:2c:50:b6:56:3b:8e:2d:93:c3:11
+# SHA256 Fingerprint: 17:93:92:7a:06:14:54:97:89:ad:ce:2f:8f:34:f7:f0:b6:6d:0f:3a:e3:a3:b8:4d:21:ec:15:db:ba:4f:ad:c7
+-----BEGIN CERTIFICATE-----
+MIICiTCCAg+gAwIBAgIQH0evqmIAcFBUTAGem2OZKjAKBggqhkjOPQQDAzCBhTEL
+MAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE
+BxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMT
+IkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDgwMzA2MDAw
+MDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdy
+ZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09N
+T0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlv
+biBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQDR3svdcmCFYX7deSR
+FtSrYpn1PlILBs5BAH+X4QokPB0BBO490o0JlwzgdeT6+3eKKvUDYEs2ixYjFq0J
+cfRK9ChQtP6IHG4/bC8vCVlbpVsLM5niwz2J+Wos77LTBumjQjBAMB0GA1UdDgQW
+BBR1cacZSBm8nZ3qQUfflMRId5nTeTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/
+BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA7wNbeqy3eApyt4jf/7VGFAkK+qDm
+fQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdv
+GDeAU/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY=
+-----END CERTIFICATE-----
+
+# Issuer: CN=TC TrustCenter Class 2 CA II O=TC TrustCenter GmbH OU=TC TrustCenter Class 2 CA
+# Subject: CN=TC TrustCenter Class 2 CA II O=TC TrustCenter GmbH OU=TC TrustCenter Class 2 CA
+# Label: "TC TrustCenter Class 2 CA II"
+# Serial: 941389028203453866782103406992443
+# MD5 Fingerprint: ce:78:33:5c:59:78:01:6e:18:ea:b9:36:a0:b9:2e:23
+# SHA1 Fingerprint: ae:50:83:ed:7c:f4:5c:bc:8f:61:c6:21:fe:68:5d:79:42:21:15:6e
+# SHA256 Fingerprint: e6:b8:f8:76:64:85:f8:07:ae:7f:8d:ac:16:70:46:1f:07:c0:a1:3e:ef:3a:1f:f7:17:53:8d:7a:ba:d3:91:b4
+-----BEGIN CERTIFICATE-----
+MIIEqjCCA5KgAwIBAgIOLmoAAQACH9dSISwRXDswDQYJKoZIhvcNAQEFBQAwdjEL
+MAkGA1UEBhMCREUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxIjAgBgNV
+BAsTGVRDIFRydXN0Q2VudGVyIENsYXNzIDIgQ0ExJTAjBgNVBAMTHFRDIFRydXN0
+Q2VudGVyIENsYXNzIDIgQ0EgSUkwHhcNMDYwMTEyMTQzODQzWhcNMjUxMjMxMjI1
+OTU5WjB2MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMgVHJ1c3RDZW50ZXIgR21i
+SDEiMCAGA1UECxMZVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMiBDQTElMCMGA1UEAxMc
+VEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMiBDQSBJSTCCASIwDQYJKoZIhvcNAQEBBQAD
+ggEPADCCAQoCggEBAKuAh5uO8MN8h9foJIIRszzdQ2Lu+MNF2ujhoF/RKrLqk2jf
+tMjWQ+nEdVl//OEd+DFwIxuInie5e/060smp6RQvkL4DUsFJzfb95AhmC1eKokKg
+uNV/aVyQMrKXDcpK3EY+AlWJU+MaWss2xgdW94zPEfRMuzBwBJWl9jmM/XOBCH2J
+XjIeIqkiRUuwZi4wzJ9l/fzLganx4Duvo4bRierERXlQXa7pIXSSTYtZgo+U4+lK
+8edJsBTj9WLL1XK9H7nSn6DNqPoByNkN39r8R52zyFTfSUrxIan+GE7uSNQZu+99
+5OKdy1u2bv/jzVrndIIFuoAlOMvkaZ6vQaoahPUCAwEAAaOCATQwggEwMA8GA1Ud
+EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTjq1RMgKHbVkO3
+kUrL84J6E1wIqzCB7QYDVR0fBIHlMIHiMIHfoIHcoIHZhjVodHRwOi8vd3d3LnRy
+dXN0Y2VudGVyLmRlL2NybC92Mi90Y19jbGFzc18yX2NhX0lJLmNybIaBn2xkYXA6
+Ly93d3cudHJ1c3RjZW50ZXIuZGUvQ049VEMlMjBUcnVzdENlbnRlciUyMENsYXNz
+JTIwMiUyMENBJTIwSUksTz1UQyUyMFRydXN0Q2VudGVyJTIwR21iSCxPVT1yb290
+Y2VydHMsREM9dHJ1c3RjZW50ZXIsREM9ZGU/Y2VydGlmaWNhdGVSZXZvY2F0aW9u
+TGlzdD9iYXNlPzANBgkqhkiG9w0BAQUFAAOCAQEAjNfffu4bgBCzg/XbEeprS6iS
+GNn3Bzn1LL4GdXpoUxUc6krtXvwjshOg0wn/9vYua0Fxec3ibf2uWWuFHbhOIprt
+ZjluS5TmVfwLG4t3wVMTZonZKNaL80VKY7f9ewthXbhtvsPcW3nS7Yblok2+XnR8
+au0WOB9/WIFaGusyiC2y8zl3gK9etmF1KdsjTYjKUCjLhdLTEKJZbtOTVAB6okaV
+hgWcqRmY5TFyDADiZ9lA4CQze28suVyrZZ0srHbqNZn1l7kPJOzHdiEoZa5X6AeI
+dUpWoNIFOqTmjZKILPPy4cHGYdtBxceb9w4aUUXCYWvcZCcXjFq32nQozZfkvQ==
+-----END CERTIFICATE-----
+
+# Issuer: CN=TC TrustCenter Class 3 CA II O=TC TrustCenter GmbH OU=TC TrustCenter Class 3 CA
+# Subject: CN=TC TrustCenter Class 3 CA II O=TC TrustCenter GmbH OU=TC TrustCenter Class 3 CA
+# Label: "TC TrustCenter Class 3 CA II"
+# Serial: 1506523511417715638772220530020799
+# MD5 Fingerprint: 56:5f:aa:80:61:12:17:f6:67:21:e6:2b:6d:61:56:8e
+# SHA1 Fingerprint: 80:25:ef:f4:6e:70:c8:d4:72:24:65:84:fe:40:3b:8a:8d:6a:db:f5
+# SHA256 Fingerprint: 8d:a0:84:fc:f9:9c:e0:77:22:f8:9b:32:05:93:98:06:fa:5c:b8:11:e1:c8:13:f6:a1:08:c7:d3:36:b3:40:8e
+-----BEGIN CERTIFICATE-----
+MIIEqjCCA5KgAwIBAgIOSkcAAQAC5aBd1j8AUb8wDQYJKoZIhvcNAQEFBQAwdjEL
+MAkGA1UEBhMCREUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxIjAgBgNV
+BAsTGVRDIFRydXN0Q2VudGVyIENsYXNzIDMgQ0ExJTAjBgNVBAMTHFRDIFRydXN0
+Q2VudGVyIENsYXNzIDMgQ0EgSUkwHhcNMDYwMTEyMTQ0MTU3WhcNMjUxMjMxMjI1
+OTU5WjB2MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMgVHJ1c3RDZW50ZXIgR21i
+SDEiMCAGA1UECxMZVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMyBDQTElMCMGA1UEAxMc
+VEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMyBDQSBJSTCCASIwDQYJKoZIhvcNAQEBBQAD
+ggEPADCCAQoCggEBALTgu1G7OVyLBMVMeRwjhjEQY0NVJz/GRcekPewJDRoeIMJW
+Ht4bNwcwIi9v8Qbxq63WyKthoy9DxLCyLfzDlml7forkzMA5EpBCYMnMNWju2l+Q
+Vl/NHE1bWEnrDgFPZPosPIlY2C8u4rBo6SI7dYnWRBpl8huXJh0obazovVkdKyT2
+1oQDZogkAHhg8fir/gKya/si+zXmFtGt9i4S5Po1auUZuV3bOx4a+9P/FRQI2Alq
+ukWdFHlgfa9Aigdzs5OW03Q0jTo3Kd5c7PXuLjHCINy+8U9/I1LZW+Jk2ZyqBwi1
+Rb3R0DHBq1SfqdLDYmAD8bs5SpJKPQq5ncWg/jcCAwEAAaOCATQwggEwMA8GA1Ud
+EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTUovyfs8PYA9NX
+XAek0CSnwPIA1DCB7QYDVR0fBIHlMIHiMIHfoIHcoIHZhjVodHRwOi8vd3d3LnRy
+dXN0Y2VudGVyLmRlL2NybC92Mi90Y19jbGFzc18zX2NhX0lJLmNybIaBn2xkYXA6
+Ly93d3cudHJ1c3RjZW50ZXIuZGUvQ049VEMlMjBUcnVzdENlbnRlciUyMENsYXNz
+JTIwMyUyMENBJTIwSUksTz1UQyUyMFRydXN0Q2VudGVyJTIwR21iSCxPVT1yb290
+Y2VydHMsREM9dHJ1c3RjZW50ZXIsREM9ZGU/Y2VydGlmaWNhdGVSZXZvY2F0aW9u
+TGlzdD9iYXNlPzANBgkqhkiG9w0BAQUFAAOCAQEANmDkcPcGIEPZIxpC8vijsrlN
+irTzwppVMXzEO2eatN9NDoqTSheLG43KieHPOh6sHfGcMrSOWXaiQYUlN6AT0PV8
+TtXqluJucsG7Kv5sbviRmEb8yRtXW+rIGjs/sFGYPAfaLFkB2otE6OF0/ado3VS6
+g0bsyEa1+K+XwDsJHI/OcpY9M1ZwvJbL2NV9IJqDnxrcOfHFcqMRA/07QlIp2+gB
+95tejNaNhk4Z+rwcvsUhpYeeeC422wlxo3I0+GzjBgnyXlal092Y+tTmBvTwtiBj
+S+opvaqCZh77gaqnN60TGOaSw4HBM7uIHqHn4rS9MWwOUT1v+5ZWgOI2F9Hc5A==
+-----END CERTIFICATE-----
+
+# Issuer: CN=TC TrustCenter Universal CA I O=TC TrustCenter GmbH OU=TC TrustCenter Universal CA
+# Subject: CN=TC TrustCenter Universal CA I O=TC TrustCenter GmbH OU=TC TrustCenter Universal CA
+# Label: "TC TrustCenter Universal CA I"
+# Serial: 601024842042189035295619584734726
+# MD5 Fingerprint: 45:e1:a5:72:c5:a9:36:64:40:9e:f5:e4:58:84:67:8c
+# SHA1 Fingerprint: 6b:2f:34:ad:89:58:be:62:fd:b0:6b:5c:ce:bb:9d:d9:4f:4e:39:f3
+# SHA256 Fingerprint: eb:f3:c0:2a:87:89:b1:fb:7d:51:19:95:d6:63:b7:29:06:d9:13:ce:0d:5e:10:56:8a:8a:77:e2:58:61:67:e7
+-----BEGIN CERTIFICATE-----
+MIID3TCCAsWgAwIBAgIOHaIAAQAC7LdggHiNtgYwDQYJKoZIhvcNAQEFBQAweTEL
+MAkGA1UEBhMCREUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxJDAiBgNV
+BAsTG1RDIFRydXN0Q2VudGVyIFVuaXZlcnNhbCBDQTEmMCQGA1UEAxMdVEMgVHJ1
+c3RDZW50ZXIgVW5pdmVyc2FsIENBIEkwHhcNMDYwMzIyMTU1NDI4WhcNMjUxMjMx
+MjI1OTU5WjB5MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMgVHJ1c3RDZW50ZXIg
+R21iSDEkMCIGA1UECxMbVEMgVHJ1c3RDZW50ZXIgVW5pdmVyc2FsIENBMSYwJAYD
+VQQDEx1UQyBUcnVzdENlbnRlciBVbml2ZXJzYWwgQ0EgSTCCASIwDQYJKoZIhvcN
+AQEBBQADggEPADCCAQoCggEBAKR3I5ZEr5D0MacQ9CaHnPM42Q9e3s9B6DGtxnSR
+JJZ4Hgmgm5qVSkr1YnwCqMqs+1oEdjneX/H5s7/zA1hV0qq34wQi0fiU2iIIAI3T
+fCZdzHd55yx4Oagmcw6iXSVphU9VDprvxrlE4Vc93x9UIuVvZaozhDrzznq+VZeu
+jRIPFDPiUHDDSYcTvFHe15gSWu86gzOSBnWLknwSaHtwag+1m7Z3W0hZneTvWq3z
+wZ7U10VOylY0Ibw+F1tvdwxIAUMpsN0/lm7mlaoMwCC2/T42J5zjXM9OgdwZu5GQ
+fezmlwQek8wiSdeXhrYTCjxDI3d+8NzmzSQfO4ObNDqDNOMCAwEAAaNjMGEwHwYD
+VR0jBBgwFoAUkqR1LKSevoFE63n8isWVpesQdXMwDwYDVR0TAQH/BAUwAwEB/zAO
+BgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFJKkdSyknr6BROt5/IrFlaXrEHVzMA0G
+CSqGSIb3DQEBBQUAA4IBAQAo0uCG1eb4e/CX3CJrO5UUVg8RMKWaTzqwOuAGy2X1
+7caXJ/4l8lfmXpWMPmRgFVp/Lw0BxbFg/UU1z/CyvwbZ71q+s2IhtNerNXxTPqYn
+8aEt2hojnczd7Dwtnic0XQ/CNnm8yUpiLe1r2X1BQ3y2qsrtYbE3ghUJGooWMNjs
+ydZHcnhLEEYUjl8Or+zHL6sQ17bxbuyGssLoDZJz3KL0Dzq/YSMQiZxIQG5wALPT
+ujdEWBF6AmqI8Dc08BnprNRlc/ZpjGSUOnmFKbAWKwyCPwacx/0QK54PLLae4xW/
+2TYcuiUaUj0a7CIMHOCkoj3w6DnPgcB77V0fb8XQC9eY
+-----END CERTIFICATE-----
+
+# Issuer: CN=Cybertrust Global Root O=Cybertrust, Inc
+# Subject: CN=Cybertrust Global Root O=Cybertrust, Inc
+# Label: "Cybertrust Global Root"
+# Serial: 4835703278459682877484360
+# MD5 Fingerprint: 72:e4:4a:87:e3:69:40:80:77:ea:bc:e3:f4:ff:f0:e1
+# SHA1 Fingerprint: 5f:43:e5:b1:bf:f8:78:8c:ac:1c:c7:ca:4a:9a:c6:22:2b:cc:34:c6
+# SHA256 Fingerprint: 96:0a:df:00:63:e9:63:56:75:0c:29:65:dd:0a:08:67:da:0b:9c:bd:6e:77:71:4a:ea:fb:23:49:ab:39:3d:a3
+-----BEGIN CERTIFICATE-----
+MIIDoTCCAomgAwIBAgILBAAAAAABD4WqLUgwDQYJKoZIhvcNAQEFBQAwOzEYMBYG
+A1UEChMPQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2Jh
+bCBSb290MB4XDTA2MTIxNTA4MDAwMFoXDTIxMTIxNTA4MDAwMFowOzEYMBYGA1UE
+ChMPQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2JhbCBS
+b290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA+Mi8vRRQZhP/8NN5
+7CPytxrHjoXxEnOmGaoQ25yiZXRadz5RfVb23CO21O1fWLE3TdVJDm71aofW0ozS
+J8bi/zafmGWgE07GKmSb1ZASzxQG9Dvj1Ci+6A74q05IlG2OlTEQXO2iLb3VOm2y
+HLtgwEZLAfVJrn5GitB0jaEMAs7u/OePuGtm839EAL9mJRQr3RAwHQeWP032a7iP
+t3sMpTjr3kfb1V05/Iin89cqdPHoWqI7n1C6poxFNcJQZZXcY4Lv3b93TZxiyWNz
+FtApD0mpSPCzqrdsxacwOUBdrsTiXSZT8M4cIwhhqJQZugRiQOwfOHB3EgZxpzAY
+XSUnpQIDAQABo4GlMIGiMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/
+MB0GA1UdDgQWBBS2CHsNesysIEyGVjJez6tuhS1wVzA/BgNVHR8EODA2MDSgMqAw
+hi5odHRwOi8vd3d3Mi5wdWJsaWMtdHJ1c3QuY29tL2NybC9jdC9jdHJvb3QuY3Js
+MB8GA1UdIwQYMBaAFLYIew16zKwgTIZWMl7Pq26FLXBXMA0GCSqGSIb3DQEBBQUA
+A4IBAQBW7wojoFROlZfJ+InaRcHUowAl9B8Tq7ejhVhpwjCt2BWKLePJzYFa+HMj
+Wqd8BfP9IjsO0QbE2zZMcwSO5bAi5MXzLqXZI+O4Tkogp24CJJ8iYGd7ix1yCcUx
+XOl5n4BHPa2hCwcUPUf/A2kaDAtE52Mlp3+yybh2hO0j9n0Hq0V+09+zv+mKts2o
+omcrUtW3ZfA5TGOgkXmTUg9U3YO7n9GPp1Nzw8v/MOx8BLjYRB+TX3EJIrduPuoc
+A06dGiBh+4E37F78CkWr1+cXVdCg6mCbpvbjjFspwgZgFJ0tl0ypkxWdYcQBX0jW
+WL1WMRJOEcgh4LMRkWXbtKaIOM5V
+-----END CERTIFICATE-----
+
+# Issuer: CN=GeoTrust Primary Certification Authority - G3 O=GeoTrust Inc. OU=(c) 2008 GeoTrust Inc. - For authorized use only
+# Subject: CN=GeoTrust Primary Certification Authority - G3 O=GeoTrust Inc. OU=(c) 2008 GeoTrust Inc. - For authorized use only
+# Label: "GeoTrust Primary Certification Authority - G3"
+# Serial: 28809105769928564313984085209975885599
+# MD5 Fingerprint: b5:e8:34:36:c9:10:44:58:48:70:6d:2e:83:d4:b8:05
+# SHA1 Fingerprint: 03:9e:ed:b8:0b:e7:a0:3c:69:53:89:3b:20:d2:d9:32:3a:4c:2a:fd
+# SHA256 Fingerprint: b4:78:b8:12:25:0d:f8:78:63:5c:2a:a7:ec:7d:15:5e:aa:62:5e:e8:29:16:e2:cd:29:43:61:88:6c:d1:fb:d4
+-----BEGIN CERTIFICATE-----
+MIID/jCCAuagAwIBAgIQFaxulBmyeUtB9iepwxgPHzANBgkqhkiG9w0BAQsFADCB
+mDELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsT
+MChjKSAyMDA4IEdlb1RydXN0IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25s
+eTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhv
+cml0eSAtIEczMB4XDTA4MDQwMjAwMDAwMFoXDTM3MTIwMTIzNTk1OVowgZgxCzAJ
+BgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAoYykg
+MjAwOCBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0
+BgNVBAMTLUdlb1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg
+LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANziXmJYHTNXOTIz
++uvLh4yn1ErdBojqZI4xmKU4kB6Yzy5jK/BGvESyiaHAKAxJcCGVn2TAppMSAmUm
+hsalifD614SgcK9PGpc/BkTVyetyEH3kMSj7HGHmKAdEc5IiaacDiGydY8hS2pgn
+5whMcD60yRLBxWeDXTPzAxHsatBT4tG6NmCUgLthY2xbF37fQJQeqw3CIShwiP/W
+JmxsYAQlTlV+fe+/lEjetx3dcI0FX4ilm/LC7urRQEFtYjgdVgbFA0dRIBn8exAL
+DmKudlW/X3e+PkkBUz2YJQN2JFodtNuJ6nnltrM7P7pMKEF/BqxqjsHQ9gUdfeZC
+huOl1UcCAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYw
+HQYDVR0OBBYEFMR5yo6hTgMdHNxr2zFblD4/MH8tMA0GCSqGSIb3DQEBCwUAA4IB
+AQAtxRPPVoB7eni9n64smefv2t+UXglpp+duaIy9cr5HqQ6XErhK8WTTOd8lNNTB
+zU6B8A8ExCSzNJbGpqow32hhc9f5joWJ7w5elShKKiePEI4ufIbEAp7aDHdlDkQN
+kv39sxY2+hENHYwOB4lqKVb3cvTdFZx3NWZXqxNT2I7BQMXXExZacse3aQHEerGD
+AWh9jUGhlBjBJVz88P6DAod8DQ3PLghcSkANPuyBYeYk28rgDi0Hsj5W3I31QYUH
+SJsMC8tJP33st/3LjWeJGqvtux6jAAgIFyqCXDFdRootD4abdNlF+9RAsXqqaC2G
+spki4cErx5z481+oghLrGREt
+-----END CERTIFICATE-----
+
+# Issuer: CN=thawte Primary Root CA - G2 O=thawte, Inc. OU=(c) 2007 thawte, Inc. - For authorized use only
+# Subject: CN=thawte Primary Root CA - G2 O=thawte, Inc. OU=(c) 2007 thawte, Inc. - For authorized use only
+# Label: "thawte Primary Root CA - G2"
+# Serial: 71758320672825410020661621085256472406
+# MD5 Fingerprint: 74:9d:ea:60:24:c4:fd:22:53:3e:cc:3a:72:d9:29:4f
+# SHA1 Fingerprint: aa:db:bc:22:23:8f:c4:01:a1:27:bb:38:dd:f4:1d:db:08:9e:f0:12
+# SHA256 Fingerprint: a4:31:0d:50:af:18:a6:44:71:90:37:2a:86:af:af:8b:95:1f:fb:43:1d:83:7f:1e:56:88:b4:59:71:ed:15:57
+-----BEGIN CERTIFICATE-----
+MIICiDCCAg2gAwIBAgIQNfwmXNmET8k9Jj1Xm67XVjAKBggqhkjOPQQDAzCBhDEL
+MAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjE4MDYGA1UECxMvKGMp
+IDIwMDcgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAi
+BgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMjAeFw0wNzExMDUwMDAw
+MDBaFw0zODAxMTgyMzU5NTlaMIGEMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhh
+d3RlLCBJbmMuMTgwNgYDVQQLEy8oYykgMjAwNyB0aGF3dGUsIEluYy4gLSBGb3Ig
+YXV0aG9yaXplZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9v
+dCBDQSAtIEcyMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEotWcgnuVnfFSeIf+iha/
+BebfowJPDQfGAFG6DAJSLSKkQjnE/o/qycG+1E3/n3qe4rF8mq2nhglzh9HnmuN6
+papu+7qzcMBniKI11KOasf2twu8x+qi58/sIxpHR+ymVo0IwQDAPBgNVHRMBAf8E
+BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUmtgAMADna3+FGO6Lts6K
+DPgR4bswCgYIKoZIzj0EAwMDaQAwZgIxAN344FdHW6fmCsO99YCKlzUNG4k8VIZ3
+KMqh9HneteY4sPBlcIx/AlTCv//YoT7ZzwIxAMSNlPzcU9LcnXgWHxUzI1NS41ox
+XZ3Krr0TKUQNJ1uo52icEvdYPy5yAlejj6EULg==
+-----END CERTIFICATE-----
+
+# Issuer: CN=thawte Primary Root CA - G3 O=thawte, Inc. OU=Certification Services Division/(c) 2008 thawte, Inc. - For authorized use only
+# Subject: CN=thawte Primary Root CA - G3 O=thawte, Inc. OU=Certification Services Division/(c) 2008 thawte, Inc. - For authorized use only
+# Label: "thawte Primary Root CA - G3"
+# Serial: 127614157056681299805556476275995414779
+# MD5 Fingerprint: fb:1b:5d:43:8a:94:cd:44:c6:76:f2:43:4b:47:e7:31
+# SHA1 Fingerprint: f1:8b:53:8d:1b:e9:03:b6:a6:f0:56:43:5b:17:15:89:ca:f3:6b:f2
+# SHA256 Fingerprint: 4b:03:f4:58:07:ad:70:f2:1b:fc:2c:ae:71:c9:fd:e4:60:4c:06:4c:f5:ff:b6:86:ba:e5:db:aa:d7:fd:d3:4c
+-----BEGIN CERTIFICATE-----
+MIIEKjCCAxKgAwIBAgIQYAGXt0an6rS0mtZLL/eQ+zANBgkqhkiG9w0BAQsFADCB
+rjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMf
+Q2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIw
+MDggdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAiBgNV
+BAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMzAeFw0wODA0MDIwMDAwMDBa
+Fw0zNzEyMDEyMzU5NTlaMIGuMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhhd3Rl
+LCBJbmMuMSgwJgYDVQQLEx9DZXJ0aWZpY2F0aW9uIFNlcnZpY2VzIERpdmlzaW9u
+MTgwNgYDVQQLEy8oYykgMjAwOCB0aGF3dGUsIEluYy4gLSBGb3IgYXV0aG9yaXpl
+ZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAtIEcz
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsr8nLPvb2FvdeHsbnndm
+gcs+vHyu86YnmjSjaDFxODNi5PNxZnmxqWWjpYvVj2AtP0LMqmsywCPLLEHd5N/8
+YZzic7IilRFDGF/Eth9XbAoFWCLINkw6fKXRz4aviKdEAhN0cXMKQlkC+BsUa0Lf
+b1+6a4KinVvnSr0eAXLbS3ToO39/fR8EtCab4LRarEc9VbjXsCZSKAExQGbY2SS9
+9irY7CFJXJv2eul/VTV+lmuNk5Mny5K76qxAwJ/C+IDPXfRa3M50hqY+bAtTyr2S
+zhkGcuYMXDhpxwTWvGzOW/b3aJzcJRVIiKHpqfiYnODz1TEoYRFsZ5aNOZnLwkUk
+OQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNV
+HQ4EFgQUrWyqlGCc7eT/+j4KdCtjA/e2Wb8wDQYJKoZIhvcNAQELBQADggEBABpA
+2JVlrAmSicY59BDlqQ5mU1143vokkbvnRFHfxhY0Cu9qRFHqKweKA3rD6z8KLFIW
+oCtDuSWQP3CpMyVtRRooOyfPqsMpQhvfO0zAMzRbQYi/aytlryjvsvXDqmbOe1bu
+t8jLZ8HJnBoYuMTDSQPxYA5QzUbF83d597YV4Djbxy8ooAw/dyZ02SUS2jHaGh7c
+KUGRIjxpp7sC8rZcJwOJ9Abqm+RyguOhCcHpABnTPtRwa7pxpqpYrvS76Wy274fM
+m7v/OeZWYdMKp8RcTGB7BXcmer/YB1IsYvdwY9k5vG8cwnncdimvzsUsZAReiDZu
+MdRAGmI0Nj81Aa6sY6A=
+-----END CERTIFICATE-----
+
+# Issuer: CN=GeoTrust Primary Certification Authority - G2 O=GeoTrust Inc. OU=(c) 2007 GeoTrust Inc. - For authorized use only
+# Subject: CN=GeoTrust Primary Certification Authority - G2 O=GeoTrust Inc. OU=(c) 2007 GeoTrust Inc. - For authorized use only
+# Label: "GeoTrust Primary Certification Authority - G2"
+# Serial: 80682863203381065782177908751794619243
+# MD5 Fingerprint: 01:5e:d8:6b:bd:6f:3d:8e:a1:31:f8:12:e0:98:73:6a
+# SHA1 Fingerprint: 8d:17:84:d5:37:f3:03:7d:ec:70:fe:57:8b:51:9a:99:e6:10:d7:b0
+# SHA256 Fingerprint: 5e:db:7a:c4:3b:82:a0:6a:87:61:e8:d7:be:49:79:eb:f2:61:1f:7d:d7:9b:f9:1c:1c:6b:56:6a:21:9e:d7:66
+-----BEGIN CERTIFICATE-----
+MIICrjCCAjWgAwIBAgIQPLL0SAoA4v7rJDteYD7DazAKBggqhkjOPQQDAzCBmDEL
+MAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChj
+KSAyMDA3IEdlb1RydXN0IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2
+MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0
+eSAtIEcyMB4XDTA3MTEwNTAwMDAwMFoXDTM4MDExODIzNTk1OVowgZgxCzAJBgNV
+BAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAoYykgMjAw
+NyBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNV
+BAMTLUdlb1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBH
+MjB2MBAGByqGSM49AgEGBSuBBAAiA2IABBWx6P0DFUPlrOuHNxFi79KDNlJ9RVcL
+So17VDs6bl8VAsBQps8lL33KSLjHUGMcKiEIfJo22Av+0SbFWDEwKCXzXV2juLal
+tJLtbCyf691DiaI8S0iRHVDsJt/WYC69IaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAO
+BgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBVfNVdRVfslsq0DafwBo/q+EVXVMAoG
+CCqGSM49BAMDA2cAMGQCMGSWWaboCd6LuvpaiIjwH5HTRqjySkwCY/tsXzjbLkGT
+qQ7mndwxHLKgpxgceeHHNgIwOlavmnRs9vuD4DPTCF+hnMJbn0bWtsuRBmOiBucz
+rD6ogRLQy7rQkgu2npaqBA+K
+-----END CERTIFICATE-----
+
+# Issuer: CN=VeriSign Universal Root Certification Authority O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2008 VeriSign, Inc. - For authorized use only
+# Subject: CN=VeriSign Universal Root Certification Authority O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2008 VeriSign, Inc. - For authorized use only
+# Label: "VeriSign Universal Root Certification Authority"
+# Serial: 85209574734084581917763752644031726877
+# MD5 Fingerprint: 8e:ad:b5:01:aa:4d:81:e4:8c:1d:d1:e1:14:00:95:19
+# SHA1 Fingerprint: 36:79:ca:35:66:87:72:30:4d:30:a5:fb:87:3b:0f:a7:7b:b7:0d:54
+# SHA256 Fingerprint: 23:99:56:11:27:a5:71:25:de:8c:ef:ea:61:0d:df:2f:a0:78:b5:c8:06:7f:4e:82:82:90:bf:b8:60:e8:4b:3c
+-----BEGIN CERTIFICATE-----
+MIIEuTCCA6GgAwIBAgIQQBrEZCGzEyEDDrvkEhrFHTANBgkqhkiG9w0BAQsFADCB
+vTELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL
+ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwOCBWZXJp
+U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MTgwNgYDVQQDEy9W
+ZXJpU2lnbiBVbml2ZXJzYWwgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAe
+Fw0wODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIG9MQswCQYDVQQGEwJVUzEX
+MBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0
+IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9y
+IGF1dGhvcml6ZWQgdXNlIG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNh
+bCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEF
+AAOCAQ8AMIIBCgKCAQEAx2E3XrEBNNti1xWb/1hajCMj1mCOkdeQmIN65lgZOIzF
+9uVkhbSicfvtvbnazU0AtMgtc6XHaXGVHzk8skQHnOgO+k1KxCHfKWGPMiJhgsWH
+H26MfF8WIFFE0XBPV+rjHOPMee5Y2A7Cs0WTwCznmhcrewA3ekEzeOEz4vMQGn+H
+LL729fdC4uW/h2KJXwBL38Xd5HVEMkE6HnFuacsLdUYI0crSK5XQz/u5QGtkjFdN
+/BMReYTtXlT2NJ8IAfMQJQYXStrxHXpma5hgZqTZ79IugvHw7wnqRMkVauIDbjPT
+rJ9VAMf2CGqUuV/c4DPxhGD5WycRtPwW8rtWaoAljQIDAQABo4GyMIGvMA8GA1Ud
+EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMG0GCCsGAQUFBwEMBGEwX6FdoFsw
+WTBXMFUWCWltYWdlL2dpZjAhMB8wBwYFKw4DAhoEFI/l0xqGrI2Oa8PPgGrUSBgs
+exkuMCUWI2h0dHA6Ly9sb2dvLnZlcmlzaWduLmNvbS92c2xvZ28uZ2lmMB0GA1Ud
+DgQWBBS2d/ppSEefUxLVwuoHMnYH0ZcHGTANBgkqhkiG9w0BAQsFAAOCAQEASvj4
+sAPmLGd75JR3Y8xuTPl9Dg3cyLk1uXBPY/ok+myDjEedO2Pzmvl2MpWRsXe8rJq+
+seQxIcaBlVZaDrHC1LGmWazxY8u4TB1ZkErvkBYoH1quEPuBUDgMbMzxPcP1Y+Oz
+4yHJJDnp/RVmRvQbEdBNc6N9Rvk97ahfYtTxP/jgdFcrGJ2BtMQo2pSXpXDrrB2+
+BxHw1dvd5Yzw1TKwg+ZX4o+/vqGqvz0dtdQ46tewXDpPaj+PwGZsY6rp2aQW9IHR
+lRQOfc2VNNnSj3BzgXucfr2YYdhFh5iQxeuGMMY1v/D/w1WIg0vvBZIGcfK4mJO3
+7M2CYfE45k+XmCpajQ==
+-----END CERTIFICATE-----
+
+# Issuer: CN=VeriSign Class 3 Public Primary Certification Authority - G4 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2007 VeriSign, Inc. - For authorized use only
+# Subject: CN=VeriSign Class 3 Public Primary Certification Authority - G4 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2007 VeriSign, Inc. - For authorized use only
+# Label: "VeriSign Class 3 Public Primary Certification Authority - G4"
+# Serial: 63143484348153506665311985501458640051
+# MD5 Fingerprint: 3a:52:e1:e7:fd:6f:3a:e3:6f:f3:6f:99:1b:f9:22:41
+# SHA1 Fingerprint: 22:d5:d8:df:8f:02:31:d1:8d:f7:9d:b7:cf:8a:2d:64:c9:3f:6c:3a
+# SHA256 Fingerprint: 69:dd:d7:ea:90:bb:57:c9:3e:13:5d:c8:5e:a6:fc:d5:48:0b:60:32:39:bd:c4:54:fc:75:8b:2a:26:cf:7f:79
+-----BEGIN CERTIFICATE-----
+MIIDhDCCAwqgAwIBAgIQL4D+I4wOIg9IZxIokYesszAKBggqhkjOPQQDAzCByjEL
+MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW
+ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2ln
+biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJp
+U2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9y
+aXR5IC0gRzQwHhcNMDcxMTA1MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCByjELMAkG
+A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJp
+U2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwg
+SW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2ln
+biBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5
+IC0gRzQwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASnVnp8Utpkmw4tXNherJI9/gHm
+GUo9FANL+mAnINmDiWn6VMaaGF5VKmTeBvaNSjutEDxlPZCIBIngMGGzrl0Bp3ve
+fLK+ymVhAIau2o970ImtTR1ZmkGxvEeA3J5iw/mjgbIwga8wDwYDVR0TAQH/BAUw
+AwEB/zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJ
+aW1hZ2UvZ2lmMCEwHzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYj
+aHR0cDovL2xvZ28udmVyaXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFLMW
+kf3upm7ktS5Jj4d4gYDs5bG1MAoGCCqGSM49BAMDA2gAMGUCMGYhDBgmYFo4e1ZC
+4Kf8NoRRkSAsdk1DPcQdhCPQrNZ8NQbOzWm9kA3bbEhCHQ6qQgIxAJw9SDkjOVga
+FRJZap7v1VmyHVIsmXHNxynfGyphe3HR3vPA5Q06Sqotp9iGKt0uEA==
+-----END CERTIFICATE-----
+
+# Issuer: O=VeriSign, Inc. OU=Class 3 Public Primary Certification Authority
+# Subject: O=VeriSign, Inc. OU=Class 3 Public Primary Certification Authority
+# Label: "Verisign Class 3 Public Primary Certification Authority"
+# Serial: 80507572722862485515306429940691309246
+# MD5 Fingerprint: ef:5a:f1:33:ef:f1:cd:bb:51:02:ee:12:14:4b:96:c4
+# SHA1 Fingerprint: a1:db:63:93:91:6f:17:e4:18:55:09:40:04:15:c7:02:40:b0:ae:6b
+# SHA256 Fingerprint: a4:b6:b3:99:6f:c2:f3:06:b3:fd:86:81:bd:63:41:3d:8c:50:09:cc:4f:a3:29:c2:cc:f0:e2:fa:1b:14:03:05
+-----BEGIN CERTIFICATE-----
+MIICPDCCAaUCEDyRMcsf9tAbDpq40ES/Er4wDQYJKoZIhvcNAQEFBQAwXzELMAkG
+A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz
+cyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2
+MDEyOTAwMDAwMFoXDTI4MDgwMjIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV
+BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmlt
+YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN
+ADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhE
+BarsAx94f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/is
+I19wKTakyYbnsZogy1Olhec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0G
+CSqGSIb3DQEBBQUAA4GBABByUqkFFBkyCEHwxWsKzH4PIRnN5GfcX6kb5sroc50i
+2JhucwNhkcV8sEVAbkSdjbCxlnRhLQ2pRdKkkirWmnWXbj9T/UWZYB2oK0z5XqcJ
+2HUw19JlYD1n1khVdWk/kfVIC0dpImmClr7JyDiGSnoscxlIaU5rfGW/D/xwzoiQ
+-----END CERTIFICATE-----
+
+# Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R3
+# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R3
+# Label: "GlobalSign Root CA - R3"
+# Serial: 4835703278459759426209954
+# MD5 Fingerprint: c5:df:b8:49:ca:05:13:55:ee:2d:ba:1a:c3:3e:b0:28
+# SHA1 Fingerprint: d6:9b:56:11:48:f0:1c:77:c5:45:78:c1:09:26:df:5b:85:69:76:ad
+# SHA256 Fingerprint: cb:b5:22:d7:b7:f1:27:ad:6a:01:13:86:5b:df:1c:d4:10:2e:7d:07:59:af:63:5a:7c:f4:72:0d:c9:63:c5:3b
+-----BEGIN CERTIFICATE-----
+MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4G
+A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNp
+Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4
+MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEG
+A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWtiHL8
+RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsT
+gHeMCOFJ0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmm
+KPZpO/bLyCiR5Z2KYVc3rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zd
+QQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjlOCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZ
+XriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2xmmFghcCAwEAAaNCMEAw
+DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI/wS3+o
+LkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZU
+RUm7lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMp
+jjM5RcOO5LlXbKr8EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK
+6fBdRoyV3XpYKBovHd7NADdBj+1EbddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQX
+mcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18YIvDQVETI53O9zJrlAGomecs
+Mx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7rkpeDMdmztcpH
+WD9f
+-----END CERTIFICATE-----
+
+# Issuer: CN=TC TrustCenter Universal CA III O=TC TrustCenter GmbH OU=TC TrustCenter Universal CA
+# Subject: CN=TC TrustCenter Universal CA III O=TC TrustCenter GmbH OU=TC TrustCenter Universal CA
+# Label: "TC TrustCenter Universal CA III"
+# Serial: 2010889993983507346460533407902964
+# MD5 Fingerprint: 9f:dd:db:ab:ff:8e:ff:45:21:5f:f0:6c:9d:8f:fe:2b
+# SHA1 Fingerprint: 96:56:cd:7b:57:96:98:95:d0:e1:41:46:68:06:fb:b8:c6:11:06:87
+# SHA256 Fingerprint: 30:9b:4a:87:f6:ca:56:c9:31:69:aa:a9:9c:6d:98:88:54:d7:89:2b:d5:43:7e:2d:07:b2:9c:be:da:55:d3:5d
+-----BEGIN CERTIFICATE-----
+MIID4TCCAsmgAwIBAgIOYyUAAQACFI0zFQLkbPQwDQYJKoZIhvcNAQEFBQAwezEL
+MAkGA1UEBhMCREUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxJDAiBgNV
+BAsTG1RDIFRydXN0Q2VudGVyIFVuaXZlcnNhbCBDQTEoMCYGA1UEAxMfVEMgVHJ1
+c3RDZW50ZXIgVW5pdmVyc2FsIENBIElJSTAeFw0wOTA5MDkwODE1MjdaFw0yOTEy
+MzEyMzU5NTlaMHsxCzAJBgNVBAYTAkRFMRwwGgYDVQQKExNUQyBUcnVzdENlbnRl
+ciBHbWJIMSQwIgYDVQQLExtUQyBUcnVzdENlbnRlciBVbml2ZXJzYWwgQ0ExKDAm
+BgNVBAMTH1RDIFRydXN0Q2VudGVyIFVuaXZlcnNhbCBDQSBJSUkwggEiMA0GCSqG
+SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDC2pxisLlxErALyBpXsq6DFJmzNEubkKLF
+5+cvAqBNLaT6hdqbJYUtQCggbergvbFIgyIpRJ9Og+41URNzdNW88jBmlFPAQDYv
+DIRlzg9uwliT6CwLOunBjvvya8o84pxOjuT5fdMnnxvVZ3iHLX8LR7PH6MlIfK8v
+zArZQe+f/prhsq75U7Xl6UafYOPfjdN/+5Z+s7Vy+EutCHnNaYlAJ/Uqwa1D7KRT
+yGG299J5KmcYdkhtWyUB0SbFt1dpIxVbYYqt8Bst2a9c8SaQaanVDED1M4BDj5yj
+dipFtK+/fz6HP3bFzSreIMUWWMv5G/UPyw0RUmS40nZid4PxWJ//AgMBAAGjYzBh
+MB8GA1UdIwQYMBaAFFbn4VslQ4Dg9ozhcbyO5YAvxEjiMA8GA1UdEwEB/wQFMAMB
+Af8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRW5+FbJUOA4PaM4XG8juWAL8RI
+4jANBgkqhkiG9w0BAQUFAAOCAQEAg8ev6n9NCjw5sWi+e22JLumzCecYV42Fmhfz
+dkJQEw/HkG8zrcVJYCtsSVgZ1OK+t7+rSbyUyKu+KGwWaODIl0YgoGhnYIg5IFHY
+aAERzqf2EQf27OysGh+yZm5WZ2B6dF7AbZc2rrUNXWZzwCUyRdhKBgePxLcHsU0G
+DeGl6/R1yrqc0L2z0zIkTO5+4nYES0lT2PLpVDP85XEfPRRclkvxOvIAu2y0+pZV
+CIgJwcyRGSmwIC3/yzikQOEXvnlhgP8HA4ZMTnsGnxGGjYnuJ8Tb4rwZjgvDwxPH
+LQNjO9Po5KIqwoIIlBZU8O8fJ5AluA0OKBtHd0e9HKgl8ZS0Zg==
+-----END CERTIFICATE-----
+
+# Issuer: CN=Go Daddy Root Certificate Authority - G2 O=GoDaddy.com, Inc.
+# Subject: CN=Go Daddy Root Certificate Authority - G2 O=GoDaddy.com, Inc.
+# Label: "Go Daddy Root Certificate Authority - G2"
+# Serial: 0
+# MD5 Fingerprint: 80:3a:bc:22:c1:e6:fb:8d:9b:3b:27:4a:32:1b:9a:01
+# SHA1 Fingerprint: 47:be:ab:c9:22:ea:e8:0e:78:78:34:62:a7:9f:45:c2:54:fd:e6:8b
+# SHA256 Fingerprint: 45:14:0b:32:47:eb:9c:c8:c5:b4:f0:d7:b5:30:91:f7:32:92:08:9e:6e:5a:63:e2:74:9d:d3:ac:a9:19:8e:da
+-----BEGIN CERTIFICATE-----
+MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMx
+EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoT
+EUdvRGFkZHkuY29tLCBJbmMuMTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRp
+ZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIz
+NTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQH
+EwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8GA1UE
+AxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIw
+DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKD
+E6bFIEMBO4Tx5oVJnyfq9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH
+/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD+qK+ihVqf94Lw7YZFAXK6sOoBJQ7Rnwy
+DfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutdfMh8+7ArU6SSYmlRJQVh
+GkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMlNAJWJwGR
+tDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEA
+AaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE
+FDqahQcQZyi27/a9BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmX
+WWcDYfF+OwYxdS2hII5PZYe096acvNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu
+9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r5N9ss4UXnT3ZJE95kTXWXwTr
+gIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYVN8Gb5DKj7Tjo
+2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO
+LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI
+4uJEvlz36hz1
+-----END CERTIFICATE-----
+
+# Issuer: CN=Starfield Root Certificate Authority - G2 O=Starfield Technologies, Inc.
+# Subject: CN=Starfield Root Certificate Authority - G2 O=Starfield Technologies, Inc.
+# Label: "Starfield Root Certificate Authority - G2"
+# Serial: 0
+# MD5 Fingerprint: d6:39:81:c6:52:7e:96:69:fc:fc:ca:66:ed:05:f2:96
+# SHA1 Fingerprint: b5:1c:06:7c:ee:2b:0c:3d:f8:55:ab:2d:92:f4:fe:39:d4:e7:0f:0e
+# SHA256 Fingerprint: 2c:e1:cb:0b:f9:d2:f9:e1:02:99:3f:be:21:51:52:c3:b2:dd:0c:ab:de:1c:68:e5:31:9b:83:91:54:db:b7:f5
+-----BEGIN CERTIFICATE-----
+MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMx
+EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT
+HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVs
+ZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAw
+MFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6
+b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQgVGVj
+aG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZp
+Y2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBAL3twQP89o/8ArFvW59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMg
+nLRJdzIpVv257IzdIvpy3Cdhl+72WoTsbhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1
+HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNkN3mSwOxGXn/hbVNMYq/N
+Hwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7NfZTD4p7dN
+dloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0
+HZbUJtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAO
+BgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0G
+CSqGSIb3DQEBCwUAA4IBAQARWfolTwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjU
+sHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx4mcujJUDJi5DnUox9g61DLu3
+4jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUwF5okxBDgBPfg
+8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K
+pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1
+mMpYjn0q7pBZc2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0
+-----END CERTIFICATE-----
+
+# Issuer: CN=Starfield Services Root Certificate Authority - G2 O=Starfield Technologies, Inc.
+# Subject: CN=Starfield Services Root Certificate Authority - G2 O=Starfield Technologies, Inc.
+# Label: "Starfield Services Root Certificate Authority - G2"
+# Serial: 0
+# MD5 Fingerprint: 17:35:74:af:7b:61:1c:eb:f4:f9:3c:e2:ee:40:f9:a2
+# SHA1 Fingerprint: 92:5a:8f:8d:2c:6d:04:e0:66:5f:59:6a:ff:22:d8:63:e8:25:6f:3f
+# SHA256 Fingerprint: 56:8d:69:05:a2:c8:87:08:a4:b3:02:51:90:ed:cf:ed:b1:97:4a:60:6a:13:c6:e5:29:0f:cb:2a:e6:3e:da:b5
+-----BEGIN CERTIFICATE-----
+MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMx
+EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT
+HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVs
+ZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5
+MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgZgxCzAJBgNVBAYTAlVTMRAwDgYD
+VQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFy
+ZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTswOQYDVQQDEzJTdGFyZmllbGQgU2Vy
+dmljZXMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBANUMOsQq+U7i9b4Zl1+OiFOxHz/Lz58gE20p
+OsgPfTz3a3Y4Y9k2YKibXlwAgLIvWX/2h/klQ4bnaRtSmpDhcePYLQ1Ob/bISdm2
+8xpWriu2dBTrz/sm4xq6HZYuajtYlIlHVv8loJNwU4PahHQUw2eeBGg6345AWh1K
+Ts9DkTvnVtYAcMtS7nt9rjrnvDH5RfbCYM8TWQIrgMw0R9+53pBlbQLPLJGmpufe
+hRhJfGZOozptqbXuNC66DQO4M99H67FrjSXZm86B0UVGMpZwh94CDklDhbZsc7tk
+6mFBrMnUVN+HL8cisibMn1lUaJ/8viovxFUcdUBgF4UCVTmLfwUCAwEAAaNCMEAw
+DwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJxfAN+q
+AdcwKziIorhtSpzyEZGDMA0GCSqGSIb3DQEBCwUAA4IBAQBLNqaEd2ndOxmfZyMI
+bw5hyf2E3F/YNoHN2BtBLZ9g3ccaaNnRbobhiCPPE95Dz+I0swSdHynVv/heyNXB
+ve6SbzJ08pGCL72CQnqtKrcgfU28elUSwhXqvfdqlS5sdJ/PHLTyxQGjhdByPq1z
+qwubdQxtRbeOlKyWN7Wg0I8VRw7j6IPdj/3vQQF3zCepYoUz8jcI73HPdwbeyBkd
+iEDPfUYd/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn
+0q23KXB56jzaYyWf/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCN
+sSi6
+-----END CERTIFICATE-----
+
+# Issuer: CN=AffirmTrust Commercial O=AffirmTrust
+# Subject: CN=AffirmTrust Commercial O=AffirmTrust
+# Label: "AffirmTrust Commercial"
+# Serial: 8608355977964138876
+# MD5 Fingerprint: 82:92:ba:5b:ef:cd:8a:6f:a6:3d:55:f9:84:f6:d6:b7
+# SHA1 Fingerprint: f9:b5:b6:32:45:5f:9c:be:ec:57:5f:80:dc:e9:6e:2c:c7:b2:78:b7
+# SHA256 Fingerprint: 03:76:ab:1d:54:c5:f9:80:3c:e4:b2:e2:01:a0:ee:7e:ef:7b:57:b6:36:e8:a9:3c:9b:8d:48:60:c9:6f:5f:a7
+-----BEGIN CERTIFICATE-----
+MIIDTDCCAjSgAwIBAgIId3cGJyapsXwwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UE
+BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz
+dCBDb21tZXJjaWFsMB4XDTEwMDEyOTE0MDYwNloXDTMwMTIzMTE0MDYwNlowRDEL
+MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp
+cm1UcnVzdCBDb21tZXJjaWFsMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
+AQEA9htPZwcroRX1BiLLHwGy43NFBkRJLLtJJRTWzsO3qyxPxkEylFf6EqdbDuKP
+Hx6GGaeqtS25Xw2Kwq+FNXkyLbscYjfysVtKPcrNcV/pQr6U6Mje+SJIZMblq8Yr
+ba0F8PrVC8+a5fBQpIs7R6UjW3p6+DM/uO+Zl+MgwdYoic+U+7lF7eNAFxHUdPAL
+MeIrJmqbTFeurCA+ukV6BfO9m2kVrn1OIGPENXY6BwLJN/3HR+7o8XYdcxXyl6S1
+yHp52UKqK39c/s4mT6NmgTWvRLpUHhwwMmWd5jyTXlBOeuM61G7MGvv50jeuJCqr
+VwMiKA1JdX+3KNp1v47j3A55MQIDAQABo0IwQDAdBgNVHQ4EFgQUnZPGU4teyq8/
+nx4P5ZmVvCT2lI8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ
+KoZIhvcNAQELBQADggEBAFis9AQOzcAN/wr91LoWXym9e2iZWEnStB03TX8nfUYG
+XUPGhi4+c7ImfU+TqbbEKpqrIZcUsd6M06uJFdhrJNTxFq7YpFzUf1GO7RgBsZNj
+vbz4YYCanrHOQnDiqX0GJX0nof5v7LMeJNrjS1UaADs1tDvZ110w/YETifLCBivt
+Z8SOyUOyXGsViQK8YvxO8rUzqrJv0wqiUOP2O+guRMLbZjipM1ZI8W0bM40NjD9g
+N53Tym1+NH4Nn3J2ixufcv1SNUFFApYvHLKac0khsUlHRUe072o0EclNmsxZt9YC
+nlpOZbWUrhvfKbAW8b8Angc6F2S1BLUjIZkKlTuXfO8=
+-----END CERTIFICATE-----
+
+# Issuer: CN=AffirmTrust Networking O=AffirmTrust
+# Subject: CN=AffirmTrust Networking O=AffirmTrust
+# Label: "AffirmTrust Networking"
+# Serial: 8957382827206547757
+# MD5 Fingerprint: 42:65:ca:be:01:9a:9a:4c:a9:8c:41:49:cd:c0:d5:7f
+# SHA1 Fingerprint: 29:36:21:02:8b:20:ed:02:f5:66:c5:32:d1:d6:ed:90:9f:45:00:2f
+# SHA256 Fingerprint: 0a:81:ec:5a:92:97:77:f1:45:90:4a:f3:8d:5d:50:9f:66:b5:e2:c5:8f:cd:b5:31:05:8b:0e:17:f3:f0:b4:1b
+-----BEGIN CERTIFICATE-----
+MIIDTDCCAjSgAwIBAgIIfE8EORzUmS0wDQYJKoZIhvcNAQEFBQAwRDELMAkGA1UE
+BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz
+dCBOZXR3b3JraW5nMB4XDTEwMDEyOTE0MDgyNFoXDTMwMTIzMTE0MDgyNFowRDEL
+MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp
+cm1UcnVzdCBOZXR3b3JraW5nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
+AQEAtITMMxcua5Rsa2FSoOujz3mUTOWUgJnLVWREZY9nZOIG41w3SfYvm4SEHi3y
+YJ0wTsyEheIszx6e/jarM3c1RNg1lho9Nuh6DtjVR6FqaYvZ/Ls6rnla1fTWcbua
+kCNrmreIdIcMHl+5ni36q1Mr3Lt2PpNMCAiMHqIjHNRqrSK6mQEubWXLviRmVSRL
+QESxG9fhwoXA3hA/Pe24/PHxI1Pcv2WXb9n5QHGNfb2V1M6+oF4nI979ptAmDgAp
+6zxG8D1gvz9Q0twmQVGeFDdCBKNwV6gbh+0t+nvujArjqWaJGctB+d1ENmHP4ndG
+yH329JKBNv3bNPFyfvMMFr20FQIDAQABo0IwQDAdBgNVHQ4EFgQUBx/S55zawm6i
+QLSwelAQUHTEyL0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ
+KoZIhvcNAQEFBQADggEBAIlXshZ6qML91tmbmzTCnLQyFE2npN/svqe++EPbkTfO
+tDIuUFUaNU52Q3Eg75N3ThVwLofDwR1t3Mu1J9QsVtFSUzpE0nPIxBsFZVpikpzu
+QY0x2+c06lkh1QF612S4ZDnNye2v7UsDSKegmQGA3GWjNq5lWUhPgkvIZfFXHeVZ
+Lgo/bNjR9eUJtGxUAArgFU2HdW23WJZa3W3SAKD0m0i+wzekujbgfIeFlxoVot4u
+olu9rxj5kFDNcFn4J2dHy8egBzp90SxdbBk6ZrV9/ZFvgrG+CJPbFEfxojfHRZ48
+x3evZKiT3/Zpg4Jg8klCNO1aAFSFHBY2kgxc+qatv9s=
+-----END CERTIFICATE-----
+
+# Issuer: CN=AffirmTrust Premium O=AffirmTrust
+# Subject: CN=AffirmTrust Premium O=AffirmTrust
+# Label: "AffirmTrust Premium"
+# Serial: 7893706540734352110
+# MD5 Fingerprint: c4:5d:0e:48:b6:ac:28:30:4e:0a:bc:f9:38:16:87:57
+# SHA1 Fingerprint: d8:a6:33:2c:e0:03:6f:b1:85:f6:63:4f:7d:6a:06:65:26:32:28:27
+# SHA256 Fingerprint: 70:a7:3f:7f:37:6b:60:07:42:48:90:45:34:b1:14:82:d5:bf:0e:69:8e:cc:49:8d:f5:25:77:eb:f2:e9:3b:9a
+-----BEGIN CERTIFICATE-----
+MIIFRjCCAy6gAwIBAgIIbYwURrGmCu4wDQYJKoZIhvcNAQEMBQAwQTELMAkGA1UE
+BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVz
+dCBQcmVtaXVtMB4XDTEwMDEyOTE0MTAzNloXDTQwMTIzMTE0MTAzNlowQTELMAkG
+A1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1U
+cnVzdCBQcmVtaXVtMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxBLf
+qV/+Qd3d9Z+K4/as4Tx4mrzY8H96oDMq3I0gW64tb+eT2TZwamjPjlGjhVtnBKAQ
+JG9dKILBl1fYSCkTtuG+kU3fhQxTGJoeJKJPj/CihQvL9Cl/0qRY7iZNyaqoe5rZ
++jjeRFcV5fiMyNlI4g0WJx0eyIOFJbe6qlVBzAMiSy2RjYvmia9mx+n/K+k8rNrS
+s8PhaJyJ+HoAVt70VZVs+7pk3WKL3wt3MutizCaam7uqYoNMtAZ6MMgpv+0GTZe5
+HMQxK9VfvFMSF5yZVylmd2EhMQcuJUmdGPLu8ytxjLW6OQdJd/zvLpKQBY0tL3d7
+70O/Nbua2Plzpyzy0FfuKE4mX4+QaAkvuPjcBukumj5Rp9EixAqnOEhss/n/fauG
+V+O61oV4d7pD6kh/9ti+I20ev9E2bFhc8e6kGVQa9QPSdubhjL08s9NIS+LI+H+S
+qHZGnEJlPqQewQcDWkYtuJfzt9WyVSHvutxMAJf7FJUnM7/oQ0dG0giZFmA7mn7S
+5u046uwBHjxIVkkJx0w3AJ6IDsBz4W9m6XJHMD4Q5QsDyZpCAGzFlH5hxIrff4Ia
+C1nEWTJ3s7xgaVY5/bQGeyzWZDbZvUjthB9+pSKPKrhC9IK31FOQeE4tGv2Bb0TX
+OwF0lkLgAOIua+rF7nKsu7/+6qqo+Nz2snmKtmcCAwEAAaNCMEAwHQYDVR0OBBYE
+FJ3AZ6YMItkm9UWrpmVSESfYRaxjMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/
+BAQDAgEGMA0GCSqGSIb3DQEBDAUAA4ICAQCzV00QYk465KzquByvMiPIs0laUZx2
+KI15qldGF9X1Uva3ROgIRL8YhNILgM3FEv0AVQVhh0HctSSePMTYyPtwni94loMg
+Nt58D2kTiKV1NpgIpsbfrM7jWNa3Pt668+s0QNiigfV4Py/VpfzZotReBA4Xrf5B
+8OWycvpEgjNC6C1Y91aMYj+6QrCcDFx+LmUmXFNPALJ4fqENmS2NuB2OosSw/WDQ
+MKSOyARiqcTtNd56l+0OOF6SL5Nwpamcb6d9Ex1+xghIsV5n61EIJenmJWtSKZGc
+0jlzCFfemQa0W50QBuHCAKi4HEoCChTQwUHK+4w1IX2COPKpVJEZNZOUbWo6xbLQ
+u4mGk+ibyQ86p3q4ofB4Rvr8Ny/lioTz3/4E2aFooC8k4gmVBtWVyuEklut89pMF
+u+1z6S3RdTnX5yTb2E5fQ4+e0BQ5v1VwSJlXMbSc7kqYA5YwH2AG7hsj/oFgIxpH
+YoWlzBk0gG+zrBrjn/B7SK3VAdlntqlyk+otZrWyuOQ9PLLvTIzq6we/qzWaVYa8
+GKa1qF60g2xraUDTn9zxw2lrueFtCfTxqlB2Cnp9ehehVZZCmTEJ3WARjQUwfuaO
+RtGdFNrHF+QFlozEJLUbzxQHskD4o55BhrwE0GuWyCqANP2/7waj3VjFhT0+j/6e
+KeC2uAloGRwYQw==
+-----END CERTIFICATE-----
+
+# Issuer: CN=AffirmTrust Premium ECC O=AffirmTrust
+# Subject: CN=AffirmTrust Premium ECC O=AffirmTrust
+# Label: "AffirmTrust Premium ECC"
+# Serial: 8401224907861490260
+# MD5 Fingerprint: 64:b0:09:55:cf:b1:d5:99:e2:be:13:ab:a6:5d:ea:4d
+# SHA1 Fingerprint: b8:23:6b:00:2f:1d:16:86:53:01:55:6c:11:a4:37:ca:eb:ff:c3:bb
+# SHA256 Fingerprint: bd:71:fd:f6:da:97:e4:cf:62:d1:64:7a:dd:25:81:b0:7d:79:ad:f8:39:7e:b4:ec:ba:9c:5e:84:88:82:14:23
+-----BEGIN CERTIFICATE-----
+MIIB/jCCAYWgAwIBAgIIdJclisc/elQwCgYIKoZIzj0EAwMwRTELMAkGA1UEBhMC
+VVMxFDASBgNVBAoMC0FmZmlybVRydXN0MSAwHgYDVQQDDBdBZmZpcm1UcnVzdCBQ
+cmVtaXVtIEVDQzAeFw0xMDAxMjkxNDIwMjRaFw00MDEyMzExNDIwMjRaMEUxCzAJ
+BgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1UcnVzdDEgMB4GA1UEAwwXQWZmaXJt
+VHJ1c3QgUHJlbWl1bSBFQ0MwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQNMF4bFZ0D
+0KF5Nbc6PJJ6yhUczWLznCZcBz3lVPqj1swS6vQUX+iOGasvLkjmrBhDeKzQN8O9
+ss0s5kfiGuZjuD0uL3jET9v0D6RoTFVya5UdThhClXjMNzyR4ptlKymjQjBAMB0G
+A1UdDgQWBBSaryl6wBE1NSZRMADDav5A1a7WPDAPBgNVHRMBAf8EBTADAQH/MA4G
+A1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNnADBkAjAXCfOHiFBar8jAQr9HX/Vs
+aobgxCd05DhT1wV/GzTjxi+zygk8N53X57hG8f2h4nECMEJZh0PUUd+60wkyWs6I
+flc9nF9Ca/UHLbXwgpP5WW+uZPpY5Yse42O+tYHNbwKMeQ==
+-----END CERTIFICATE-----
+
+# Issuer: CN=StartCom Certification Authority O=StartCom Ltd. OU=Secure Digital Certificate Signing
+# Subject: CN=StartCom Certification Authority O=StartCom Ltd. OU=Secure Digital Certificate Signing
+# Label: "StartCom Certification Authority"
+# Serial: 45
+# MD5 Fingerprint: c9:3b:0d:84:41:fc:a4:76:79:23:08:57:de:10:19:16
+# SHA1 Fingerprint: a3:f1:33:3f:e2:42:bf:cf:c5:d1:4e:8f:39:42:98:40:68:10:d1:a0
+# SHA256 Fingerprint: e1:78:90:ee:09:a3:fb:f4:f4:8b:9c:41:4a:17:d6:37:b7:a5:06:47:e9:bc:75:23:22:72:7f:cc:17:42:a9:11
+-----BEGIN CERTIFICATE-----
+MIIHhzCCBW+gAwIBAgIBLTANBgkqhkiG9w0BAQsFADB9MQswCQYDVQQGEwJJTDEW
+MBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwg
+Q2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNh
+dGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0NjM3WhcNMzYwOTE3MTk0NjM2WjB9
+MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMi
+U2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3Rh
+cnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUA
+A4ICDwAwggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZk
+pMyONvg45iPwbm2xPN1yo4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rf
+OQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/C
+Ji/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/deMotHweXMAEtcnn6RtYT
+Kqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt2PZE4XNi
+HzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMM
+Av+Z6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w
++2OqqGwaVLRcJXrJosmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+
+Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3
+Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVcUjyJthkqcwEKDwOzEmDyei+B
+26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT37uMdBNSSwID
+AQABo4ICEDCCAgwwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD
+VR0OBBYEFE4L7xqkQFulF2mHMMo0aEPQQa7yMB8GA1UdIwQYMBaAFE4L7xqkQFul
+F2mHMMo0aEPQQa7yMIIBWgYDVR0gBIIBUTCCAU0wggFJBgsrBgEEAYG1NwEBATCC
+ATgwLgYIKwYBBQUHAgEWImh0dHA6Ly93d3cuc3RhcnRzc2wuY29tL3BvbGljeS5w
+ZGYwNAYIKwYBBQUHAgEWKGh0dHA6Ly93d3cuc3RhcnRzc2wuY29tL2ludGVybWVk
+aWF0ZS5wZGYwgc8GCCsGAQUFBwICMIHCMCcWIFN0YXJ0IENvbW1lcmNpYWwgKFN0
+YXJ0Q29tKSBMdGQuMAMCAQEagZZMaW1pdGVkIExpYWJpbGl0eSwgcmVhZCB0aGUg
+c2VjdGlvbiAqTGVnYWwgTGltaXRhdGlvbnMqIG9mIHRoZSBTdGFydENvbSBDZXJ0
+aWZpY2F0aW9uIEF1dGhvcml0eSBQb2xpY3kgYXZhaWxhYmxlIGF0IGh0dHA6Ly93
+d3cuc3RhcnRzc2wuY29tL3BvbGljeS5wZGYwEQYJYIZIAYb4QgEBBAQDAgAHMDgG
+CWCGSAGG+EIBDQQrFilTdGFydENvbSBGcmVlIFNTTCBDZXJ0aWZpY2F0aW9uIEF1
+dGhvcml0eTANBgkqhkiG9w0BAQsFAAOCAgEAjo/n3JR5fPGFf59Jb2vKXfuM/gTF
+wWLRfUKKvFO3lANmMD+x5wqnUCBVJX92ehQN6wQOQOY+2IirByeDqXWmN3PH/UvS
+Ta0XQMhGvjt/UfzDtgUx3M2FIk5xt/JxXrAaxrqTi3iSSoX4eA+D/i+tLPfkpLst
+0OcNOrg+zvZ49q5HJMqjNTbOx8aHmNrs++myziebiMMEofYLWWivydsQD032ZGNc
+pRJvkrKTlMeIFw6Ttn5ii5B/q06f/ON1FE8qMt9bDeD1e5MNq6HPh+GlBEXoPBKl
+CcWw0bdT82AUuoVpaiF8H3VhFyAXe2w7QSlc4axa0c2Mm+tgHRns9+Ww2vl5GKVF
+P0lDV9LdJNUso/2RjSe15esUBppMeyG7Oq0wBhjA2MFrLH9ZXF2RsXAiV+uKa0hK
+1Q8p7MZAwC+ITGgBF3f0JBlPvfrhsiAhS90a2Cl9qrjeVOwhVYBsHvUwyKMQ5bLm
+KhQxw4UtjJixhlpPiVktucf3HMiKf8CdBUrmQk9io20ppB+Fq9vlgcitKj1MXVuE
+JnHEhV5xJMqlG2zYYdMa4FTbzrqpMrUi9nNBCV24F10OD5mQ1kfabwo6YigUZ4LZ
+8dCAWZvLMdibD4x3TrVoivJs9iQOLWxwxXPR3hTQcY+203sC9uO41Alua551hDnm
+fyWl8kgAwKQB2j8=
+-----END CERTIFICATE-----
+
+# Issuer: CN=StartCom Certification Authority G2 O=StartCom Ltd.
+# Subject: CN=StartCom Certification Authority G2 O=StartCom Ltd.
+# Label: "StartCom Certification Authority G2"
+# Serial: 59
+# MD5 Fingerprint: 78:4b:fb:9e:64:82:0a:d3:b8:4c:62:f3:64:f2:90:64
+# SHA1 Fingerprint: 31:f1:fd:68:22:63:20:ee:c6:3b:3f:9d:ea:4a:3e:53:7c:7c:39:17
+# SHA256 Fingerprint: c7:ba:65:67:de:93:a7:98:ae:1f:aa:79:1e:71:2d:37:8f:ae:1f:93:c4:39:7f:ea:44:1b:b7:cb:e6:fd:59:95
+-----BEGIN CERTIFICATE-----
+MIIFYzCCA0ugAwIBAgIBOzANBgkqhkiG9w0BAQsFADBTMQswCQYDVQQGEwJJTDEW
+MBQGA1UEChMNU3RhcnRDb20gTHRkLjEsMCoGA1UEAxMjU3RhcnRDb20gQ2VydGlm
+aWNhdGlvbiBBdXRob3JpdHkgRzIwHhcNMTAwMTAxMDEwMDAxWhcNMzkxMjMxMjM1
+OTAxWjBTMQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjEsMCoG
+A1UEAxMjU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgRzIwggIiMA0G
+CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2iTZbB7cgNr2Cu+EWIAOVeq8Oo1XJ
+JZlKxdBWQYeQTSFgpBSHO839sj60ZwNq7eEPS8CRhXBF4EKe3ikj1AENoBB5uNsD
+vfOpL9HG4A/LnooUCri99lZi8cVytjIl2bLzvWXFDSxu1ZJvGIsAQRSCb0AgJnoo
+D/Uefyf3lLE3PbfHkffiAez9lInhzG7TNtYKGXmu1zSCZf98Qru23QumNK9LYP5/
+Q0kGi4xDuFby2X8hQxfqp0iVAXV16iulQ5XqFYSdCI0mblWbq9zSOdIxHWDirMxW
+RST1HFSr7obdljKF+ExP6JV2tgXdNiNnvP8V4so75qbsO+wmETRIjfaAKxojAuuK
+HDp2KntWFhxyKrOq42ClAJ8Em+JvHhRYW6Vsi1g8w7pOOlz34ZYrPu8HvKTlXcxN
+nw3h3Kq74W4a7I/htkxNeXJdFzULHdfBR9qWJODQcqhaX2YtENwvKhOuJv4KHBnM
+0D4LnMgJLvlblnpHnOl68wVQdJVznjAJ85eCXuaPOQgeWeU1FEIT/wCc976qUM/i
+UUjXuG+v+E5+M5iSFGI6dWPPe/regjupuznixL0sAA7IF6wT700ljtizkC+p2il9
+Ha90OrInwMEePnWjFqmveiJdnxMaz6eg6+OGCtP95paV1yPIN93EfKo2rJgaErHg
+TuixO/XWb/Ew1wIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQE
+AwIBBjAdBgNVHQ4EFgQUS8W0QGutHLOlHGVuRjaJhwUMDrYwDQYJKoZIhvcNAQEL
+BQADggIBAHNXPyzVlTJ+N9uWkusZXn5T50HsEbZH77Xe7XRcxfGOSeD8bpkTzZ+K
+2s06Ctg6Wgk/XzTQLwPSZh0avZyQN8gMjgdalEVGKua+etqhqaRpEpKwfTbURIfX
+UfEpY9Z1zRbkJ4kd+MIySP3bmdCPX1R0zKxnNBFi2QwKN4fRoxdIjtIXHfbX/dtl
+6/2o1PXWT6RbdejF0mCy2wl+JYt7ulKSnj7oxXehPOBKc2thz4bcQ///If4jXSRK
+9dNtD2IEBVeC2m6kMyV5Sy5UGYvMLD0w6dEG/+gyRr61M3Z3qAFdlsHB1b6uJcDJ
+HgoJIIihDsnzb02CVAAgp9KP5DlUFy6NHrgbuxu9mk47EDTcnIhT76IxW1hPkWLI
+wpqazRVdOKnWvvgTtZ8SafJQYqz7Fzf07rh1Z2AQ+4NQ+US1dZxAF7L+/XldblhY
+XzD8AK6vM8EOTmy6p6ahfzLbOOCxchcKK5HsamMm7YnUeMx0HgX4a/6ManY5Ka5l
+IxKVCCIcl85bBu4M4ru8H0ST9tg4RQUh7eStqxK2A6RCLi3ECToDZ2mEmuFZkIoo
+hdVddLHRDiBYmxOlsGOm7XtH/UVVMKTumtTm4ofvmMkyghEpIrwACjFeLQ/Ajulr
+so8uBtjRkcfGEvRM/TAXw8HaOFvjqermobp573PYtlNXLfbQ4ddI
+-----END CERTIFICATE-----
diff --git a/lib/google/Google/Model.php b/lib/google/Google/Model.php
new file mode 100755 (executable)
index 0000000..34904ab
--- /dev/null
@@ -0,0 +1,250 @@
+<?php
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * This class defines attributes, valid values, and usage which is generated
+ * from a given json schema.
+ * http://tools.ietf.org/html/draft-zyp-json-schema-03#section-5
+ *
+ * @author Chirag Shah <chirags@google.com>
+ *
+ */
+class Google_Model implements ArrayAccess
+{
+  protected $modelData = array();
+  protected $processed = array();
+
+  /**
+   * Polymorphic - accepts a variable number of arguments dependent
+   * on the type of the model subclass.
+   */
+  public function __construct()
+  {
+    if (func_num_args() == 1 && is_array(func_get_arg(0))) {
+      // Initialize the model with the array's contents.
+      $array = func_get_arg(0);
+      $this->mapTypes($array);
+    }
+  }
+
+  public function __get($key)
+  {
+    $keyTypeName = $this->keyType($key);
+    $keyDataType = $this->dataType($key);
+    if (isset($this->$keyTypeName) && !isset($this->processed[$key])) {
+      if (isset($this->modelData[$key])) {
+        $val = $this->modelData[$key];
+      } else if (isset($this->$keyDataType) &&
+          ($this->$keyDataType == 'array' || $this->$keyDataType == 'map')) {
+        $val = array();
+      } else {
+        $val = null;
+      }
+
+      if ($this->isAssociativeArray($val)) {
+        if (isset($this->$keyDataType) && 'map' == $this->$keyDataType) {
+          foreach ($val as $arrayKey => $arrayItem) {
+              $this->modelData[$key][$arrayKey] =
+                $this->createObjectFromName($keyTypeName, $arrayItem);
+          }
+        } else {
+          $this->modelData[$key] = $this->createObjectFromName($keyTypeName, $val);
+        }
+      } else if (is_array($val)) {
+        $arrayObject = array();
+        foreach ($val as $arrayIndex => $arrayItem) {
+          $arrayObject[$arrayIndex] =
+            $this->createObjectFromName($keyTypeName, $arrayItem);
+        }
+        $this->modelData[$key] = $arrayObject;
+      }
+      $this->processed[$key] = true;
+    }
+
+    return $this->modelData[$key];
+  }
+
+  /**
+   * Initialize this object's properties from an array.
+   *
+   * @param array $array Used to seed this object's properties.
+   * @return void
+   */
+  protected function mapTypes($array)
+  {
+    // Hard initilise simple types, lazy load more complex ones.
+    foreach ($array as $key => $val) {
+      if ( !property_exists($this, $this->keyType($key)) &&
+        property_exists($this, $key)) {
+          $this->$key = $val;
+          unset($array[$key]);
+      } elseif (property_exists($this, $camelKey = Google_Utils::camelCase($key))) {
+          // This checks if property exists as camelCase, leaving it in array as snake_case
+          // in case of backwards compatibility issues.
+          $this->$camelKey = $val;
+      }
+    }
+    $this->modelData = $array;
+  }
+
+  /**
+   * Create a simplified object suitable for straightforward
+   * conversion to JSON. This is relatively expensive
+   * due to the usage of reflection, but shouldn't be called
+   * a whole lot, and is the most straightforward way to filter.
+   */
+  public function toSimpleObject()
+  {
+    $object = new stdClass();
+
+    // Process all other data.
+    foreach ($this->modelData as $key => $val) {
+      $result = $this->getSimpleValue($val);
+      if ($result !== null) {
+        $object->$key = $result;
+      }
+    }
+
+    // Process all public properties.
+    $reflect = new ReflectionObject($this);
+    $props = $reflect->getProperties(ReflectionProperty::IS_PUBLIC);
+    foreach ($props as $member) {
+      $name = $member->getName();
+      $result = $this->getSimpleValue($this->$name);
+      if ($result !== null) {
+        $object->$name = $result;
+      }
+    }
+
+    return $object;
+  }
+
+  /**
+   * Handle different types of values, primarily
+   * other objects and map and array data types.
+   */
+  private function getSimpleValue($value)
+  {
+    if ($value instanceof Google_Model) {
+      return $value->toSimpleObject();
+    } else if (is_array($value)) {
+      $return = array();
+      foreach ($value as $key => $a_value) {
+        $a_value = $this->getSimpleValue($a_value);
+        if ($a_value !== null) {
+          $return[$key] = $a_value;
+        }
+      }
+      return $return;
+    }
+    return $value;
+  }
+
+  /**
+   * Returns true only if the array is associative.
+   * @param array $array
+   * @return bool True if the array is associative.
+   */
+  protected function isAssociativeArray($array)
+  {
+    if (!is_array($array)) {
+      return false;
+    }
+    $keys = array_keys($array);
+    foreach ($keys as $key) {
+      if (is_string($key)) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  /**
+   * Given a variable name, discover its type.
+   *
+   * @param $name
+   * @param $item
+   * @return object The object from the item.
+   */
+  private function createObjectFromName($name, $item)
+  {
+    $type = $this->$name;
+    return new $type($item);
+  }
+
+  /**
+   * Verify if $obj is an array.
+   * @throws Google_Exception Thrown if $obj isn't an array.
+   * @param array $obj Items that should be validated.
+   * @param string $method Method expecting an array as an argument.
+   */
+  public function assertIsArray($obj, $method)
+  {
+    if ($obj && !is_array($obj)) {
+      throw new Google_Exception(
+          "Incorrect parameter type passed to $method(). Expected an array."
+      );
+    }
+  }
+
+  public function offsetExists($offset)
+  {
+    return isset($this->$offset) || isset($this->modelData[$offset]);
+  }
+
+  public function offsetGet($offset)
+  {
+    return isset($this->$offset) ?
+        $this->$offset :
+        $this->__get($offset);
+  }
+
+  public function offsetSet($offset, $value)
+  {
+    if (property_exists($this, $offset)) {
+      $this->$offset = $value;
+    } else {
+      $this->modelData[$offset] = $value;
+      $this->processed[$offset] = true;
+    }
+  }
+
+  public function offsetUnset($offset)
+  {
+    unset($this->modelData[$offset]);
+  }
+
+  protected function keyType($key)
+  {
+    return $key . "Type";
+  }
+
+  protected function dataType($key)
+  {
+    return $key . "DataType";
+  }
+
+  public function __isset($key)
+  {
+    return isset($this->modelData[$key]);
+  }
+
+  public function __unset($key)
+  {
+    unset($this->modelData[$key]);
+  }
+}
diff --git a/lib/google/Google/Service.php b/lib/google/Google/Service.php
new file mode 100755 (executable)
index 0000000..2e0b6c5
--- /dev/null
@@ -0,0 +1,39 @@
+<?php
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+class Google_Service
+{
+  public $version;
+  public $servicePath;
+  public $availableScopes;
+  public $resource;
+  private $client;
+
+  public function __construct(Google_Client $client)
+  {
+    $this->client = $client;
+  }
+
+  /**
+   * Return the associated Google_Client class.
+   * @return Google_Client
+   */
+  public function getClient()
+  {
+    return $this->client;
+  }
+}
diff --git a/lib/google/Google/Service/AdExchangeBuyer.php b/lib/google/Google/Service/AdExchangeBuyer.php
new file mode 100755 (executable)
index 0000000..0ed6627
--- /dev/null
@@ -0,0 +1,2033 @@
+<?php
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+/**
+ * Service definition for AdExchangeBuyer (v1.3).
+ *
+ * <p>
+ * Accesses your bidding-account information, submits creatives for validation, finds available direct deals, and retrieves performance reports.
+ * </p>
+ *
+ * <p>
+ * For more information about this service, see the API
+ * <a href="https://developers.google.com/ad-exchange/buyer-rest" target="_blank">Documentation</a>
+ * </p>
+ *
+ * @author Google, Inc.
+ */
+class Google_Service_AdExchangeBuyer extends Google_Service
+{
+  /** Manage your Ad Exchange buyer account configuration. */
+  const ADEXCHANGE_BUYER = "https://www.googleapis.com/auth/adexchange.buyer";
+
+  public $accounts;
+  public $billingInfo;
+  public $creatives;
+  public $directDeals;
+  public $performanceReport;
+  public $pretargetingConfig;
+  
+
+  /**
+   * Constructs the internal representation of the AdExchangeBuyer service.
+   *
+   * @param Google_Client $client
+   */
+  public function __construct(Google_Client $client)
+  {
+    parent::__construct($client);
+    $this->servicePath = 'adexchangebuyer/v1.3/';
+    $this->version = 'v1.3';
+    $this->serviceName = 'adexchangebuyer';
+
+    $this->accounts = new Google_Service_AdExchangeBuyer_Accounts_Resource(
+        $this,
+        $this->serviceName,
+        'accounts',
+        array(
+          'methods' => array(
+            'get' => array(
+              'path' => 'accounts/{id}',
+              'httpMethod' => 'GET',
+              'parameters' => array(
+                'id' => array(
+                  'location' => 'path',
+                  'type' => 'integer',
+                  'required' => true,
+                ),
+              ),
+            ),'list' => array(
+              'path' => 'accounts',
+              'httpMethod' => 'GET',
+              'parameters' => array(),
+            ),'patch' => array(
+              'path' => 'accounts/{id}',
+              'httpMethod' => 'PATCH',
+              'parameters' => array(
+                'id' => array(
+                  'location' => 'path',
+                  'type' => 'integer',
+                  'required' => true,
+                ),
+              ),
+            ),'update' => array(
+              'path' => 'accounts/{id}',
+              'httpMethod' => 'PUT',
+              'parameters' => array(
+                'id' => array(
+                  'location' => 'path',
+                  'type' => 'integer',
+                  'required' => true,
+                ),
+              ),
+            ),
+          )
+        )
+    );
+    $this->billingInfo = new Google_Service_AdExchangeBuyer_BillingInfo_Resource(
+        $this,
+        $this->serviceName,
+        'billingInfo',
+        array(
+          'methods' => array(
+            'get' => array(
+              'path' => 'billinginfo/{accountId}',
+              'httpMethod' => 'GET',
+              'parameters' => array(
+                'accountId' => array(
+                  'location' => 'path',
+                  'type' => 'integer',
+                  'required' => true,
+                ),
+              ),
+            ),'list' => array(
+              'path' => 'billinginfo',
+              'httpMethod' => 'GET',
+              'parameters' => array(),
+            ),
+          )
+        )
+    );
+    $this->creatives = new Google_Service_AdExchangeBuyer_Creatives_Resource(
+        $this,
+        $this->serviceName,
+        'creatives',
+        array(
+          'methods' => array(
+            'get' => array(
+              'path' => 'creatives/{accountId}/{buyerCreativeId}',
+              'httpMethod' => 'GET',
+              'parameters' => array(
+                'accountId' => array(
+                  'location' => 'path',
+                  'type' => 'integer',
+                  'required' => true,
+                ),
+                'buyerCreativeId' => array(
+                  'location' => 'path',
+                  'type' => 'string',
+                  'required' => true,
+                ),
+              ),
+            ),'insert' => array(
+              'path' => 'creatives',
+              'httpMethod' => 'POST',
+              'parameters' => array(),
+            ),'list' => array(
+              'path' => 'creatives',
+              'httpMethod' => 'GET',
+              'parameters' => array(
+                'statusFilter' => array(
+                  'location' => 'query',
+                  'type' => 'string',
+                ),
+                'pageToken' => array(
+                  'location' => 'query',
+                  'type' => 'string',
+                ),
+                'maxResults' => array(
+                  'location' => 'query',
+                  'type' => 'integer',
+                ),
+                'buyerCreativeId' => array(
+                  'location' => 'query',
+                  'type' => 'string',
+                  'repeated' => true,
+                ),
+                'accountId' => array(
+                  'location' => 'query',
+                  'type' => 'integer',
+                  'repeated' => true,
+                ),
+              ),
+            ),
+          )
+        )
+    );
+    $this->directDeals = new Google_Service_AdExchangeBuyer_DirectDeals_Resource(
+        $this,
+        $this->serviceName,
+        'directDeals',
+        array(
+          'methods' => array(
+            'get' => array(
+              'path' => 'directdeals/{id}',
+              'httpMethod' => 'GET',
+              'parameters' => array(
+                'id' => array(
+                  'location' => 'path',
+                  'type' => 'string',
+                  'required' => true,
+                ),
+              ),
+            ),'list' => array(
+              'path' => 'directdeals',
+              'httpMethod' => 'GET',
+              'parameters' => array(),
+            ),
+          )
+        )
+    );
+    $this->performanceReport = new Google_Service_AdExchangeBuyer_PerformanceReport_Resource(
+        $this,
+        $this->serviceName,
+        'performanceReport',
+        array(
+          'methods' => array(
+            'list' => array(
+              'path' => 'performancereport',
+              'httpMethod' => 'GET',
+              'parameters' => array(
+                'accountId' => array(
+                  'location' => 'query',
+                  'type' => 'string',
+                  'required' => true,
+                ),
+                'endDateTime' => array(
+                  'location' => 'query',
+                  'type' => 'string',
+                  'required' => true,
+                ),
+                'startDateTime' => array(
+                  'location' => 'query',
+                  'type' => 'string',
+                  'required' => true,
+                ),
+                'pageToken' => array(
+                  'location' => 'query',
+                  'type' => 'string',
+                ),
+                'maxResults' => array(
+                  'location' => 'query',
+                  'type' => 'integer',
+                ),
+              ),
+            ),
+          )
+        )
+    );
+    $this->pretargetingConfig = new Google_Service_AdExchangeBuyer_PretargetingConfig_Resource(
+        $this,
+        $this->serviceName,
+        'pretargetingConfig',
+        array(
+          'methods' => array(
+            'delete' => array(
+              'path' => 'pretargetingconfigs/{accountId}/{configId}',
+              'httpMethod' => 'DELETE',
+              'parameters' => array(
+                'accountId' => array(
+                  'location' => 'path',
+                  'type' => 'string',
+                  'required' => true,
+                ),
+                'configId' => array(
+                  'location' => 'path',
+                  'type' => 'string',
+                  'required' => true,
+                ),
+              ),
+            ),'get' => array(
+              'path' => 'pretargetingconfigs/{accountId}/{configId}',
+              'httpMethod' => 'GET',
+              'parameters' => array(
+                'accountId' => array(
+                  'location' => 'path',
+                  'type' => 'string',
+                  'required' => true,
+                ),
+                'configId' => array(
+                  'location' => 'path',
+                  'type' => 'string',
+                  'required' => true,
+                ),
+              ),
+            ),'insert' => array(
+              'path' => 'pretargetingconfigs/{accountId}',
+              'httpMethod' => 'POST',
+              'parameters' => array(
+                'accountId' => array(
+                  'location' => 'path',
+                  'type' => 'string',
+                  'required' => true,
+                ),
+              ),
+            ),'list' => array(
+              'path' => 'pretargetingconfigs/{accountId}',
+              'httpMethod' => 'GET',
+              'parameters' => array(
+                'accountId' => array(
+                  'location' => 'path',
+                  'type' => 'string',
+                  'required' => true,
+                ),
+              ),
+            ),'patch' => array(
+              'path' => 'pretargetingconfigs/{accountId}/{configId}',
+              'httpMethod' => 'PATCH',
+              'parameters' => array(
+                'accountId' => array(
+                  'location' => 'path',
+                  'type' => 'string',
+                  'required' => true,
+                ),
+                'configId' => array(
+                  'location' => 'path',
+                  'type' => 'string',
+                  'required' => true,
+                ),
+              ),
+            ),'update' => array(
+              'path' => 'pretargetingconfigs/{accountId}/{configId}',
+              'httpMethod' => 'PUT',
+              'parameters' => array(
+                'accountId' => array(
+                  'location' => 'path',
+                  'type' => 'string',
+                  'required' => true,
+                ),
+                'configId' => array(
+                  'location' => 'path',
+                  'type' => 'string',
+                  'required' => true,
+                ),
+              ),
+            ),
+          )
+        )
+    );
+  }
+}
+
+
+/**
+ * The "accounts" collection of methods.
+ * Typical usage is:
+ *  <code>
+ *   $adexchangebuyerService = new Google_Service_AdExchangeBuyer(...);
+ *   $accounts = $adexchangebuyerService->accounts;
+ *  </code>
+ */
+class Google_Service_AdExchangeBuyer_Accounts_Resource extends Google_Service_Resource
+{
+
+  /**
+   * Gets one account by ID. (accounts.get)
+   *
+   * @param int $id
+   * The account id
+   * @param array $optParams Optional parameters.
+   * @return Google_Service_AdExchangeBuyer_Account
+   */
+  public function get($id, $optParams = array())
+  {
+    $params = array('id' => $id);
+    $params = array_merge($params, $optParams);
+    return $this->call('get', array($params), "Google_Service_AdExchangeBuyer_Account");
+  }
+  /**
+   * Retrieves the authenticated user's list of accounts. (accounts.listAccounts)
+   *
+   * @param array $optParams Optional parameters.
+   * @return Google_Service_AdExchangeBuyer_AccountsList
+   */
+  public function listAccounts($optParams = array())
+  {
+    $params = array();
+    $params = array_merge($params, $optParams);
+    return $this->call('list', array($params), "Google_Service_AdExchangeBuyer_AccountsList");
+  }
+  /**
+   * Updates an existing account. This method supports patch semantics.
+   * (accounts.patch)
+   *
+   * @param int $id
+   * The account id
+   * @param Google_Account $postBody
+   * @param array $optParams Optional parameters.
+   * @return Google_Service_AdExchangeBuyer_Account
+   */
+  public function patch($id, Google_Service_AdExchangeBuyer_Account $postBody, $optParams = array())
+  {
+    $params = array('id' => $id, 'postBody' => $postBody);
+    $params = array_merge($params, $optParams);
+    return $this->call('patch', array($params), "Google_Service_AdExchangeBuyer_Account");
+  }
+  /**
+   * Updates an existing account. (accounts.update)
+   *
+   * @param int $id
+   * The account id
+   * @param Google_Account $postBody
+   * @param array $optParams Optional parameters.
+   * @return Google_Service_AdExchangeBuyer_Account
+   */
+  public function update($id, Google_Service_AdExchangeBuyer_Account $postBody, $optParams = array())
+  {
+    $params = array('id' => $id, 'postBody' => $postBody);
+    $params = array_merge($params, $optParams);
+    return $this->call('update', array($params), "Google_Service_AdExchangeBuyer_Account");
+  }
+}
+
+/**
+ * The "billingInfo" collection of methods.
+ * Typical usage is:
+ *  <code>
+ *   $adexchangebuyerService = new Google_Service_AdExchangeBuyer(...);
+ *   $billingInfo = $adexchangebuyerService->billingInfo;
+ *  </code>
+ */
+class Google_Service_AdExchangeBuyer_BillingInfo_Resource extends Google_Service_Resource
+{
+
+  /**
+   * Returns the billing information for one account specified by account ID.
+   * (billingInfo.get)
+   *
+   * @param int $accountId
+   * The account id.
+   * @param array $optParams Optional parameters.
+   * @return Google_Service_AdExchangeBuyer_BillingInfo
+   */
+  public function get($accountId, $optParams = array())
+  {
+    $params = array('accountId' => $accountId);
+    $params = array_merge($params, $optParams);
+    return $this->call('get', array($params), "Google_Service_AdExchangeBuyer_BillingInfo");
+  }
+  /**
+   * Retrieves a list of billing information for all accounts of the authenticated
+   * user. (billingInfo.listBillingInfo)
+   *
+   * @param array $optParams Optional parameters.
+   * @return Google_Service_AdExchangeBuyer_BillingInfoList
+   */
+  public function listBillingInfo($optParams = array())
+  {
+    $params = array();
+    $params = array_merge($params, $optParams);
+    return $this->call('list', array($params), "Google_Service_AdExchangeBuyer_BillingInfoList");
+  }
+}
+
+/**
+ * The "creatives" collection of methods.
+ * Typical usage is:
+ *  <code>
+ *   $adexchangebuyerService = new Google_Service_AdExchangeBuyer(...);
+ *   $creatives = $adexchangebuyerService->creatives;
+ *  </code>
+ */
+class Google_Service_AdExchangeBuyer_Creatives_Resource extends Google_Service_Resource
+{
+
+  /**
+   * Gets the status for a single creative. A creative will be available 30-40
+   * minutes after submission. (creatives.get)
+   *
+   * @param int $accountId
+   * The id for the account that will serve this creative.
+   * @param string $buyerCreativeId
+   * The buyer-specific id for this creative.
+   * @param array $optParams Optional parameters.
+   * @return Google_Service_AdExchangeBuyer_Creative
+   */
+  public function get($accountId, $buyerCreativeId, $optParams = array())
+  {
+    $params = array('accountId' => $accountId, 'buyerCreativeId' => $buyerCreativeId);
+    $params = array_merge($params, $optParams);
+    return $this->call('get', array($params), "Google_Service_AdExchangeBuyer_Creative");
+  }
+  /**
+   * Submit a new creative. (creatives.insert)
+   *
+   * @param Google_Creative $postBody
+   * @param array $optParams Optional parameters.
+   * @return Google_Service_AdExchangeBuyer_Creative
+   */
+  public function insert(Google_Service_AdExchangeBuyer_Creative $postBody, $optParams = array())
+  {
+    $params = array('postBody' => $postBody);
+    $params = array_merge($params, $optParams);
+    return $this->call('insert', array($params), "Google_Service_AdExchangeBuyer_Creative");
+  }
+  /**
+   * Retrieves a list of the authenticated user's active creatives. A creative
+   * will be available 30-40 minutes after submission. (creatives.listCreatives)
+   *
+   * @param array $optParams Optional parameters.
+   *
+   * @opt_param string statusFilter
+   * When specified, only creatives having the given status are returned.
+   * @opt_param string pageToken
+   * A continuation token, used to page through ad clients. To retrieve the next page, set this
+    * parameter to the value of "nextPageToken" from the previous response. Optional.
+   * @opt_param string maxResults
+   * Maximum number of entries returned on one result page. If not set, the default is 100. Optional.
+   * @opt_param string buyerCreativeId
+   * When specified, only creatives for the given buyer creative ids are returned.
+   * @opt_param int accountId
+   * When specified, only creatives for the given account ids are returned.
+   * @return Google_Service_AdExchangeBuyer_CreativesList
+   */
+  public function listCreatives($optParams = array())
+  {
+    $params = array();
+    $params = array_merge($params, $optParams);
+    return $this->call('list', array($params), "Google_Service_AdExchangeBuyer_CreativesList");
+  }
+}
+
+/**
+ * The "directDeals" collection of methods.
+ * Typical usage is:
+ *  <code>
+ *   $adexchangebuyerService = new Google_Service_AdExchangeBuyer(...);
+ *   $directDeals = $adexchangebuyerService->directDeals;
+ *  </code>
+ */
+class Google_Service_AdExchangeBuyer_DirectDeals_Resource extends Google_Service_Resource
+{
+
+  /**
+   * Gets one direct deal by ID. (directDeals.get)
+   *
+   * @param string $id
+   * The direct deal id
+   * @param array $optParams Optional parameters.
+   * @return Google_Service_AdExchangeBuyer_DirectDeal
+   */
+  public function get($id, $optParams = array())
+  {
+    $params = array('id' => $id);
+    $params = array_merge($params, $optParams);
+    return $this->call('get', array($params), "Google_Service_AdExchangeBuyer_DirectDeal");
+  }
+  /**
+   * Retrieves the authenticated user's list of direct deals.
+   * (directDeals.listDirectDeals)
+   *
+   * @param array $optParams Optional parameters.
+   * @return Google_Service_AdExchangeBuyer_DirectDealsList
+   */
+  public function listDirectDeals($optParams = array())
+  {
+    $params = array();
+    $params = array_merge($params, $optParams);
+    return $this->call('list', array($params), "Google_Service_AdExchangeBuyer_DirectDealsList");
+  }
+}
+
+/**
+ * The "performanceReport" collection of methods.
+ * Typical usage is:
+ *  <code>
+ *   $adexchangebuyerService = new Google_Service_AdExchangeBuyer(...);
+ *   $performanceReport = $adexchangebuyerService->performanceReport;
+ *  </code>
+ */
+class Google_Service_AdExchangeBuyer_PerformanceReport_Resource extends Google_Service_Resource
+{
+
+  /**
+   * Retrieves the authenticated user's list of performance metrics.
+   * (performanceReport.listPerformanceReport)
+   *
+   * @param string $accountId
+   * The account id to get the reports.
+   * @param string $endDateTime
+   * The end time of the report in ISO 8601 timestamp format using UTC.
+   * @param string $startDateTime
+   * The start time of the report in ISO 8601 timestamp format using UTC.
+   * @param array $optParams Optional parameters.
+   *
+   * @opt_param string pageToken
+   * A continuation token, used to page through performance reports. To retrieve the next page, set
+    * this parameter to the value of "nextPageToken" from the previous response. Optional.
+   * @opt_param string maxResults
+   * Maximum number of entries returned on one result page. If not set, the default is 100. Optional.
+   * @return Google_Service_AdExchangeBuyer_PerformanceReportList
+   */
+  public function listPerformanceReport($accountId, $endDateTime, $startDateTime, $optParams = array())
+  {
+    $params = array('accountId' => $accountId, 'endDateTime' => $endDateTime, 'startDateTime' => $startDateTime);
+    $params = array_merge($params, $optParams);
+    return $this->call('list', array($params), "Google_Service_AdExchangeBuyer_PerformanceReportList");
+  }
+}
+
+/**
+ * The "pretargetingConfig" collection of methods.
+ * Typical usage is:
+ *  <code>
+ *   $adexchangebuyerService = new Google_Service_AdExchangeBuyer(...);
+ *   $pretargetingConfig = $adexchangebuyerService->pretargetingConfig;
+ *  </code>
+ */
+class Google_Service_AdExchangeBuyer_PretargetingConfig_Resource extends Google_Service_Resource
+{
+
+  /**
+   * Deletes an existing pretargeting config. (pretargetingConfig.delete)
+   *
+   * @param string $accountId
+   * The account id to delete the pretargeting config for.
+   * @param string $configId
+   * The specific id of the configuration to delete.
+   * @param array $optParams Optional parameters.
+   */
+  public function delete($accountId, $configId, $optParams = array())
+  {
+    $params = array('accountId' => $accountId, 'configId' => $configId);
+    $params = array_merge($params, $optParams);
+    return $this->call('delete', array($params));
+  }
+  /**
+   * Gets a specific pretargeting configuration (pretargetingConfig.get)
+   *
+   * @param string $accountId
+   * The account id to get the pretargeting config for.
+   * @param string $configId
+   * The specific id of the configuration to retrieve.
+   * @param array $optParams Optional parameters.
+   * @return Google_Service_AdExchangeBuyer_PretargetingConfig
+   */
+  public function get($accountId, $configId, $optParams = array())
+  {
+    $params = array('accountId' => $accountId, 'configId' => $configId);
+    $params = array_merge($params, $optParams);
+    return $this->call('get', array($params), "Google_Service_AdExchangeBuyer_PretargetingConfig");
+  }
+  /**
+   * Inserts a new pretargeting configuration. (pretargetingConfig.insert)
+   *
+   * @param string $accountId
+   * The account id to insert the pretargeting config for.
+   * @param Google_PretargetingConfig $postBody
+   * @param array $optParams Optional parameters.
+   * @return Google_Service_AdExchangeBuyer_PretargetingConfig
+   */
+  public function insert($accountId, Google_Service_AdExchangeBuyer_PretargetingConfig $postBody, $optParams = array())
+  {
+    $params = array('accountId' => $accountId, 'postBody' => $postBody);
+    $params = array_merge($params, $optParams);
+    return $this->call('insert', array($params), "Google_Service_AdExchangeBuyer_PretargetingConfig");
+  }
+  /**
+   * Retrieves a list of the authenticated user's pretargeting configurations.
+   * (pretargetingConfig.listPretargetingConfig)
+   *
+   * @param string $accountId
+   * The account id to get the pretargeting configs for.
+   * @param array $optParams Optional parameters.
+   * @return Google_Service_AdExchangeBuyer_PretargetingConfigList
+   */
+  public function listPretargetingConfig($accountId, $optParams = array())
+  {
+    $params = array('accountId' => $accountId);
+    $params = array_merge($params, $optParams);
+    return $this->call('list', array($params), "Google_Service_AdExchangeBuyer_PretargetingConfigList");
+  }
+  /**
+   * Updates an existing pretargeting config. This method supports patch
+   * semantics. (pretargetingConfig.patch)
+   *
+   * @param string $accountId
+   * The account id to update the pretargeting config for.
+   * @param string $configId
+   * The specific id of the configuration to update.
+   * @param Google_PretargetingConfig $postBody
+   * @param array $optParams Optional parameters.
+   * @return Google_Service_AdExchangeBuyer_PretargetingConfig
+   */
+  public function patch($accountId, $configId, Google_Service_AdExchangeBuyer_PretargetingConfig $postBody, $optParams = array())
+  {
+    $params = array('accountId' => $accountId, 'configId' => $configId, 'postBody' => $postBody);
+    $params = array_merge($params, $optParams);
+    return $this->call('patch', array($params), "Google_Service_AdExchangeBuyer_PretargetingConfig");
+  }
+  /**
+   * Updates an existing pretargeting config. (pretargetingConfig.update)
+   *
+   * @param string $accountId
+   * The account id to update the pretargeting config for.
+   * @param string $configId
+   * The specific id of the configuration to update.
+   * @param Google_PretargetingConfig $postBody
+   * @param array $optParams Optional parameters.
+   * @return Google_Service_AdExchangeBuyer_PretargetingConfig
+   */
+  public function update($accountId, $configId, Google_Service_AdExchangeBuyer_PretargetingConfig $postBody, $optParams = array())
+  {
+    $params = array('accountId' => $accountId, 'configId' => $configId, 'postBody' => $postBody);
+    $params = array_merge($params, $optParams);
+    return $this->call('update', array($params), "Google_Service_AdExchangeBuyer_PretargetingConfig");
+  }
+}
+
+
+
+
+class Google_Service_AdExchangeBuyer_Account extends Google_Collection
+{
+  protected $collection_key = 'bidderLocation';
+  protected $bidderLocationType = 'Google_Service_AdExchangeBuyer_AccountBidderLocation';
+  protected $bidderLocationDataType = 'array';
+  public $cookieMatchingNid;
+  public $cookieMatchingUrl;
+  public $id;
+  public $kind;
+  public $maximumTotalQps;
+
+  public function setBidderLocation($bidderLocation)
+  {
+    $this->bidderLocation = $bidderLocation;
+  }
+
+  public function getBidderLocation()
+  {
+    return $this->bidderLocation;
+  }
+
+  public function setCookieMatchingNid($cookieMatchingNid)
+  {
+    $this->cookieMatchingNid = $cookieMatchingNid;
+  }
+
+  public function getCookieMatchingNid()
+  {
+    return $this->cookieMatchingNid;
+  }
+
+  public function setCookieMatchingUrl($cookieMatchingUrl)
+  {
+    $this->cookieMatchingUrl = $cookieMatchingUrl;
+  }
+
+  public function getCookieMatchingUrl()
+  {
+    return $this->cookieMatchingUrl;
+  }
+
+  public function setId($id)
+  {
+    $this->id = $id;
+  }
+
+  public function getId()
+  {
+    return $this->id;
+  }
+
+  public function setKind($kind)
+  {
+    $this->kind = $kind;
+  }
+
+  public function getKind()
+  {
+    return $this->kind;
+  }
+
+  public function setMaximumTotalQps($maximumTotalQps)
+  {
+    $this->maximumTotalQps = $maximumTotalQps;
+  }
+
+  public function getMaximumTotalQps()
+  {
+    return $this->maximumTotalQps;
+  }
+}
+
+class Google_Service_AdExchangeBuyer_AccountBidderLocation extends Google_Model
+{
+  public $maximumQps;
+  public $region;
+  public $url;
+
+  public function setMaximumQps($maximumQps)
+  {
+    $this->maximumQps = $maximumQps;
+  }
+
+  public function getMaximumQps()
+  {
+    return $this->maximumQps;
+  }
+
+  public function setRegion($region)
+  {
+    $this->region = $region;
+  }
+
+  public function getRegion()
+  {
+    return $this->region;
+  }
+
+  public function setUrl($url)
+  {
+    $this->url = $url;
+  }
+
+  public function getUrl()
+  {
+    return $this->url;
+  }
+}
+
+class Google_Service_AdExchangeBuyer_AccountsList extends Google_Collection
+{
+  protected $collection_key = 'items';
+  protected $itemsType = 'Google_Service_AdExchangeBuyer_Account';
+  protected $itemsDataType = 'array';
+  public $kind;
+
+  public function setItems($items)
+  {
+    $this->items = $items;
+  }
+
+  public function getItems()
+  {
+    return $this->items;
+  }
+
+  public function setKind($kind)
+  {
+    $this->kind = $kind;
+  }
+
+  public function getKind()
+  {
+    return $this->kind;
+  }
+}
+
+class Google_Service_AdExchangeBuyer_BillingInfo extends Google_Collection
+{
+  protected $collection_key = 'billingId';
+  public $accountId;
+  public $accountName;
+  public $billingId;
+  public $kind;
+
+  public function setAccountId($accountId)
+  {
+    $this->accountId = $accountId;
+  }
+
+  public function getAccountId()
+  {
+    return $this->accountId;
+  }
+
+  public function setAccountName($accountName)
+  {
+    $this->accountName = $accountName;
+  }
+
+  public function getAccountName()
+  {
+    return $this->accountName;
+  }
+
+  public function setBillingId($billingId)
+  {
+    $this->billingId = $billingId;
+  }
+
+  public function getBillingId()
+  {
+    return $this->billingId;
+  }
+
+  public function setKind($kind)
+  {
+    $this->kind = $kind;
+  }
+
+  public function getKind()
+  {
+    return $this->kind;
+  }
+}
+
+class Google_Service_AdExchangeBuyer_BillingInfoList extends Google_Collection
+{
+  protected $collection_key = 'items';
+  protected $itemsType = 'Google_Service_AdExchangeBuyer_BillingInfo';
+  protected $itemsDataType = 'array';
+  public $kind;
+
+  public function setItems($items)
+  {
+    $this->items = $items;
+  }
+
+  public function getItems()
+  {
+    return $this->items;
+  }
+
+  public function setKind($kind)
+  {
+    $this->kind = $kind;
+  }
+
+  public function getKind()
+  {
+    return $this->kind;
+  }
+}
+
+class Google_Service_AdExchangeBuyer_Creative extends Google_Collection
+{
+  protected $collection_key = 'vendorType';
+  public $hTMLSnippet;
+  public $accountId;
+  public $advertiserId;
+  public $advertiserName;
+  public $agencyId;
+  public $attribute;
+  public $buyerCreativeId;
+  public $clickThroughUrl;
+  protected $correctionsType = 'Google_Service_AdExchangeBuyer_CreativeCorrections';
+  protected $correctionsDataType = 'array';
+  protected $disapprovalReasonsType = 'Google_Service_AdExchangeBuyer_CreativeDisapprovalReasons';
+  protected $disapprovalReasonsDataType = 'array';
+  protected $filteringReasonsType = 'Google_Service_AdExchangeBuyer_CreativeFilteringReasons';
+  protected $filteringReasonsDataType = '';
+  public $height;
+  public $kind;
+  public $productCategories;
+  public $restrictedCategories;
+  public $sensitiveCategories;
+  public $status;
+  public $vendorType;
+  public $videoURL;
+  public $width;
+
+  public function setHTMLSnippet($hTMLSnippet)
+  {
+    $this->hTMLSnippet = $hTMLSnippet;
+  }
+
+  public function getHTMLSnippet()
+  {
+    return $this->hTMLSnippet;
+  }
+
+  public function setAccountId($accountId)
+  {
+    $this->accountId = $accountId;
+  }
+
+  public function getAccountId()
+  {
+    return $this->accountId;
+  }
+
+  public function setAdvertiserId($advertiserId)
+  {
+    $this->advertiserId = $advertiserId;
+  }
+
+  public function getAdvertiserId()
+  {
+    return $this->advertiserId;
+  }
+
+  public function setAdvertiserName($advertiserName)
+  {
+    $this->advertiserName = $advertiserName;
+  }
+
+  public function getAdvertiserName()
+  {
+    return $this->advertiserName;
+  }
+
+  public function setAgencyId($agencyId)
+  {
+    $this->agencyId = $agencyId;
+  }
+
+  public function getAgencyId()
+  {
+    return $this->agencyId;
+  }
+
+  public function setAttribute($attribute)
+  {
+    $this->attribute = $attribute;
+  }
+
+  public function getAttribute()
+  {
+    return $this->attribute;
+  }
+
+  public function setBuyerCreativeId($buyerCreativeId)
+  {
+    $this->buyerCreativeId = $buyerCreativeId;
+  }
+
+  public function getBuyerCreativeId()
+  {
+    return $this->buyerCreativeId;
+  }
+
+  public function setClickThroughUrl($clickThroughUrl)
+  {
+    $this->clickThroughUrl = $clickThroughUrl;
+  }
+
+  public function getClickThroughUrl()
+  {
+    return $this->clickThroughUrl;
+  }
+
+  public function setCorrections($corrections)
+  {
+    $this->corrections = $corrections;
+  }
+
+  public function getCorrections()
+  {
+    return $this->corrections;
+  }
+
+  public function setDisapprovalReasons($disapprovalReasons)
+  {
+    $this->disapprovalReasons = $disapprovalReasons;
+  }
+
+  public function getDisapprovalReasons()
+  {
+    return $this->disapprovalReasons;
+  }
+
+  public function setFilteringReasons(Google_Service_AdExchangeBuyer_CreativeFilteringReasons $filteringReasons)
+  {
+    $this->filteringReasons = $filteringReasons;
+  }
+
+  public function getFilteringReasons()
+  {
+    return $this->filteringReasons;
+  }
+
+  public function setHeight($height)
+  {
+    $this->height = $height;
+  }
+
+  public function getHeight()
+  {
+    return $this->height;
+  }
+
+  public function setKind($kind)
+  {
+    $this->kind = $kind;
+  }
+
+  public function getKind()
+  {
+    return $this->kind;
+  }
+
+  public function setProductCategories($productCategories)
+  {
+    $this->productCategories = $productCategories;
+  }
+
+  public function getProductCategories()
+  {
+    return $this->productCategories;
+  }
+
+  public function setRestrictedCategories($restrictedCategories)
+  {
+    $this->restrictedCategories = $restrictedCategories;
+  }
+
+  public function getRestrictedCategories()
+  {
+    return $this->restrictedCategories;
+  }
+
+  public function setSensitiveCategories($sensitiveCategories)
+  {
+    $this->sensitiveCategories = $sensitiveCategories;
+  }
+
+  public function getSensitiveCategories()
+  {
+    return $this->sensitiveCategories;
+  }
+
+  public function setStatus($status)
+  {
+    $this->status = $status;
+  }
+
+  public function getStatus()
+  {
+    return $this->status;
+  }
+
+  public function setVendorType($vendorType)
+  {
+    $this->vendorType = $vendorType;
+  }
+
+  public function getVendorType()
+  {
+    return $this->vendorType;
+  }
+
+  public function setVideoURL($videoURL)
+  {
+    $this->videoURL = $videoURL;
+  }
+
+  public function getVideoURL()
+  {
+    return $this->videoURL;
+  }
+
+  public function setWidth($width)
+  {
+    $this->width = $width;
+  }
+
+  public function getWidth()
+  {
+    return $this->width;
+  }
+}
+
+class Google_Service_AdExchangeBuyer_CreativeCorrections extends Google_Collection
+{
+  protected $collection_key = 'details';
+  public $details;
+  public $reason;
+
+  public function setDetails($details)
+  {
+    $this->details = $details;
+  }
+
+  public function getDetails()
+  {
+    return $this->details;
+  }
+
+  public function setReason($reason)
+  {
+    $this->reason = $reason;
+  }
+
+  public function getReason()
+  {
+    return $this->reason;
+  }
+}
+
+class Google_Service_AdExchangeBuyer_CreativeDisapprovalReasons extends Google_Collection
+{
+  protected $collection_key = 'details';
+  public $details;
+  public $reason;
+
+  public function setDetails($details)
+  {
+    $this->details = $details;
+  }
+
+  public function getDetails()
+  {
+    return $this->details;
+  }
+
+  public function setReason($reason)
+  {
+    $this->reason = $reason;
+  }
+
+  public function getReason()
+  {
+    return $this->reason;
+  }
+}
+
+class Google_Service_AdExchangeBuyer_CreativeFilteringReasons extends Google_Collection
+{
+  protected $collection_key = 'reasons';
+  public $date;
+  protected $reasonsType = 'Google_Service_AdExchangeBuyer_CreativeFilteringReasonsReasons';
+  protected $reasonsDataType = 'array';
+
+  public function setDate($date)
+  {
+    $this->date = $date;
+  }
+
+  public function getDate()
+  {
+    return $this->date;
+  }
+
+  public function setReasons($reasons)
+  {
+    $this->reasons = $reasons;
+  }
+
+  public function getReasons()
+  {
+    return $this->reasons;
+  }
+}
+
+class Google_Service_AdExchangeBuyer_CreativeFilteringReasonsReasons extends Google_Model
+{
+  public $filteringCount;
+  public $filteringStatus;
+
+  public function setFilteringCount($filteringCount)
+  {
+    $this->filteringCount = $filteringCount;
+  }
+
+  public function getFilteringCount()
+  {
+    return $this->filteringCount;
+  }
+
+  public function setFilteringStatus($filteringStatus)
+  {
+    $this->filteringStatus = $filteringStatus;
+  }
+
+  public function getFilteringStatus()
+  {
+    return $this->filteringStatus;
+  }
+}
+
+class Google_Service_AdExchangeBuyer_CreativesList extends Google_Collection
+{
+  protected $collection_key = 'items';
+  protected $itemsType = 'Google_Service_AdExchangeBuyer_Creative';
+  protected $itemsDataType = 'array';
+  public $kind;
+  public $nextPageToken;
+
+  public function setItems($items)
+  {
+    $this->items = $items;
+  }
+
+  public function getItems()
+  {
+    return $this->items;
+  }
+
+  public function setKind($kind)
+  {
+    $this->kind = $kind;
+  }
+
+  public function getKind()
+  {
+    return $this->kind;
+  }
+
+  public function setNextPageToken($nextPageToken)
+  {
+    $this->nextPageToken = $nextPageToken;
+  }
+
+  public function getNextPageToken()
+  {
+    return $this->nextPageToken;
+  }
+}
+
+class Google_Service_AdExchangeBuyer_DirectDeal extends Google_Model
+{
+  public $accountId;
+  public $advertiser;
+  public $currencyCode;
+  public $endTime;
+  public $fixedCpm;
+  public $id;
+  public $kind;
+  public $name;
+  public $privateExchangeMinCpm;
+  public $publisherBlocksOverriden;
+  public $sellerNetwork;
+  public $startTime;
+
+  public function setAccountId($accountId)
+  {
+    $this->accountId = $accountId;
+  }
+
+  public function getAccountId()
+  {
+    return $this->accountId;
+  }
+
+  public function setAdvertiser($advertiser)
+  {
+    $this->advertiser = $advertiser;
+  }
+
+  public function getAdvertiser()
+  {
+    return $this->advertiser;
+  }
+
+  public function setCurrencyCode($currencyCode)
+  {
+    $this->currencyCode = $currencyCode;
+  }
+
+  public function getCurrencyCode()
+  {
+    return $this->currencyCode;
+  }
+
+  public function setEndTime($endTime)
+  {
+    $this->endTime = $endTime;
+  }
+
+  public function getEndTime()
+  {
+    return $this->endTime;
+  }
+
+  public function setFixedCpm($fixedCpm)
+  {
+    $this->fixedCpm = $fixedCpm;
+  }
+
+  public function getFixedCpm()
+  {
+    return $this->fixedCpm;
+  }
+
+  public function setId($id)
+  {
+    $this->id = $id;
+  }
+
+  public function getId()
+  {
+    return $this->id;
+  }
+
+  public function setKind($kind)
+  {
+    $this->kind = $kind;
+  }
+
+  public function getKind()
+  {
+    return $this->kind;
+  }
+
+  public function setName($name)
+  {
+    $this->name = $name;
+  }
+
+  public function getName()
+  {
+    return $this->name;
+  }
+
+  public function setPrivateExchangeMinCpm($privateExchangeMinCpm)
+  {
+    $this->privateExchangeMinCpm = $privateExchangeMinCpm;
+  }
+
+  public function getPrivateExchangeMinCpm()
+  {
+    return $this->privateExchangeMinCpm;
+  }
+
+  public function setPublisherBlocksOverriden($publisherBlocksOverriden)
+  {
+    $this->publisherBlocksOverriden = $publisherBlocksOverriden;
+  }
+
+  public function getPublisherBlocksOverriden()
+  {
+    return $this->publisherBlocksOverriden;
+  }
+
+  public function setSellerNetwork($sellerNetwork)
+  {
+    $this->sellerNetwork = $sellerNetwork;
+  }
+
+  public function getSellerNetwork()
+  {
+    return $this->sellerNetwork;
+  }
+
+  public function setStartTime($startTime)
+  {
+    $this->startTime = $startTime;
+  }
+
+  public function getStartTime()
+  {
+    return $this->startTime;
+  }
+}
+
+class Google_Service_AdExchangeBuyer_DirectDealsList extends Google_Collection
+{
+  protected $collection_key = 'directDeals';
+  protected $directDealsType = 'Google_Service_AdExchangeBuyer_DirectDeal';
+  protected $directDealsDataType = 'array';
+  public $kind;
+
+  public function setDirectDeals($directDeals)
+  {
+    $this->directDeals = $directDeals;
+  }
+
+  public function getDirectDeals()
+  {
+    return $this->directDeals;
+  }
+
+  public function setKind($kind)
+  {
+    $this->kind = $kind;
+  }
+
+  public function getKind()
+  {
+    return $this->kind;
+  }
+}
+
+class Google_Service_AdExchangeBuyer_PerformanceReport extends Google_Collection
+{
+  protected $collection_key = 'hostedMatchStatusRate';
+  public $calloutStatusRate;
+  public $cookieMatcherStatusRate;
+  public $creativeStatusRate;
+  public $hostedMatchStatusRate;
+  public $kind;
+  public $latency50thPercentile;
+  public $latency85thPercentile;
+  public $latency95thPercentile;
+  public $noQuotaInRegion;
+  public $outOfQuota;
+  public $pixelMatchRequests;
+  public $pixelMatchResponses;
+  public $quotaConfiguredLimit;
+  public $quotaThrottledLimit;
+  public $region;
+  public $timestamp;
+
+  public function setCalloutStatusRate($calloutStatusRate)
+  {
+    $this->calloutStatusRate = $calloutStatusRate;
+  }
+
+  public function getCalloutStatusRate()
+  {
+    return $this->calloutStatusRate;
+  }
+
+  public function setCookieMatcherStatusRate($cookieMatcherStatusRate)
+  {
+    $this->cookieMatcherStatusRate = $cookieMatcherStatusRate;
+  }
+
+  public function getCookieMatcherStatusRate()
+  {
+    return $this->cookieMatcherStatusRate;
+  }
+
+  public function setCreativeStatusRate($creativeStatusRate)
+  {
+    $this->creativeStatusRate = $creativeStatusRate;
+  }
+
+  public function getCreativeStatusRate()
+  {
+    return $this->creativeStatusRate;
+  }
+
+  public function setHostedMatchStatusRate($hostedMatchStatusRate)
+  {
+    $this->hostedMatchStatusRate = $hostedMatchStatusRate;
+  }
+
+  public function getHostedMatchStatusRate()
+  {
+    return $this->hostedMatchStatusRate;
+  }
+
+  public function setKind($kind)
+  {
+    $this->kind = $kind;
+  }
+
+  public function getKind()
+  {
+    return $this->kind;
+  }
+
+  public function setLatency50thPercentile($latency50thPercentile)
+  {
+    $this->latency50thPercentile = $latency50thPercentile;
+  }
+
+  public function getLatency50thPercentile()
+  {
+    return $this->latency50thPercentile;
+  }
+
+  public function setLatency85thPercentile($latency85thPercentile)
+  {
+    $this->latency85thPercentile = $latency85thPercentile;
+  }
+
+  public function getLatency85thPercentile()
+  {
+    return $this->latency85thPercentile;
+  }
+
+  public function setLatency95thPercentile($latency95thPercentile)
+  {
+    $this->latency95thPercentile = $latency95thPercentile;
+  }
+
+  public function getLatency95thPercentile()
+  {
+    return $this->latency95thPercentile;
+  }
+
+  public function setNoQuotaInRegion($noQuotaInRegion)
+  {
+    $this->noQuotaInRegion = $noQuotaInRegion;
+  }
+
+  public function getNoQuotaInRegion()
+  {
+    return $this->noQuotaInRegion;
+  }
+
+  public function setOutOfQuota($outOfQuota)
+  {
+    $this->outOfQuota = $outOfQuota;
+  }
+
+  public function getOutOfQuota()
+  {
+    return $this->outOfQuota;
+  }
+
+  public function setPixelMatchRequests($pixelMatchRequests)
+  {
+    $this->pixelMatchRequests = $pixelMatchRequests;
+  }
+
+  public function getPixelMatchRequests()
+  {
+    return $this->pixelMatchRequests;
+  }
+
+  public function setPixelMatchResponses($pixelMatchResponses)
+  {
+    $this->pixelMatchResponses = $pixelMatchResponses;
+  }
+
+  public function getPixelMatchResponses()
+  {
+    return $this->pixelMatchResponses;
+  }
+
+  public function setQuotaConfiguredLimit($quotaConfiguredLimit)
+  {
+    $this->quotaConfiguredLimit = $quotaConfiguredLimit;
+  }
+
+  public function getQuotaConfiguredLimit()
+  {
+    return $this->quotaConfiguredLimit;
+  }
+
+  public function setQuotaThrottledLimit($quotaThrottledLimit)
+  {
+    $this->quotaThrottledLimit = $quotaThrottledLimit;
+  }
+
+  public function getQuotaThrottledLimit()
+  {
+    return $this->quotaThrottledLimit;
+  }
+
+  public function setRegion($region)
+  {
+    $this->region = $region;
+  }
+
+  public function getRegion()
+  {
+    return $this->region;
+  }
+
+  public function setTimestamp($timestamp)
+  {
+    $this->timestamp = $timestamp;
+  }
+
+  public function getTimestamp()
+  {
+    return $this->timestamp;
+  }
+}
+
+class Google_Service_AdExchangeBuyer_PerformanceReportList extends Google_Collection
+{
+  protected $collection_key = 'performanceReport';
+  public $kind;
+  protected $performanceReportType = 'Google_Service_AdExchangeBuyer_PerformanceReport';
+  protected $performanceReportDataType = 'array';
+
+  public function setKind($kind)
+  {
+    $this->kind = $kind;
+  }
+
+  public function getKind()
+  {
+    return $this->kind;
+  }
+
+  public function setPerformanceReport($performanceReport)
+  {
+    $this->performanceReport = $performanceReport;
+  }
+
+  public function getPerformanceReport()
+  {
+    return $this->performanceReport;
+  }
+}
+
+class Google_Service_AdExchangeBuyer_PretargetingConfig extends Google_Collection
+{
+  protected $collection_key = 'verticals';
+  public $billingId;
+  public $configId;
+  public $configName;
+  public $creativeType;
+  protected $dimensionsType = 'Google_Service_AdExchangeBuyer_PretargetingConfigDimensions';
+  protected $dimensionsDataType = 'array';
+  public $excludedContentLabels;
+  public $excludedGeoCriteriaIds;
+  protected $excludedPlacementsType = 'Google_Service_AdExchangeBuyer_PretargetingConfigExcludedPlacements';
+  protected $excludedPlacementsDataType = 'array';
+  public $excludedUserLists;
+  public $excludedVerticals;
+  public $geoCriteriaIds;
+  public $isActive;
+  public $kind;
+  public $languages;
+  public $mobileCarriers;
+  public $mobileDevices;
+  public $mobileOperatingSystemVersions;
+  protected $placementsType = 'Google_Service_AdExchangeBuyer_PretargetingConfigPlacements';
+  protected $placementsDataType = 'array';
+  public $platforms;
+  public $supportedCreativeAttributes;
+  public $userLists;
+  public $vendorTypes;
+  public $verticals;
+
+  public function setBillingId($billingId)
+  {
+    $this->billingId = $billingId;
+  }
+
+  public function getBillingId()
+  {
+    return $this->billingId;
+  }
+
+  public function setConfigId($configId)
+  {
+    $this->configId = $configId;
+  }
+
+  public function getConfigId()
+  {
+    return $this->configId;
+  }
+
+  public function setConfigName($configName)
+  {
+    $this->configName = $configName;
+  }
+
+  public function getConfigName()
+  {
+    return $this->configName;
+  }
+
+  public function setCreativeType($creativeType)
+  {
+    $this->creativeType = $creativeType;
+  }
+
+  public function getCreativeType()
+  {
+    return $this->creativeType;
+  }
+
+  public function setDimensions($dimensions)
+  {
+    $this->dimensions = $dimensions;
+  }
+
+  public function getDimensions()
+  {
+    return $this->dimensions;
+  }
+
+  public function setExcludedContentLabels($excludedContentLabels)
+  {
+    $this->excludedContentLabels = $excludedContentLabels;
+  }
+
+  public function getExcludedContentLabels()
+  {
+    return $this->excludedContentLabels;
+  }
+
+  public function setExcludedGeoCriteriaIds($excludedGeoCriteriaIds)
+  {
+    $this->excludedGeoCriteriaIds = $excludedGeoCriteriaIds;
+  }
+
+  public function getExcludedGeoCriteriaIds()
+  {
+    return $this->excludedGeoCriteriaIds;
+  }
+
+  public function setExcludedPlacements($excludedPlacements)
+  {
+    $this->excludedPlacements = $excludedPlacements;
+  }
+
+  public function getExcludedPlacements()
+  {
+    return $this->excludedPlacements;
+  }
+
+  public function setExcludedUserLists($excludedUserLists)
+  {
+    $this->excludedUserLists = $excludedUserLists;
+  }
+
+  public function getExcludedUserLists()
+  {
+    return $this->excludedUserLists;
+  }
+
+  public function setExcludedVerticals($excludedVerticals)
+  {
+    $this->excludedVerticals = $excludedVerticals;
+  }
+
+  public function getExcludedVerticals()
+  {
+    return $this->excludedVerticals;
+  }
+
+  public function setGeoCriteriaIds($geoCriteriaIds)
+  {
+    $this->geoCriteriaIds = $geoCriteriaIds;
+  }
+
+  public function getGeoCriteriaIds()
+  {
+    return $this->geoCriteriaIds;
+  }
+
+  public function setIsActive($isActive)
+  {
+    $this->isActive = $isActive;
+  }
+
+  public function getIsActive()
+  {
+    return $this->isActive;
+  }
+
+  public function setKind($kind)
+  {
+    $this->kind = $kind;
+  }
+
+  public function getKind()
+  {
+    return $this->kind;
+  }
+
+  public function setLanguages($languages)
+  {
+    $this->languages = $languages;
+  }
+
+  public function getLanguages()
+  {
+    return $this->languages;
+  }
+
+  public function setMobileCarriers($mobileCarriers)
+  {
+    $this->mobileCarriers = $mobileCarriers;
+  }
+
+  public function getMobileCarriers()
+  {
+    return $this->mobileCarriers;
+  }
+
+  public function setMobileDevices($mobileDevices)
+  {
+    $this->mobileDevices = $mobileDevices;
+  }
+
+  public function getMobileDevices()
+  {
+    return $this->mobileDevices;
+  }
+
+  public function setMobileOperatingSystemVersions($mobileOperatingSystemVersions)
+  {
+    $this->mobileOperatingSystemVersions = $mobileOperatingSystemVersions;
+  }
+
+  public function getMobileOperatingSystemVersions()
+  {
+    return $this->mobileOperatingSystemVersions;
+  }
+
+  public function setPlacements($placements)
+  {
+    $this->placements = $placements;
+  }
+
+  public function getPlacements()
+  {
+    return $this->placements;
+  }
+
+  public function setPlatforms($platforms)
+  {
+    $this->platforms = $platforms;
+  }
+
+  public function getPlatforms()
+  {
+    return $this->platforms;
+  }
+
+  public function setSupportedCreativeAttributes($supportedCreativeAttributes)
+  {
+    $this->supportedCreativeAttributes = $supportedCreativeAttributes;
+  }
+
+  public function getSupportedCreativeAttributes()
+  {
+    return $this->supportedCreativeAttributes;
+  }
+
+  public function setUserLists($userLists)
+  {
+    $this->userLists = $userLists;
+  }
+
+  public function getUserLists()
+  {
+    return $this->userLists;
+  }
+
+  public function setVendorTypes($vendorTypes)
+  {
+    $this->vendorTypes = $vendorTypes;
+  }
+
+  public function getVendorTypes()
+  {
+    return $this->vendorTypes;
+  }
+
+  public function setVerticals($verticals)
+  {
+    $this->verticals = $verticals;
+  }
+
+  public function getVerticals()
+  {
+    return $this->verticals;
+  }
+}
+
+class Google_Service_AdExchangeBuyer_PretargetingConfigDimensions extends Google_Model
+{
+  public $height;
+  public $width;
+
+  public function setHeight($height)
+  {
+    $this->height = $height;
+  }
+
+  public function getHeight()
+  {
+    return $this->height;
+  }
+
+  public function setWidth($width)
+  {
+    $this->width = $width;
+  }
+
+  public function getWidth()
+  {
+    return $this->width;
+  }
+}
+
+class Google_Service_AdExchangeBuyer_PretargetingConfigExcludedPlacements extends Google_Model
+{
+  public $token;
+  public $type;
+
+  public function setToken($token)
+  {
+    $this->token = $token;
+  }
+
+  public function getToken()
+  {
+    return $this->token;
+  }
+
+  public function setType($type)
+  {
+    $this->type = $type;
+  }
+
+  public function getType()
+  {
+    return $this->type;
+  }
+}
+
+class Google_Service_AdExchangeBuyer_PretargetingConfigList extends Google_Collection
+{
+  protected $collection_key = 'items';
+  protected $itemsType = 'Google_Service_AdExchangeBuyer_PretargetingConfig';
+  protected $itemsDataType = 'array';
+  public $kind;
+
+  public function setItems($items)
+  {
+    $this->items = $items;
+  }
+
+  public function getItems()
+  {
+    return $this->items;
+  }
+
+  public function setKind($kind)
+  {
+    $this->kind = $kind;
+  }
+
+  public function getKind()
+  {
+    return $this->kind;
+  }
+}
+
+class Google_Service_AdExchangeBuyer_PretargetingConfigPlacements extends Google_Model
+{
+  public $token;
+  public $type;
+
+  public function setToken($token)
+  {
+    $this->token = $token;
+  }
+
+  public function getToken()
+  {
+    return $this->token;
+  }
+
+  public function setType($type)
+  {
+    $this->type = $type;
+  }
+
+  public function getType()
+  {
+    return $this->type;
+  }
+}
diff --git a/lib/google/Google/Service/AdExchangeSeller.php b/lib/google/Google/Service/AdExchangeSeller.php
new file mode 100755 (executable)
index 0000000..9c1c823
--- /dev/null
@@ -0,0 +1,2006 @@
+<?php
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+/**
+ * Service definition for AdExchangeSeller (v1.1).
+ *
+ * <p>
+ * Gives Ad Exchange seller users access to their inventory and the ability to generate reports
+ * </p>
+ *
+ * <p>
+ * For more information about this service, see the API
+ * <a href="https://developers.google.com/ad-exchange/seller-rest/" target="_blank">Documentation</a>
+ * </p>
+ *
+ * @author Google, Inc.
+ */
+class Google_Service_AdExchangeSeller extends Google_Service
+{
+  /** View and manage your Ad Exchange data. */
+  const ADEXCHANGE_SELLER = "https://www.googleapis.com/auth/adexchange.seller";
+  /** View your Ad Exchange data. */
+  const ADEXCHANGE_SELLER_READONLY = "https://www.googleapis.com/auth/adexchange.seller.readonly";
+
+  public $accounts;
+  public $adclients;
+  public $adunits;
+  public $adunits_customchannels;
+  public $alerts;
+  public $customchannels;
+  public $customchannels_adunits;
+  public $metadata_dimensions;
+  public $metadata_metrics;
+  public $preferreddeals;
+  public $reports;
+  public $reports_saved;
+  public $urlchannels;
+  
+
+  /**
+   * Constructs the internal representation of the AdExchangeSeller service.
+   *
+   * @param Google_Client $client
+   */
+  public function __construct(Google_Client $client)
+  {
+    parent::__construct($client);
+    $this->servicePath = 'adexchangeseller/v1.1/';
+    $this->version = 'v1.1';
+    $this->serviceName = 'adexchangeseller';
+
+    $this->accounts = new Google_Service_AdExchangeSeller_Accounts_Resource(
+        $this,
+        $this->serviceName,
+        'accounts',
+        array(
+          'methods' => array(
+            'get' => array(
+              'path' => 'accounts/{accountId}',
+              'httpMethod' => 'GET',
+              'parameters' => array(
+                'accountId' => array(
+                  'location' => 'path',
+                  'type' => 'string',
+                  'required' => true,
+                ),
+              ),
+            ),
+          )
+        )
+    );
+    $this->adclients = new Google_Service_AdExchangeSeller_Adclients_Resource(
+        $this,
+        $this->serviceName,
+        'adclients',
+        array(
+          'methods' => array(
+            'list' => array(
+              'path' => 'adclients',
+              'httpMethod' => 'GET',
+              'parameters' => array(
+                'pageToken' => array(
+                  'location' => 'query',
+                  'type' => 'string',
+                ),
+                'maxResults' => array(
+                  'location' => 'query',
+                  'type' => 'integer',
+                ),
+              ),
+            ),
+          )
+        )
+    );
+    $this->adunits = new Google_Service_AdExchangeSeller_Adunits_Resource(
+        $this,
+        $this->serviceName,
+        'adunits',
+        array(
+          'methods' => array(
+            'get' => array(
+              'path' => 'adclients/{adClientId}/adunits/{adUnitId}',
+              'httpMethod' => 'GET',
+              'parameters' => array(
+                'adClientId' => array(
+                  'location' => 'path',
+                  'type' => 'string',
+                  'required' => true,
+                ),
+                'adUnitId' => array(
+                  'location' => 'path',
+                  'type' => 'string',
+                  'required' => true,
+                ),
+              ),
+            ),'list' => array(
+              'path' => 'adclients/{adClientId}/adunits',
+              'httpMethod' => 'GET',
+              'parameters' => array(
+                'adClientId' => array(
+                  'location' => 'path',
+                  'type' => 'string',
+                  'required' => true,
+                ),
+                'includeInactive' => array(
+                  'location' => 'query',
+                  'type' => 'boolean',
+                ),
+                'pageToken' => array(
+                  'location' => 'query',
+                  'type' => 'string',
+                ),
+                'maxResults' => array(
+                  'location' => 'query',
+                  'type' => 'integer',
+                ),
+              ),
+            ),
+          )
+        )
+    );
+    $this->adunits_customchannels = new Google_Service_AdExchangeSeller_AdunitsCustomchannels_Resource(
+        $this,
+        $this->serviceName,
+        'customchannels',
+        array(
+          'methods' => array(
+            'list' => array(
+              'path' => 'adclients/{adClientId}/adunits/{adUnitId}/customchannels',
+              'httpMethod' => 'GET',
+              'parameters' => array(
+                'adClientId' => array(
+                  'location' => 'path',
+                  'type' => 'string',
+                  'required' => true,
+                ),
+                'adUnitId' => array(
+                  'location' => 'path',
+                  'type' => 'string',
+                  'required' => true,
+                ),
+                'pageToken' => array(
+                  'location' => 'query',
+                  'type' => 'string',
+                ),
+                'maxResults' => array(
+                  'location' => 'query',
+                  'type' => 'integer',
+                ),
+              ),
+            ),
+          )
+        )
+    );
+    $this->alerts = new Google_Service_AdExchangeSeller_Alerts_Resource(
+        $this,
+        $this->serviceName,
+        'alerts',
+        array(
+          'methods' => array(
+            'list' => array(
+              'path' => 'alerts',
+              'httpMethod' => 'GET',
+              'parameters' => array(
+                'locale' => array(
+                  'location' => 'query',
+                  'type' => 'string',
+                ),
+              ),
+            ),
+          )
+        )
+    );
+    $this->customchannels = new Google_Service_AdExchangeSeller_Customchannels_Resource(
+        $this,
+        $this->serviceName,
+        'customchannels',
+        array(
+          'methods' => array(
+            'get' => array(
+              'path' => 'adclients/{adClientId}/customchannels/{customChannelId}',
+              'httpMethod' => 'GET',
+              'parameters' => array(
+                'adClientId' => array(
+                  'location' => 'path',
+                  'type' => 'string',
+                  'required' => true,
+                ),
+                'customChannelId' => array(
+                  'location' => 'path',
+                  'type' => 'string',
+                  'required' => true,
+                ),
+              ),
+            ),'list' => array(
+              'path' => 'adclients/{adClientId}/customchannels',
+              'httpMethod' => 'GET',
+              'parameters' => array(
+                'adClientId' => array(
+                  'location' => 'path',
+                  'type' => 'string',
+                  'required' => true,
+                ),
+                'pageToken' => array(
+                  'location' => 'query',
+                  'type' => 'string',
+                ),
+                'maxResults' => array(
+                  'location' => 'query',
+                  'type' => 'integer',
+                ),
+              ),
+            ),
+          )
+        )
+    );
+    $this->customchannels_adunits = new Google_Service_AdExchangeSeller_CustomchannelsAdunits_Resource(
+        $this,
+        $this->serviceName,
+        'adunits',
+        array(
+          'methods' => array(
+            'list' => array(
+              'path' => 'adclients/{adClientId}/customchannels/{customChannelId}/adunits',
+              'httpMethod' => 'GET',
+              'parameters' => array(
+                'adClientId' => array(
+                  'location' => 'path',
+                  'type' => 'string',
+                  'required' => true,
+                ),
+                'customChannelId' => array(
+                  'location' => 'path',
+                  'type' => 'string',
+                  'required' => true,
+                ),
+                'includeInactive' => array(
+                  'location' => 'query',
+                  'type' => 'boolean',
+                ),
+                'pageToken' => array(
+                  'location' => 'query',
+                  'type' => 'string',
+                ),
+                'maxResults' => array(
+                  'location' => 'query',
+                  'type' => 'integer',
+                ),
+              ),
+            ),
+          )
+        )
+    );
+    $this->metadata_dimensions = new Google_Service_AdExchangeSeller_MetadataDimensions_Resource(
+        $this,
+        $this->serviceName,
+        'dimensions',
+        array(
+          'methods' => array(
+            'list' => array(
+              'path' => 'metadata/dimensions',
+              'httpMethod' => 'GET',
+              'parameters' => array(),
+            ),
+          )
+        )
+    );
+    $this->metadata_metrics = new Google_Service_AdExchangeSeller_MetadataMetrics_Resource(
+        $this,
+        $this->serviceName,
+        'metrics',
+        array(
+          'methods' => array(
+            'list' => array(
+              'path' => 'metadata/metrics',
+              'httpMethod' => 'GET',
+              'parameters' => array(),
+            ),
+          )
+        )
+    );
+    $this->preferreddeals = new Google_Service_AdExchangeSeller_Preferreddeals_Resource(
+        $this,
+        $this->serviceName,
+        'preferreddeals',
+        array(
+          'methods' => array(
+            'get' => array(
+              'path' => 'preferreddeals/{dealId}',
+              'httpMethod' => 'GET',
+              'parameters' => array(
+                'dealId' => array(
+                  'location' => 'path',
+                  'type' => 'string',
+                  'required' => true,
+                ),
+              ),
+            ),'list' => array(
+              'path' => 'preferreddeals',
+              'httpMethod' => 'GET',
+              'parameters' => array(),
+            ),
+          )
+        )
+    );
+    $this->reports = new Google_Service_AdExchangeSeller_Reports_Resource(
+        $this,
+        $this->serviceName,
+        'reports',
+        array(
+          'methods' => array(
+            'generate' => array(
+              'path' => 'reports',
+              'httpMethod' => 'GET',
+              'parameters' => array(
+                'startDate' => array(
+                  'location' => 'query',
+                  'type' => 'string',
+                  'required' => true,
+                ),
+                'endDate' => array(
+                  'location' => 'query',
+                  'type' => 'string',
+                  'required' => true,
+                ),
+                'sort' => array(
+                  'location' => 'query',
+                  'type' => 'string',
+                  'repeated' => true,
+                ),
+                'locale' => array(
+                  'location' => 'query',
+                  'type' => 'string',
+                ),
+                'metric' => array(
+                  'location' => 'query',
+                  'type' => 'string',
+                  'repeated' => true,
+                ),
+                'maxResults' => array(
+                  'location' => 'query',
+                  'type' => 'integer',
+                ),
+                'filter' => array(
+                  'location' => 'query',
+                  'type' => 'string',
+                  'repeated' => true,
+                ),
+                'startIndex' => array(
+                  'location' => 'query',
+                  'type' => 'integer',
+                ),
+                'dimension' => array(
+                  'location' => 'query',
+                  'type' => 'string',
+                  'repeated' => true,
+                ),
+              ),
+            ),
+          )
+        )
+    );
+    $this->reports_saved = new Google_Service_AdExchangeSeller_ReportsSaved_Resource(
+        $this,
+        $this->serviceName,
+        'saved',
+        array(
+          'methods' => array(
+            'generate' => array(
+              'path' => 'reports/{savedReportId}',
+              'httpMethod' => 'GET',
+              'parameters' => array(
+                'savedReportId' => array(
+                  'location' => 'path',
+                  'type' => 'string',
+                  'required' => true,
+                ),
+                'locale' => array(
+                  'location' => 'query',
+                  'type' => 'string',
+                ),
+                'startIndex' => array(
+                  'location' => 'query',
+                  'type' => 'integer',
+                ),
+                'maxResults' => array(
+                  'location' => 'query',
+                  'type' => 'integer',
+                ),
+              ),
+            ),'list' => array(
+              'path' => 'reports/saved',
+              'httpMethod' => 'GET',
+              'parameters' => array(
+                'pageToken' => array(
+                  'location' => 'query',
+                  'type' => 'string',
+                ),
+                'maxResults' => array(
+                  'location' => 'query',
+                  'type' => 'integer',
+                ),
+              ),
+            ),
+          )
+        )
+    );
+    $this->urlchannels = new Google_Service_AdExchangeSeller_Urlchannels_Resource(
+        $this,
+        $this->serviceName,
+        'urlchannels',
+        array(
+          'methods' => array(
+            'list' => array(
+              'path' => 'adclients/{adClientId}/urlchannels',
+              'httpMethod' => 'GET',
+              'parameters' => array(
+                'adClientId' => array(
+                  'location' => 'path',
+                  'type' => 'string',
+                  'required' => true,
+                ),
+                'pageToken' => array(
+                  'location' => 'query',
+                  'type' => 'string',
+                ),
+                'maxResults' => array(
+                  'location' => 'query',
+                  'type' => 'integer',
+                ),
+              ),
+            ),
+          )
+        )
+    );
+  }
+}
+
+
+/**
+ * The "accounts" collection of methods.
+ * Typical usage is:
+ *  <code>
+ *   $adexchangesellerService = new Google_Service_AdExchangeSeller(...);
+ *   $accounts = $adexchangesellerService->accounts;
+ *  </code>
+ */
+class Google_Service_AdExchangeSeller_Accounts_Resource extends Google_Service_Resource
+{
+
+  /**
+   * Get information about the selected Ad Exchange account. (accounts.get)
+   *
+   * @param string $accountId
+   * Account to get information about. Tip: 'myaccount' is a valid ID.
+   * @param array $optParams Optional parameters.
+   * @return Google_Service_AdExchangeSeller_Account
+   */
+  public function get($accountId, $optParams = array())
+  {
+    $params = array('accountId' => $accountId);
+    $params = array_merge($params, $optParams);
+    return $this->call('get', array($params), "Google_Service_AdExchangeSeller_Account");
+  }
+}
+
+/**
+ * The "adclients" collection of methods.
+ * Typical usage is:
+ *  <code>
+ *   $adexchangesellerService = new Google_Service_AdExchangeSeller(...);
+ *   $adclients = $adexchangesellerService->adclients;
+ *  </code>
+ */
+class Google_Service_AdExchangeSeller_Adclients_Resource extends Google_Service_Resource
+{
+
+  /**
+   * List all ad clients in this Ad Exchange account. (adclients.listAdclients)
+   *
+   * @param array $optParams Optional parameters.
+   *
+   * @opt_param string pageToken
+   * A continuation token, used to page through ad clients. To retrieve the next page, set this
+    * parameter to the value of "nextPageToken" from the previous response.
+   * @opt_param string maxResults
+   * The maximum number of ad clients to include in the response, used for paging.
+   * @return Google_Service_AdExchangeSeller_AdClients
+   */
+  public function listAdclients($optParams = array())
+  {
+    $params = array();
+    $params = array_merge($params, $optParams);
+    return $this->call('list', array($params), "Google_Service_AdExchangeSeller_AdClients");
+  }
+}
+
+/**
+ * The "adunits" collection of methods.
+ * Typical usage is:
+ *  <code>
+ *   $adexchangesellerService = new Google_Service_AdExchangeSeller(...);
+ *   $adunits = $adexchangesellerService->adunits;
+ *  </code>
+ */
+class Google_Service_AdExchangeSeller_Adunits_Resource extends Google_Service_Resource
+{
+
+  /**
+   * Gets the specified ad unit in the specified ad client. (adunits.get)
+   *
+   * @param string $adClientId
+   * Ad client for which to get the ad unit.
+   * @param string $adUnitId
+   * Ad unit to retrieve.
+   * @param array $optParams Optional parameters.
+   * @return Google_Service_AdExchangeSeller_AdUnit
+   */
+  public function get($adClientId, $adUnitId, $optParams = array())
+  {
+    $params = array('adClientId' => $adClientId, 'adUnitId' => $adUnitId);
+    $params = array_merge($params, $optParams);
+    return $this->call('get', array($params), "Google_Service_AdExchangeSeller_AdUnit");
+  }
+  /**
+   * List all ad units in the specified ad client for this Ad Exchange account.
+   * (adunits.listAdunits)
+   *
+   * @param string $adClientId
+   * Ad client for which to list ad units.
+   * @param array $optParams Optional parameters.
+   *
+   * @opt_param bool includeInactive
+   * Whether to include inactive ad units. Default: true.
+   * @opt_param string pageToken
+   * A continuation token, used to page through ad units. To retrieve the next page, set this
+    * parameter to the value of "nextPageToken" from the previous response.
+   * @opt_param string maxResults
+   * The maximum number of ad units to include in the response, used for paging.
+   * @return Google_Service_AdExchangeSeller_AdUnits
+   */
+  public function listAdunits($adClientId, $optParams = array())
+  {
+    $params = array('adClientId' => $adClientId);
+    $params = array_merge($params, $optParams);
+    return $this->call('list', array($params), "Google_Service_AdExchangeSeller_AdUnits");
+  }
+}
+
+/**
+ * The "customchannels" collection of methods.
+ * Typical usage is:
+ *  <code>
+ *   $adexchangesellerService = new Google_Service_AdExchangeSeller(...);
+ *   $customchannels = $adexchangesellerService->customchannels;
+ *  </code>
+ */
+class Google_Service_AdExchangeSeller_AdunitsCustomchannels_Resource extends Google_Service_Resource
+{
+
+  /**
+   * List all custom channels which the specified ad unit belongs to.
+   * (customchannels.listAdunitsCustomchannels)
+   *
+   * @param string $adClientId
+   * Ad client which contains the ad unit.
+   * @param string $adUnitId
+   * Ad unit for which to list custom channels.
+   * @param array $optParams Optional parameters.
+   *
+   * @opt_param string pageToken
+   * A continuation token, used to page through custom channels. To retrieve the next page, set this
+    * parameter to the value of "nextPageToken" from the previous response.
+   * @opt_param string maxResults
+   * The maximum number of custom channels to include in the response, used for paging.
+   * @return Google_Service_AdExchangeSeller_CustomChannels
+   */
+  public function listAdunitsCustomchannels($adClientId, $adUnitId, $optParams = array())
+  {
+    $params = array('adClientId' => $adClientId, 'adUnitId' => $adUnitId);
+    $params = array_merge($params, $optParams);
+    return $this->call('list', array($params), "Google_Service_AdExchangeSeller_CustomChannels");
+  }
+}
+
+/**
+ * The "alerts" collection of methods.
+ * Typical usage is:
+ *  <code>
+ *   $adexchangesellerService = new Google_Service_AdExchangeSeller(...);
+ *   $alerts = $adexchangesellerService->alerts;
+ *  </code>
+ */
+class Google_Service_AdExchangeSeller_Alerts_Resource extends Google_Service_Resource
+{
+
+  /**
+   * List the alerts for this Ad Exchange account. (alerts.listAlerts)
+   *
+   * @param array $optParams Optional parameters.
+   *
+   * @opt_param string locale
+   * The locale to use for translating alert messages. The account locale will be used if this is not
+    * supplied. The AdSense default (English) will be used if the supplied locale is invalid or
+    * unsupported.
+   * @return Google_Service_AdExchangeSeller_Alerts
+   */
+  public function listAlerts($optParams = array())
+  {
+    $params = array();
+    $params = array_merge($params, $optParams);
+    return $this->call('list', array($params), "Google_Service_AdExchangeSeller_Alerts");
+  }
+}
+
+/**
+ * The "customchannels" collection of methods.
+ * Typical usage is:
+ *  <code>
+ *   $adexchangesellerService = new Google_Service_AdExchangeSeller(...);
+ *   $customchannels = $adexchangesellerService->customchannels;
+ *  </code>
+ */
+class Google_Service_AdExchangeSeller_Customchannels_Resource extends Google_Service_Resource
+{
+
+  /**
+   * Get the specified custom channel from the specified ad client.
+   * (customchannels.get)
+   *
+   * @param string $adClientId
+   * Ad client which contains the custom channel.
+   * @param string $customChannelId
+   * Custom channel to retrieve.
+   * @param array $optParams Optional parameters.
+   * @return Google_Service_AdExchangeSeller_CustomChannel
+   */
+  public function get($adClientId, $customChannelId, $optParams = array())
+  {
+    $params = array('adClientId' => $adClientId, 'customChannelId' => $customChannelId);
+    $params = array_merge($params, $optParams);
+    return $this->call('get', array($params), "Google_Service_AdExchangeSeller_CustomChannel");
+  }
+  /**
+   * List all custom channels in the specified ad client for this Ad Exchange
+   * account. (customchannels.listCustomchannels)
+   *
+   * @param string $adClientId
+   * Ad client for which to list custom channels.
+   * @param array $optParams Optional parameters.
+   *
+   * @opt_param string pageToken
+   * A continuation token, used to page through custom channels. To retrieve the next page, set this
+    * parameter to the value of "nextPageToken" from the previous response.
+   * @opt_param string maxResults
+   * The maximum number of custom channels to include in the response, used for paging.
+   * @return Google_Service_AdExchangeSeller_CustomChannels
+   */
+  public function listCustomchannels($adClientId, $optParams = array())
+  {
+    $params = array('adClientId' => $adClientId);
+    $params = array_merge($params, $optParams);
+    return $this->call('list', array($params), "G