2
0

Abstract.php 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. <?php
  2. /**
  3. * Zend Framework
  4. *
  5. * LICENSE
  6. *
  7. * This source file is subject to the new BSD license that is bundled
  8. * with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://framework.zend.com/license/new-bsd
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@zend.com so we can send you a copy immediately.
  14. *
  15. * @category Zend
  16. * @package Zend_Service_Amazon
  17. * @subpackage Ec2
  18. * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
  19. * @license http://framework.zend.com/license/new-bsd New BSD License
  20. * @version $Id$
  21. */
  22. /**
  23. * @see Zend_Service_Amazon_Abstract
  24. */
  25. require_once 'Zend/Service/Amazon/Abstract.php';
  26. /**
  27. * @see Zend_Service_Amazon_Ec2_Response
  28. */
  29. require_once 'Zend/Service/Amazon/Ec2/Response.php';
  30. /**
  31. * @see Zend_Service_Amazon_Ec2_Exception
  32. */
  33. require_once 'Zend/Service/Amazon/Ec2/Exception.php';
  34. /**
  35. * Provides the basic functionality to send a request to the Amazon Ec2 Query API
  36. *
  37. * @category Zend
  38. * @package Zend_Service_Amazon
  39. * @subpackage Ec2
  40. * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
  41. * @license http://framework.zend.com/license/new-bsd New BSD License
  42. */
  43. abstract class Zend_Service_Amazon_Ec2_Abstract extends Zend_Service_Amazon_Abstract
  44. {
  45. /**
  46. * The HTTP query server
  47. */
  48. protected $_ec2Endpoint = 'ec2.amazonaws.com';
  49. /**
  50. * The API version to use
  51. */
  52. protected $_ec2ApiVersion = '2009-04-04';
  53. /**
  54. * Signature Version
  55. */
  56. protected $_ec2SignatureVersion = '2';
  57. /**
  58. * Signature Encoding Method
  59. */
  60. protected $_ec2SignatureMethod = 'HmacSHA256';
  61. /**
  62. * Period after which HTTP request will timeout in seconds
  63. */
  64. protected $_httpTimeout = 10;
  65. /**
  66. * Sends a HTTP request to the queue service using Zend_Http_Client
  67. *
  68. * @param array $params List of parameters to send with the request
  69. * @return Zend_Service_Amazon_Ec2_Response
  70. * @throws Zend_Service_Amazon_Ec2_Exception
  71. */
  72. protected function sendRequest(array $params = array())
  73. {
  74. $url = 'https://' . $this->_getRegion() . $this->_ec2Endpoint . '/';
  75. $params = $this->addRequiredParameters($params);
  76. try {
  77. /* @var $request Zend_Http_Client */
  78. $request = self::getHttpClient();
  79. $request->resetParameters();
  80. $request->setConfig(array(
  81. 'timeout' => $this->_httpTimeout
  82. ));
  83. $request->setUri($url);
  84. $request->setMethod(Zend_Http_Client::POST);
  85. $request->setParameterPost($params);
  86. $httpResponse = $request->request();
  87. } catch (Zend_Http_Client_Exception $zhce) {
  88. $message = 'Error in request to AWS service: ' . $zhce->getMessage();
  89. throw new Zend_Service_Amazon_Ec2_Exception($message, $zhce->getCode());
  90. }
  91. $response = new Zend_Service_Amazon_Ec2_Response($httpResponse);
  92. $this->checkForErrors($response);
  93. return $response;
  94. }
  95. /**
  96. * Adds required authentication and version parameters to an array of
  97. * parameters
  98. *
  99. * The required parameters are:
  100. * - AWSAccessKey
  101. * - SignatureVersion
  102. * - Timestamp
  103. * - Version and
  104. * - Signature
  105. *
  106. * If a required parameter is already set in the <tt>$parameters</tt> array,
  107. * it is overwritten.
  108. *
  109. * @param array $parameters the array to which to add the required
  110. * parameters.
  111. *
  112. * @return array
  113. */
  114. protected function addRequiredParameters(array $parameters)
  115. {
  116. $parameters['AWSAccessKeyId'] = $this->_getAccessKey();
  117. $parameters['SignatureVersion'] = $this->_ec2SignatureVersion;
  118. $parameters['Timestamp'] = gmdate('Y-m-d\TH:i:s\Z');
  119. $parameters['Version'] = $this->_ec2ApiVersion;
  120. $parameters['SignatureMethod'] = $this->_ec2SignatureMethod;
  121. $parameters['Signature'] = $this->signParameters($parameters);
  122. return $parameters;
  123. }
  124. /**
  125. * Computes the RFC 2104-compliant HMAC signature for request parameters
  126. *
  127. * This implements the Amazon Web Services signature, as per the following
  128. * specification:
  129. *
  130. * 1. Sort all request parameters (including <tt>SignatureVersion</tt> and
  131. * excluding <tt>Signature</tt>, the value of which is being created),
  132. * ignoring case.
  133. *
  134. * 2. Iterate over the sorted list and append the parameter name (in its
  135. * original case) and then its value. Do not URL-encode the parameter
  136. * values before constructing this string. Do not use any separator
  137. * characters when appending strings.
  138. *
  139. * @param array $parameters the parameters for which to get the signature.
  140. * @param string $secretKey the secret key to use to sign the parameters.
  141. *
  142. * @return string the signed data.
  143. */
  144. protected function signParameters(array $paramaters)
  145. {
  146. $data = "POST\n";
  147. $data .= $this->_getRegion() . $this->_ec2Endpoint . "\n";
  148. $data .= "/\n";
  149. uksort($paramaters, 'strcmp');
  150. unset($paramaters['Signature']);
  151. $arrData = array();
  152. foreach($paramaters as $key => $value) {
  153. $arrData[] = $key . '=' . str_replace("%7E", "~", urlencode($value));
  154. }
  155. $data .= implode('&', $arrData);
  156. require_once 'Zend/Crypt/Hmac.php';
  157. $hmac = Zend_Crypt_Hmac::compute($this->_getSecretKey(), 'SHA256', $data, Zend_Crypt_Hmac::BINARY);
  158. return base64_encode($hmac);
  159. }
  160. /**
  161. * Checks for errors responses from Amazon
  162. *
  163. * @param Zend_Service_Amazon_Ec2_Response $response the response object to
  164. * check.
  165. *
  166. * @return void
  167. *
  168. * @throws Zend_Service_Amazon_Ec2_Exception if one or more errors are
  169. * returned from Amazon.
  170. */
  171. private function checkForErrors(Zend_Service_Amazon_Ec2_Response $response)
  172. {
  173. $xpath = new DOMXPath($response->getDocument());
  174. $list = $xpath->query('//Error');
  175. if ($list->length > 0) {
  176. $node = $list->item(0);
  177. $code = $xpath->evaluate('string(Code/text())', $node);
  178. $message = $xpath->evaluate('string(Message/text())', $node);
  179. throw new Zend_Service_Amazon_Ec2_Exception($message, 0, $code);
  180. }
  181. }
  182. }