web/lib/Zend/Service/Amazon/S3.php
changeset 886 1e110b03ae96
parent 807 877f952ae2bd
child 1230 68c69c656a2c
equal deleted inserted replaced
885:2251fb41dbc7 886:1e110b03ae96
    13  * to license@zend.com so we can send you a copy immediately.
    13  * to license@zend.com so we can send you a copy immediately.
    14  *
    14  *
    15  * @category   Zend
    15  * @category   Zend
    16  * @package    Zend_Service
    16  * @package    Zend_Service
    17  * @subpackage Amazon_S3
    17  * @subpackage Amazon_S3
    18  * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
    18  * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
    19  * @license    http://framework.zend.com/license/new-bsd     New BSD License
    19  * @license    http://framework.zend.com/license/new-bsd     New BSD License
    20  * @version    $Id: S3.php 23224 2010-10-22 13:45:57Z matthew $
    20  * @version    $Id: S3.php 24593 2012-01-05 20:35:02Z matthew $
    21  */
    21  */
    22 
    22 
    23 /**
    23 /**
    24  * @see Zend_Service_Amazon_Abstract
    24  * @see Zend_Service_Amazon_Abstract
    25  */
    25  */
    34  * Amazon S3 PHP connection class
    34  * Amazon S3 PHP connection class
    35  *
    35  *
    36  * @category   Zend
    36  * @category   Zend
    37  * @package    Zend_Service
    37  * @package    Zend_Service
    38  * @subpackage Amazon_S3
    38  * @subpackage Amazon_S3
    39  * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
    39  * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
    40  * @license    http://framework.zend.com/license/new-bsd     New BSD License
    40  * @license    http://framework.zend.com/license/new-bsd     New BSD License
    41  * @see        http://docs.amazonwebservices.com/AmazonS3/2006-03-01/
    41  * @see        http://docs.amazonwebservices.com/AmazonS3/2006-03-01/
    42  */
    42  */
    43 class Zend_Service_Amazon_S3 extends Zend_Service_Amazon_Abstract
    43 class Zend_Service_Amazon_S3 extends Zend_Service_Amazon_Abstract
    44 {
    44 {
   155      * @return boolean
   155      * @return boolean
   156      */
   156      */
   157     public function createBucket($bucket, $location = null)
   157     public function createBucket($bucket, $location = null)
   158     {
   158     {
   159         $this->_validBucketName($bucket);
   159         $this->_validBucketName($bucket);
   160 
   160         $headers=array();
   161         if($location) {
   161         if($location) {
   162             $data = '<CreateBucketConfiguration><LocationConstraint>'.$location.'</LocationConstraint></CreateBucketConfiguration>';
   162             $data = '<CreateBucketConfiguration><LocationConstraint>'.$location.'</LocationConstraint></CreateBucketConfiguration>';
   163         }
   163             $headers[self::S3_CONTENT_TYPE_HEADER]= 'text/plain';
   164         else {
   164             $headers['Content-size']= strlen($data);
       
   165         } else {
   165             $data = null;
   166             $data = null;
   166         }
   167         }
   167         $response = $this->_makeRequest('PUT', $bucket, null, array(), $data);
   168         $response = $this->_makeRequest('PUT', $bucket, null, $headers, $data);
   168 
   169 
   169         return ($response->getStatus() == 200);
   170         return ($response->getStatus() == 200);
   170     }
   171     }
   171 
   172 
   172     /**
   173     /**
   271         $objects = $this->getObjectsByBucket($bucket);
   272         $objects = $this->getObjectsByBucket($bucket);
   272         if (!$objects) {
   273         if (!$objects) {
   273             return false;
   274             return false;
   274         }
   275         }
   275 
   276 
   276         foreach ($objects as $object) {
   277         while (!empty($objects)) {
   277             $this->removeObject("$bucket/$object");
   278             foreach ($objects as $object) {
   278         }
   279                 $this->removeObject("$bucket/$object");
       
   280             }
       
   281             $params= array (
       
   282                 'marker' => $objects[count($objects)-1]
       
   283             );
       
   284             $objects = $this->getObjectsByBucket($bucket,$params);
       
   285         }
       
   286         
   279         return true;
   287         return true;
   280     }
   288     }
   281 
   289 
   282     /**
   290     /**
   283      * List the objects in a bucket.
   291      * List the objects in a bucket.
   311             }
   319             }
   312         }
   320         }
   313 
   321 
   314         return $objects;
   322         return $objects;
   315     }
   323     }
   316 
   324      /**
       
   325      * List the objects and common prefixes in a bucket.
       
   326      *
       
   327      * Provides the list of object keys and common prefixes that are contained in the bucket.  Valid params include the following.
       
   328      * prefix - Limits the response to keys which begin with the indicated prefix. You can use prefixes to separate a bucket into different sets of keys in a way similar to how a file system uses folders.
       
   329      * marker - Indicates where in the bucket to begin listing. The list will only include keys that occur lexicographically after marker. This is convenient for pagination: To get the next page of results use the last key of the current page as the marker.
       
   330      * max-keys - The maximum number of keys you'd like to see in the response body. The server might return fewer than this many keys, but will not return more.
       
   331      * delimiter - Causes keys that contain the same string between the prefix and the first occurrence of the delimiter to be rolled up into a single result element in the CommonPrefixes collection. These rolled-up keys are not returned elsewhere in the response.
       
   332      *
       
   333      * @see ZF-11401
       
   334      * @param  string $bucket
       
   335      * @param array $params S3 GET Bucket Paramater
       
   336      * @return array|false
       
   337      */
       
   338     public function getObjectsAndPrefixesByBucket($bucket, $params = array())
       
   339     {
       
   340         $response = $this->_makeRequest('GET', $bucket, $params);
       
   341 
       
   342         if ($response->getStatus() != 200) {
       
   343             return false;
       
   344         }
       
   345 
       
   346         $xml = new SimpleXMLElement($response->getBody());
       
   347 
       
   348         $objects = array();
       
   349         if (isset($xml->Contents)) {
       
   350             foreach ($xml->Contents as $contents) {
       
   351                 foreach ($contents->Key as $object) {
       
   352                     $objects[] = (string)$object;
       
   353                 }
       
   354             }
       
   355         }
       
   356         $prefixes = array();
       
   357         if (isset($xml->CommonPrefixes)) {
       
   358             foreach ($xml->CommonPrefixes as $prefix) {
       
   359                 foreach ($prefix->Prefix as $object) {
       
   360                     $prefixes[] = (string)$object;
       
   361                 }
       
   362             }
       
   363         }
       
   364 
       
   365         return array(
       
   366             'objects'  => $objects,
       
   367             'prefixes' => $prefixes
       
   368         );
       
   369     }
   317     /**
   370     /**
   318      * Make sure the object name is valid
   371      * Make sure the object name is valid
   319      *
   372      *
   320      * @param  string $object
   373      * @param  string $object
   321      * @return string
   374      * @return string
   480         if (!isset($meta[self::S3_CONTENT_TYPE_HEADER])) {
   533         if (!isset($meta[self::S3_CONTENT_TYPE_HEADER])) {
   481            $meta[self::S3_CONTENT_TYPE_HEADER] = self::getMimeType($path);
   534            $meta[self::S3_CONTENT_TYPE_HEADER] = self::getMimeType($path);
   482         }
   535         }
   483 
   536 
   484         if(!isset($meta['Content-MD5'])) {
   537         if(!isset($meta['Content-MD5'])) {
   485             $headers['Content-MD5'] = base64_encode(md5_file($path, true));
   538             $meta['Content-MD5'] = base64_encode(md5_file($path, true));
   486         }
   539         }
   487 
   540 
   488         return $this->putObject($object, $data, $meta);
   541         return $this->putObject($object, $data, $meta);
   489     }
   542     }
   490 
   543 
   555     }
   608     }
   556 
   609 
   557     /**
   610     /**
   558      * Make a request to Amazon S3
   611      * Make a request to Amazon S3
   559      *
   612      *
   560      * @param  string $method	Request method
   613      * @param  string $method    Request method
   561      * @param  string $path		Path to requested object
   614      * @param  string $path        Path to requested object
   562      * @param  array  $params	Request parameters
   615      * @param  array  $params    Request parameters
   563      * @param  array  $headers	HTTP headers
   616      * @param  array  $headers    HTTP headers
   564      * @param  string|resource $data		Request data
   617      * @param  string|resource $data        Request data
   565      * @return Zend_Http_Response
   618      * @return Zend_Http_Response
   566      */
   619      */
   567     public function _makeRequest($method, $path='', $params=null, $headers=array(), $data=null)
   620     public function _makeRequest($method, $path='', $params=null, $headers=array(), $data=null)
   568     {
   621     {
   569         $retry_count = 0;
   622         $retry_count = 0;
   588         if ($parts[0]) {
   641         if ($parts[0]) {
   589             // prepend bucket name to the hostname
   642             // prepend bucket name to the hostname
   590             $endpoint->setHost($parts[0].'.'.$endpoint->getHost());
   643             $endpoint->setHost($parts[0].'.'.$endpoint->getHost());
   591         }
   644         }
   592         if (!empty($parts[1])) {
   645         if (!empty($parts[1])) {
   593             $endpoint->setPath('/'.$parts[1]);
   646             // ZF-10218, ZF-10122
       
   647             $pathparts = explode('?',$parts[1]);
       
   648             $endpath = $pathparts[0];
       
   649             $endpoint->setPath('/'.$endpath);
       
   650             
   594         }
   651         }
   595         else {
   652         else {
   596             $endpoint->setPath('/');
   653             $endpoint->setPath('/');
   597             if ($parts[0]) {
   654             if ($parts[0]) {
   598                 $path = $parts[0].'/';
   655                 $path = $parts[0].'/';
   599             }
   656             }
   600         }
   657         }
   601 
       
   602         self::addSignature($method, $path, $headers);
   658         self::addSignature($method, $path, $headers);
   603 
   659 
   604         $client = self::getHttpClient();
   660         $client = self::getHttpClient();
   605 
   661 
   606         $client->resetParameters();
   662         $client->resetParameters(true);
   607         $client->setUri($endpoint);
   663         $client->setUri($endpoint);
   608         $client->setAuth(false);
   664         $client->setAuth(false);
   609         // Work around buglet in HTTP client - it doesn't clean headers
   665         // Work around buglet in HTTP client - it doesn't clean headers
   610         // Remove when ZHC is fixed
   666         // Remove when ZHC is fixed
       
   667         /*
   611         $client->setHeaders(array('Content-MD5'              => null,
   668         $client->setHeaders(array('Content-MD5'              => null,
   612                                   'Content-Encoding'         => null,
   669                                   'Content-Encoding'         => null,
   613                                   'Expect'                   => null,
   670                                   'Expect'                   => null,
   614                                   'Range'                    => null,
   671                                   'Range'                    => null,
   615                                   'x-amz-acl'                => null,
   672                                   'x-amz-acl'                => null,
   616                                   'x-amz-copy-source'        => null,
   673                                   'x-amz-copy-source'        => null,
   617                                   'x-amz-metadata-directive' => null));
   674                                   'x-amz-metadata-directive' => null));
   618 
   675         */
   619         $client->setHeaders($headers);
   676         $client->setHeaders($headers);
   620 
   677 
   621         if (is_array($params)) {
   678         if (is_array($params)) {
   622             foreach ($params as $name=>$value) {
   679             foreach ($params as $name=>$value) {
   623                 $client->setParameterGet($name, $value);
   680                 $client->setParameterGet($name, $value);
   627          if (($method == 'PUT') && ($data !== null)) {
   684          if (($method == 'PUT') && ($data !== null)) {
   628              if (!isset($headers['Content-type'])) {
   685              if (!isset($headers['Content-type'])) {
   629                  $headers['Content-type'] = self::getMimeType($path);
   686                  $headers['Content-type'] = self::getMimeType($path);
   630              }
   687              }
   631              $client->setRawData($data, $headers['Content-type']);
   688              $client->setRawData($data, $headers['Content-type']);
   632          }
   689          } 
   633          do {
   690          do {
   634             $retry = false;
   691             $retry = false;
   635 
   692 
   636             $response = $client->request($method);
   693             $response = $client->request($method);
   637             $response_code = $response->getStatus();
   694             $response_code = $response->getStatus();
   718             $sig_str .= '?acl';
   775             $sig_str .= '?acl';
   719         }
   776         }
   720         else if (strpos($path, '?torrent') !== false) {
   777         else if (strpos($path, '?torrent') !== false) {
   721             $sig_str .= '?torrent';
   778             $sig_str .= '?torrent';
   722         }
   779         }
       
   780         else if (strpos($path, '?versions') !== false) {
       
   781             $sig_str .= '?versions';
       
   782         }
   723 
   783 
   724         $signature = base64_encode(Zend_Crypt_Hmac::compute($this->_getSecretKey(), 'sha1', utf8_encode($sig_str), Zend_Crypt_Hmac::BINARY));
   784         $signature = base64_encode(Zend_Crypt_Hmac::compute($this->_getSecretKey(), 'sha1', utf8_encode($sig_str), Zend_Crypt_Hmac::BINARY));
   725         $headers['Authorization'] = 'AWS '.$this->_getAccessKey().':'.$signature;
   785         $headers['Authorization'] = 'AWS '.$this->_getAccessKey().':'.$signature;
   726 
   786 
   727         return $sig_str;
   787         return $sig_str;