PageRenderTime 298ms CodeModel.GetById 39ms RepoModel.GetById 0ms app.codeStats 0ms

/demo/scalr/app/src/api/2.2.0/class.ScalrAPICore.php

https://github.com/kennethjiang/Wolke
PHP | 323 lines | 265 code | 46 blank | 12 comment | 55 complexity | 89ad69dd4948c85130fe30d38a548f66 MD5 | raw file
  1. <?php
  2. define("API_SERVER_IP", "174.132.108.66");
  3. abstract class ScalrAPICore
  4. {
  5. const HASH_ALGO = 'SHA256';
  6. protected $Request;
  7. /**
  8. *
  9. * @var Client
  10. */
  11. protected $Client;
  12. /**
  13. *
  14. * @var Scalr_Environment
  15. */
  16. protected $Environment;
  17. protected $DB;
  18. protected $Logger;
  19. public $Version;
  20. protected $debug = array();
  21. protected $LastTransactionID;
  22. function __construct($version)
  23. {
  24. $this->DB = Core::GetDBInstance();
  25. $this->Logger = Logger::getLogger(__CLASS__);
  26. $this->Version = $version;
  27. }
  28. protected function insensitiveUksort($a,$b) {
  29. return strtolower($a)>strtolower($b);
  30. }
  31. private function AuthenticateRESTv2($request)
  32. {
  33. if (!$request['Signature'])
  34. throw new Exception("Signature is missing");
  35. if (!$request['KeyID'])
  36. throw new Exception("KeyID is missing");
  37. if (!$request['Timestamp'] && !$request['TimeStamp'])
  38. throw new Exception("Timestamp is missing");
  39. foreach ($request as $k=>$v)
  40. {
  41. if (is_array($v))
  42. {
  43. foreach ($v as $kk => $vv)
  44. $request["{$k}[{$kk}]"] = $vv;
  45. unset($request[$k]);
  46. }
  47. }
  48. uksort($request, array($this, 'insensitiveUksort'));
  49. $string_to_sign = "";
  50. foreach ($request as $k=>$v)
  51. {
  52. if (!in_array($k, array("Signature", "SysDebug"))) {
  53. if (is_array($v)) {
  54. foreach ($v as $kk => $vv) {
  55. $string_to_sign.= "{$k}[{$kk}]{$vv}";
  56. }
  57. }
  58. else {
  59. $string_to_sign.= "{$k}{$v}";
  60. }
  61. }
  62. }
  63. $this->debug['stringToSign'] = $string_to_sign;
  64. $this->Environment = Scalr_Model::init(Scalr_Model::ENVIRONMENT)->loadByApiKeyId($request['KeyID']);
  65. $this->Client = Client::Load($this->Environment->clientId);
  66. $auth_key = $this->Environment->getPlatformConfigValue(ENVIRONMENT_SETTINGS::API_ACCESS_KEY, false);
  67. $valid_sign = base64_encode(hash_hmac(self::HASH_ALGO, trim($string_to_sign), $auth_key, 1));
  68. $request['Signature'] = str_replace(" ", "+", $request['Signature']);
  69. $this->debug['reqSignature'] = $request['Signature'];
  70. $this->debug['validSignature'] = $valid_sign;
  71. if ($valid_sign != $request['Signature'])
  72. throw new Exception("Signature doesn't match");
  73. }
  74. private function AuthenticateREST($request)
  75. {
  76. if (!$request['Signature'])
  77. throw new Exception("Signature is missing");
  78. if (!$request['KeyID'])
  79. throw new Exception("KeyID is missing");
  80. if (!$request['Timestamp'] && !$request['TimeStamp'])
  81. throw new Exception("Timestamp is missing");
  82. ksort($request);
  83. $string_to_sign = "";
  84. foreach ($request as $k=>$v) {
  85. if (!in_array($k, array("Signature"))) {
  86. if (is_array($v)) {
  87. foreach ($v as $kk => $vv) {
  88. $string_to_sign.= "{$k}[{$kk}]{$vv}";
  89. }
  90. }
  91. else {
  92. $string_to_sign.= "{$k}{$v}";
  93. }
  94. }
  95. }
  96. $this->debug['stringToSign'] = $string_to_sign;
  97. $this->Environment = Scalr_Model::init(Scalr_Model::ENVIRONMENT)->loadByApiKeyId($request['KeyID']);
  98. $this->Client = Client::Load($this->Environment->clientId);
  99. $auth_key = $this->Environment->getPlatformConfigValue(ENVIRONMENT_SETTINGS::API_ACCESS_KEY, false);
  100. $valid_sign = base64_encode(hash_hmac(self::HASH_ALGO, trim($string_to_sign), $auth_key, 1));
  101. if ($valid_sign != $request['Signature'])
  102. throw new Exception("Signature doesn't match " . $string_to_sign );
  103. }
  104. public function BuildRestServer($request)
  105. {
  106. try
  107. {
  108. $Reflect = new ReflectionObject($this);
  109. if ($Reflect->hasMethod($request['Action']))
  110. {
  111. //Authenticate
  112. if ($request['AuthVersion'] == 2)
  113. $this->AuthenticateRESTv2($request);
  114. else
  115. $this->AuthenticateREST($request);
  116. if ($this->Environment->getPlatformConfigValue(ENVIRONMENT_SETTINGS::API_ENABLED) != 1)
  117. throw new Exception(_("API disabled for you. You can enable it at 'Settings -> Environments'"));
  118. //Check IP Addresses
  119. if ($this->Environment->getPlatformConfigValue(ENVIRONMENT_SETTINGS::API_ALLOWED_IPS))
  120. {
  121. $ips = explode(",", $this->Environment->getPlatformConfigValue(ENVIRONMENT_SETTINGS::API_ALLOWED_IPS));
  122. if (!$this->IPAccessCheck($ips) && $_SERVER['REMOTE_ADDR'] != API_SERVER_IP)
  123. throw new Exception(sprintf(_("Access to the API is not allowed from your IP '%s'"), $_SERVER['REMOTE_ADDR']));
  124. }
  125. //Execute API call
  126. $ReflectMethod = $Reflect->getMethod($request['Action']);
  127. $args = array();
  128. foreach ($ReflectMethod->getParameters() as $param)
  129. {
  130. if (!$param->isOptional() && !isset($request[$param->getName()]))
  131. throw new Exception(sprintf("Missing required parameter '%s'", $param->getName()));
  132. else
  133. $args[$param->getName()] = $request[$param->getName()];
  134. }
  135. $result = $ReflectMethod->invokeArgs($this, $args);
  136. $this->LastTransactionID = $result->TransactionID;
  137. // Create response
  138. $DOMDocument = new DOMDocument('1.0', 'UTF-8');
  139. $DOMDocument->loadXML("<{$request['Action']}Response></{$request['Action']}Response>");
  140. $this->ObjectToXML($result, $DOMDocument->documentElement, $DOMDocument);
  141. $retval = $DOMDocument->saveXML();
  142. }
  143. else
  144. throw new Exception(sprintf("Action '%s' is not defined", $request['Action']));
  145. }
  146. catch(Exception $e)
  147. {
  148. if (!$this->LastTransactionID)
  149. $this->LastTransactionID = Scalr::GenerateUID();
  150. if ($request['SysDebug'])
  151. {
  152. $debugInfo = "<StringToSign>{$this->debug['stringToSign']}</StringToSign>";
  153. $debugInfo .= "<reqSignature>{$this->debug['reqSignature']}</reqSignature>";
  154. $debugInfo .= "<validSignature>{$this->debug['validSignature']}</validSignature>";
  155. }
  156. $retval = "<?xml version=\"1.0\"?>\n".
  157. "<Error>\n".
  158. "\t<TransactionID>{$this->LastTransactionID}</TransactionID>\n".
  159. "\t<Message>{$e->getMessage()}</Message>\n".
  160. $debugInfo.
  161. "</Error>\n";
  162. }
  163. $this->LogRequest(
  164. $this->LastTransactionID,
  165. $request['Action'],
  166. (($_SERVER['REMOTE_ADDR'] == API_SERVER_IP) ? 'Mobile app' : $_SERVER['REMOTE_ADDR']),
  167. $request,
  168. $retval
  169. );
  170. header("Content-type: text/xml");
  171. header("Content-length: ".strlen($retval));
  172. print $retval;
  173. }
  174. protected function LogRequest($trans_id, $action, $ipaddr, $request, $response)
  175. {
  176. if ($request['debug'] == 1 || $request['Debug'] == 1)
  177. {
  178. try
  179. {
  180. $this->DB->Execute("INSERT INTO api_log SET
  181. transaction_id = ?,
  182. dtadded = ?,
  183. action = ?,
  184. ipaddress = ?,
  185. request = ?,
  186. response = ?,
  187. clientid = ?,
  188. env_id = ?
  189. ",array(
  190. $trans_id,
  191. time(),
  192. $action,
  193. $ipaddr,
  194. http_build_query($request),
  195. $response,
  196. $this->Client->ID,
  197. $this->Environment->id
  198. ));
  199. }
  200. catch(Exception $e) {}
  201. }
  202. }
  203. protected function IPAccessCheck($allowed_ips)
  204. {
  205. $current_ip = $_SERVER['REMOTE_ADDR'];
  206. $current_ip_parts = explode(".", $current_ip);
  207. foreach ($allowed_ips as $allowed_ip)
  208. {
  209. $allowedhost = trim($allowed_ip);
  210. if ($allowedhost == '')
  211. continue;
  212. if (preg_match("/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/si", $allowedhost))
  213. {
  214. if (ip2long($allowedhost) == ip2long($current_ip))
  215. return true;
  216. }
  217. elseif (stristr($allowedhost, "*"))
  218. {
  219. $ip_parts = explode(".", trim($allowedhost));
  220. if (
  221. ($ip_parts[0] == "*" || $ip_parts[0] == $current_ip_parts[0]) &&
  222. ($ip_parts[1] == "*" || $ip_parts[1] == $current_ip_parts[1]) &&
  223. ($ip_parts[2] == "*" || $ip_parts[2] == $current_ip_parts[2]) &&
  224. ($ip_parts[3] == "*" || $ip_parts[3] == $current_ip_parts[3])
  225. )
  226. return true;
  227. }
  228. else
  229. {
  230. $ip = @gethostbyname($allowedhost);
  231. if ($ip != $allowedhost)
  232. {
  233. if (ip2long($ip) == ip2long($current_ip))
  234. return true;
  235. }
  236. }
  237. }
  238. return false;
  239. }
  240. protected function ObjectToXML($obj, &$DOMElement, &$DOMDocument)
  241. {
  242. if (is_object($obj) || is_array($obj))
  243. {
  244. foreach ($obj as $k=>$v)
  245. {
  246. if (is_object($v))
  247. $this->ObjectToXML($v, $DOMElement->appendChild($DOMDocument->createElement($k)), $DOMDocument);
  248. elseif (is_array($v))
  249. foreach ($v as $vv)
  250. {
  251. $e = &$DOMElement->appendChild($DOMDocument->createElement($k));
  252. $this->ObjectToXML($vv, $e, $DOMDocument);
  253. }
  254. else
  255. $DOMElement->appendChild($DOMDocument->createElement($k, $v));
  256. }
  257. }
  258. else
  259. $DOMElement->appendChild($DOMDocument->createTextNode($obj));
  260. }
  261. protected function CreateInitialResponse()
  262. {
  263. $response = new stdClass();
  264. $response->{"TransactionID"} = Scalr::GenerateUID();
  265. return $response;
  266. }
  267. }
  268. ?>