PageRenderTime 49ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/OpenVBX/libraries/GoogleUtilityClient.php

https://github.com/ibnoe/OpenVBX
PHP | 329 lines | 249 code | 55 blank | 25 comment | 16 complexity | d5cc046dab987c53305e6a24df34280e MD5 | raw file
  1. <?php
  2. /**
  3. * "The contents of this file are subject to the Mozilla Public License
  4. * Version 1.1 (the "License"); you may not use this file except in
  5. * compliance with the License. You may obtain a copy of the License at
  6. * http://www.mozilla.org/MPL/
  7. * Software distributed under the License is distributed on an "AS IS"
  8. * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
  9. * License for the specific language governing rights and limitations
  10. * under the License.
  11. * The Original Code is OpenVBX, released June 15, 2010.
  12. * The Initial Developer of the Original Code is Twilio Inc.
  13. * Portions created by Twilio Inc. are Copyright (C) 2010.
  14. * All Rights Reserved.
  15. * Contributor(s):
  16. */
  17. class GoogleUtilityClientException extends Exception {}
  18. class GoogleLoginChallenge
  19. {
  20. public static $errors = array(
  21. 'BadAuthentication' => 'The login request used a username or password that is not recognized.',
  22. 'NotVerified' => 'The account email address has not been verified. The user will need to access their Google account directly to resolve the issue before logging in using a non-Google application.',
  23. 'TermsNotAgreed' => 'The user has not agreed to terms. The user will need to access their Google account directly to resolve the issue before logging in using a non-Google application. ',
  24. 'CaptchaRequired' => 'A CAPTCHA is required. (A response with this error code will also contain an image URL and a CAPTCHA token.)',
  25. 'ServiceUnavailable' => 'The service is not available; try again later.',
  26. 'ServiceDisabled' => 'The user\'s access to the specified service has been disabled. (The user account may still be valid.)',
  27. 'AccountDisabled' => 'The user account has been disabled.',
  28. 'AccountDeleted' => 'The user account has been deleted.',
  29. 'Unknown' => 'The error is unknown or unspecified; the request contained invalid input or was malformed.',
  30. );
  31. public static $public_errors = array(
  32. 'BadAuthentication' => 'Email or password were incorrect',
  33. 'NotVerified' => 'The account email address has not been verified. The user will need to access their Google account directly to resolve the issue before logging in using a non-Google application.',
  34. 'TermsNotAgreed' => 'The user has not agreed to terms. The user will need to access their Google account directly to resolve the issue before logging in using a non-Google application. ',
  35. 'CaptchaRequired' => 'A CAPTCHA is required.',
  36. 'ServiceUnavailable' => 'The service is not available; try again later.',
  37. 'ServiceDisabled' => 'The user\'s access to the specified service has been disabled. (The user account may still be valid.)',
  38. 'AccountDisabled' => 'The user account has been disabled.',
  39. 'AccountDeleted' => 'The user account has been deleted.',
  40. 'Unknown' => 'The error is unknown or unspecified; the request contained invalid input or was malformed.',
  41. );
  42. public static function get_error_message($key)
  43. {
  44. return self::$public_errors[$key];
  45. }
  46. public static function get_error_code($key)
  47. {
  48. $error_keys = array_keys(self::$errors);
  49. return array_search($key, $error_keys);
  50. }
  51. public static function get_error($code) {
  52. $error_keys = array_keys(self::$errors);
  53. return $error_keys[$code];
  54. }
  55. }
  56. class GoogleUtilityClient
  57. {
  58. public $domain;
  59. private static $curl = null;
  60. private $authenticated = false;
  61. private $auth_token;
  62. private $api_key;
  63. private $api_secret;
  64. private $account_type;
  65. private $login_token;
  66. private $login_captcha;
  67. private $memcache;
  68. public function __construct($api_key,
  69. $api_secret,
  70. $account_type = 'HOSTED_OR_GOOGLE',
  71. $login_captcha = '',
  72. $login_token = '',
  73. $cache_config = NULL)
  74. {
  75. $this->api_key = $api_key;
  76. $this->api_secret = $api_secret;
  77. $this->login_token = $login_token;
  78. $this->login_captcha = $login_captcha;
  79. $this->account_type = $account_type;
  80. $keys = explode('@', $this->api_key);
  81. if(count($keys) == 2)
  82. {
  83. $this->domain = $keys[1];
  84. }
  85. if(empty($this->domain))
  86. {
  87. throw new GoogleUtilityClientException('Invalid api_key');
  88. }
  89. if(!empty($cache_config))
  90. {
  91. $this->setup_memcache($cache_config['memcache_servers'],
  92. $cache_config['memcache_port'],
  93. $cache_config['key_prefix']);
  94. }
  95. }
  96. public function setup_memcache($memcache_servers, $memcache_port, $key_prefix)
  97. {
  98. $this->memcache = new Memcache();
  99. foreach ($memcache_servers as $memcache_server)
  100. {
  101. $this->memcache->addServer($memcache_server, $memcache_port);
  102. }
  103. $this->key_prefix = $key_prefix;
  104. }
  105. public function build_key($url, $req_per_hour=1)
  106. {
  107. $stamp = intval(time() * ($req_per_hour / 3600));
  108. return $this->key_prefix . ':' . $stamp . ':' . $url;
  109. }
  110. function fetch($url, $method, $args, $req_per_hour=1)
  111. {
  112. if(!$this->memcache)
  113. {
  114. return $this->perform_request($url, $method, $args);
  115. }
  116. $key = $this->build_key($url, $req_per_hour);
  117. $value = $this->memcache->get($key);
  118. if (!$value)
  119. {
  120. $value = $this->perform_request($url, $method, $args);
  121. $value = json_encode($value);
  122. $this->memcache->set($key, $value);
  123. }
  124. if (!$value)
  125. {
  126. return null;
  127. }
  128. return json_decode($value, true);
  129. }
  130. public function perform_request($url, $method, $args)
  131. {
  132. $method = strtoupper($method);
  133. switch($method)
  134. {
  135. case 'GET':
  136. break;
  137. case 'UPDATE':
  138. case 'DELETE':
  139. case 'PUT':
  140. curl_setopt(self::$curl, CURLOPT_CUSTOMREQUEST, $method);
  141. break;
  142. case 'POST':
  143. curl_setopt(self::$curl, CURLOPT_POSTFIELDS, http_build_query($args));
  144. curl_setopt(self::$curl, CURLOPT_POST, true);
  145. break;
  146. }
  147. // Send the HTTP request.
  148. curl_setopt(self::$curl, CURLOPT_URL, $url);
  149. curl_setopt(self::$curl, CURLOPT_RETURNTRANSFER, true);
  150. curl_setopt(self::$curl, CURLOPT_HTTPHEADER, array('Content-Type: application/atom+xml',
  151. 'Authorization: GoogleLogin auth='.$this->auth_token));
  152. $response = curl_exec(self::$curl);
  153. // Throw an exception on connection failure.
  154. if (!$response) throw new GoogleAuthenticationClientError('Connection failed');
  155. // Deserialize the response string and store the result.
  156. $result = self::response_decode($response);
  157. return $result;
  158. }
  159. public function authenticate()
  160. {
  161. $auth_url = "https://www.google.com/accounts/ClientLogin";
  162. if (is_null(self::$curl))
  163. {
  164. self::$curl = curl_init();
  165. }
  166. $args = array(
  167. 'Email' => $this->api_key,
  168. 'Passwd' => $this->api_secret,
  169. 'accountType' => $this->account_type,
  170. 'service' => 'apps',
  171. 'source' => 'twilio-openVBX-1.0',
  172. 'logintoken' => $this->login_token,
  173. 'logincaptcha' => $this->login_captcha,
  174. );
  175. error_log(var_export($args, true));
  176. curl_setopt(self::$curl, CURLOPT_HTTPHEADER, array('Content-Type: application/x-www-form-urlencoded'));
  177. curl_setopt(self::$curl, CURLOPT_POST, true);
  178. curl_setopt(self::$curl, CURLOPT_POSTFIELDS, http_build_query($args));
  179. curl_setopt(self::$curl, CURLOPT_RETURNTRANSFER, true);
  180. curl_setopt(self::$curl, CURLOPT_URL, $auth_url);
  181. $response = curl_exec(self::$curl);
  182. $response = explode("\n", $response);
  183. $auth_response = array();
  184. foreach($response as $response_pair)
  185. {
  186. $response_pair = explode('=', $response_pair);
  187. $auth_response[$response_pair[0]] = isset($response_pair[1])? $response_pair[1] : '';
  188. $auth_response[$response_pair[0]] .= isset($response_pair[2])? '='.$response_pair[2] : '';
  189. }
  190. if(!empty($auth_response['Auth']))
  191. {
  192. $this->auth_token = $auth_response['Auth'];
  193. $this->authenticated = true;
  194. return $this->authenticated;
  195. }
  196. if(!empty($auth_response['Error']))
  197. {
  198. $this->auth_response = $auth_response;
  199. $error_code = GoogleLoginChallenge::get_error_code($auth_response['Error']);
  200. $error_message = GoogleLoginChallenge::get_error_message($auth_response['Error']);
  201. throw new GoogleUtilityClientException($error_message, $error_code);
  202. }
  203. }
  204. public function __call($method, $args)
  205. {
  206. static $api_cumulative_time = 0;
  207. $time = microtime(true);
  208. // Initialize CURL
  209. self::$curl = curl_init();
  210. if(isset($args[0]))
  211. {
  212. $name = $args[0];
  213. }
  214. if(isset($args[1]))
  215. {
  216. $args = $args[1];
  217. }
  218. curl_setopt(self::$curl, CURLOPT_HTTPHEADER, array('Content-type: application/atom+xml',
  219. 'Authorization: GoogleLogin auth='.$this->auth_token));
  220. if(preg_match('/^(http)/', $name, $matches) > 0)
  221. {
  222. $url = $name;
  223. }
  224. else
  225. {
  226. $url = 'https://apps-apis.google.com/a/feeds'
  227. . '/'
  228. . $name;
  229. }
  230. $response = $this->fetch($url, $method, $args);
  231. // If the response is a hash containing a key called 'error', assume
  232. // that an error occurred on the other end and throw an exception.
  233. if (isset($response['error']))
  234. {
  235. throw new GoogleAuthenticationClientError($response['error'], $response['code']);
  236. }
  237. else
  238. {
  239. return $response['result'];
  240. }
  241. }
  242. function response_decode($xml)
  243. {
  244. $error = NULL;
  245. $result = NULL;
  246. $doc = @DOMDocument::loadXML($xml);
  247. if(!$doc)
  248. {
  249. throw new GoogleUtilityClientError('Server Unavailable', 500);
  250. }
  251. $result["list"] = $doc;
  252. return array("result" => $result);
  253. }
  254. }
  255. class GoogleUtilityClientNSWrapper
  256. {
  257. private $object;
  258. private $ns;
  259. function __construct($obj, $ns)
  260. {
  261. $this->object = $obj;
  262. $this->ns = $ns;
  263. }
  264. function __call($method, $args)
  265. {
  266. $args = array_merge(array($this->ns), $args);
  267. return call_user_func_array(array($this->object, $method), $args);
  268. }
  269. }
  270. ?>